1107 lines · cpp
1//===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"10#include "../tools/llvm-cfi-verify/lib/GraphBuilder.h"11#include "gmock/gmock.h"12#include "gtest/gtest.h"13 14#include "llvm/BinaryFormat/ELF.h"15#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"16#include "llvm/MC/MCAsmInfo.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCDisassembler/MCDisassembler.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstPrinter.h"21#include "llvm/MC/MCInstrAnalysis.h"22#include "llvm/MC/MCInstrDesc.h"23#include "llvm/MC/MCInstrInfo.h"24#include "llvm/MC/MCObjectFileInfo.h"25#include "llvm/MC/MCRegisterInfo.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/MC/TargetRegistry.h"28#include "llvm/Object/Binary.h"29#include "llvm/Object/COFF.h"30#include "llvm/Object/ELFObjectFile.h"31#include "llvm/Object/ObjectFile.h"32#include "llvm/Support/Casting.h"33#include "llvm/Support/CommandLine.h"34#include "llvm/Support/Error.h"35#include "llvm/Support/MemoryBuffer.h"36#include "llvm/Support/TargetSelect.h"37#include "llvm/Support/raw_ostream.h"38 39#include <cstdlib>40 41using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;42using ::testing::Eq;43using ::testing::Field;44 45namespace llvm {46namespace cfi_verify {47namespace {48class ELFTestFileAnalysis : public FileAnalysis {49public:50 ELFTestFileAnalysis(StringRef Trip)51 : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}52 53 // Expose this method publicly for testing.54 void parseSectionContents(ArrayRef<uint8_t> SectionBytes,55 object::SectionedAddress Address) {56 FileAnalysis::parseSectionContents(SectionBytes, Address);57 }58 59 Error initialiseDisassemblyMembers() {60 return FileAnalysis::initialiseDisassemblyMembers();61 }62};63 64class BasicFileAnalysisTest : public ::testing::Test {65public:66 BasicFileAnalysisTest(StringRef Trip)67 : SuccessfullyInitialised(false), Analysis(Trip) {}68protected:69 void SetUp() override {70 IgnoreDWARFFlag = true;71 SuccessfullyInitialised = true;72 if (auto Err = Analysis.initialiseDisassemblyMembers()) {73 handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {74 SuccessfullyInitialised = false;75 outs()76 << "Note: CFIVerifyTests are disabled due to lack of support "77 "on this build.\n";78 });79 }80 }81 82 bool SuccessfullyInitialised;83 ELFTestFileAnalysis Analysis;84};85 86class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {87public:88 BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}89};90 91class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {92public:93 BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}94};95 96TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {97 if (!SuccessfullyInitialised)98 GTEST_SKIP();99 Analysis.parseSectionContents(100 {101 0x90, // 0: nop102 0xb0, 0x00, // 1: mov $0x0, %al103 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp104 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp105 0x48, 0xbe, 0xc4, 0x07, 0x40,106 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi107 0x2f, // 20: (bad)108 0x41, 0x0e, // 21: rex.B (bad)109 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}110 },111 {0xDEADBEEF, 0x0});112 113 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));114 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));115 116 // 0xDEADBEEF: nop117 const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);118 EXPECT_NE(nullptr, InstrMeta);119 EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);120 EXPECT_EQ(1u, InstrMeta->InstructionSize);121 EXPECT_TRUE(InstrMeta->Valid);122 123 const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);124 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));125 const auto *PrevInstrMeta = InstrMeta;126 127 // 0xDEADBEEF + 1: mov $0x0, %al128 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);129 EXPECT_NE(nullptr, InstrMeta);130 EXPECT_EQ(NextInstrMeta, InstrMeta);131 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);132 EXPECT_EQ(2u, InstrMeta->InstructionSize);133 EXPECT_TRUE(InstrMeta->Valid);134 135 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);136 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));137 PrevInstrMeta = InstrMeta;138 139 // 0xDEADBEEF + 3: mov %rsp, %rbp140 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);141 EXPECT_NE(nullptr, InstrMeta);142 EXPECT_EQ(NextInstrMeta, InstrMeta);143 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);144 EXPECT_EQ(3u, InstrMeta->InstructionSize);145 EXPECT_TRUE(InstrMeta->Valid);146 147 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);148 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));149 PrevInstrMeta = InstrMeta;150 151 // 0xDEADBEEF + 6: sub $0x18, %rsp152 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);153 EXPECT_NE(nullptr, InstrMeta);154 EXPECT_EQ(NextInstrMeta, InstrMeta);155 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);156 EXPECT_EQ(4u, InstrMeta->InstructionSize);157 EXPECT_TRUE(InstrMeta->Valid);158 159 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);160 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));161 PrevInstrMeta = InstrMeta;162 163 // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi164 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);165 EXPECT_NE(nullptr, InstrMeta);166 EXPECT_EQ(NextInstrMeta, InstrMeta);167 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);168 EXPECT_EQ(10u, InstrMeta->InstructionSize);169 EXPECT_TRUE(InstrMeta->Valid);170 171 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));172 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));173 PrevInstrMeta = InstrMeta;174 175 // 0xDEADBEEF + 20: (bad)176 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);177 EXPECT_NE(nullptr, InstrMeta);178 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);179 EXPECT_EQ(1u, InstrMeta->InstructionSize);180 EXPECT_FALSE(InstrMeta->Valid);181 182 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));183 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));184 185 // 0xDEADBEEF + 21: rex.B (bad)186 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);187 EXPECT_NE(nullptr, InstrMeta);188 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);189 EXPECT_EQ(2u, InstrMeta->InstructionSize);190 EXPECT_FALSE(InstrMeta->Valid);191 192 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));193 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));194 195 // 0xDEADBEEF + 6: (bad) {%k1}196 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);197 EXPECT_NE(nullptr, InstrMeta);198 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);199 EXPECT_EQ(5u, InstrMeta->InstructionSize);200 EXPECT_FALSE(InstrMeta->Valid);201 202 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));203 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));204}205 206TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {207 if (!SuccessfullyInitialised)208 GTEST_SKIP();209 Analysis.parseSectionContents(210 {211 0x90, // 0: nop212 0x2f, // 1: (bad)213 0x90 // 2: nop214 },215 {0xDEADBEEF, 0x0});216 const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);217 const auto *GoodInstrMeta =218 Analysis.getPrevInstructionSequential(BadInstrMeta);219 EXPECT_NE(nullptr, GoodInstrMeta);220 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);221 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);222 223 GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);224 EXPECT_NE(nullptr, GoodInstrMeta);225 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);226 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);227}228 229TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {230 if (!SuccessfullyInitialised)231 GTEST_SKIP();232 Analysis.parseSectionContents(233 {234 0x90, // 0: nop235 0xb0, 0x00, // 1: mov $0x0, %al236 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp237 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp238 0x48, 0xbe, 0xc4, 0x07, 0x40,239 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi240 0x2f, // 20: (bad)241 0x41, 0x0e, // 21: rex.B (bad)242 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}243 0x0f, 0x0b // 28: ud2244 },245 {0xDEADBEEF, 0x0});246 247 EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));248 EXPECT_FALSE(249 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));250 EXPECT_FALSE(251 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));252 EXPECT_FALSE(253 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));254 EXPECT_FALSE(255 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));256 EXPECT_FALSE(257 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));258 EXPECT_FALSE(259 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));260 EXPECT_TRUE(261 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));262}263 264TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {265 if (!SuccessfullyInitialised)266 GTEST_SKIP();267 Analysis.parseSectionContents(268 {269 0x90, // 0: nop270 0xb0, 0x00, // 1: mov $0x0, %al271 0x2f, // 3: (bad)272 0x0f, 0x0b, // 4: ud2273 0xff, 0x20, // 6: jmpq *(%rax)274 0xeb, 0x00, // 8: jmp +0275 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]276 0xff, 0x10, // 15: callq *(rax)277 0x75, 0x00, // 17: jne +0278 0xc3, // 19: retq279 },280 {0xDEADBEEF, 0x0});281 282 EXPECT_TRUE(283 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));284 EXPECT_TRUE(285 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));286 EXPECT_FALSE(287 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));288 EXPECT_FALSE(289 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));290 EXPECT_FALSE(291 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));292 EXPECT_FALSE(293 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));294 EXPECT_FALSE(295 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));296 EXPECT_FALSE(297 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));298 EXPECT_TRUE(299 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));300 EXPECT_FALSE(301 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));302}303 304TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {305 if (!SuccessfullyInitialised)306 GTEST_SKIP();307 Analysis.parseSectionContents(308 {309 0x90, // 0: nop310 0xb0, 0x00, // 1: mov $0x0, %al311 0x2f, // 3: (bad)312 0x0f, 0x0b, // 4: ud2313 0xff, 0x20, // 6: jmpq *(%rax)314 0xeb, 0x00, // 8: jmp 10 [+0]315 0xeb, 0x05, // 10: jmp 17 [+5]316 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]317 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]318 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]319 0xff, 0x10, // 27: callq *(rax)320 0x75, 0x00, // 29: jne 31 [+0]321 0x75, 0xe0, // 31: jne 1 [-32]322 0xc3, // 33: retq323 0xeb, 0xdd, // 34: jmp 1 [-35]324 0xeb, 0xdd, // 36: jmp 3 [-35]325 0xeb, 0xdc, // 38: jmp 4 [-36]326 },327 {0xDEADBEEF, 0x0});328 329 const auto *Current = Analysis.getInstruction(0xDEADBEEF);330 const auto *Next = Analysis.getDefiniteNextInstruction(*Current);331 EXPECT_NE(nullptr, Next);332 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);333 334 Current = Analysis.getInstruction(0xDEADBEEF + 1);335 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));336 337 Current = Analysis.getInstruction(0xDEADBEEF + 3);338 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));339 340 Current = Analysis.getInstruction(0xDEADBEEF + 4);341 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));342 343 Current = Analysis.getInstruction(0xDEADBEEF + 6);344 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));345 346 Current = Analysis.getInstruction(0xDEADBEEF + 8);347 Next = Analysis.getDefiniteNextInstruction(*Current);348 EXPECT_NE(nullptr, Next);349 EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);350 351 Current = Analysis.getInstruction(0xDEADBEEF + 10);352 Next = Analysis.getDefiniteNextInstruction(*Current);353 EXPECT_NE(nullptr, Next);354 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);355 356 Current = Analysis.getInstruction(0xDEADBEEF + 12);357 Next = Analysis.getDefiniteNextInstruction(*Current);358 EXPECT_NE(nullptr, Next);359 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);360 361 Current = Analysis.getInstruction(0xDEADBEEF + 17);362 // Note, definite next instruction address is out of range and should fail.363 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));364 Next = Analysis.getDefiniteNextInstruction(*Current);365 366 Current = Analysis.getInstruction(0xDEADBEEF + 22);367 Next = Analysis.getDefiniteNextInstruction(*Current);368 EXPECT_NE(nullptr, Next);369 EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);370 371 Current = Analysis.getInstruction(0xDEADBEEF + 27);372 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));373 Current = Analysis.getInstruction(0xDEADBEEF + 29);374 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));375 Current = Analysis.getInstruction(0xDEADBEEF + 31);376 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));377 Current = Analysis.getInstruction(0xDEADBEEF + 33);378 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));379 380 Current = Analysis.getInstruction(0xDEADBEEF + 34);381 Next = Analysis.getDefiniteNextInstruction(*Current);382 EXPECT_NE(nullptr, Next);383 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);384 385 Current = Analysis.getInstruction(0xDEADBEEF + 36);386 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));387 388 Current = Analysis.getInstruction(0xDEADBEEF + 38);389 Next = Analysis.getDefiniteNextInstruction(*Current);390 EXPECT_NE(nullptr, Next);391 EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);392}393 394TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {395 if (!SuccessfullyInitialised)396 GTEST_SKIP();397 Analysis.parseSectionContents(398 {399 0x90, // 0: nop400 0xb0, 0x00, // 1: mov $0x0, %al401 0x2f, // 3: (bad)402 0x0f, 0x0b, // 4: ud2403 0xff, 0x20, // 6: jmpq *(%rax)404 0xeb, 0x00, // 8: jmp 10 [+0]405 0xeb, 0x05, // 10: jmp 17 [+5]406 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]407 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]408 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]409 0xff, 0x10, // 27: callq *(rax)410 0x75, 0x00, // 29: jne 31 [+0]411 0x75, 0xe0, // 31: jne 1 [-32]412 0xc3, // 33: retq413 0xeb, 0xdd, // 34: jmp 1 [-35]414 0xeb, 0xdd, // 36: jmp 3 [-35]415 0xeb, 0xdc, // 38: jmp 4 [-36]416 },417 {0xDEADBEEF, 0x0});418 const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);419 std::set<const Instr *> XRefs =420 Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);421 EXPECT_TRUE(XRefs.empty());422 423 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);424 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);425 EXPECT_THAT(XRefs, UnorderedElementsAre(426 Field(&Instr::VMAddress, Eq(0xDEADBEEF)),427 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),428 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));429 430 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);431 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);432 EXPECT_THAT(XRefs, UnorderedElementsAre(433 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),434 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));435 436 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);437 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);438 EXPECT_THAT(XRefs, UnorderedElementsAre(439 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));440 441 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);442 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());443 444 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);445 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);446 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());447 448 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);449 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);450 EXPECT_THAT(XRefs, UnorderedElementsAre(451 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));452 453 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);454 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);455 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());456 457 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);458 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);459 EXPECT_THAT(XRefs, UnorderedElementsAre(460 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),461 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));462 463 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);464 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);465 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());466 467 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);468 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);469 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());470 471 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);472 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);473 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());474 475 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);476 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);477 EXPECT_THAT(XRefs, UnorderedElementsAre(478 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),479 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));480 481 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);482 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);483 EXPECT_THAT(XRefs, UnorderedElementsAre(484 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));485 486 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);487 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);488 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());489 490 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);491 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);492 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());493 494 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);495 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);496 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());497}498 499TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {500 if (!SuccessfullyInitialised)501 GTEST_SKIP();502 Analysis.parseSectionContents(503 {504 0x90, // 0: nop505 0x0f, 0x0b, // 1: ud2506 0x75, 0x00, // 3: jne 5 [+0]507 },508 {0xDEADBEEF, 0x0});509 GraphResult Result =510 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});511 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,512 Analysis.validateCFIProtection(Result));513 Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});514 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,515 Analysis.validateCFIProtection(Result));516 Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});517 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,518 Analysis.validateCFIProtection(Result));519 Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0});520 EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,521 Analysis.validateCFIProtection(Result));522}523 524TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {525 if (!SuccessfullyInitialised)526 GTEST_SKIP();527 Analysis.parseSectionContents(528 {529 0x75, 0x02, // 0: jne 4 [+2]530 0x0f, 0x0b, // 2: ud2531 0xff, 0x10, // 4: callq *(%rax)532 },533 {0xDEADBEEF, 0x0});534 GraphResult Result =535 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});536 EXPECT_EQ(CFIProtectionStatus::PROTECTED,537 Analysis.validateCFIProtection(Result));538}539 540TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {541 if (!SuccessfullyInitialised)542 GTEST_SKIP();543 Analysis.parseSectionContents(544 {545 0x75, 0x02, // 0: jne 4 [+2]546 0xff, 0x10, // 2: callq *(%rax)547 0x0f, 0x0b, // 4: ud2548 },549 {0xDEADBEEF, 0x0});550 GraphResult Result =551 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});552 EXPECT_EQ(CFIProtectionStatus::PROTECTED,553 Analysis.validateCFIProtection(Result));554}555 556TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {557 if (!SuccessfullyInitialised)558 GTEST_SKIP();559 Analysis.parseSectionContents(560 {561 0x75, 0x03, // 0: jne 5 [+3]562 0x90, // 2: nop563 0xff, 0x10, // 3: callq *(%rax)564 0x0f, 0x0b, // 5: ud2565 0x75, 0xf9, // 7: jne 2 [-7]566 0x0f, 0x0b, // 9: ud2567 },568 {0xDEADBEEF, 0x0});569 GraphResult Result =570 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});571 EXPECT_EQ(CFIProtectionStatus::PROTECTED,572 Analysis.validateCFIProtection(Result));573}574 575TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {576 if (!SuccessfullyInitialised)577 GTEST_SKIP();578 Analysis.parseSectionContents(579 {580 0x75, 0x05, // 0: jne 7 [+5]581 0x90, // 2: nop582 0xff, 0x10, // 3: callq *(%rax)583 0x75, 0xfb, // 5: jne 2 [-5]584 0x0f, 0x0b, // 7: ud2585 },586 {0xDEADBEEF, 0x0});587 GraphResult Result =588 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});589 EXPECT_EQ(CFIProtectionStatus::PROTECTED,590 Analysis.validateCFIProtection(Result));591}592 593TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {594 if (!SuccessfullyInitialised)595 GTEST_SKIP();596 Analysis.parseSectionContents(597 {598 0x75, 0x06, // 0: jne 8 [+6]599 0x90, // 2: nop600 0x90, // 3: nop601 0x90, // 4: nop602 0x90, // 5: nop603 0xff, 0x10, // 6: callq *(%rax)604 0x0f, 0x0b, // 8: ud2605 },606 {0xDEADBEEF, 0x0});607 uint64_t PrevSearchLengthForConditionalBranch =608 SearchLengthForConditionalBranch;609 SearchLengthForConditionalBranch = 2;610 611 GraphResult Result =612 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});613 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,614 Analysis.validateCFIProtection(Result));615 616 SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;617}618 619TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {620 if (!SuccessfullyInitialised)621 GTEST_SKIP();622 Analysis.parseSectionContents(623 {624 0x75, 0x02, // 0: jne 4 [+2]625 0xff, 0x10, // 2: callq *(%rax)626 0x90, // 4: nop627 0x90, // 5: nop628 0x90, // 6: nop629 0x90, // 7: nop630 0x0f, 0x0b, // 8: ud2631 },632 {0xDEADBEEF, 0x0});633 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;634 SearchLengthForUndef = 2;635 636 GraphResult Result =637 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});638 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,639 Analysis.validateCFIProtection(Result));640 641 SearchLengthForUndef = PrevSearchLengthForUndef;642}643 644TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {645 if (!SuccessfullyInitialised)646 GTEST_SKIP();647 Analysis.parseSectionContents(648 {649 0xeb, 0x02, // 0: jmp 4 [+2]650 0x75, 0x02, // 2: jne 6 [+2]651 0xff, 0x10, // 4: callq *(%rax)652 0x0f, 0x0b, // 6: ud2653 },654 {0xDEADBEEF, 0x0});655 GraphResult Result =656 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});657 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,658 Analysis.validateCFIProtection(Result));659}660 661TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {662 if (!SuccessfullyInitialised)663 GTEST_SKIP();664 Analysis.parseSectionContents(665 {666 0x75, 0x04, // 0: jne 6 [+4]667 0xeb, 0x00, // 2: jmp 4 [+0]668 0xff, 0x10, // 4: callq *(%rax)669 0x0f, 0x0b, // 6: ud2670 },671 {0xDEADBEEF, 0x0});672 GraphResult Result =673 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});674 EXPECT_EQ(CFIProtectionStatus::PROTECTED,675 Analysis.validateCFIProtection(Result));676}677 678TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {679 if (!SuccessfullyInitialised)680 GTEST_SKIP();681 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this682 // graph.683 Analysis.parseSectionContents(684 {685 0x75, 0x12, // 0: jne 20 [+18]686 0xeb, 0x03, // 2: jmp 7 [+3]687 0x75, 0x10, // 4: jne 22 [+16]688 0x90, // 6: nop689 0x90, // 7: nop690 0x90, // 8: nop691 0xff, 0x10, // 9: callq *(%rax)692 0xeb, 0xfc, // 11: jmp 9 [-4]693 0x75, 0xfa, // 13: jne 9 [-6]694 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]695 0x90, // 20: nop696 0x90, // 21: nop697 0x0f, 0x0b, // 22: ud2698 },699 {0xDEADBEEF, 0x0});700 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;701 SearchLengthForUndef = 5;702 GraphResult Result =703 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});704 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,705 Analysis.validateCFIProtection(Result));706 SearchLengthForUndef = PrevSearchLengthForUndef;707}708 709TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {710 if (!SuccessfullyInitialised)711 GTEST_SKIP();712 Analysis.parseSectionContents(713 {714 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]715 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi716 0xff, 0xd0, // 0x68811d: callq *%rax717 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi718 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130719 0x0f, 0x0b, // 0x688127: ud2720 },721 {0x688118, 0x0});722 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;723 SearchLengthForUndef = 1;724 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});725 EXPECT_EQ(CFIProtectionStatus::PROTECTED,726 Analysis.validateCFIProtection(Result));727 SearchLengthForUndef = PrevSearchLengthForUndef;728}729 730TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {731 if (!SuccessfullyInitialised)732 GTEST_SKIP();733 Analysis.parseSectionContents(734 {735 0x74, 0x73, // 0x7759eb: je 0x775a60736 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e737 },738 {0x7759eb, 0x0});739 740 Analysis.parseSectionContents(741 {742 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e743 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx744 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi745 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi746 0xff, 0xd1, // 0x775a68: callq *%rcx747 },748 {0x775a56, 0x0});749 750 Analysis.parseSectionContents(751 {752 0x0f, 0x0b, // 0x775e0e: ud2753 },754 {0x775e0e, 0x0});755 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;756 SearchLengthForUndef = 1;757 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});758 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,759 Analysis.validateCFIProtection(Result));760 SearchLengthForUndef = 2;761 Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});762 EXPECT_EQ(CFIProtectionStatus::PROTECTED,763 Analysis.validateCFIProtection(Result));764 SearchLengthForUndef = 3;765 Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});766 EXPECT_EQ(CFIProtectionStatus::PROTECTED,767 Analysis.validateCFIProtection(Result));768 SearchLengthForUndef = PrevSearchLengthForUndef;769}770 771TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {772 if (!SuccessfullyInitialised)773 GTEST_SKIP();774 Analysis.parseSectionContents(775 {776 0x75, 0x02, // 0: jne 4 [+2]777 0x0f, 0x0b, // 2: ud2778 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax779 0xff, 0x10, // 10: callq *(%rax)780 },781 {0xDEADBEEF, 0x0});782 GraphResult Result =783 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});784 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,785 Analysis.validateCFIProtection(Result));786}787 788TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {789 if (!SuccessfullyInitialised)790 GTEST_SKIP();791 Analysis.parseSectionContents(792 {793 0x75, 0x02, // 0: jne 4 [+2]794 0x0f, 0x0b, // 2: ud2795 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax796 0xff, 0x10, // 8: callq *(%rax)797 },798 {0xDEADBEEF, 0x0});799 GraphResult Result =800 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});801 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,802 Analysis.validateCFIProtection(Result));803}804 805TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {806 if (!SuccessfullyInitialised)807 GTEST_SKIP();808 Analysis.parseSectionContents(809 {810 0x75, 0x02, // 0: jne 4 [+2]811 0x0f, 0x0b, // 2: ud2812 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax813 0xff, 0x10, // 9: callq *(%rax)814 },815 {0xDEADBEEF, 0x0});816 GraphResult Result =817 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});818 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,819 Analysis.validateCFIProtection(Result));820}821 822TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {823 if (!SuccessfullyInitialised)824 GTEST_SKIP();825 Analysis.parseSectionContents(826 {827 0x75, 0x04, // 0: jne 6 [+4]828 0x0f, 0x31, // 2: rdtsc (note: affects eax)829 0xff, 0x10, // 4: callq *(%rax)830 0x0f, 0x0b, // 6: ud2831 0x75, 0xf9, // 8: jne 2 [-7]832 0x0f, 0x0b, // 10: ud2833 },834 {0xDEADBEEF, 0x0});835 GraphResult Result =836 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});837 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,838 Analysis.validateCFIProtection(Result));839}840 841TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {842 if (!SuccessfullyInitialised)843 GTEST_SKIP();844 Analysis.parseSectionContents(845 {846 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8847 },848 {0xDEADBEEF, 0x0});849 GraphResult Result =850 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});851 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,852 Analysis.validateCFIProtection(Result));853}854 855TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {856 if (!SuccessfullyInitialised)857 GTEST_SKIP();858 Analysis.parseSectionContents(859 {860 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8861 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1862 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8863 },864 {0xDEADBEEF, 0x0});865 GraphResult Result =866 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});867 EXPECT_EQ(CFIProtectionStatus::PROTECTED,868 Analysis.validateCFIProtection(Result));869}870 871TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {872 if (!SuccessfullyInitialised)873 GTEST_SKIP();874 Analysis.parseSectionContents(875 {876 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8877 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1878 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1879 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8880 },881 {0xDEADBEEF, 0x0});882 GraphResult Result =883 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});884 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,885 Analysis.validateCFIProtection(Result));886}887 888TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {889 if (!SuccessfullyInitialised)890 GTEST_SKIP();891 Analysis.parseSectionContents(892 {893 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8894 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1895 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]896 0x20, 0x00, 0x1f, 0xd6, // 12: br x1897 },898 {0xDEADBEEF, 0x0});899 GraphResult Result =900 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});901 EXPECT_EQ(CFIProtectionStatus::PROTECTED,902 Analysis.validateCFIProtection(Result));903}904 905TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {906 if (!SuccessfullyInitialised)907 GTEST_SKIP();908 Analysis.parseSectionContents(909 {910 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8911 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1912 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1913 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]914 0x20, 0x00, 0x1f, 0xd6, // 16: br x1915 },916 {0xDEADBEEF, 0x0});917 GraphResult Result =918 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});919 EXPECT_EQ(CFIProtectionStatus::PROTECTED,920 Analysis.validateCFIProtection(Result));921}922 923TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {924 if (!SuccessfullyInitialised)925 GTEST_SKIP();926 Analysis.parseSectionContents(927 {928 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8929 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1930 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]931 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1932 0x20, 0x00, 0x1f, 0xd6, // 16: br x1933 },934 {0xDEADBEEF, 0x0});935 GraphResult Result =936 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});937 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,938 Analysis.validateCFIProtection(Result));939}940 941TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {942 if (!SuccessfullyInitialised)943 GTEST_SKIP();944 Analysis.parseSectionContents(945 {946 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8947 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1948 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1949 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]950 0x20, 0x00, 0x1f, 0xd6, // 16: br x1951 },952 {0xDEADBEEF, 0x0});953 GraphResult Result =954 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});955 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,956 Analysis.validateCFIProtection(Result));957}958 959TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {960 if (!SuccessfullyInitialised)961 GTEST_SKIP();962 Analysis.parseSectionContents(963 {964 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8965 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1966 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]967 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]968 0x20, 0x00, 0x1f, 0xd6, // 16: br x1969 },970 {0xDEADBEEF, 0x0});971 GraphResult Result =972 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});973 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,974 Analysis.validateCFIProtection(Result));975}976 977TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {978 if (!SuccessfullyInitialised)979 GTEST_SKIP();980 Analysis.parseSectionContents(981 {982 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8983 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1984 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]985 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]986 0x20, 0x00, 0x1f, 0xd6, // 16: br x1987 },988 {0xDEADBEEF, 0x0});989 GraphResult Result =990 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});991 EXPECT_EQ(CFIProtectionStatus::PROTECTED,992 Analysis.validateCFIProtection(Result));993}994 995TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {996 if (!SuccessfullyInitialised)997 GTEST_SKIP();998 Analysis.parseSectionContents(999 {1000 0x49, 0x00, 0x00, 0x54, // 0: b.ls 81001 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x11002 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]1003 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]1004 0x20, 0x00, 0x1f, 0xd6, // 16: br x11005 },1006 {0xDEADBEEF, 0x0});1007 GraphResult Result =1008 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});1009 EXPECT_EQ(CFIProtectionStatus::PROTECTED,1010 Analysis.validateCFIProtection(Result));1011}1012 1013TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {1014 if (!SuccessfullyInitialised)1015 GTEST_SKIP();1016 Analysis.parseSectionContents(1017 {1018 0x03, 0x00, 0x00, 0x14, // 0: b 121019 0x49, 0x00, 0x00, 0x54, // 4: b.ls 81020 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x11021 0x20, 0x00, 0x1f, 0xd6, // 12: br x11022 },1023 {0xDEADBEEF, 0x0});1024 GraphResult Result =1025 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});1026 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,1027 Analysis.validateCFIProtection(Result));1028}1029 1030TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {1031 if (!SuccessfullyInitialised)1032 GTEST_SKIP();1033 Analysis.parseSectionContents(1034 {1035 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 241036 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]1037 0x03, 0x00, 0x00, 0x14, // 8: b 121038 0x69, 0x00, 0x00, 0x54, // 12: b.ls 121039 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]1040 0x20, 0x00, 0x1f, 0xd6, // 20: br x11041 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x11042 },1043 {0xDEADBEEF, 0x0});1044 GraphResult Result =1045 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});1046 EXPECT_EQ(CFIProtectionStatus::PROTECTED,1047 Analysis.validateCFIProtection(Result));1048}1049 1050TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {1051 if (!SuccessfullyInitialised)1052 GTEST_SKIP();1053 Analysis.parseSectionContents(1054 {1055 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 281056 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]1057 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]1058 0x03, 0x00, 0x00, 0x14, // 12: b 121059 0x69, 0x00, 0x00, 0x54, // 16: b.ls 121060 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]1061 0x20, 0x00, 0x1f, 0xd6, // 24: br x11062 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x11063 },1064 {0xDEADBEEF, 0x0});1065 GraphResult Result =1066 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});1067 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,1068 Analysis.validateCFIProtection(Result));1069}1070 1071TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {1072 if (!SuccessfullyInitialised)1073 GTEST_SKIP();1074 Analysis.parseSectionContents(1075 {1076 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 281077 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]1078 0x03, 0x00, 0x00, 0x14, // 8: b 121079 0x89, 0x00, 0x00, 0x54, // 12: b.ls 161080 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]1081 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]1082 0x20, 0x00, 0x1f, 0xd6, // 24: br x11083 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x11084 },1085 {0xDEADBEEF, 0x0});1086 GraphResult Result =1087 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});1088 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,1089 Analysis.validateCFIProtection(Result));1090}1091 1092} // anonymous namespace1093} // end namespace cfi_verify1094} // end namespace llvm1095 1096int main(int argc, char **argv) {1097 ::testing::InitGoogleTest(&argc, argv);1098 llvm::cl::ParseCommandLineOptions(argc, argv);1099 1100 llvm::InitializeAllTargetInfos();1101 llvm::InitializeAllTargetMCs();1102 llvm::InitializeAllAsmParsers();1103 llvm::InitializeAllDisassemblers();1104 1105 return RUN_ALL_TESTS();1106}1107