From 3df7d2f70bb316ebeec8a8c862b3da5386fbb145 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 19 Jun 2013 21:37:13 +0000 Subject: [PATCH] llvm-dwarfdump: Add support for dumping the .debug_loc section This is a basic implementation - we still don't have any support (that I know of) for dumping DWARF expressions in a meaningful way, so the location information itself is just printed as a sequence of bytes as we do elsewhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184361 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/DIContext.h | 1 + lib/DebugInfo/CMakeLists.txt | 1 + lib/DebugInfo/DWARFContext.cpp | 19 +++++ lib/DebugInfo/DWARFContext.h | 11 +++ lib/DebugInfo/DWARFDebugLoc.cpp | 74 ++++++++++++++++++ lib/DebugInfo/DWARFDebugLoc.h | 60 ++++++++++++++ lib/DebugInfo/DWARFFormValue.cpp | 6 +- .../dwarfdump-test-loc-list-32bit.elf.cpp | 13 +++ .../dwarfdump-test-loc-list-32bit.elf.o | Bin 0 -> 2604 bytes .../DebugInfo/dwarfdump-debug-loc-simple.test | 26 ++++++ tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 1 + 11 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 lib/DebugInfo/DWARFDebugLoc.cpp create mode 100644 lib/DebugInfo/DWARFDebugLoc.h create mode 100644 test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp create mode 100644 test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o create mode 100644 test/DebugInfo/dwarfdump-debug-loc-simple.test diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 8fcd9e0b824..bdd8dce08da 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -105,6 +105,7 @@ enum DIDumpType { DIDT_Info, DIDT_InfoDwo, DIDT_Line, + DIDT_Loc, DIDT_Ranges, DIDT_Pubnames, DIDT_Str, diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt index e97455abace..4a6221d454a 100644 --- a/lib/DebugInfo/CMakeLists.txt +++ b/lib/DebugInfo/CMakeLists.txt @@ -9,6 +9,7 @@ add_llvm_library(LLVMDebugInfo DWARFDebugFrame.cpp DWARFDebugInfoEntry.cpp DWARFDebugLine.cpp + DWARFDebugLoc.cpp DWARFDebugRangeList.cpp DWARFFormValue.cpp ) diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index aaae952da5b..6ecd0a75a1d 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -35,6 +35,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { getCompileUnitAtIndex(i)->dump(OS); } + if (DumpType == DIDT_All || DumpType == DIDT_Loc) { + OS << ".debug_loc contents:\n"; + getDebugLoc()->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Frames) { OS << "\n.debug_frame contents:\n"; getDebugFrame()->dump(OS); @@ -171,6 +176,18 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { return AbbrevDWO.get(); } +const DWARFDebugLoc *DWARFContext::getDebugLoc() { + if (Loc) + return Loc.get(); + + DataExtractor LocData(getLocSection(), isLittleEndian(), 0); + Loc.reset(new DWARFDebugLoc(locRelocMap())); + // assume all compile units have the same address byte size + if (getNumCompileUnits()) + Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize()); + return Loc.get(); +} + const DWARFDebugAranges *DWARFContext::getDebugAranges() { if (Aranges) return Aranges.get(); @@ -542,6 +559,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : StringRef *Section = StringSwitch(name) .Case("debug_info", &InfoSection) .Case("debug_abbrev", &AbbrevSection) + .Case("debug_loc", &LocSection) .Case("debug_line", &LineSection) .Case("debug_aranges", &ARangeSection) .Case("debug_frame", &DebugFrameSection) @@ -576,6 +594,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : // Record relocations for the debug_info and debug_line sections. RelocAddrMap *Map = StringSwitch(RelSecName) .Case("debug_info", &InfoRelocMap) + .Case("debug_loc", &LocRelocMap) .Case("debug_info.dwo", &InfoDWORelocMap) .Case("debug_line", &LineRelocMap) .Default(0); diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index 78c18e61680..af9965fd1d3 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -14,6 +14,7 @@ #include "DWARFDebugAranges.h" #include "DWARFDebugFrame.h" #include "DWARFDebugLine.h" +#include "DWARFDebugLoc.h" #include "DWARFDebugRangeList.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -28,6 +29,7 @@ namespace llvm { class DWARFContext : public DIContext { SmallVector CUs; OwningPtr Abbrev; + OwningPtr Loc; OwningPtr Aranges; OwningPtr Line; OwningPtr DebugFrame; @@ -80,6 +82,9 @@ public: /// Get a pointer to the parsed DebugAbbrev object. const DWARFDebugAbbrev *getDebugAbbrev(); + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + /// Get a pointer to the parsed dwo abbreviations object. const DWARFDebugAbbrev *getDebugAbbrevDWO(); @@ -104,8 +109,10 @@ public: virtual uint8_t getAddressSize() const = 0; virtual const RelocAddrMap &infoRelocMap() const = 0; virtual const RelocAddrMap &lineRelocMap() const = 0; + virtual const RelocAddrMap &locRelocMap() const = 0; virtual StringRef getInfoSection() = 0; virtual StringRef getAbbrevSection() = 0; + virtual StringRef getLocSection() = 0; virtual StringRef getARangeSection() = 0; virtual StringRef getDebugFrameSection() = 0; virtual StringRef getLineSection() = 0; @@ -142,9 +149,11 @@ class DWARFContextInMemory : public DWARFContext { bool IsLittleEndian; uint8_t AddressSize; RelocAddrMap InfoRelocMap; + RelocAddrMap LocRelocMap; RelocAddrMap LineRelocMap; StringRef InfoSection; StringRef AbbrevSection; + StringRef LocSection; StringRef ARangeSection; StringRef DebugFrameSection; StringRef LineSection; @@ -169,9 +178,11 @@ public: virtual bool isLittleEndian() const { return IsLittleEndian; } virtual uint8_t getAddressSize() const { return AddressSize; } virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; } + virtual const RelocAddrMap &locRelocMap() const { return LocRelocMap; } virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; } virtual StringRef getInfoSection() { return InfoSection; } virtual StringRef getAbbrevSection() { return AbbrevSection; } + virtual StringRef getLocSection() { return LocSection; } virtual StringRef getARangeSection() { return ARangeSection; } virtual StringRef getDebugFrameSection() { return DebugFrameSection; } virtual StringRef getLineSection() { return LineSection; } diff --git a/lib/DebugInfo/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARFDebugLoc.cpp new file mode 100644 index 00000000000..46de4892049 --- /dev/null +++ b/lib/DebugInfo/DWARFDebugLoc.cpp @@ -0,0 +1,74 @@ +//===-- DWARFDebugLoc.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugLoc.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void DWARFDebugLoc::dump(raw_ostream &OS) const { + for (LocationLists::const_iterator I = Locations.begin(), E = Locations.end(); I != E; ++I) { + OS << format("0x%8.8x: ", I->Offset); + const unsigned Indent = 12; + for (SmallVectorImpl::const_iterator I2 = I->Entries.begin(), E2 = I->Entries.end(); I2 != E2; ++I2) { + if (I2 != I->Entries.begin()) + OS.indent(Indent); + OS << "Begining address offset: " << format("0x%016" PRIx64, I2->Begin) + << '\n'; + OS.indent(Indent) << " Ending address offset: " + << format("0x%016" PRIx64, I2->End) << '\n'; + OS.indent(Indent) << " Location description: "; + for (SmallVectorImpl::const_iterator I3 = I2->Loc.begin(), E3 = I2->Loc.end(); I3 != E3; ++I3) { + OS << format("%2.2x ", *I3); + } + OS << "\n\n"; + } + } +} + +void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) { + uint32_t Offset = 0; + while (data.isValidOffset(Offset)) { + Locations.resize(Locations.size() + 1); + LocationList &Loc = Locations.back(); + Loc.Offset = Offset; + // 2.6.2 Location Lists + // A location list entry consists of: + while (true) { + Entry E; + RelocAddrMap::const_iterator AI = RelocMap.find(Offset); + // 1. A beginning address offset. ... + E.Begin = data.getUnsigned(&Offset, AddressSize); + if (AI != RelocMap.end()) + E.Begin += AI->second.second; + + AI = RelocMap.find(Offset); + // 2. An ending address offset. ... + E.End = data.getUnsigned(&Offset, AddressSize); + if (AI != RelocMap.end()) + E.End += AI->second.second; + + // The end of any given location list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset and a 0 for the + // ending address offset. + if (E.Begin == 0 && E.End == 0) + break; + + unsigned Bytes = data.getU16(&Offset); + // A single location description describing the location of the object... + StringRef str = data.getData().substr(Offset, Bytes); + Offset += Bytes; + E.Loc.reserve(str.size()); + std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); + Loc.Entries.push_back(llvm_move(E)); + } + } +} diff --git a/lib/DebugInfo/DWARFDebugLoc.h b/lib/DebugInfo/DWARFDebugLoc.h new file mode 100644 index 00000000000..d31aaaa1273 --- /dev/null +++ b/lib/DebugInfo/DWARFDebugLoc.h @@ -0,0 +1,60 @@ +//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGLOC_H +#define LLVM_DEBUGINFO_DWARFDEBUGLOC_H + +#include "DWARFRelocMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLoc { + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + /// A map used to resolve binary relocations. + const RelocAddrMap &RelocMap; + +public: + DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS) const; + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// specified address size to interpret the address ranges. + void parse(DataExtractor data, unsigned AddressSize); +}; +} + +#endif diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index 5f06f43d81c..1a1cf2452cd 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -126,9 +126,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, Value.uval = data.getU16(offset_ptr); break; case DW_FORM_data4: - case DW_FORM_ref4: + case DW_FORM_ref4: { + RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); Value.uval = data.getU32(offset_ptr); + if (AI != cu->getRelocMap()->end()) + Value.uval += AI->second.second; break; + } case DW_FORM_data8: case DW_FORM_ref8: Value.uval = data.getU64(offset_ptr); diff --git a/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp new file mode 100644 index 00000000000..04a0b20cc2c --- /dev/null +++ b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp @@ -0,0 +1,13 @@ +// clang -c -g -o dwarfdump-test-loc-list-32bit.elf.o -m32 dwarfdump-test-loc-list-32bit.elf.cpp + +namespace pr14763 { +struct foo { + foo(const foo&); +}; + +foo func(bool b, foo f, foo g) { + if (b) + return f; + return g; +} +} diff --git a/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o new file mode 100644 index 0000000000000000000000000000000000000000..25d10b980907fded4abe76b141a4b276f0e43a0b GIT binary patch literal 2604 zcma)8OKe+36uskTCoi`1@^PS;R$x@~mGb(DMb#48@NrAjH0npL5F%LqJf{Z#WIulpMjJx7gVn)o0r6|#41a{82oCtwB1|37KFQbKMk?R-R&Ln!l+l?lu z{AQtDDR=9wdEe{!^R;GazE*{@aJX3YU9VPgORW}yArbjgC8PGHeZXF~9|_sW#E$)F zg3dAUMuw=XMu0$4XoAi%C^zq{lv1tGSWj(u?M}7XNG-UT)QANg@arvVwGU;EJiS2q zS5}WGJyYp6O4;J-h5SOL+00%zm?yRn2opb^dPyvaz&XaiC7JK92@O3Qb z0oeB`AD2tdIrg>C^OKPm-?zvud&Ta0zECW-y$y2PUd{Er%RafqPDeXi-J*Y`(bO z+|DIT;TMX~G+wDoUM~0rwa!t1ZzliRe4tpC(B%FwflLQLQ@{zOGc1Cz?>;mh&llfD z`$2L2INby{MLkV~yCCELFHT;4Bf(AR-x-|eX5pv7tZxP625ekk1Wnh+@p=qYS_Ao# z6(!o|f@_^!dwqd?&u$k+)3&Q)#>%bc@SjXqk&H75Hj~`Vn z+V>d@X1S?_5TcaVc19CtZTWzRXdJ*!X}(Ixc{tqgju z?uc=ps5o8LKIF@&TnzeLeGJ`PZyKAX_m4kZdc9vmH%mGT@*`|obbWVV&~viy_Bc@r z&ikSB`R9C$x6#aecQL7Xk90nS?Gn=-rayK}=kBjM=Qn3yu2&t5vgAo0X0Qmw8e++v z7#gfyJH`3