From 6214c11cb7ddb7813ecc2c37923ed95d35c53cef Mon Sep 17 00:00:00 2001 From: Wolfgang Pieb Date: Fri, 19 Oct 2018 19:23:16 +0000 Subject: [PATCH] [DWARF] Make llvm-dwarfdump display location lists in a .dwp file correctly. Fixes PR38990. Considers the index when extracting location lists from a .dwp file. Majority of the patch by David Blaikie. Reviewers: dblaikie Differential revision: https://reviews.llvm.org/D53155 llvm-svn: 344807 --- .../llvm/DebugInfo/DWARF/DWARFCompileUnit.h | 8 +-- .../llvm/DebugInfo/DWARF/DWARFTypeUnit.h | 8 +-- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 23 ++++--- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 10 ++- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 48 ++++++++------ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 14 +++-- llvm/test/DebugInfo/Inputs/loclists-dwp-b.ll | 32 ++++++++++ llvm/test/DebugInfo/X86/loclists-dwp.ll | 62 +++++++++++++++++++ 8 files changed, 160 insertions(+), 45 deletions(-) create mode 100644 llvm/test/DebugInfo/Inputs/loclists-dwp-b.ll create mode 100644 llvm/test/DebugInfo/X86/loclists-dwp.ll diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index 27d56d72f0a7..33797419a7b8 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -18,13 +18,13 @@ namespace llvm { class DWARFCompileUnit : public DWARFUnit { public: DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector) - : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitVector) {} + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} /// VTable anchor. ~DWARFCompileUnit() override; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index 0a5a1aaa79d1..8ca5ba13fc23 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -26,13 +26,13 @@ class raw_ostream; class DWARFTypeUnit : public DWARFUnit { public: DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector) - : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitVector) {} + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} uint64_t getTypeHash() const { return getHeader().getTypeHash(); } uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); } diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 39d43b91485f..c267cf173d14 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -153,10 +153,10 @@ public: private: void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, const DWARFDebugAbbrev *DA, - const DWARFSection *RS, StringRef SS, - const DWARFSection &SOS, const DWARFSection *AOS, - const DWARFSection &LS, bool LE, bool IsDWO, bool Lazy, - DWARFSectionKind SectionKind); + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, + bool IsDWO, bool Lazy, DWARFSectionKind SectionKind); }; /// Represents base address of the CU. @@ -198,6 +198,12 @@ class DWARFUnit { const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; uint32_t RangeSectionBase; + /// We either keep track of the location list section or its data, depending + /// on whether we are handling a split DWARF section or not. + union { + const DWARFSection *LocSection; + StringRef LocSectionData; + }; const DWARFSection &LineSection; StringRef StringSection; const DWARFSection &StringOffsetSection; @@ -258,16 +264,19 @@ protected: public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, - const DWARFSection &SOS, const DWARFSection *AOS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector); virtual ~DWARFUnit(); + bool isDWOUnit() const { return isDWO; } DWARFContext& getContext() const { return Context; } const DWARFSection &getInfoSection() const { return InfoSection; } + const DWARFSection *getLocSection() const { return LocSection; } + StringRef getLocSectionData() const { return LocSectionData; } uint32_t getOffset() const { return Header.getOffset(); } const dwarf::FormParams &getFormParams() const { return Header.getFormParams(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index cf10c1134a7a..6b69b822aad4 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -101,12 +101,10 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, FormValue.dump(OS, DumpOpts); if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - const DWARFSection &LocSection = Obj.getLocSection(); - const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); uint32_t Offset = *FormValue.getAsSectionOffset(); - if (!LocSection.Data.empty()) { + if (!U->isDWOUnit()) { DWARFDebugLoc DebugLoc; - DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), + DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), Obj.getAddressSize()); auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { @@ -117,8 +115,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, Indent); } else OS << "error extracting location list."; - } else if (!LocDWOSection.Data.empty()) { - DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0); + } else { + DataExtractor Data(U->getLocSectionData(), Ctx.isLittleEndian(), 0); auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); if (LL) LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 6c3c62d86ef0..dbac5a82b578 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -39,9 +39,10 @@ void DWARFUnitVector::addUnitsForSection(DWARFContext &C, DWARFSectionKind SectionKind) { const DWARFObject &D = C.getDWARFObj(); addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(), - D.getStringSection(), D.getStringOffsetSection(), - &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), - false, false, SectionKind); + &D.getLocSection(), D.getStringSection(), + D.getStringOffsetSection(), &D.getAddrSection(), + D.getLineSection(), D.isLittleEndian(), false, false, + SectionKind); } void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, @@ -50,16 +51,18 @@ void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, bool Lazy) { const DWARFObject &D = C.getDWARFObj(); addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), - D.getStringDWOSection(), D.getStringOffsetDWOSection(), - &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), - true, Lazy, SectionKind); + &D.getLocDWOSection(), D.getStringDWOSection(), + D.getStringOffsetDWOSection(), &D.getAddrSection(), + D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, + SectionKind); } void DWARFUnitVector::addUnitsImpl( DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, - const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, - bool LE, bool IsDWO, bool Lazy, DWARFSectionKind SectionKind) { + const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, + bool Lazy, DWARFSectionKind SectionKind) { DWARFDataExtractor Data(Obj, Section, LE, 0); // Lazy initialization of Parser, now that we have all section info. if (!Parser) { @@ -79,12 +82,12 @@ void DWARFUnitVector::addUnitsImpl( std::unique_ptr U; if (Header.isTypeUnit()) U = llvm::make_unique(Context, InfoSection, Header, DA, - RS, SS, SOS, AOS, LS, LE, IsDWO, - *this); + RS, LocSection, SS, SOS, AOS, LS, + LE, IsDWO, *this); else U = llvm::make_unique(Context, InfoSection, Header, - DA, RS, SS, SOS, AOS, LS, LE, - IsDWO, *this); + DA, RS, LocSection, SS, SOS, + AOS, LS, LE, IsDWO, *this); return U; }; } @@ -164,16 +167,25 @@ DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { } DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector) : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), - RangeSection(RS), LineSection(LS), StringSection(SS), - StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), - isDWO(IsDWO), UnitVector(UnitVector) { + RangeSection(RS), LocSection(LocSection), LineSection(LS), + StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), + isLittleEndian(LE), isDWO(IsDWO), UnitVector(UnitVector) { clear(); + // For split DWARF we only need to keep track of the location list section's + // data (no relocations), and if we are reading a package file, we need to + // adjust the location list data based on the index entries. + if (IsDWO) { + LocSectionData = LocSection->Data; + if (auto *IndexEntry = Header.getIndexEntry()) + if (const auto *C = IndexEntry->getOffset(DW_SECT_LOC)) + LocSectionData = LocSectionData.substr(C->Offset, C->Length); + } } DWARFUnit::~DWARFUnit() = default; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index e78e13bf4af2..d30600accd0f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -325,9 +325,10 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, case dwarf::DW_UT_split_type: { Unit = TypeUnitVector.addUnit(llvm::make_unique( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), - DObj.getStringSection(), DObj.getStringOffsetSection(), - &DObj.getAppleObjCSection(), DObj.getLineSection(), - DCtx.isLittleEndian(), false, TypeUnitVector)); + &DObj.getLocSection(), DObj.getStringSection(), + DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + DObj.getLineSection(), DCtx.isLittleEndian(), false, + TypeUnitVector)); break; } case dwarf::DW_UT_skeleton: @@ -338,9 +339,10 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, case 0: { Unit = CompileUnitVector.addUnit(llvm::make_unique( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), - DObj.getStringSection(), DObj.getStringOffsetSection(), - &DObj.getAppleObjCSection(), DObj.getLineSection(), - DCtx.isLittleEndian(), false, CompileUnitVector)); + &DObj.getLocSection(), DObj.getStringSection(), + DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + DObj.getLineSection(), DCtx.isLittleEndian(), false, + CompileUnitVector)); break; } default: { llvm_unreachable("Invalid UnitType."); } diff --git a/llvm/test/DebugInfo/Inputs/loclists-dwp-b.ll b/llvm/test/DebugInfo/Inputs/loclists-dwp-b.ll new file mode 100644 index 000000000000..77081bd7c283 --- /dev/null +++ b/llvm/test/DebugInfo/Inputs/loclists-dwp-b.ll @@ -0,0 +1,32 @@ +target triple = "x86_64-unknown-linux-gnu" + +define dso_local void @_Z1bi(i32 %i) local_unnamed_addr !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %i, metadata !12, metadata !DIExpression()), !dbg !13 + tail call void asm sideeffect "", "~{rdi},~{dirflag},~{fpsr},~{flags}"() , !dbg !14, !srcloc !15 + ret void, !dbg !16 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (https://git.llvm.org/git/clang.git/ 41055c6168135fe539801799e5c5636247cf0302) (https://git.llvm.org/git/llvm.git/ de0558be123ffbb5b5bd692c17dbd57a75fe684f)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "b.cpp", directory: "/home/test/PRs/PR38990") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (https://git.llvm.org/git/clang.git/ 41055c6168135fe539801799e5c5636247cf0302) (https://git.llvm.org/git/llvm.git/ de0558be123ffbb5b5bd692c17dbd57a75fe684f)"} +!7 = distinct !DISubprogram(name: "b", linkageName: "_Z1bi", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DILocation(line: 1, column: 12, scope: !7) +!14 = !DILocation(line: 1, column: 17, scope: !7) +!15 = !{i32 22} +!16 = !DILocation(line: 1, column: 38, scope: !7) diff --git a/llvm/test/DebugInfo/X86/loclists-dwp.ll b/llvm/test/DebugInfo/X86/loclists-dwp.ll new file mode 100644 index 000000000000..a5ce92270d6d --- /dev/null +++ b/llvm/test/DebugInfo/X86/loclists-dwp.ll @@ -0,0 +1,62 @@ +; RUN: llc -split-dwarf-file=%t1.dwo -filetype=obj -o %t1.o < %s +; RUN: llc -split-dwarf-file=%t2.dwo -filetype=obj -o %t2.o < %p/../Inputs/loclists-dwp-b.ll +; RUN: llvm-dwp %t1.o %t2.o -o %t.dwp +; RUN: llvm-dwarfdump -v %t.dwp | FileCheck %s + +; Make sure that 2 location lists from different units within a dwp file are +; dumped correctly. The 2 location lists differ in the length of their address +; ranges. +; +; Generate both .ll files with clang -S -emit-llvm from the following sources: +; a.cpp: +; void y(); +; void a(int i) { +; y(); +; asm("" : : : "rdi"); +; } +; +; b.cpp: +; void b(int i) { asm("" : : : "rdi"); } + +; CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000 +; CHECK-NEXT: Addr idx 0 (w/ length 6): DW_OP_reg5 RDI) + +; CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000 +; CHECK-NEXT: Addr idx 0 (w/ length 0): DW_OP_reg5 RDI) + +target triple = "x86_64-unknown-linux-gnu" + +define dso_local void @_Z1ai(i32 %i) local_unnamed_addr !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %i, metadata !12, metadata !DIExpression()), !dbg !13 + tail call void @_Z1yv(), !dbg !14 + tail call void asm sideeffect "", "~{rdi},~{dirflag},~{fpsr},~{flags}"(), !dbg !15, !srcloc !16 + ret void, !dbg !17 +} + +declare dso_local void @_Z1yv() local_unnamed_addr + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (https://git.llvm.org/git/clang.git/ 41055c6168135fe539801799e5c5636247cf0302) (https://git.llvm.org/git/llvm.git/ de0558be123ffbb5b5bd692c17dbd57a75fe684f)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "a.cpp", directory: "/home/test/PRs/PR38990") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (https://git.llvm.org/git/clang.git/ 41055c6168135fe539801799e5c5636247cf0302) (https://git.llvm.org/git/llvm.git/ de0558be123ffbb5b5bd692c17dbd57a75fe684f)"} +!7 = distinct !DISubprogram(name: "a", linkageName: "_Z1ai", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 2, type: !10) +!13 = !DILocation(line: 2, column: 12, scope: !7) +!14 = !DILocation(line: 3, column: 3, scope: !7) +!15 = !DILocation(line: 4, column: 3, scope: !7) +!16 = !{i32 41} +!17 = !DILocation(line: 5, column: 1, scope: !7)