summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp')
-rw-r--r--llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp b/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
index 928571bfd0a..278e861dfd3 100644
--- a/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
+++ b/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
@@ -11,6 +11,7 @@
#include "GraphBuilder.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -42,6 +43,19 @@ using Instr = llvm::cfi_verify::FileAnalysis::Instr;
namespace llvm {
namespace cfi_verify {
+static cl::opt<bool> IgnoreDWARF(
+ "ignore-dwarf",
+ cl::desc(
+ "Ignore all DWARF data. This relaxes the requirements for all "
+ "statically linked libraries to have been compiled with '-g', but "
+ "will result in false positives for 'CFI unprotected' instructions."),
+ cl::init(false));
+
+cl::opt<unsigned long long> DWARFSearchRange(
+ "dwarf-search-range",
+ cl::desc("Address search range used to determine if instruction is valid."),
+ cl::init(0x10));
+
Expected<FileAnalysis> FileAnalysis::Create(StringRef Filename) {
// Open the filename provided.
Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
@@ -294,6 +308,28 @@ Error FileAnalysis::initialiseDisassemblyMembers() {
}
Error FileAnalysis::parseCodeSections() {
+ if (!IgnoreDWARF) {
+ DWARF.reset(DWARFContext::create(*Object).release());
+ if (!DWARF)
+ return make_error<StringError>("Could not create DWARF information.",
+ inconvertibleErrorCode());
+
+ bool LineInfoValid = false;
+
+ for (auto &Unit : DWARF->compile_units()) {
+ const auto &LineTable = DWARF->getLineTableForUnit(Unit.get());
+ if (LineTable && !LineTable->Rows.empty()) {
+ LineInfoValid = true;
+ break;
+ }
+ }
+
+ if (!LineInfoValid)
+ return make_error<StringError>(
+ "DWARF line information missing. Did you compile with '-g'?",
+ inconvertibleErrorCode());
+ }
+
for (const object::SectionRef &Section : Object->sections()) {
// Ensure only executable sections get analysed.
if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR))
@@ -311,6 +347,19 @@ Error FileAnalysis::parseCodeSections() {
return Error::success();
}
+DILineInfoTable FileAnalysis::getLineInfoForAddressRange(uint64_t Address) {
+ if (!hasLineTableInfo())
+ return DILineInfoTable();
+
+ return DWARF->getLineInfoForAddressRange(Address, DWARFSearchRange);
+}
+
+bool FileAnalysis::hasValidLineInfoForAddressRange(uint64_t Address) {
+ return !getLineInfoForAddressRange(Address).empty();
+}
+
+bool FileAnalysis::hasLineTableInfo() const { return DWARF != nullptr; }
+
void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
uint64_t SectionAddress) {
MCInst Instruction;
@@ -330,6 +379,11 @@ void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
InstrMeta.VMAddress = VMAddress;
InstrMeta.InstructionSize = InstructionSize;
InstrMeta.Valid = ValidInstruction;
+
+ // Check if this instruction exists in the range of the DWARF metadata.
+ if (hasLineTableInfo() && !hasValidLineInfoForAddressRange(VMAddress))
+ continue;
+
addInstruction(InstrMeta);
if (!ValidInstruction)
OpenPOWER on IntegriCloud