FileAnalysis.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
  9. #include "../tools/llvm-cfi-verify/lib/GraphBuilder.h"
  10. #include "gmock/gmock.h"
  11. #include "gtest/gtest.h"
  12. #include "llvm/BinaryFormat/ELF.h"
  13. #include "llvm/MC/MCAsmInfo.h"
  14. #include "llvm/MC/MCContext.h"
  15. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  16. #include "llvm/MC/MCInst.h"
  17. #include "llvm/MC/MCInstPrinter.h"
  18. #include "llvm/MC/MCInstrAnalysis.h"
  19. #include "llvm/MC/MCInstrDesc.h"
  20. #include "llvm/MC/MCInstrInfo.h"
  21. #include "llvm/MC/MCObjectFileInfo.h"
  22. #include "llvm/MC/MCRegisterInfo.h"
  23. #include "llvm/MC/MCSubtargetInfo.h"
  24. #include "llvm/Object/Binary.h"
  25. #include "llvm/Object/COFF.h"
  26. #include "llvm/Object/ELFObjectFile.h"
  27. #include "llvm/Object/ObjectFile.h"
  28. #include "llvm/Support/Casting.h"
  29. #include "llvm/Support/CommandLine.h"
  30. #include "llvm/Support/Error.h"
  31. #include "llvm/Support/MemoryBuffer.h"
  32. #include "llvm/Support/TargetRegistry.h"
  33. #include "llvm/Support/TargetSelect.h"
  34. #include "llvm/Support/raw_ostream.h"
  35. #include <cstdlib>
  36. using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
  37. using ::testing::Eq;
  38. using ::testing::Field;
  39. namespace llvm {
  40. namespace cfi_verify {
  41. namespace {
  42. class ELFTestFileAnalysis : public FileAnalysis {
  43. public:
  44. ELFTestFileAnalysis(StringRef Trip)
  45. : FileAnalysis(Triple(Trip), SubtargetFeatures()) {}
  46. // Expose this method publicly for testing.
  47. void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
  48. object::SectionedAddress Address) {
  49. FileAnalysis::parseSectionContents(SectionBytes, Address);
  50. }
  51. Error initialiseDisassemblyMembers() {
  52. return FileAnalysis::initialiseDisassemblyMembers();
  53. }
  54. };
  55. class BasicFileAnalysisTest : public ::testing::Test {
  56. public:
  57. BasicFileAnalysisTest(StringRef Trip) : Analysis(Trip) {}
  58. protected:
  59. virtual void SetUp() {
  60. IgnoreDWARFFlag = true;
  61. SuccessfullyInitialised = true;
  62. if (auto Err = Analysis.initialiseDisassemblyMembers()) {
  63. handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
  64. SuccessfullyInitialised = false;
  65. outs()
  66. << "Note: CFIVerifyTests are disabled due to lack of support "
  67. "on this build.\n";
  68. });
  69. }
  70. }
  71. bool SuccessfullyInitialised;
  72. ELFTestFileAnalysis Analysis;
  73. };
  74. class BasicX86FileAnalysisTest : public BasicFileAnalysisTest {
  75. public:
  76. BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {}
  77. };
  78. class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest {
  79. public:
  80. BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {}
  81. };
  82. TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
  83. if (!SuccessfullyInitialised)
  84. return;
  85. Analysis.parseSectionContents(
  86. {
  87. 0x90, // 0: nop
  88. 0xb0, 0x00, // 1: mov $0x0, %al
  89. 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
  90. 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
  91. 0x48, 0xbe, 0xc4, 0x07, 0x40,
  92. 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
  93. 0x2f, // 20: (bad)
  94. 0x41, 0x0e, // 21: rex.B (bad)
  95. 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
  96. },
  97. {0xDEADBEEF, 0x0});
  98. EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
  99. EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
  100. // 0xDEADBEEF: nop
  101. const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
  102. EXPECT_NE(nullptr, InstrMeta);
  103. EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
  104. EXPECT_EQ(1u, InstrMeta->InstructionSize);
  105. EXPECT_TRUE(InstrMeta->Valid);
  106. const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
  107. EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
  108. const auto *PrevInstrMeta = InstrMeta;
  109. // 0xDEADBEEF + 1: mov $0x0, %al
  110. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
  111. EXPECT_NE(nullptr, InstrMeta);
  112. EXPECT_EQ(NextInstrMeta, InstrMeta);
  113. EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
  114. EXPECT_EQ(2u, InstrMeta->InstructionSize);
  115. EXPECT_TRUE(InstrMeta->Valid);
  116. NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
  117. EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
  118. PrevInstrMeta = InstrMeta;
  119. // 0xDEADBEEF + 3: mov %rsp, %rbp
  120. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
  121. EXPECT_NE(nullptr, InstrMeta);
  122. EXPECT_EQ(NextInstrMeta, InstrMeta);
  123. EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
  124. EXPECT_EQ(3u, InstrMeta->InstructionSize);
  125. EXPECT_TRUE(InstrMeta->Valid);
  126. NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
  127. EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
  128. PrevInstrMeta = InstrMeta;
  129. // 0xDEADBEEF + 6: sub $0x18, %rsp
  130. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
  131. EXPECT_NE(nullptr, InstrMeta);
  132. EXPECT_EQ(NextInstrMeta, InstrMeta);
  133. EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
  134. EXPECT_EQ(4u, InstrMeta->InstructionSize);
  135. EXPECT_TRUE(InstrMeta->Valid);
  136. NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
  137. EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
  138. PrevInstrMeta = InstrMeta;
  139. // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
  140. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
  141. EXPECT_NE(nullptr, InstrMeta);
  142. EXPECT_EQ(NextInstrMeta, InstrMeta);
  143. EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
  144. EXPECT_EQ(10u, InstrMeta->InstructionSize);
  145. EXPECT_TRUE(InstrMeta->Valid);
  146. EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
  147. EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
  148. PrevInstrMeta = InstrMeta;
  149. // 0xDEADBEEF + 20: (bad)
  150. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
  151. EXPECT_NE(nullptr, InstrMeta);
  152. EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
  153. EXPECT_EQ(1u, InstrMeta->InstructionSize);
  154. EXPECT_FALSE(InstrMeta->Valid);
  155. EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
  156. EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
  157. // 0xDEADBEEF + 21: rex.B (bad)
  158. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
  159. EXPECT_NE(nullptr, InstrMeta);
  160. EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
  161. EXPECT_EQ(2u, InstrMeta->InstructionSize);
  162. EXPECT_FALSE(InstrMeta->Valid);
  163. EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
  164. EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
  165. // 0xDEADBEEF + 6: (bad) {%k1}
  166. InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
  167. EXPECT_NE(nullptr, InstrMeta);
  168. EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
  169. EXPECT_EQ(5u, InstrMeta->InstructionSize);
  170. EXPECT_FALSE(InstrMeta->Valid);
  171. EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
  172. EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
  173. }
  174. TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {
  175. if (!SuccessfullyInitialised)
  176. return;
  177. Analysis.parseSectionContents(
  178. {
  179. 0x90, // 0: nop
  180. 0x2f, // 1: (bad)
  181. 0x90 // 2: nop
  182. },
  183. {0xDEADBEEF, 0x0});
  184. const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
  185. const auto *GoodInstrMeta =
  186. Analysis.getPrevInstructionSequential(BadInstrMeta);
  187. EXPECT_NE(nullptr, GoodInstrMeta);
  188. EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
  189. EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
  190. GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
  191. EXPECT_NE(nullptr, GoodInstrMeta);
  192. EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
  193. EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
  194. }
  195. TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {
  196. if (!SuccessfullyInitialised)
  197. return;
  198. Analysis.parseSectionContents(
  199. {
  200. 0x90, // 0: nop
  201. 0xb0, 0x00, // 1: mov $0x0, %al
  202. 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
  203. 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
  204. 0x48, 0xbe, 0xc4, 0x07, 0x40,
  205. 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
  206. 0x2f, // 20: (bad)
  207. 0x41, 0x0e, // 21: rex.B (bad)
  208. 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
  209. 0x0f, 0x0b // 28: ud2
  210. },
  211. {0xDEADBEEF, 0x0});
  212. EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
  213. EXPECT_FALSE(
  214. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
  215. EXPECT_FALSE(
  216. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
  217. EXPECT_FALSE(
  218. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
  219. EXPECT_FALSE(
  220. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
  221. EXPECT_FALSE(
  222. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
  223. EXPECT_FALSE(
  224. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
  225. EXPECT_TRUE(
  226. Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
  227. }
  228. TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
  229. if (!SuccessfullyInitialised)
  230. return;
  231. Analysis.parseSectionContents(
  232. {
  233. 0x90, // 0: nop
  234. 0xb0, 0x00, // 1: mov $0x0, %al
  235. 0x2f, // 3: (bad)
  236. 0x0f, 0x0b, // 4: ud2
  237. 0xff, 0x20, // 6: jmpq *(%rax)
  238. 0xeb, 0x00, // 8: jmp +0
  239. 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
  240. 0xff, 0x10, // 15: callq *(rax)
  241. 0x75, 0x00, // 17: jne +0
  242. 0xc3, // 19: retq
  243. },
  244. {0xDEADBEEF, 0x0});
  245. EXPECT_TRUE(
  246. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
  247. EXPECT_TRUE(
  248. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
  249. EXPECT_FALSE(
  250. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
  251. EXPECT_FALSE(
  252. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
  253. EXPECT_FALSE(
  254. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
  255. EXPECT_FALSE(
  256. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
  257. EXPECT_FALSE(
  258. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
  259. EXPECT_FALSE(
  260. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
  261. EXPECT_TRUE(
  262. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
  263. EXPECT_FALSE(
  264. Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
  265. }
  266. TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
  267. if (!SuccessfullyInitialised)
  268. return;
  269. Analysis.parseSectionContents(
  270. {
  271. 0x90, // 0: nop
  272. 0xb0, 0x00, // 1: mov $0x0, %al
  273. 0x2f, // 3: (bad)
  274. 0x0f, 0x0b, // 4: ud2
  275. 0xff, 0x20, // 6: jmpq *(%rax)
  276. 0xeb, 0x00, // 8: jmp 10 [+0]
  277. 0xeb, 0x05, // 10: jmp 17 [+5]
  278. 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
  279. 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
  280. 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
  281. 0xff, 0x10, // 27: callq *(rax)
  282. 0x75, 0x00, // 29: jne 31 [+0]
  283. 0x75, 0xe0, // 31: jne 1 [-32]
  284. 0xc3, // 33: retq
  285. 0xeb, 0xdd, // 34: jmp 1 [-35]
  286. 0xeb, 0xdd, // 36: jmp 3 [-35]
  287. 0xeb, 0xdc, // 38: jmp 4 [-36]
  288. },
  289. {0xDEADBEEF, 0x0});
  290. const auto *Current = Analysis.getInstruction(0xDEADBEEF);
  291. const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
  292. EXPECT_NE(nullptr, Next);
  293. EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
  294. Current = Analysis.getInstruction(0xDEADBEEF + 1);
  295. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  296. Current = Analysis.getInstruction(0xDEADBEEF + 3);
  297. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  298. Current = Analysis.getInstruction(0xDEADBEEF + 4);
  299. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  300. Current = Analysis.getInstruction(0xDEADBEEF + 6);
  301. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  302. Current = Analysis.getInstruction(0xDEADBEEF + 8);
  303. Next = Analysis.getDefiniteNextInstruction(*Current);
  304. EXPECT_NE(nullptr, Next);
  305. EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
  306. Current = Analysis.getInstruction(0xDEADBEEF + 10);
  307. Next = Analysis.getDefiniteNextInstruction(*Current);
  308. EXPECT_NE(nullptr, Next);
  309. EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
  310. Current = Analysis.getInstruction(0xDEADBEEF + 12);
  311. Next = Analysis.getDefiniteNextInstruction(*Current);
  312. EXPECT_NE(nullptr, Next);
  313. EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
  314. Current = Analysis.getInstruction(0xDEADBEEF + 17);
  315. // Note, definite next instruction address is out of range and should fail.
  316. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  317. Next = Analysis.getDefiniteNextInstruction(*Current);
  318. Current = Analysis.getInstruction(0xDEADBEEF + 22);
  319. Next = Analysis.getDefiniteNextInstruction(*Current);
  320. EXPECT_NE(nullptr, Next);
  321. EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
  322. Current = Analysis.getInstruction(0xDEADBEEF + 27);
  323. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  324. Current = Analysis.getInstruction(0xDEADBEEF + 29);
  325. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  326. Current = Analysis.getInstruction(0xDEADBEEF + 31);
  327. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  328. Current = Analysis.getInstruction(0xDEADBEEF + 33);
  329. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  330. Current = Analysis.getInstruction(0xDEADBEEF + 34);
  331. Next = Analysis.getDefiniteNextInstruction(*Current);
  332. EXPECT_NE(nullptr, Next);
  333. EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
  334. Current = Analysis.getInstruction(0xDEADBEEF + 36);
  335. EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
  336. Current = Analysis.getInstruction(0xDEADBEEF + 38);
  337. Next = Analysis.getDefiniteNextInstruction(*Current);
  338. EXPECT_NE(nullptr, Next);
  339. EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
  340. }
  341. TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {
  342. if (!SuccessfullyInitialised)
  343. return;
  344. Analysis.parseSectionContents(
  345. {
  346. 0x90, // 0: nop
  347. 0xb0, 0x00, // 1: mov $0x0, %al
  348. 0x2f, // 3: (bad)
  349. 0x0f, 0x0b, // 4: ud2
  350. 0xff, 0x20, // 6: jmpq *(%rax)
  351. 0xeb, 0x00, // 8: jmp 10 [+0]
  352. 0xeb, 0x05, // 10: jmp 17 [+5]
  353. 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
  354. 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
  355. 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
  356. 0xff, 0x10, // 27: callq *(rax)
  357. 0x75, 0x00, // 29: jne 31 [+0]
  358. 0x75, 0xe0, // 31: jne 1 [-32]
  359. 0xc3, // 33: retq
  360. 0xeb, 0xdd, // 34: jmp 1 [-35]
  361. 0xeb, 0xdd, // 36: jmp 3 [-35]
  362. 0xeb, 0xdc, // 38: jmp 4 [-36]
  363. },
  364. {0xDEADBEEF, 0x0});
  365. const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
  366. std::set<const Instr *> XRefs =
  367. Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  368. EXPECT_TRUE(XRefs.empty());
  369. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
  370. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  371. EXPECT_THAT(XRefs, UnorderedElementsAre(
  372. Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
  373. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
  374. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
  375. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
  376. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  377. EXPECT_THAT(XRefs, UnorderedElementsAre(
  378. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
  379. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
  380. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
  381. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  382. EXPECT_THAT(XRefs, UnorderedElementsAre(
  383. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
  384. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
  385. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  386. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
  387. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  388. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  389. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
  390. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  391. EXPECT_THAT(XRefs, UnorderedElementsAre(
  392. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
  393. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
  394. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  395. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  396. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
  397. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  398. EXPECT_THAT(XRefs, UnorderedElementsAre(
  399. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
  400. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
  401. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
  402. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  403. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  404. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
  405. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  406. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  407. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
  408. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  409. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  410. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
  411. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  412. EXPECT_THAT(XRefs, UnorderedElementsAre(
  413. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
  414. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
  415. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
  416. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  417. EXPECT_THAT(XRefs, UnorderedElementsAre(
  418. Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
  419. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
  420. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  421. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  422. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
  423. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  424. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  425. InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
  426. XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
  427. EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
  428. }
  429. TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {
  430. if (!SuccessfullyInitialised)
  431. return;
  432. Analysis.parseSectionContents(
  433. {
  434. 0x90, // 0: nop
  435. 0x0f, 0x0b, // 1: ud2
  436. 0x75, 0x00, // 3: jne 5 [+0]
  437. },
  438. {0xDEADBEEF, 0x0});
  439. GraphResult Result =
  440. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
  441. EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
  442. Analysis.validateCFIProtection(Result));
  443. Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
  444. EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
  445. Analysis.validateCFIProtection(Result));
  446. Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
  447. EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
  448. Analysis.validateCFIProtection(Result));
  449. Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0});
  450. EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,
  451. Analysis.validateCFIProtection(Result));
  452. }
  453. TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
  454. if (!SuccessfullyInitialised)
  455. return;
  456. Analysis.parseSectionContents(
  457. {
  458. 0x75, 0x02, // 0: jne 4 [+2]
  459. 0x0f, 0x0b, // 2: ud2
  460. 0xff, 0x10, // 4: callq *(%rax)
  461. },
  462. {0xDEADBEEF, 0x0});
  463. GraphResult Result =
  464. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
  465. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  466. Analysis.validateCFIProtection(Result));
  467. }
  468. TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
  469. if (!SuccessfullyInitialised)
  470. return;
  471. Analysis.parseSectionContents(
  472. {
  473. 0x75, 0x02, // 0: jne 4 [+2]
  474. 0xff, 0x10, // 2: callq *(%rax)
  475. 0x0f, 0x0b, // 4: ud2
  476. },
  477. {0xDEADBEEF, 0x0});
  478. GraphResult Result =
  479. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
  480. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  481. Analysis.validateCFIProtection(Result));
  482. }
  483. TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
  484. if (!SuccessfullyInitialised)
  485. return;
  486. Analysis.parseSectionContents(
  487. {
  488. 0x75, 0x03, // 0: jne 5 [+3]
  489. 0x90, // 2: nop
  490. 0xff, 0x10, // 3: callq *(%rax)
  491. 0x0f, 0x0b, // 5: ud2
  492. 0x75, 0xf9, // 7: jne 2 [-7]
  493. 0x0f, 0x0b, // 9: ud2
  494. },
  495. {0xDEADBEEF, 0x0});
  496. GraphResult Result =
  497. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
  498. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  499. Analysis.validateCFIProtection(Result));
  500. }
  501. TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
  502. if (!SuccessfullyInitialised)
  503. return;
  504. Analysis.parseSectionContents(
  505. {
  506. 0x75, 0x05, // 0: jne 7 [+5]
  507. 0x90, // 2: nop
  508. 0xff, 0x10, // 3: callq *(%rax)
  509. 0x75, 0xfb, // 5: jne 2 [-5]
  510. 0x0f, 0x0b, // 7: ud2
  511. },
  512. {0xDEADBEEF, 0x0});
  513. GraphResult Result =
  514. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
  515. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  516. Analysis.validateCFIProtection(Result));
  517. }
  518. TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
  519. if (!SuccessfullyInitialised)
  520. return;
  521. Analysis.parseSectionContents(
  522. {
  523. 0x75, 0x06, // 0: jne 8 [+6]
  524. 0x90, // 2: nop
  525. 0x90, // 3: nop
  526. 0x90, // 4: nop
  527. 0x90, // 5: nop
  528. 0xff, 0x10, // 6: callq *(%rax)
  529. 0x0f, 0x0b, // 8: ud2
  530. },
  531. {0xDEADBEEF, 0x0});
  532. uint64_t PrevSearchLengthForConditionalBranch =
  533. SearchLengthForConditionalBranch;
  534. SearchLengthForConditionalBranch = 2;
  535. GraphResult Result =
  536. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
  537. EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
  538. Analysis.validateCFIProtection(Result));
  539. SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
  540. }
  541. TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
  542. if (!SuccessfullyInitialised)
  543. return;
  544. Analysis.parseSectionContents(
  545. {
  546. 0x75, 0x02, // 0: jne 4 [+2]
  547. 0xff, 0x10, // 2: callq *(%rax)
  548. 0x90, // 4: nop
  549. 0x90, // 5: nop
  550. 0x90, // 6: nop
  551. 0x90, // 7: nop
  552. 0x0f, 0x0b, // 8: ud2
  553. },
  554. {0xDEADBEEF, 0x0});
  555. uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
  556. SearchLengthForUndef = 2;
  557. GraphResult Result =
  558. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
  559. EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
  560. Analysis.validateCFIProtection(Result));
  561. SearchLengthForUndef = PrevSearchLengthForUndef;
  562. }
  563. TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {
  564. if (!SuccessfullyInitialised)
  565. return;
  566. Analysis.parseSectionContents(
  567. {
  568. 0xeb, 0x02, // 0: jmp 4 [+2]
  569. 0x75, 0x02, // 2: jne 6 [+2]
  570. 0xff, 0x10, // 4: callq *(%rax)
  571. 0x0f, 0x0b, // 6: ud2
  572. },
  573. {0xDEADBEEF, 0x0});
  574. GraphResult Result =
  575. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
  576. EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
  577. Analysis.validateCFIProtection(Result));
  578. }
  579. TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) {
  580. if (!SuccessfullyInitialised)
  581. return;
  582. Analysis.parseSectionContents(
  583. {
  584. 0x75, 0x04, // 0: jne 6 [+4]
  585. 0xeb, 0x00, // 2: jmp 4 [+0]
  586. 0xff, 0x10, // 4: callq *(%rax)
  587. 0x0f, 0x0b, // 6: ud2
  588. },
  589. {0xDEADBEEF, 0x0});
  590. GraphResult Result =
  591. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
  592. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  593. Analysis.validateCFIProtection(Result));
  594. }
  595. TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
  596. if (!SuccessfullyInitialised)
  597. return;
  598. // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this
  599. // graph.
  600. Analysis.parseSectionContents(
  601. {
  602. 0x75, 0x12, // 0: jne 20 [+18]
  603. 0xeb, 0x03, // 2: jmp 7 [+3]
  604. 0x75, 0x10, // 4: jne 22 [+16]
  605. 0x90, // 6: nop
  606. 0x90, // 7: nop
  607. 0x90, // 8: nop
  608. 0xff, 0x10, // 9: callq *(%rax)
  609. 0xeb, 0xfc, // 11: jmp 9 [-4]
  610. 0x75, 0xfa, // 13: jne 9 [-6]
  611. 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
  612. 0x90, // 20: nop
  613. 0x90, // 21: nop
  614. 0x0f, 0x0b, // 22: ud2
  615. },
  616. {0xDEADBEEF, 0x0});
  617. uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
  618. SearchLengthForUndef = 5;
  619. GraphResult Result =
  620. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
  621. EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
  622. Analysis.validateCFIProtection(Result));
  623. SearchLengthForUndef = PrevSearchLengthForUndef;
  624. }
  625. TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
  626. Analysis.parseSectionContents(
  627. {
  628. 0x77, 0x0d, // 0x688118: ja 0x688127 [+12]
  629. 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi
  630. 0xff, 0xd0, // 0x68811d: callq *%rax
  631. 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi
  632. 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
  633. 0x0f, 0x0b, // 0x688127: ud2
  634. },
  635. {0x688118, 0x0});
  636. uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
  637. SearchLengthForUndef = 1;
  638. GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});
  639. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  640. Analysis.validateCFIProtection(Result));
  641. SearchLengthForUndef = PrevSearchLengthForUndef;
  642. }
  643. TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
  644. Analysis.parseSectionContents(
  645. {
  646. 0x74, 0x73, // 0x7759eb: je 0x775a60
  647. 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
  648. },
  649. {0x7759eb, 0x0});
  650. Analysis.parseSectionContents(
  651. {
  652. 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e
  653. 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx
  654. 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi
  655. 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
  656. 0xff, 0xd1, // 0x775a68: callq *%rcx
  657. },
  658. {0x775a56, 0x0});
  659. Analysis.parseSectionContents(
  660. {
  661. 0x0f, 0x0b, // 0x775e0e: ud2
  662. },
  663. {0x775e0e, 0x0});
  664. uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
  665. SearchLengthForUndef = 1;
  666. GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
  667. EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
  668. Analysis.validateCFIProtection(Result));
  669. SearchLengthForUndef = 2;
  670. Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
  671. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  672. Analysis.validateCFIProtection(Result));
  673. SearchLengthForUndef = 3;
  674. Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
  675. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  676. Analysis.validateCFIProtection(Result));
  677. SearchLengthForUndef = PrevSearchLengthForUndef;
  678. }
  679. TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
  680. if (!SuccessfullyInitialised)
  681. return;
  682. Analysis.parseSectionContents(
  683. {
  684. 0x75, 0x02, // 0: jne 4 [+2]
  685. 0x0f, 0x0b, // 2: ud2
  686. 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
  687. 0xff, 0x10, // 10: callq *(%rax)
  688. },
  689. {0xDEADBEEF, 0x0});
  690. GraphResult Result =
  691. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});
  692. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  693. Analysis.validateCFIProtection(Result));
  694. }
  695. TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
  696. if (!SuccessfullyInitialised)
  697. return;
  698. Analysis.parseSectionContents(
  699. {
  700. 0x75, 0x02, // 0: jne 4 [+2]
  701. 0x0f, 0x0b, // 2: ud2
  702. 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
  703. 0xff, 0x10, // 8: callq *(%rax)
  704. },
  705. {0xDEADBEEF, 0x0});
  706. GraphResult Result =
  707. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
  708. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  709. Analysis.validateCFIProtection(Result));
  710. }
  711. TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
  712. if (!SuccessfullyInitialised)
  713. return;
  714. Analysis.parseSectionContents(
  715. {
  716. 0x75, 0x02, // 0: jne 4 [+2]
  717. 0x0f, 0x0b, // 2: ud2
  718. 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
  719. 0xff, 0x10, // 9: callq *(%rax)
  720. },
  721. {0xDEADBEEF, 0x0});
  722. GraphResult Result =
  723. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
  724. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  725. Analysis.validateCFIProtection(Result));
  726. }
  727. TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
  728. if (!SuccessfullyInitialised)
  729. return;
  730. Analysis.parseSectionContents(
  731. {
  732. 0x75, 0x04, // 0: jne 6 [+4]
  733. 0x0f, 0x31, // 2: rdtsc (note: affects eax)
  734. 0xff, 0x10, // 4: callq *(%rax)
  735. 0x0f, 0x0b, // 6: ud2
  736. 0x75, 0xf9, // 8: jne 2 [-7]
  737. 0x0f, 0x0b, // 10: ud2
  738. },
  739. {0xDEADBEEF, 0x0});
  740. GraphResult Result =
  741. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
  742. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  743. Analysis.validateCFIProtection(Result));
  744. }
  745. TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
  746. if (!SuccessfullyInitialised)
  747. return;
  748. Analysis.parseSectionContents(
  749. {
  750. 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
  751. },
  752. {0xDEADBEEF, 0x0});
  753. GraphResult Result =
  754. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
  755. EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
  756. Analysis.validateCFIProtection(Result));
  757. }
  758. TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
  759. if (!SuccessfullyInitialised)
  760. return;
  761. Analysis.parseSectionContents(
  762. {
  763. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  764. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  765. 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
  766. },
  767. {0xDEADBEEF, 0x0});
  768. GraphResult Result =
  769. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
  770. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  771. Analysis.validateCFIProtection(Result));
  772. }
  773. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
  774. if (!SuccessfullyInitialised)
  775. return;
  776. Analysis.parseSectionContents(
  777. {
  778. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  779. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  780. 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
  781. 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
  782. },
  783. {0xDEADBEEF, 0x0});
  784. GraphResult Result =
  785. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
  786. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  787. Analysis.validateCFIProtection(Result));
  788. }
  789. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
  790. if (!SuccessfullyInitialised)
  791. return;
  792. Analysis.parseSectionContents(
  793. {
  794. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  795. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  796. 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
  797. 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
  798. },
  799. {0xDEADBEEF, 0x0});
  800. GraphResult Result =
  801. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
  802. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  803. Analysis.validateCFIProtection(Result));
  804. }
  805. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
  806. if (!SuccessfullyInitialised)
  807. return;
  808. Analysis.parseSectionContents(
  809. {
  810. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  811. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  812. 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1
  813. 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
  814. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  815. },
  816. {0xDEADBEEF, 0x0});
  817. GraphResult Result =
  818. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  819. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  820. Analysis.validateCFIProtection(Result));
  821. }
  822. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
  823. if (!SuccessfullyInitialised)
  824. return;
  825. Analysis.parseSectionContents(
  826. {
  827. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  828. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  829. 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
  830. 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
  831. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  832. },
  833. {0xDEADBEEF, 0x0});
  834. GraphResult Result =
  835. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  836. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  837. Analysis.validateCFIProtection(Result));
  838. }
  839. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
  840. if (!SuccessfullyInitialised)
  841. return;
  842. Analysis.parseSectionContents(
  843. {
  844. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  845. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  846. 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1
  847. 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
  848. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  849. },
  850. {0xDEADBEEF, 0x0});
  851. GraphResult Result =
  852. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  853. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  854. Analysis.validateCFIProtection(Result));
  855. }
  856. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
  857. if (!SuccessfullyInitialised)
  858. return;
  859. Analysis.parseSectionContents(
  860. {
  861. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  862. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  863. 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
  864. 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
  865. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  866. },
  867. {0xDEADBEEF, 0x0});
  868. GraphResult Result =
  869. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  870. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  871. Analysis.validateCFIProtection(Result));
  872. }
  873. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
  874. if (!SuccessfullyInitialised)
  875. return;
  876. Analysis.parseSectionContents(
  877. {
  878. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  879. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  880. 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
  881. 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
  882. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  883. },
  884. {0xDEADBEEF, 0x0});
  885. GraphResult Result =
  886. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  887. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  888. Analysis.validateCFIProtection(Result));
  889. }
  890. TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
  891. if (!SuccessfullyInitialised)
  892. return;
  893. Analysis.parseSectionContents(
  894. {
  895. 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8
  896. 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
  897. 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16]
  898. 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
  899. 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
  900. },
  901. {0xDEADBEEF, 0x0});
  902. GraphResult Result =
  903. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
  904. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  905. Analysis.validateCFIProtection(Result));
  906. }
  907. TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
  908. if (!SuccessfullyInitialised)
  909. return;
  910. Analysis.parseSectionContents(
  911. {
  912. 0x03, 0x00, 0x00, 0x14, // 0: b 12
  913. 0x49, 0x00, 0x00, 0x54, // 4: b.ls 8
  914. 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
  915. 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
  916. },
  917. {0xDEADBEEF, 0x0});
  918. GraphResult Result =
  919. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
  920. EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
  921. Analysis.validateCFIProtection(Result));
  922. }
  923. TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
  924. if (!SuccessfullyInitialised)
  925. return;
  926. Analysis.parseSectionContents(
  927. {
  928. 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24
  929. 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
  930. 0x03, 0x00, 0x00, 0x14, // 8: b 12
  931. 0x69, 0x00, 0x00, 0x54, // 12: b.ls 12
  932. 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
  933. 0x20, 0x00, 0x1f, 0xd6, // 20: br x1
  934. 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
  935. },
  936. {0xDEADBEEF, 0x0});
  937. GraphResult Result =
  938. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});
  939. EXPECT_EQ(CFIProtectionStatus::PROTECTED,
  940. Analysis.validateCFIProtection(Result));
  941. }
  942. TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
  943. if (!SuccessfullyInitialised)
  944. return;
  945. Analysis.parseSectionContents(
  946. {
  947. 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
  948. 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
  949. 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16]
  950. 0x03, 0x00, 0x00, 0x14, // 12: b 12
  951. 0x69, 0x00, 0x00, 0x54, // 16: b.ls 12
  952. 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
  953. 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
  954. 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
  955. },
  956. {0xDEADBEEF, 0x0});
  957. GraphResult Result =
  958. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
  959. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  960. Analysis.validateCFIProtection(Result));
  961. }
  962. TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
  963. if (!SuccessfullyInitialised)
  964. return;
  965. Analysis.parseSectionContents(
  966. {
  967. 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28
  968. 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16]
  969. 0x03, 0x00, 0x00, 0x14, // 8: b 12
  970. 0x89, 0x00, 0x00, 0x54, // 12: b.ls 16
  971. 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16]
  972. 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16]
  973. 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
  974. 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
  975. },
  976. {0xDEADBEEF, 0x0});
  977. GraphResult Result =
  978. GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
  979. EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
  980. Analysis.validateCFIProtection(Result));
  981. }
  982. } // anonymous namespace
  983. } // end namespace cfi_verify
  984. } // end namespace llvm
  985. int main(int argc, char **argv) {
  986. ::testing::InitGoogleTest(&argc, argv);
  987. llvm::cl::ParseCommandLineOptions(argc, argv);
  988. llvm::InitializeAllTargetInfos();
  989. llvm::InitializeAllTargetMCs();
  990. llvm::InitializeAllAsmParsers();
  991. llvm::InitializeAllDisassemblers();
  992. return RUN_ALL_TESTS();
  993. }