From 3df7d2f70bb316ebeec8a8c862b3da5386fbb145 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 19 Jun 2013 21:37:13 +0000 Subject: 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 --- 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 +++- 6 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 lib/DebugInfo/DWARFDebugLoc.cpp create mode 100644 lib/DebugInfo/DWARFDebugLoc.h (limited to 'lib') diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt index e97455abac..4a6221d454 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 aaae952da5..6ecd0a75a1 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 78c18e6168..af9965fd1d 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 0000000000..46de489204 --- /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 0000000000..d31aaaa127 --- /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 5f06f43d81..1a1cf2452c 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); -- cgit v1.2.3