12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100 |
- //===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
- #include "../tools/llvm-cfi-verify/lib/GraphBuilder.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;
- using ::testing::Field;
- namespace llvm {
- namespace cfi_verify {
- namespace {
- class ELFTestFileAnalysis : public FileAnalysis {
- public:
- ELFTestFileAnalysis(StringRef Trip)
- : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}
- // Expose this method publicly for testing.
- void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
- object::SectionedAddress Address) {
- FileAnalysis::parseSectionContents(SectionBytes, Address);
- }
- Error initialiseDisassemblyMembers() {
- return FileAnalysis::initialiseDisassemblyMembers();
- }
- };
- class BasicFileAnalysisTest : public ::testing::Test {
- public:
- BasicFileAnalysisTest(StringRef Trip) : Analysis(Trip) {}
- protected:
- virtual void SetUp() {
- IgnoreDWARFFlag = true;
- SuccessfullyInitialised = true;
- if (auto Err = Analysis.initialiseDisassemblyMembers()) {
- handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
- SuccessfullyInitialised = false;
- outs()
- << "Note: CFIVerifyTests are disabled due to lack of support "
- "on this build.\n";
- });
- }
- }
- bool SuccessfullyInitialised;
- ELFTestFileAnalysis Analysis;
- };
- class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {
- public:
- BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
- };
- class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
- public:
- BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
- };
- TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
- if (!SuccessfullyInitialised)
- return;
- 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, 0x0});
- 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(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x90, // 0: nop
- 0x2f, // 1: (bad)
- 0x90 // 2: nop
- },
- {0xDEADBEEF, 0x0});
- 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);
- }
- TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {
- if (!SuccessfullyInitialised)
- return;
- 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}
- 0x0f, 0x0b // 28: ud2
- },
- {0xDEADBEEF, 0x0});
- EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
- EXPECT_FALSE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
- EXPECT_TRUE(
- Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
- }
- TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x90, // 0: nop
- 0xb0, 0x00, // 1: mov $0x0, %al
- 0x2f, // 3: (bad)
- 0x0f, 0x0b, // 4: ud2
- 0xff, 0x20, // 6: jmpq *(%rax)
- 0xeb, 0x00, // 8: jmp +0
- 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
- 0xff, 0x10, // 15: callq *(rax)
- 0x75, 0x00, // 17: jne +0
- 0xc3, // 19: retq
- },
- {0xDEADBEEF, 0x0});
- EXPECT_TRUE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
- EXPECT_TRUE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
- EXPECT_TRUE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
- EXPECT_FALSE(
- Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
- }
- TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x90, // 0: nop
- 0xb0, 0x00, // 1: mov $0x0, %al
- 0x2f, // 3: (bad)
- 0x0f, 0x0b, // 4: ud2
- 0xff, 0x20, // 6: jmpq *(%rax)
- 0xeb, 0x00, // 8: jmp 10 [+0]
- 0xeb, 0x05, // 10: jmp 17 [+5]
- 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
- 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
- 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
- 0xff, 0x10, // 27: callq *(rax)
- 0x75, 0x00, // 29: jne 31 [+0]
- 0x75, 0xe0, // 31: jne 1 [-32]
- 0xc3, // 33: retq
- 0xeb, 0xdd, // 34: jmp 1 [-35]
- 0xeb, 0xdd, // 36: jmp 3 [-35]
- 0xeb, 0xdc, // 38: jmp 4 [-36]
- },
- {0xDEADBEEF, 0x0});
- const auto *Current = Analysis.getInstruction(0xDEADBEEF);
- const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 1);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 3);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 4);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 6);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 8);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 10);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 12);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 17);
- // Note, definite next instruction address is out of range and should fail.
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Next = Analysis.getDefiniteNextInstruction(*Current);
- Current = Analysis.getInstruction(0xDEADBEEF + 22);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 27);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 29);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 31);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 33);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 34);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
- Current = Analysis.getInstruction(0xDEADBEEF + 36);
- EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
- Current = Analysis.getInstruction(0xDEADBEEF + 38);
- Next = Analysis.getDefiniteNextInstruction(*Current);
- EXPECT_NE(nullptr, Next);
- EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
- }
- TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x90, // 0: nop
- 0xb0, 0x00, // 1: mov $0x0, %al
- 0x2f, // 3: (bad)
- 0x0f, 0x0b, // 4: ud2
- 0xff, 0x20, // 6: jmpq *(%rax)
- 0xeb, 0x00, // 8: jmp 10 [+0]
- 0xeb, 0x05, // 10: jmp 17 [+5]
- 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
- 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
- 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
- 0xff, 0x10, // 27: callq *(rax)
- 0x75, 0x00, // 29: jne 31 [+0]
- 0x75, 0xe0, // 31: jne 1 [-32]
- 0xc3, // 33: retq
- 0xeb, 0xdd, // 34: jmp 1 [-35]
- 0xeb, 0xdd, // 36: jmp 3 [-35]
- 0xeb, 0xdc, // 38: jmp 4 [-36]
- },
- {0xDEADBEEF, 0x0});
- const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
- std::set<const Instr *> XRefs =
- Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(XRefs.empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_THAT(XRefs, UnorderedElementsAre(
- Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
- XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
- EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x90, // 0: nop
- 0x0f, 0x0b, // 1: ud2
- 0x75, 0x00, // 3: jne 5 [+0]
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
- Analysis.validateCFIProtection(Result));
- Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
- Analysis.validateCFIProtection(Result));
- Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
- Analysis.validateCFIProtection(Result));
- Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0x0f, 0x0b, // 2: ud2
- 0xff, 0x10, // 4: callq *(%rax)
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0xff, 0x10, // 2: callq *(%rax)
- 0x0f, 0x0b, // 4: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x03, // 0: jne 5 [+3]
- 0x90, // 2: nop
- 0xff, 0x10, // 3: callq *(%rax)
- 0x0f, 0x0b, // 5: ud2
- 0x75, 0xf9, // 7: jne 2 [-7]
- 0x0f, 0x0b, // 9: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x05, // 0: jne 7 [+5]
- 0x90, // 2: nop
- 0xff, 0x10, // 3: callq *(%rax)
- 0x75, 0xfb, // 5: jne 2 [-5]
- 0x0f, 0x0b, // 7: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x06, // 0: jne 8 [+6]
- 0x90, // 2: nop
- 0x90, // 3: nop
- 0x90, // 4: nop
- 0x90, // 5: nop
- 0xff, 0x10, // 6: callq *(%rax)
- 0x0f, 0x0b, // 8: ud2
- },
- {0xDEADBEEF, 0x0});
- uint64_t PrevSearchLengthForConditionalBranch =
- SearchLengthForConditionalBranch;
- SearchLengthForConditionalBranch = 2;
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
- Analysis.validateCFIProtection(Result));
- SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0xff, 0x10, // 2: callq *(%rax)
- 0x90, // 4: nop
- 0x90, // 5: nop
- 0x90, // 6: nop
- 0x90, // 7: nop
- 0x0f, 0x0b, // 8: ud2
- },
- {0xDEADBEEF, 0x0});
- uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
- SearchLengthForUndef = 2;
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = PrevSearchLengthForUndef;
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0xeb, 0x02, // 0: jmp 4 [+2]
- 0x75, 0x02, // 2: jne 6 [+2]
- 0xff, 0x10, // 4: callq *(%rax)
- 0x0f, 0x0b, // 6: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x04, // 0: jne 6 [+4]
- 0xeb, 0x00, // 2: jmp 4 [+0]
- 0xff, 0x10, // 4: callq *(%rax)
- 0x0f, 0x0b, // 6: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
- if (!SuccessfullyInitialised)
- return;
- // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
- // graph.
- Analysis.parseSectionContents(
- {
- 0x75, 0x12, // 0: jne 20 [+18]
- 0xeb, 0x03, // 2: jmp 7 [+3]
- 0x75, 0x10, // 4: jne 22 [+16]
- 0x90, // 6: nop
- 0x90, // 7: nop
- 0x90, // 8: nop
- 0xff, 0x10, // 9: callq *(%rax)
- 0xeb, 0xfc, // 11: jmp 9 [-4]
- 0x75, 0xfa, // 13: jne 9 [-6]
- 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
- 0x90, // 20: nop
- 0x90, // 21: nop
- 0x0f, 0x0b, // 22: ud2
- },
- {0xDEADBEEF, 0x0});
- uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
- SearchLengthForUndef = 5;
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = PrevSearchLengthForUndef;
- }
- TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
- Analysis.parseSectionContents(
- {
- 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
- 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
- 0xff, 0xd0, // 0x68811d: callq *%rax
- 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
- 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
- 0x0f, 0x0b, // 0x688127: ud2
- },
- {0x688118, 0x0});
- uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
- SearchLengthForUndef = 1;
- GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = PrevSearchLengthForUndef;
- }
- TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
- Analysis.parseSectionContents(
- {
- 0x74, 0x73, // 0x7759eb: je 0x775a60
- 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
- },
- {0x7759eb, 0x0});
- Analysis.parseSectionContents(
- {
- 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
- 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
- 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
- 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
- 0xff, 0xd1, // 0x775a68: callq *%rcx
- },
- {0x775a56, 0x0});
- Analysis.parseSectionContents(
- {
- 0x0f, 0x0b, // 0x775e0e: ud2
- },
- {0x775e0e, 0x0});
- uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
- SearchLengthForUndef = 1;
- GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = 2;
- Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = 3;
- Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- SearchLengthForUndef = PrevSearchLengthForUndef;
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0x0f, 0x0b, // 2: ud2
- 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
- 0xff, 0x10, // 10: callq *(%rax)
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0x0f, 0x0b, // 2: ud2
- 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
- 0xff, 0x10, // 8: callq *(%rax)
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x02, // 0: jne 4 [+2]
- 0x0f, 0x0b, // 2: ud2
- 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
- 0xff, 0x10, // 9: callq *(%rax)
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x75, 0x04, // 0: jne 6 [+4]
- 0x0f, 0x31, // 2: rdtsc (note: affects eax)
- 0xff, 0x10, // 4: callq *(%rax)
- 0x0f, 0x0b, // 6: ud2
- 0x75, 0xf9, // 8: jne 2 [-7]
- 0x0f, 0x0b, // 10: ud2
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
- 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
- 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
- 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
- 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
- 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
- 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
- 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
- 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0x03, 0x00, 0x00, 0x14, // 0: b 12
- 0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
- 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
- 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
- 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
- 0x03, 0x00, 0x00, 0x14, // 8: b 12
- 0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
- 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 20: br x1
- 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});
- EXPECT_EQ(CFIProtectionStatus::PROTECTED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
- 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
- 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
- 0x03, 0x00, 0x00, 0x14, // 12: b 12
- 0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
- 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
- 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
- if (!SuccessfullyInitialised)
- return;
- Analysis.parseSectionContents(
- {
- 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
- 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
- 0x03, 0x00, 0x00, 0x14, // 8: b 12
- 0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
- 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
- 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
- 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
- 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
- },
- {0xDEADBEEF, 0x0});
- GraphResult Result =
- GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
- EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
- Analysis.validateCFIProtection(Result));
- }
- } // 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();
- }
|