FileAnalysis.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. //===- FileAnalysis.cpp -----------------------------------------*- C++ -*-===//
  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 "FileAnalysis.h"
  9. #include "GraphBuilder.h"
  10. #include "llvm/BinaryFormat/ELF.h"
  11. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  12. #include "llvm/DebugInfo/Symbolize/SymbolizableModule.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/MC/MCTargetOptions.h"
  25. #include "llvm/MC/TargetRegistry.h"
  26. #include "llvm/Object/Binary.h"
  27. #include "llvm/Object/COFF.h"
  28. #include "llvm/Object/ELFObjectFile.h"
  29. #include "llvm/Object/ObjectFile.h"
  30. #include "llvm/Support/Casting.h"
  31. #include "llvm/Support/CommandLine.h"
  32. #include "llvm/Support/Error.h"
  33. #include "llvm/Support/MemoryBuffer.h"
  34. #include "llvm/Support/TargetSelect.h"
  35. #include "llvm/Support/raw_ostream.h"
  36. using Instr = llvm::cfi_verify::FileAnalysis::Instr;
  37. using LLVMSymbolizer = llvm::symbolize::LLVMSymbolizer;
  38. namespace llvm {
  39. namespace cfi_verify {
  40. bool IgnoreDWARFFlag;
  41. static cl::opt<bool, true> IgnoreDWARFArg(
  42. "ignore-dwarf",
  43. cl::desc(
  44. "Ignore all DWARF data. This relaxes the requirements for all "
  45. "statically linked libraries to have been compiled with '-g', but "
  46. "will result in false positives for 'CFI unprotected' instructions."),
  47. cl::location(IgnoreDWARFFlag), cl::init(false));
  48. StringRef stringCFIProtectionStatus(CFIProtectionStatus Status) {
  49. switch (Status) {
  50. case CFIProtectionStatus::PROTECTED:
  51. return "PROTECTED";
  52. case CFIProtectionStatus::FAIL_NOT_INDIRECT_CF:
  53. return "FAIL_NOT_INDIRECT_CF";
  54. case CFIProtectionStatus::FAIL_ORPHANS:
  55. return "FAIL_ORPHANS";
  56. case CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH:
  57. return "FAIL_BAD_CONDITIONAL_BRANCH";
  58. case CFIProtectionStatus::FAIL_REGISTER_CLOBBERED:
  59. return "FAIL_REGISTER_CLOBBERED";
  60. case CFIProtectionStatus::FAIL_INVALID_INSTRUCTION:
  61. return "FAIL_INVALID_INSTRUCTION";
  62. }
  63. llvm_unreachable("Attempted to stringify an unknown enum value.");
  64. }
  65. Expected<FileAnalysis> FileAnalysis::Create(StringRef Filename) {
  66. // Open the filename provided.
  67. Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
  68. object::createBinary(Filename);
  69. if (!BinaryOrErr)
  70. return BinaryOrErr.takeError();
  71. // Construct the object and allow it to take ownership of the binary.
  72. object::OwningBinary<object::Binary> Binary = std::move(BinaryOrErr.get());
  73. FileAnalysis Analysis(std::move(Binary));
  74. Analysis.Object = dyn_cast<object::ObjectFile>(Analysis.Binary.getBinary());
  75. if (!Analysis.Object)
  76. return make_error<UnsupportedDisassembly>("Failed to cast object");
  77. switch (Analysis.Object->getArch()) {
  78. case Triple::x86:
  79. case Triple::x86_64:
  80. case Triple::aarch64:
  81. case Triple::aarch64_be:
  82. break;
  83. default:
  84. return make_error<UnsupportedDisassembly>("Unsupported architecture.");
  85. }
  86. Analysis.ObjectTriple = Analysis.Object->makeTriple();
  87. Expected<SubtargetFeatures> Features = Analysis.Object->getFeatures();
  88. if (!Features)
  89. return Features.takeError();
  90. Analysis.Features = *Features;
  91. // Init the rest of the object.
  92. if (auto InitResponse = Analysis.initialiseDisassemblyMembers())
  93. return std::move(InitResponse);
  94. if (auto SectionParseResponse = Analysis.parseCodeSections())
  95. return std::move(SectionParseResponse);
  96. if (auto SymbolTableParseResponse = Analysis.parseSymbolTable())
  97. return std::move(SymbolTableParseResponse);
  98. return std::move(Analysis);
  99. }
  100. FileAnalysis::FileAnalysis(object::OwningBinary<object::Binary> Binary)
  101. : Binary(std::move(Binary)) {}
  102. FileAnalysis::FileAnalysis(const Triple &ObjectTriple,
  103. const SubtargetFeatures &Features)
  104. : ObjectTriple(ObjectTriple), Features(Features) {}
  105. const Instr *
  106. FileAnalysis::getPrevInstructionSequential(const Instr &InstrMeta) const {
  107. std::map<uint64_t, Instr>::const_iterator KV =
  108. Instructions.find(InstrMeta.VMAddress);
  109. if (KV == Instructions.end() || KV == Instructions.begin())
  110. return nullptr;
  111. if (!(--KV)->second.Valid)
  112. return nullptr;
  113. return &KV->second;
  114. }
  115. const Instr *
  116. FileAnalysis::getNextInstructionSequential(const Instr &InstrMeta) const {
  117. std::map<uint64_t, Instr>::const_iterator KV =
  118. Instructions.find(InstrMeta.VMAddress);
  119. if (KV == Instructions.end() || ++KV == Instructions.end())
  120. return nullptr;
  121. if (!KV->second.Valid)
  122. return nullptr;
  123. return &KV->second;
  124. }
  125. bool FileAnalysis::usesRegisterOperand(const Instr &InstrMeta) const {
  126. for (const auto &Operand : InstrMeta.Instruction) {
  127. if (Operand.isReg())
  128. return true;
  129. }
  130. return false;
  131. }
  132. const Instr *FileAnalysis::getInstruction(uint64_t Address) const {
  133. const auto &InstrKV = Instructions.find(Address);
  134. if (InstrKV == Instructions.end())
  135. return nullptr;
  136. return &InstrKV->second;
  137. }
  138. const Instr &FileAnalysis::getInstructionOrDie(uint64_t Address) const {
  139. const auto &InstrKV = Instructions.find(Address);
  140. assert(InstrKV != Instructions.end() && "Address doesn't exist.");
  141. return InstrKV->second;
  142. }
  143. bool FileAnalysis::isCFITrap(const Instr &InstrMeta) const {
  144. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  145. return InstrDesc.isTrap() || willTrapOnCFIViolation(InstrMeta);
  146. }
  147. bool FileAnalysis::willTrapOnCFIViolation(const Instr &InstrMeta) const {
  148. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  149. if (!InstrDesc.isCall())
  150. return false;
  151. uint64_t Target;
  152. if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress,
  153. InstrMeta.InstructionSize, Target))
  154. return false;
  155. return TrapOnFailFunctionAddresses.contains(Target);
  156. }
  157. bool FileAnalysis::canFallThrough(const Instr &InstrMeta) const {
  158. if (!InstrMeta.Valid)
  159. return false;
  160. if (isCFITrap(InstrMeta))
  161. return false;
  162. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  163. if (InstrDesc.mayAffectControlFlow(InstrMeta.Instruction, *RegisterInfo))
  164. return InstrDesc.isConditionalBranch();
  165. return true;
  166. }
  167. const Instr *
  168. FileAnalysis::getDefiniteNextInstruction(const Instr &InstrMeta) const {
  169. if (!InstrMeta.Valid)
  170. return nullptr;
  171. if (isCFITrap(InstrMeta))
  172. return nullptr;
  173. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  174. const Instr *NextMetaPtr;
  175. if (InstrDesc.mayAffectControlFlow(InstrMeta.Instruction, *RegisterInfo)) {
  176. if (InstrDesc.isConditionalBranch())
  177. return nullptr;
  178. uint64_t Target;
  179. if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress,
  180. InstrMeta.InstructionSize, Target))
  181. return nullptr;
  182. NextMetaPtr = getInstruction(Target);
  183. } else {
  184. NextMetaPtr =
  185. getInstruction(InstrMeta.VMAddress + InstrMeta.InstructionSize);
  186. }
  187. if (!NextMetaPtr || !NextMetaPtr->Valid)
  188. return nullptr;
  189. return NextMetaPtr;
  190. }
  191. std::set<const Instr *>
  192. FileAnalysis::getDirectControlFlowXRefs(const Instr &InstrMeta) const {
  193. std::set<const Instr *> CFCrossReferences;
  194. const Instr *PrevInstruction = getPrevInstructionSequential(InstrMeta);
  195. if (PrevInstruction && canFallThrough(*PrevInstruction))
  196. CFCrossReferences.insert(PrevInstruction);
  197. const auto &TargetRefsKV = StaticBranchTargetings.find(InstrMeta.VMAddress);
  198. if (TargetRefsKV == StaticBranchTargetings.end())
  199. return CFCrossReferences;
  200. for (uint64_t SourceInstrAddress : TargetRefsKV->second) {
  201. const auto &SourceInstrKV = Instructions.find(SourceInstrAddress);
  202. if (SourceInstrKV == Instructions.end()) {
  203. errs() << "Failed to find source instruction at address "
  204. << format_hex(SourceInstrAddress, 2)
  205. << " for the cross-reference to instruction at address "
  206. << format_hex(InstrMeta.VMAddress, 2) << ".\n";
  207. continue;
  208. }
  209. CFCrossReferences.insert(&SourceInstrKV->second);
  210. }
  211. return CFCrossReferences;
  212. }
  213. const std::set<object::SectionedAddress> &
  214. FileAnalysis::getIndirectInstructions() const {
  215. return IndirectInstructions;
  216. }
  217. const MCRegisterInfo *FileAnalysis::getRegisterInfo() const {
  218. return RegisterInfo.get();
  219. }
  220. const MCInstrInfo *FileAnalysis::getMCInstrInfo() const { return MII.get(); }
  221. const MCInstrAnalysis *FileAnalysis::getMCInstrAnalysis() const {
  222. return MIA.get();
  223. }
  224. Expected<DIInliningInfo>
  225. FileAnalysis::symbolizeInlinedCode(object::SectionedAddress Address) {
  226. assert(Symbolizer != nullptr && "Symbolizer is invalid.");
  227. return Symbolizer->symbolizeInlinedCode(std::string(Object->getFileName()),
  228. Address);
  229. }
  230. CFIProtectionStatus
  231. FileAnalysis::validateCFIProtection(const GraphResult &Graph) const {
  232. const Instr *InstrMetaPtr = getInstruction(Graph.BaseAddress);
  233. if (!InstrMetaPtr)
  234. return CFIProtectionStatus::FAIL_INVALID_INSTRUCTION;
  235. const auto &InstrDesc = MII->get(InstrMetaPtr->Instruction.getOpcode());
  236. if (!InstrDesc.mayAffectControlFlow(InstrMetaPtr->Instruction, *RegisterInfo))
  237. return CFIProtectionStatus::FAIL_NOT_INDIRECT_CF;
  238. if (!usesRegisterOperand(*InstrMetaPtr))
  239. return CFIProtectionStatus::FAIL_NOT_INDIRECT_CF;
  240. if (!Graph.OrphanedNodes.empty())
  241. return CFIProtectionStatus::FAIL_ORPHANS;
  242. for (const auto &BranchNode : Graph.ConditionalBranchNodes) {
  243. if (!BranchNode.CFIProtection)
  244. return CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH;
  245. }
  246. if (indirectCFOperandClobber(Graph) != Graph.BaseAddress)
  247. return CFIProtectionStatus::FAIL_REGISTER_CLOBBERED;
  248. return CFIProtectionStatus::PROTECTED;
  249. }
  250. uint64_t FileAnalysis::indirectCFOperandClobber(const GraphResult &Graph) const {
  251. assert(Graph.OrphanedNodes.empty() && "Orphaned nodes should be empty.");
  252. // Get the set of registers we must check to ensure they're not clobbered.
  253. const Instr &IndirectCF = getInstructionOrDie(Graph.BaseAddress);
  254. DenseSet<unsigned> RegisterNumbers;
  255. for (const auto &Operand : IndirectCF.Instruction) {
  256. if (Operand.isReg())
  257. RegisterNumbers.insert(Operand.getReg());
  258. }
  259. assert(RegisterNumbers.size() && "Zero register operands on indirect CF.");
  260. // Now check all branches to indirect CFs and ensure no clobbering happens.
  261. for (const auto &Branch : Graph.ConditionalBranchNodes) {
  262. uint64_t Node;
  263. if (Branch.IndirectCFIsOnTargetPath)
  264. Node = Branch.Target;
  265. else
  266. Node = Branch.Fallthrough;
  267. // Some architectures (e.g., AArch64) cannot load in an indirect branch, so
  268. // we allow them one load.
  269. bool canLoad = !MII->get(IndirectCF.Instruction.getOpcode()).mayLoad();
  270. // We walk backwards from the indirect CF. It is the last node returned by
  271. // Graph.flattenAddress, so we skip it since we already handled it.
  272. DenseSet<unsigned> CurRegisterNumbers = RegisterNumbers;
  273. std::vector<uint64_t> Nodes = Graph.flattenAddress(Node);
  274. for (auto I = Nodes.rbegin() + 1, E = Nodes.rend(); I != E; ++I) {
  275. Node = *I;
  276. const Instr &NodeInstr = getInstructionOrDie(Node);
  277. const auto &InstrDesc = MII->get(NodeInstr.Instruction.getOpcode());
  278. for (auto RI = CurRegisterNumbers.begin(), RE = CurRegisterNumbers.end();
  279. RI != RE; ++RI) {
  280. unsigned RegNum = *RI;
  281. if (InstrDesc.hasDefOfPhysReg(NodeInstr.Instruction, RegNum,
  282. *RegisterInfo)) {
  283. if (!canLoad || !InstrDesc.mayLoad())
  284. return Node;
  285. canLoad = false;
  286. CurRegisterNumbers.erase(RI);
  287. // Add the registers this load reads to those we check for clobbers.
  288. for (unsigned i = InstrDesc.getNumDefs(),
  289. e = InstrDesc.getNumOperands(); i != e; i++) {
  290. const auto &Operand = NodeInstr.Instruction.getOperand(i);
  291. if (Operand.isReg())
  292. CurRegisterNumbers.insert(Operand.getReg());
  293. }
  294. break;
  295. }
  296. }
  297. }
  298. }
  299. return Graph.BaseAddress;
  300. }
  301. void FileAnalysis::printInstruction(const Instr &InstrMeta,
  302. raw_ostream &OS) const {
  303. Printer->printInst(&InstrMeta.Instruction, 0, "", *SubtargetInfo, OS);
  304. }
  305. Error FileAnalysis::initialiseDisassemblyMembers() {
  306. std::string TripleName = ObjectTriple.getTriple();
  307. ArchName = "";
  308. MCPU = "";
  309. std::string ErrorString;
  310. LLVMSymbolizer::Options Opt;
  311. Opt.UseSymbolTable = false;
  312. Symbolizer.reset(new LLVMSymbolizer(Opt));
  313. ObjectTarget =
  314. TargetRegistry::lookupTarget(ArchName, ObjectTriple, ErrorString);
  315. if (!ObjectTarget)
  316. return make_error<UnsupportedDisassembly>(
  317. (Twine("Couldn't find target \"") + ObjectTriple.getTriple() +
  318. "\", failed with error: " + ErrorString)
  319. .str());
  320. RegisterInfo.reset(ObjectTarget->createMCRegInfo(TripleName));
  321. if (!RegisterInfo)
  322. return make_error<UnsupportedDisassembly>(
  323. "Failed to initialise RegisterInfo.");
  324. MCTargetOptions MCOptions;
  325. AsmInfo.reset(
  326. ObjectTarget->createMCAsmInfo(*RegisterInfo, TripleName, MCOptions));
  327. if (!AsmInfo)
  328. return make_error<UnsupportedDisassembly>("Failed to initialise AsmInfo.");
  329. SubtargetInfo.reset(ObjectTarget->createMCSubtargetInfo(
  330. TripleName, MCPU, Features.getString()));
  331. if (!SubtargetInfo)
  332. return make_error<UnsupportedDisassembly>(
  333. "Failed to initialise SubtargetInfo.");
  334. MII.reset(ObjectTarget->createMCInstrInfo());
  335. if (!MII)
  336. return make_error<UnsupportedDisassembly>("Failed to initialise MII.");
  337. Context.reset(new MCContext(Triple(TripleName), AsmInfo.get(),
  338. RegisterInfo.get(), SubtargetInfo.get()));
  339. Disassembler.reset(
  340. ObjectTarget->createMCDisassembler(*SubtargetInfo, *Context));
  341. if (!Disassembler)
  342. return make_error<UnsupportedDisassembly>(
  343. "No disassembler available for target");
  344. MIA.reset(ObjectTarget->createMCInstrAnalysis(MII.get()));
  345. Printer.reset(ObjectTarget->createMCInstPrinter(
  346. ObjectTriple, AsmInfo->getAssemblerDialect(), *AsmInfo, *MII,
  347. *RegisterInfo));
  348. return Error::success();
  349. }
  350. Error FileAnalysis::parseCodeSections() {
  351. if (!IgnoreDWARFFlag) {
  352. std::unique_ptr<DWARFContext> DWARF = DWARFContext::create(*Object);
  353. if (!DWARF)
  354. return make_error<StringError>("Could not create DWARF information.",
  355. inconvertibleErrorCode());
  356. bool LineInfoValid = false;
  357. for (auto &Unit : DWARF->compile_units()) {
  358. const auto &LineTable = DWARF->getLineTableForUnit(Unit.get());
  359. if (LineTable && !LineTable->Rows.empty()) {
  360. LineInfoValid = true;
  361. break;
  362. }
  363. }
  364. if (!LineInfoValid)
  365. return make_error<StringError>(
  366. "DWARF line information missing. Did you compile with '-g'?",
  367. inconvertibleErrorCode());
  368. }
  369. for (const object::SectionRef &Section : Object->sections()) {
  370. // Ensure only executable sections get analysed.
  371. if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR))
  372. continue;
  373. // Avoid checking the PLT since it produces spurious failures on AArch64
  374. // when ignoring DWARF data.
  375. Expected<StringRef> NameOrErr = Section.getName();
  376. if (NameOrErr && *NameOrErr == ".plt")
  377. continue;
  378. consumeError(NameOrErr.takeError());
  379. Expected<StringRef> Contents = Section.getContents();
  380. if (!Contents)
  381. return Contents.takeError();
  382. ArrayRef<uint8_t> SectionBytes = arrayRefFromStringRef(*Contents);
  383. parseSectionContents(SectionBytes,
  384. {Section.getAddress(), Section.getIndex()});
  385. }
  386. return Error::success();
  387. }
  388. void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
  389. object::SectionedAddress Address) {
  390. assert(Symbolizer && "Symbolizer is uninitialised.");
  391. MCInst Instruction;
  392. Instr InstrMeta;
  393. uint64_t InstructionSize;
  394. for (uint64_t Byte = 0; Byte < SectionBytes.size();) {
  395. bool ValidInstruction =
  396. Disassembler->getInstruction(Instruction, InstructionSize,
  397. SectionBytes.drop_front(Byte), 0,
  398. outs()) == MCDisassembler::Success;
  399. Byte += InstructionSize;
  400. uint64_t VMAddress = Address.Address + Byte - InstructionSize;
  401. InstrMeta.Instruction = Instruction;
  402. InstrMeta.VMAddress = VMAddress;
  403. InstrMeta.InstructionSize = InstructionSize;
  404. InstrMeta.Valid = ValidInstruction;
  405. addInstruction(InstrMeta);
  406. if (!ValidInstruction)
  407. continue;
  408. // Skip additional parsing for instructions that do not affect the control
  409. // flow.
  410. const auto &InstrDesc = MII->get(Instruction.getOpcode());
  411. if (!InstrDesc.mayAffectControlFlow(Instruction, *RegisterInfo))
  412. continue;
  413. uint64_t Target;
  414. if (MIA->evaluateBranch(Instruction, VMAddress, InstructionSize, Target)) {
  415. // If the target can be evaluated, it's not indirect.
  416. StaticBranchTargetings[Target].push_back(VMAddress);
  417. continue;
  418. }
  419. if (!usesRegisterOperand(InstrMeta))
  420. continue;
  421. if (InstrDesc.isReturn())
  422. continue;
  423. // Check if this instruction exists in the range of the DWARF metadata.
  424. if (!IgnoreDWARFFlag) {
  425. auto LineInfo =
  426. Symbolizer->symbolizeCode(std::string(Object->getFileName()),
  427. {VMAddress, Address.SectionIndex});
  428. if (!LineInfo) {
  429. handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) {
  430. errs() << "Symbolizer failed to get line: " << E.message() << "\n";
  431. });
  432. continue;
  433. }
  434. if (LineInfo->FileName == DILineInfo::BadString)
  435. continue;
  436. }
  437. IndirectInstructions.insert({VMAddress, Address.SectionIndex});
  438. }
  439. }
  440. void FileAnalysis::addInstruction(const Instr &Instruction) {
  441. const auto &KV =
  442. Instructions.insert(std::make_pair(Instruction.VMAddress, Instruction));
  443. if (!KV.second) {
  444. errs() << "Failed to add instruction at address "
  445. << format_hex(Instruction.VMAddress, 2)
  446. << ": Instruction at this address already exists.\n";
  447. exit(EXIT_FAILURE);
  448. }
  449. }
  450. Error FileAnalysis::parseSymbolTable() {
  451. // Functions that will trap on CFI violations.
  452. SmallSet<StringRef, 4> TrapOnFailFunctions;
  453. TrapOnFailFunctions.insert("__cfi_slowpath");
  454. TrapOnFailFunctions.insert("__cfi_slowpath_diag");
  455. TrapOnFailFunctions.insert("abort");
  456. // Look through the list of symbols for functions that will trap on CFI
  457. // violations.
  458. for (auto &Sym : Object->symbols()) {
  459. auto SymNameOrErr = Sym.getName();
  460. if (!SymNameOrErr)
  461. consumeError(SymNameOrErr.takeError());
  462. else if (TrapOnFailFunctions.contains(*SymNameOrErr)) {
  463. auto AddrOrErr = Sym.getAddress();
  464. if (!AddrOrErr)
  465. consumeError(AddrOrErr.takeError());
  466. else
  467. TrapOnFailFunctionAddresses.insert(*AddrOrErr);
  468. }
  469. }
  470. if (auto *ElfObject = dyn_cast<object::ELFObjectFileBase>(Object)) {
  471. for (const auto &Addr : ElfObject->getPltAddresses()) {
  472. if (!Addr.first)
  473. continue;
  474. object::SymbolRef Sym(*Addr.first, Object);
  475. auto SymNameOrErr = Sym.getName();
  476. if (!SymNameOrErr)
  477. consumeError(SymNameOrErr.takeError());
  478. else if (TrapOnFailFunctions.contains(*SymNameOrErr))
  479. TrapOnFailFunctionAddresses.insert(Addr.second);
  480. }
  481. }
  482. return Error::success();
  483. }
  484. UnsupportedDisassembly::UnsupportedDisassembly(StringRef Text)
  485. : Text(std::string(Text)) {}
  486. char UnsupportedDisassembly::ID;
  487. void UnsupportedDisassembly::log(raw_ostream &OS) const {
  488. OS << "Could not initialise disassembler: " << Text;
  489. }
  490. std::error_code UnsupportedDisassembly::convertToErrorCode() const {
  491. return std::error_code();
  492. }
  493. } // namespace cfi_verify
  494. } // namespace llvm