From 438f5391b2d502a132a4a20469e9e56305b221a4 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 23 Sep 2013 22:44:47 +0000 Subject: [PATCH] llvm-dwarfdump/libDebugInfo support for type units git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191234 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/DIContext.h | 1 + lib/DebugInfo/CMakeLists.txt | 1 + lib/DebugInfo/DWARFContext.cpp | 39 ++++++++++++++++-- lib/DebugInfo/DWARFContext.h | 24 +++++++++++ lib/DebugInfo/DWARFTypeUnit.cpp | 39 ++++++++++++++++++ lib/DebugInfo/DWARFTypeUnit.h | 35 ++++++++++++++++ test/DebugInfo/Inputs/dwarfdump-type-units.cc | 15 +++++++ .../Inputs/dwarfdump-type-units.elf-x86-64 | Bin 0 -> 3928 bytes test/DebugInfo/dwarfdump-type-units.test | 21 ++++++++++ 9 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 lib/DebugInfo/DWARFTypeUnit.cpp create mode 100644 lib/DebugInfo/DWARFTypeUnit.h create mode 100644 test/DebugInfo/Inputs/dwarfdump-type-units.cc create mode 100644 test/DebugInfo/Inputs/dwarfdump-type-units.elf-x86-64 create mode 100644 test/DebugInfo/dwarfdump-type-units.test diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 0e0bd2cd2be..1b421385580 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -104,6 +104,7 @@ enum DIDumpType { DIDT_Frames, DIDT_Info, DIDT_InfoDwo, + DIDT_Types, DIDT_Line, DIDT_Loc, DIDT_Ranges, diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt index e25d1499136..61a3fb066d1 100644 --- a/lib/DebugInfo/CMakeLists.txt +++ b/lib/DebugInfo/CMakeLists.txt @@ -12,5 +12,6 @@ add_llvm_library(LLVMDebugInfo DWARFDebugLoc.cpp DWARFDebugRangeList.cpp DWARFFormValue.cpp + DWARFTypeUnit.cpp DWARFUnit.cpp ) diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index ee152bd9b36..c54a1da6224 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -40,8 +40,14 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { getCompileUnitAtIndex(i)->dump(OS); } + if (DumpType == DIDT_All || DumpType == DIDT_Types) { + OS << "\n.debug_types contents:\n"; + for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i) + getTypeUnitAtIndex(i)->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Loc) { - OS << ".debug_loc contents:\n"; + OS << "\n.debug_loc contents:\n"; getDebugLoc()->dump(OS); } @@ -287,6 +293,28 @@ void DWARFContext::parseCompileUnits() { } } +void DWARFContext::parseTypeUnits() { + const std::map &Sections = getTypesSections(); + for (std::map::const_iterator + I = Sections.begin(), + E = Sections.end(); + I != E; ++I) { + uint32_t offset = 0; + const DataExtractor &DIData = + DataExtractor(I->second.Data, isLittleEndian(), 0); + while (DIData.isValidOffset(offset)) { + OwningPtr TU(new DWARFTypeUnit( + getDebugAbbrev(), I->second.Data, getAbbrevSection(), + getRangeSection(), getStringSection(), StringRef(), getAddrSection(), + &I->second.Relocs, isLittleEndian())); + if (!TU->extract(DIData, &offset)) + break; + TUs.push_back(TU.take()); + offset = TUs.back()->getNextUnitOffset(); + } + } +} + void DWARFContext::parseDWOCompileUnits() { uint32_t offset = 0; const DataExtractor &DIData = @@ -597,6 +625,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; } + } else if (name == "debug_types") { + TypesSections[*i].Data = data; } section_iterator RelocatedSection = i->getRelocatedSection(); @@ -616,8 +646,11 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) .Default(0); - if (!Map) - continue; + if (!Map) { + if (RelSecName != "debug_types") + continue; + Map = &TypesSections[*RelocatedSection].Relocs; + } if (i->begin_relocations() != i->end_relocations()) { uint64_t SectionSize; diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index cda4475482d..242d186c696 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -16,6 +16,7 @@ #include "DWARFDebugLine.h" #include "DWARFDebugLoc.h" #include "DWARFDebugRangeList.h" +#include "DWARFTypeUnit.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DIContext.h" @@ -28,6 +29,7 @@ namespace llvm { /// methods that a concrete implementation provides. class DWARFContext : public DIContext { SmallVector CUs; + SmallVector TUs; OwningPtr Abbrev; OwningPtr Loc; OwningPtr Aranges; @@ -43,6 +45,9 @@ class DWARFContext : public DIContext { /// Read compile units from the debug_info section and store them in CUs. void parseCompileUnits(); + /// Read type units from the debug_types sections and store them in CUs. + void parseTypeUnits(); + /// Read compile units from the debug_info.dwo section and store them in /// DWOCUs. void parseDWOCompileUnits(); @@ -69,6 +74,13 @@ public: return CUs.size(); } + /// Get the number of compile units in this context. + unsigned getNumTypeUnits() { + if (TUs.empty()) + parseTypeUnits(); + return TUs.size(); + } + /// Get the number of compile units in the DWO context. unsigned getNumDWOCompileUnits() { if (DWOCUs.empty()) @@ -83,6 +95,13 @@ public: return CUs[index]; } + /// Get the type unit at the specified index for this compile unit. + DWARFTypeUnit *getTypeUnitAtIndex(unsigned index) { + if (TUs.empty()) + parseTypeUnits(); + return TUs[index]; + } + /// Get the compile unit at the specified index for the DWO compile units. DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { if (DWOCUs.empty()) @@ -119,6 +138,7 @@ public: virtual bool isLittleEndian() const = 0; virtual uint8_t getAddressSize() const = 0; virtual const Section &getInfoSection() = 0; + virtual const std::map &getTypesSections() = 0; virtual StringRef getAbbrevSection() = 0; virtual const Section &getLocSection() = 0; virtual StringRef getARangeSection() = 0; @@ -157,6 +177,7 @@ class DWARFContextInMemory : public DWARFContext { bool IsLittleEndian; uint8_t AddressSize; Section InfoSection; + std::map TypesSections; StringRef AbbrevSection; Section LocSection; StringRef ARangeSection; @@ -183,6 +204,9 @@ public: virtual bool isLittleEndian() const { return IsLittleEndian; } virtual uint8_t getAddressSize() const { return AddressSize; } virtual const Section &getInfoSection() { return InfoSection; } + virtual const std::map &getTypesSections() { + return TypesSections; + } virtual StringRef getAbbrevSection() { return AbbrevSection; } virtual const Section &getLocSection() { return LocSection; } virtual StringRef getARangeSection() { return ARangeSection; } diff --git a/lib/DebugInfo/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARFTypeUnit.cpp new file mode 100644 index 00000000000..c81e2403b1d --- /dev/null +++ b/lib/DebugInfo/DWARFTypeUnit.cpp @@ -0,0 +1,39 @@ +//===-- DWARFTypeUnit.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFTypeUnit.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +bool DWARFTypeUnit::extractImpl(DataExtractor debug_info, + uint32_t *offset_ptr) { + if (!DWARFUnit::extractImpl(debug_info, offset_ptr)) + return false; + TypeHash = debug_info.getU64(offset_ptr); + TypeOffset = debug_info.getU32(offset_ptr); + return TypeOffset < getLength(); +} + +void DWARFTypeUnit::dump(raw_ostream &OS) { + OS << format("0x%08x", getOffset()) << ": Type Unit:" + << " length = " << format("0x%08x", getLength()) + << " version = " << format("0x%04x", getVersion()) + << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) + << " addr_size = " << format("0x%02x", getAddressByteSize()) + << " type_signature = " << format("0x%16lx", TypeHash) + << " type_offset = " << format("0x%04x", TypeOffset) + << " (next unit at " << format("0x%08x", getNextUnitOffset()) + << ")\n"; + + const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); + assert(CU && "Null Compile Unit?"); + CU->dump(OS, this, -1U); +} diff --git a/lib/DebugInfo/DWARFTypeUnit.h b/lib/DebugInfo/DWARFTypeUnit.h new file mode 100644 index 00000000000..7a0dab204d0 --- /dev/null +++ b/lib/DebugInfo/DWARFTypeUnit.h @@ -0,0 +1,35 @@ +//===-- DWARFTypeUnit.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_DWARFTYPEUNIT_H +#define LLVM_DEBUGINFO_DWARFTYPEUNIT_H + +#include "DWARFUnit.h" + +namespace llvm { + +class DWARFTypeUnit : public DWARFUnit { +private: + uint64_t TypeHash; + uint32_t TypeOffset; +public: + DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, + StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + const RelocAddrMap *M, bool LE) + : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {} + uint32_t getSize() const LLVM_OVERRIDE { return DWARFUnit::getSize() + 12; } + void dump(raw_ostream &OS); +protected: + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) LLVM_OVERRIDE; +}; + +} + +#endif + diff --git a/test/DebugInfo/Inputs/dwarfdump-type-units.cc b/test/DebugInfo/Inputs/dwarfdump-type-units.cc new file mode 100644 index 00000000000..06bc9a2102c --- /dev/null +++ b/test/DebugInfo/Inputs/dwarfdump-type-units.cc @@ -0,0 +1,15 @@ +struct foo {}; +struct bar {}; +void sink(void*); +int main() { + foo f; + sink(&f); + bar b; + sink(&b); +} + +// Built with GCC 4.8.1 +// $ mkdir -p /tmp/dbginfo +// $ cp dwarfdump-type-units.cc /tmp/dbginfo +// $ cd /tmp/dbginfo +// $ g++-4.8.1 -g -fdebug-types-section -c dwarfdump-type-units.cc -o dwarfdump-type-units.elf-x86-64 diff --git a/test/DebugInfo/Inputs/dwarfdump-type-units.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-type-units.elf-x86-64 new file mode 100644 index 0000000000000000000000000000000000000000..064b4f06764e930a7988d192e5c86e3fcf27121d GIT binary patch literal 3928 zcmb_fUuauZ7(XXBZ8Ec_|D3i~Fv6zWy4-bL8|$RCTbYYcXDJk6K3s2-lQdg%6O!95 z^}!)dSs#Yoiz4{ogOB?|8$L((=5GWy&D&r){d*X%1>ec9`0TiK1z ze?wE?|0VuI1b&Z`_~oY{wpu*i+y5v#+QryWkfUhB;@9jVyYtIS7Y~8Jqd$Fc`%dM` zn;WQ#PdPZ6ot5vY(>{XCdY}rk~qluyu#K0(( zJo>T*k($4aC=?sekQ%#-jCWBPksHk?nhz#kKNIV_A9@*N zRy>h7m3Sh-nAOh@B?l8$awOT$2c$k~^CyR`BX=^`X=uYNdk&+~Y7rSPFhQ|2x@((}pVx4`=>*O*HI$tp)(l zz924e2d;knQ5;M=2ItN%rRGLQQxo=-eIk{v_^Y0nE(uT6%XtvpdVYDjIh9FgCQ|8A zDqSpy+-fN;{nHJR_sdm}9rr7>=mo5;+A3l&dtr8N*#vaM}o+Z`#~%Ph`+cn zzsPvAFD94P8rdI8 zxVA5vKC=t1?=m~rXfV5!&pV=-7d77j`xU`#X(wB8WGmYc*@hix-CV9N*0!nLy6cq$ zgw=wqls$+VxIit;&Q~iH0UOBns=lyc9?}ip&0kVZV%aIy-3qvr>eW@XO4Qz7$8W%~ zKg4-fVKjfkASdCG^Q(=!`Da7?do@3blL8EPU^hHEEhxd<$mB=1Bfyv#>asn71=WG| z? zbz`#CusPt(o>0B1=5I{d;{0Ks=KSrJ|EBWWYyMjy`SJT>=Dz@#IVYHU3x9y*_atED zuW7pkXjuP$sQf=DU+f>(!pvU;%#4XHs|vh`f<~t8I_OLc&3{%P%|C@OZQ*MZTK^Y# zSb@kN>&NqF)_)x^GbTW+SM8^16f`nzuYoRX{{B+=>6~GHe9xHq-vSI{Qk}p`npgQ> zP%;gapT>7V5$6A%@*f~aHIg5V?<;@9jNLTO6Y0s1QEE%ei`X~4kV8Z6F z4;KrF{Bi#7gNOWSUU5#%cMm`;uE6h5(8#PGWwUlPe+Lg6(5zBE0Q|l1nECes7MB06 zdU4_T(8vSINqU_I>juCH#X2d$$cQ!JWqqXDf5~wW(m#Yx6+Ffo}TJjCB9Ye{I zU&b(8Eux{aLch2e2X1{KWU&JwDB9zW*iLZC1ll>v4@o?1r7@0LY-!W^vE+((Wa6xl z_^7i&cG5|}2S7ta-}5N|`UupZrR=XeYh%p0FwrP`mloETv*cYadj)4vG*;op z)u|O{5NG|LRzP$=HStlfK|&n<1+?wyo}+)u(C%UU0YY3~jsMG@?hzOp_Xy>{_XiT; zfdqGc#Sng8$@m^Z!X2jXrXv#FSwDUMDbDlC4%Z*ajPq;&w{d#k=<}eTTG~TqoU{=~ aiR}}H^-zzfJFE<_C%rG)uV}BoUH${Q(Invj literal 0 HcmV?d00001 diff --git a/test/DebugInfo/dwarfdump-type-units.test b/test/DebugInfo/dwarfdump-type-units.test new file mode 100644 index 00000000000..64f4899a17d --- /dev/null +++ b/test/DebugInfo/dwarfdump-type-units.test @@ -0,0 +1,21 @@ +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-type-units.elf-x86-64 | FileCheck %s + +CHECK: debug_info contents: +CHECK: DW_TAG_variable +CHECK-NEXT: DW_AT_name {{.*}}"f" +CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[FOO_SIG:0x[0-9a-f]*]]) +CHECK: DW_TAG_variable +CHECK-NEXT: DW_AT_name {{.*}}"b" +CHECK: DW_AT_type [DW_FORM_ref_sig8] ([[BAR_SIG:0x[0-9a-f]*]]) + +CHECK: debug_types contents: +CHECK: 0x00000000: Type Unit: {{.*}} type_signature = [[FOO_SIG]] type_offset = 0x[[FOO_OFF:[0-9a-f]*]] (next unit at +CHECK: DW_TAG_type_unit +CHECK-NOT: NULL +CHECK: 0x0000[[FOO_OFF]]: DW_TAG_structure_type +CHECK-NEXT: DW_AT_name {{.*}}"foo" +CHECK: 0x00000000: Type Unit: {{.*}} type_signature = [[BAR_SIG]] type_offset = 0x[[BAR_OFF:[0-9a-f]*]] (next unit at +CHECK: DW_TAG_type_unit +CHECK-NOT: NULL +CHECK: 0x0000[[BAR_OFF]]: DW_TAG_structure_type +CHECK-NEXT: DW_AT_name {{.*}}"bar"