summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/tools/llvm-cfi-verify
diff options
context:
space:
mode:
authorVlad Tsyrklevich <vlad@tsyrklevich.net>2017-10-11 20:35:01 +0000
committerVlad Tsyrklevich <vlad@tsyrklevich.net>2017-10-11 20:35:01 +0000
commit89c3c8c403e074755be8d853fda9266f7961b469 (patch)
tree6f6c7a9028dd001c459050928493c17ed469bd7e /llvm/unittests/tools/llvm-cfi-verify
parent75480e3871179480ce5f012ae6b73122f34216f9 (diff)
downloadbcm5719-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.txt15
-rw-r--r--llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp216
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();
+}
OpenPOWER on IntegriCloud