diff options
| author | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2017-10-11 20:35:01 +0000 |
|---|---|---|
| committer | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2017-10-11 20:35:01 +0000 |
| commit | 89c3c8c403e074755be8d853fda9266f7961b469 (patch) | |
| tree | 6f6c7a9028dd001c459050928493c17ed469bd7e /llvm/unittests/tools/llvm-cfi-verify | |
| parent | 75480e3871179480ce5f012ae6b73122f34216f9 (diff) | |
| download | bcm5719-llvm-89c3c8c403e074755be8d853fda9266f7961b469.tar.gz bcm5719-llvm-89c3c8c403e074755be8d853fda9266f7961b469.zip | |
Reland 'Classify llvm-cfi-verify.'
Summary: Move llvm-cfi-verify into a class in preparation for CFI analysis to come.
Reviewers: vlad.tsyrklevich
Reviewed By: vlad.tsyrklevich
Subscribers: mgorny, llvm-commits, pcc, kcc
Differential Revision: https://reviews.llvm.org/D38379
llvm-svn: 315504
Diffstat (limited to 'llvm/unittests/tools/llvm-cfi-verify')
| -rw-r--r-- | llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp | 216 |
2 files changed, 231 insertions, 0 deletions
diff --git a/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt b/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt new file mode 100644 index 00000000000..c9ae51f2335 --- /dev/null +++ b/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS + AllTargetsAsmPrinters + AllTargetsAsmParsers + AllTargetsDescs + AllTargetsDisassemblers + AllTargetsInfos + CFIVerify + MC + MCParser + Object + Support + ) + +add_llvm_unittest(CFIVerifyTests + FileAnalysis.cpp) diff --git a/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp new file mode 100644 index 00000000000..00bea1b4c43 --- /dev/null +++ b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp @@ -0,0 +1,216 @@ +//===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../tools/llvm-cfi-verify/lib/FileAnalysis.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" + +#include <cstdlib> + +using Instr = ::llvm::cfi_verify::FileAnalysis::Instr; +using ::testing::Eq; + +namespace llvm { +namespace cfi_verify { +namespace { +class ELFx86TestFileAnalysis : public FileAnalysis { +public: + ELFx86TestFileAnalysis() + : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {} + + // Expose this method publicly for testing. + void parseSectionContents(ArrayRef<uint8_t> SectionBytes, + uint64_t SectionAddress) { + FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); + } + + Error initialiseDisassemblyMembers() { + return FileAnalysis::initialiseDisassemblyMembers(); + } +}; + +class BasicFileAnalysisTest : public ::testing::Test { +protected: + virtual void SetUp() { + if (Analysis.initialiseDisassemblyMembers()) { + FAIL() << "Failed to initialise FileAnalysis."; + } + } + + ELFx86TestFileAnalysis Analysis; +}; + +TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) { + Analysis.parseSectionContents( + { + 0x90, // 0: nop + 0xb0, 0x00, // 1: mov $0x0, %al + 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp + 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp + 0x48, 0xbe, 0xc4, 0x07, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi + 0x2f, // 20: (bad) + 0x41, 0x0e, // 21: rex.B (bad) + 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} + }, + 0xDEADBEEF); + + EXPECT_EQ(nullptr, Analysis.getInstruction(0x0)); + EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000)); + + // 0xDEADBEEF: nop + const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress); + EXPECT_EQ(1u, InstrMeta->InstructionSize); + EXPECT_TRUE(InstrMeta->Valid); + + const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); + EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); + const auto *PrevInstrMeta = InstrMeta; + + // 0xDEADBEEF + 1: mov $0x0, %al + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(NextInstrMeta, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress); + EXPECT_EQ(2u, InstrMeta->InstructionSize); + EXPECT_TRUE(InstrMeta->Valid); + + NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); + EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); + PrevInstrMeta = InstrMeta; + + // 0xDEADBEEF + 3: mov %rsp, %rbp + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(NextInstrMeta, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress); + EXPECT_EQ(3u, InstrMeta->InstructionSize); + EXPECT_TRUE(InstrMeta->Valid); + + NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); + EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); + PrevInstrMeta = InstrMeta; + + // 0xDEADBEEF + 6: sub $0x18, %rsp + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(NextInstrMeta, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress); + EXPECT_EQ(4u, InstrMeta->InstructionSize); + EXPECT_TRUE(InstrMeta->Valid); + + NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); + EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); + PrevInstrMeta = InstrMeta; + + // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(NextInstrMeta, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress); + EXPECT_EQ(10u, InstrMeta->InstructionSize); + EXPECT_TRUE(InstrMeta->Valid); + + EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); + EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); + PrevInstrMeta = InstrMeta; + + // 0xDEADBEEF + 20: (bad) + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress); + EXPECT_EQ(1u, InstrMeta->InstructionSize); + EXPECT_FALSE(InstrMeta->Valid); + + EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); + EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); + + // 0xDEADBEEF + 21: rex.B (bad) + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress); + EXPECT_EQ(2u, InstrMeta->InstructionSize); + EXPECT_FALSE(InstrMeta->Valid); + + EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); + EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); + + // 0xDEADBEEF + 6: (bad) {%k1} + InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23); + EXPECT_NE(nullptr, InstrMeta); + EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress); + EXPECT_EQ(5u, InstrMeta->InstructionSize); + EXPECT_FALSE(InstrMeta->Valid); + + EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); + EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); +} + +TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) { + Analysis.parseSectionContents( + { + 0x90, // 0: nop + 0x2f, // 1: (bad) + 0x90 // 2: nop + }, + 0xDEADBEEF); + const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1); + const auto *GoodInstrMeta = + Analysis.getPrevInstructionSequential(BadInstrMeta); + EXPECT_NE(nullptr, GoodInstrMeta); + EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress); + EXPECT_EQ(1u, GoodInstrMeta->InstructionSize); + + GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta); + EXPECT_NE(nullptr, GoodInstrMeta); + EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress); + EXPECT_EQ(1u, GoodInstrMeta->InstructionSize); +} + +} // anonymous namespace +} // end namespace cfi_verify +} // end namespace llvm + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + llvm::cl::ParseCommandLineOptions(argc, argv); + + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + return RUN_ALL_TESTS(); +} |

