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 /lib | |
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
Diffstat (limited to 'lib')
-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 |
6 files changed, 170 insertions, 1 deletions
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); |