diff options
author | David Blaikie <dblaikie@gmail.com> | 2013-06-19 21:37:13 +0000 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2013-06-19 21:37:13 +0000 |
commit | 3df7d2f70bb316ebeec8a8c862b3da5386fbb145 (patch) | |
tree | efdb44c6da2587da53aee3079c914e688692fc13 | |
parent | ba54bca472a15d0657e1b88776f7069042b60b4e (diff) | |
download | external_llvm-3df7d2f70bb316ebeec8a8c862b3da5386fbb145.zip external_llvm-3df7d2f70bb316ebeec8a8c862b3da5386fbb145.tar.gz external_llvm-3df7d2f70bb316ebeec8a8c862b3da5386fbb145.tar.bz2 |
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
-rw-r--r-- | include/llvm/DebugInfo/DIContext.h | 1 | ||||
-rw-r--r-- | lib/DebugInfo/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 19 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 11 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugLoc.cpp | 74 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugLoc.h | 60 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.cpp | 6 | ||||
-rw-r--r-- | test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp | 13 | ||||
-rw-r--r-- | test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o | bin | 0 -> 2604 bytes | |||
-rw-r--r-- | test/DebugInfo/dwarfdump-debug-loc-simple.test | 26 | ||||
-rw-r--r-- | tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 1 |
11 files changed, 211 insertions, 1 deletions
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 8fcd9e0..bdd8dce 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 e97455a..4a6221d 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 aaae952..6ecd0a7 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<StringRef*>(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<RelocAddrMap*>(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 78c18e6..af9965f 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<DWARFCompileUnit, 1> CUs; OwningPtr<DWARFDebugAbbrev> Abbrev; + OwningPtr<DWARFDebugLoc> Loc; OwningPtr<DWARFDebugAranges> Aranges; OwningPtr<DWARFDebugLine> Line; OwningPtr<DWARFDebugFrame> 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 0000000..46de489 --- /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<Entry>::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<unsigned char>::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 0000000..d31aaaa --- /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<unsigned char, 4> 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<Entry, 2> Entries; + }; + + typedef SmallVector<LocationList, 4> 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 5f06f43..1a1cf24 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 0000000..04a0b20 --- /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 Binary files differnew file mode 100644 index 0000000..25d10b9 --- /dev/null +++ b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o diff --git a/test/DebugInfo/dwarfdump-debug-loc-simple.test b/test/DebugInfo/dwarfdump-debug-loc-simple.test new file mode 100644 index 0000000..f38be6d --- /dev/null +++ b/test/DebugInfo/dwarfdump-debug-loc-simple.test @@ -0,0 +1,26 @@ +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-loc-list-32bit.elf.o | FileCheck %s +Note: the input file was generated from Inputs/dwarfdump-test-loc-list-32bit.elf.cpp + +CHECK: .debug_info +CHECK: DW_AT_name{{.*}}"f" +CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]]) +CHECK: DW_AT_name{{.*}}"g" +CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]]) +CHECK: .debug_loc contents: +CHECK-NEXT: [[F_LOC]]: Begining address offset: 0x0000000000000000 +CHECK-NEXT: Ending address offset: 0x0000000000000023 +this is actually the wrong location due to PR14763, but that doesn't matter for +the purposes of testing dwarfdump +CHECK-NEXT: Location description: 51 +CHECK-NEXT: {{^$}} +CHECK-NEXT: Begining address offset: 0x0000000000000023 +CHECK-NEXT: Ending address offset: 0x000000000000005d +CHECK-NEXT: Location description: 75 70 +CHECK-NEXT: {{^$}} +CHECK-NEXT: [[G_LOC]]: Begining address offset: 0x0000000000000000 +CHECK-NEXT: Ending address offset: 0x0000000000000020 +CHECK-NEXT: Location description: 50 +CHECK-NEXT: {{^$}} +CHECK-NEXT: Begining address offset: 0x0000000000000020 +CHECK-NEXT: Ending address offset: 0x000000000000005d +CHECK-NEXT: Location description: 75 74 diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 8094856..eef6f79 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -63,6 +63,7 @@ DumpType("debug-dump", cl::init(DIDT_All), clEnumValN(DIDT_Info, "info", ".debug_info"), clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"), clEnumValN(DIDT_Line, "line", ".debug_line"), + clEnumValN(DIDT_Loc, "loc", ".debug_loc"), clEnumValN(DIDT_Frames, "frames", ".debug_frame"), clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"), clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"), |