From 3e25c4a1e3e58bc1d00d894854a29dd2e4e7e88a Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Mon, 2 Jul 2012 05:54:45 +0000 Subject: [PATCH] This patch extends the libLLVMDebugInfo which contains a minimalistic DWARF parser: 1) DIContext is now able to return function name for a given instruction address (besides file/line info). 2) llvm-dwarfdump accepts flag --functions that prints the function name (if address is specified by --address flag). 3) test case that checks the basic functionality of llvm-dwarfdump added git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159512 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/DIContext.h | 34 ++++++++++-- lib/DebugInfo/DWARFCompileUnit.cpp | 18 +++++-- lib/DebugInfo/DWARFCompileUnit.h | 5 ++ lib/DebugInfo/DWARFContext.cpp | 50 +++++++++++------- lib/DebugInfo/DWARFContext.h | 3 +- lib/DebugInfo/DWARFDebugAranges.cpp | 2 +- lib/DebugInfo/DWARFDebugInfoEntry.cpp | 48 +++++++++++++++++ lib/DebugInfo/DWARFDebugInfoEntry.h | 7 +++ .../Inputs/dwarfdump-test.elf-x86-64 | Bin 0 -> 10246 bytes .../Inputs/dwarfdump-test2.elf-x86-64 | Bin 0 -> 7774 bytes test/DebugInfo/dwarfdump-test.test | 25 +++++++++ tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 13 ++++- 12 files changed, 174 insertions(+), 31 deletions(-) create mode 100755 test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64 create mode 100755 test/DebugInfo/Inputs/dwarfdump-test2.elf-x86-64 create mode 100644 test/DebugInfo/dwarfdump-test.test diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 64f80c50650..6377acb634b 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -26,26 +26,49 @@ class raw_ostream; /// DILineInfo - a format-neutral container for source line information. class DILineInfo { const char *FileName; + const char *FunctionName; uint32_t Line; uint32_t Column; public: - DILineInfo() : FileName(""), Line(0), Column(0) {} - DILineInfo(const char *fileName, uint32_t line, uint32_t column) - : FileName(fileName), Line(line), Column(column) {} + DILineInfo() + : FileName(""), FunctionName(""), + Line(0), Column(0) {} + DILineInfo(const char *fileName, const char *functionName, + uint32_t line, uint32_t column) + : FileName(fileName), FunctionName(functionName), + Line(line), Column(column) {} const char *getFileName() const { return FileName; } + const char *getFunctionName() const { return FunctionName; } uint32_t getLine() const { return Line; } uint32_t getColumn() const { return Column; } bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && - std::strcmp(FileName, RHS.FileName) == 0; + std::strcmp(FileName, RHS.FileName) == 0 && + std::strcmp(FunctionName, RHS.FunctionName) == 0; } bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); } }; +/// DILineInfoSpecifier - controls which fields of DILineInfo container +/// should be filled with data. +class DILineInfoSpecifier { + const uint32_t Flags; // Or'ed flags that set the info we want to fetch. +public: + enum Specification { + FileLineInfo = 1 << 0, + FunctionName = 1 << 1 + }; + // Use file/line info by default. + DILineInfoSpecifier(uint32_t flags = FileLineInfo) : Flags(flags) {} + bool needs(Specification spec) const { + return (Flags & spec) > 0; + } +}; + class DIContext { public: virtual ~DIContext(); @@ -60,7 +83,8 @@ public: virtual void dump(raw_ostream &OS) = 0; - virtual DILineInfo getLineInfoForAddress(uint64_t address) = 0; + virtual DILineInfo getLineInfoForAddress(uint64_t address, + DILineInfoSpecifier specifier = DILineInfoSpecifier()) = 0; }; } diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp index 24bf97ff608..2683990e589 100644 --- a/lib/DebugInfo/DWARFCompileUnit.cpp +++ b/lib/DebugInfo/DWARFCompileUnit.cpp @@ -82,7 +82,7 @@ void DWARFCompileUnit::clear() { Abbrevs = 0; AddrSize = 0; BaseAddr = 0; - DieArray.clear(); + clearDIEs(false); } void DWARFCompileUnit::dump(raw_ostream &OS) { @@ -201,7 +201,7 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) { } void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) { - if (DieArray.size() > 1) { + if (DieArray.size() > (unsigned)keep_compile_unit_die) { // std::vectors never get any smaller when resized to a smaller size, // or when clear() or erase() are called, the size will report that it // is smaller, but the memory allocated remains intact (call capacity() @@ -227,8 +227,8 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, // all compile units to stay loaded when they weren't needed. So we can end // up parsing the DWARF and then throwing them all away to keep memory usage // down. - const bool clear_dies = extractDIEsIfNeeded(false) > 1; - + const bool clear_dies = extractDIEsIfNeeded(false) > 1 && + clear_dies_if_already_not_parsed; DieArray[0].buildAddressRangeTable(this, debug_aranges); // Keep memory down by clearing DIEs if this generate function @@ -236,3 +236,13 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, if (clear_dies) clearDIEs(true); } + +const DWARFDebugInfoEntryMinimal* +DWARFCompileUnit::getFunctionDIEForAddress(int64_t address) { + size_t n = extractDIEsIfNeeded(false); + for (size_t i = 0; i != n; i++) { + if (DieArray[i].addressRangeContainsAddress(this, address)) + return &DieArray[i]; + } + return 0; +} diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h index d9167292a9d..dc558da7141 100644 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ b/lib/DebugInfo/DWARFCompileUnit.h @@ -104,6 +104,11 @@ public: void buildAddressRangeTable(DWARFDebugAranges *debug_aranges, bool clear_dies_if_already_not_parsed); + /// getFunctionDIEForAddress - Returns pointer to parsed subprogram DIE, + /// address ranges of which contain the provided address, + /// or NULL if there is no such subprogram. The pointer + /// is valid until DWARFCompileUnit::clear() or clearDIEs() is called. + const DWARFDebugInfoEntryMinimal *getFunctionDIEForAddress(int64_t address); }; } diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index dccadc4ea4d..6be230e73a5 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -140,30 +140,42 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) { return 0; } -DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address) { +DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address, + DILineInfoSpecifier specifier) { // First, get the offset of the compile unit. uint32_t cuOffset = getDebugAranges()->findAddress(address); // Retrieve the compile unit. DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); if (!cu) - return DILineInfo("", 0, 0); - // Get the line table for this compile unit. - const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); - if (!lineTable) - return DILineInfo("", 0, 0); - // Get the index of the row we're looking for in the line table. - uint64_t hiPC = - cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_high_pc, - -1ULL); - uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); - if (rowIndex == -1U) - return DILineInfo("", 0, 0); - - // From here, contruct the DILineInfo. - const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; - const std::string &fileName = lineTable->Prologue.FileNames[row.File-1].Name; - - return DILineInfo(fileName.c_str(), row.Line, row.Column); + return DILineInfo(); + const char *fileName = ""; + const char *functionName = ""; + uint32_t line = 0; + uint32_t column = 0; + if (specifier.needs(DILineInfoSpecifier::FunctionName)) { + const DWARFDebugInfoEntryMinimal *function_die = + cu->getFunctionDIEForAddress(address); + if (function_die) + functionName = function_die->getSubprogramName(cu); + } + if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) { + // Get the line table for this compile unit. + const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); + if (lineTable) { + // Get the index of the row we're looking for in the line table. + uint64_t hiPC = cu->getCompileUnitDIE()->getAttributeValueAsUnsigned( + cu, DW_AT_high_pc, -1ULL); + uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); + if (rowIndex != -1U) { + const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; + // Take file/line info from the line table. + fileName = lineTable->Prologue.FileNames[row.File - 1].Name.c_str(); + line = row.Line; + column = row.Column; + } + } + } + return DILineInfo(fileName, functionName, line, column); } void DWARFContextInMemory::anchor() { } diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index d2e763a87a4..e55a27e6984 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -66,7 +66,8 @@ public: const DWARFDebugLine::LineTable * getLineTableForCompileUnit(DWARFCompileUnit *cu); - virtual DILineInfo getLineInfoForAddress(uint64_t address); + virtual DILineInfo getLineInfoForAddress(uint64_t address, + DILineInfoSpecifier specifier = DILineInfoSpecifier()); bool isLittleEndian() const { return IsLittleEndian; } diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp index 17881453561..ef470e5799c 100644 --- a/lib/DebugInfo/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARFDebugAranges.cpp @@ -93,6 +93,7 @@ bool DWARFDebugAranges::generate(DWARFContext *ctx) { cu->buildAddressRangeTable(this, true); } } + sort(true, /* overlap size */ 0); return !isEmpty(); } @@ -221,4 +222,3 @@ bool DWARFDebugAranges::getMaxRange(uint64_t &LoPC, uint64_t &HiPC) const { HiPC = Aranges.back().HiPC(); return true; } - diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index 236db97c44a..1024b452551 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -440,3 +440,51 @@ DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu, } } } + +bool +DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( + const DWARFCompileUnit *cu, const uint64_t address) const { + if (!isNULL() && getTag() == DW_TAG_subprogram) { + uint64_t hi_pc = -1ULL; + uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL); + if (lo_pc != -1ULL) + hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL); + if (hi_pc != -1ULL) { + return (lo_pc <= address && address < hi_pc); + } + } + return false; +} + +static inline const char* +getSubprogramNameFromDie(const DWARFCompileUnit *cu, + const DWARFDebugInfoEntryMinimal *die) { + const char *result = 0; + if (!die->isNULL() && die->getTag() == DW_TAG_subprogram) { + // Try to get mangled name if possible. + result = die->getAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, 0); + if (result == 0) + result = die->getAttributeValueAsString(cu, DW_AT_linkage_name, 0); + if (result == 0) + result = die->getAttributeValueAsString(cu, DW_AT_name, 0); + } + return result; +} + +const char* +DWARFDebugInfoEntryMinimal::getSubprogramName( + const DWARFCompileUnit *cu) const { + if (isNULL() || getTag() != DW_TAG_subprogram) + return 0; + const char *name = getSubprogramNameFromDie(cu, this); + if (name == 0) { + // Try to get name from specification DIE. + uint32_t ref = getAttributeValueAsReference(cu, DW_AT_specification, -1U); + if (ref != -1U) { + DWARFDebugInfoEntryMinimal spec_die; + if (spec_die.extract(cu, &ref)) + name = getSubprogramNameFromDie(cu, &spec_die); + } + } + return name; +} diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h index 37b3bcdd96e..1a040a53a38 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.h +++ b/lib/DebugInfo/DWARFDebugInfoEntry.h @@ -128,6 +128,13 @@ public: void buildAddressRangeTable(const DWARFCompileUnit *cu, DWARFDebugAranges *debug_aranges) const; + + bool addressRangeContainsAddress(const DWARFCompileUnit *cu, + const uint64_t address) const; + + // If a DIE represents a subroutine, returns its mangled name + // (or short name, if mangled is missing). Otherwise returns null. + const char* getSubprogramName(const DWARFCompileUnit *cu) const; }; } diff --git a/test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64 new file mode 100755 index 0000000000000000000000000000000000000000..7cee96807261e372daa22f0ea30046f16de4b537 GIT binary patch literal 10246 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�(Mn=cuFximR^CXNxkM%j ff~-B)p^}!|$T1AqZQ Address("address", cl::init(-1ULL), cl::desc("Print line information for a given address")); +static cl::opt +PrintFunctions("functions", cl::init(false), + cl::desc("Print function names as well as line information " + "for a given address")); + static void DumpInput(const StringRef &Filename) { OwningPtr Buff; @@ -92,7 +97,13 @@ static void DumpInput(const StringRef &Filename) { dictx->dump(outs()); } else { // Print line info for the specified address. - DILineInfo dli = dictx->getLineInfoForAddress(Address); + int spec_flags = DILineInfoSpecifier::FileLineInfo; + if (PrintFunctions) + spec_flags |= DILineInfoSpecifier::FunctionName; + DILineInfo dli = dictx->getLineInfoForAddress(Address, spec_flags); + if (PrintFunctions) + outs() << (dli.getFunctionName() ? dli.getFunctionName() : "") + << "\n"; outs() << (dli.getFileName() ? dli.getFileName() : "") << ':' << dli.getLine() << ':' << dli.getColumn() << '\n'; } -- 2.34.1