diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -34,6 +34,9 @@ /// The second value of the location entry (if applicable). uint64_t Value1; + /// The index of the section this entry is relative to (if applicable). + uint64_t SectionIndex; + /// The location expression itself (if applicable). SmallVector Loc; }; @@ -60,8 +63,9 @@ /// updated to point past the end of the current list). bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, Optional BaseAddr, - const MCRegisterInfo *MRI, DWARFUnit *U, - DIDumpOptions DumpOpts, unsigned Indent) const; + const MCRegisterInfo *MRI, const DWARFObject &Obj, + DWARFUnit *U, DIDumpOptions DumpOpts, + unsigned Indent) const; Error visitAbsoluteLocationList( uint64_t Offset, Optional BaseAddr, @@ -72,7 +76,8 @@ DWARFDataExtractor Data; virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, - unsigned Indent) const = 0; + unsigned Indent, DIDumpOptions DumpOpts, + const DWARFObject &Obj) const = 0; }; class DWARFDebugLoc final : public DWARFLocationTable { @@ -98,7 +103,8 @@ : DWARFLocationTable(std::move(Data)) {} /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + const DWARFObject &Obj, DIDumpOptions DumpOpts, Optional Offset) const; Error visitLocationList( @@ -107,7 +113,8 @@ protected: void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, - unsigned Indent) const override; + unsigned Indent, DIDumpOptions DumpOpts, + const DWARFObject &Obj) const override; }; class DWARFDebugLoclists final : public DWARFLocationTable { @@ -121,11 +128,13 @@ /// Dump all location lists within the given range. void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, - const MCRegisterInfo *MRI, DIDumpOptions DumpOpts); + const MCRegisterInfo *MRI, const DWARFObject &Obj, + DIDumpOptions DumpOpts); protected: void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, - unsigned Indent) const override; + unsigned Indent, DIDumpOptions DumpOpts, + const DWARFObject &Obj) const override; private: uint16_t Version; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -288,6 +288,7 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDataExtractor Data, const MCRegisterInfo *MRI, + const DWARFObject &Obj, Optional DumpOffset) { uint64_t Offset = 0; @@ -306,13 +307,13 @@ if (DumpOffset) { if (DumpOffset >= Offset && DumpOffset < EndOffset) { Offset = *DumpOffset; - Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, nullptr, + Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, nullptr, DumpOpts, /*Indent=*/0); OS << "\n"; return; } } else { - Loc.dumpRange(Offset, EndOffset - Offset, OS, MRI, DumpOpts); + Loc.dumpRange(Offset, EndOffset - Offset, OS, MRI, Obj, DumpOpts); } Offset = EndOffset; } @@ -394,21 +395,21 @@ if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo(), LLDumpOpts, *Off); + getDebugLoc()->dump(OS, getRegisterInfo(), *DObj, LLDumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, DObj->getLoclistsSection().Data)) { DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), 0); - dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *Off); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); } if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, DObj->getLoclistsDWOSection().Data)) { DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), isLittleEndian(), 0); - dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *Off); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); } if (const auto *Off = @@ -420,11 +421,11 @@ if (*Off) { uint64_t Offset = **Off; Loc.dumpLocationList(&Offset, OS, - /*BaseAddr=*/None, getRegisterInfo(), nullptr, + /*BaseAddr=*/None, getRegisterInfo(), *DObj, nullptr, LLDumpOpts, /*Indent=*/0); OS << "\n"; } else { - Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), + Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), *DObj, LLDumpOpts); } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -66,23 +66,24 @@ LowPC->SectionIndex}, E.Loc}; } - case dwarf::DW_LLE_offset_pair: + case dwarf::DW_LLE_offset_pair: { if (!Base) { return createStringError( inconvertibleErrorCode(), "Unable to resolve DW_LLE_offset_pair: base address unknown"); } - return DWARFLocationExpression{DWARFAddressRange{Base->Address + E.Value0, - Base->Address + E.Value1, - Base->SectionIndex}, - E.Loc}; + DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1, + Base->SectionIndex}; + if (Range.SectionIndex == SectionedAddress::UndefSection) + Range.SectionIndex = E.SectionIndex; + return DWARFLocationExpression{Range, E.Loc}; + } case dwarf::DW_LLE_base_address: - Base = SectionedAddress{E.Value0, SectionedAddress::UndefSection}; + Base = SectionedAddress{E.Value0, E.SectionIndex}; return None; case dwarf::DW_LLE_start_length: return DWARFLocationExpression{ - DWARFAddressRange{E.Value0, E.Value0 + E.Value1, - SectionedAddress::UndefSection}, + DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex}, E.Loc}; default: llvm_unreachable("unreachable locations list kind"); @@ -104,7 +105,8 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, Optional BaseAddr, const MCRegisterInfo *MRI, - DWARFUnit *U, DIDumpOptions DumpOpts, + const DWARFObject &Obj, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const { DWARFLocationInterpreter Interp( BaseAddr, [U](uint32_t Index) -> Optional { @@ -116,7 +118,7 @@ Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) { Expected> Loc = Interp.Interpret(E); if (!Loc || DumpOpts.DisplayRawContents) - dumpRawEntry(E, OS, Indent); + dumpRawEntry(E, OS, Indent, DumpOpts, Obj); if (Loc && *Loc) { OS << "\n"; OS.indent(Indent); @@ -125,10 +127,7 @@ DIDumpOptions RangeDumpOpts(DumpOpts); RangeDumpOpts.DisplayRawContents = false; - const DWARFObject *Obj = nullptr; - if (U) - Obj = &U->getContext().getDWARFObj(); - Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, Obj); + Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj); } if (!Loc) consumeError(Loc.takeError()); @@ -167,12 +166,12 @@ } void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, - DIDumpOptions DumpOpts, + const DWARFObject &Obj, DIDumpOptions DumpOpts, Optional DumpOffset) const { auto BaseAddr = None; unsigned Indent = 12; if (DumpOffset) { - dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, nullptr, DumpOpts, + dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, Obj, nullptr, DumpOpts, Indent); } else { uint64_t Offset = 0; @@ -182,7 +181,7 @@ OS << Separator; Separator = "\n"; - CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, nullptr, + CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, Obj, nullptr, DumpOpts, Indent); OS << '\n'; } @@ -194,8 +193,9 @@ function_ref Callback) const { DataExtractor::Cursor C(*Offset); while (true) { + uint64_t SectionIndex; uint64_t Value0 = Data.getRelocatedAddress(C); - uint64_t Value1 = Data.getRelocatedAddress(C); + uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex); DWARFLocationEntry E; @@ -208,10 +208,12 @@ } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) { E.Kind = dwarf::DW_LLE_base_address; E.Value0 = Value1; + E.SectionIndex = SectionIndex; } else { E.Kind = dwarf::DW_LLE_offset_pair; E.Value0 = Value0; E.Value1 = Value1; + E.SectionIndex = SectionIndex; unsigned Bytes = Data.getU16(C); // A single location description describing the location of the object... Data.getU8(C, E.Loc, Bytes); @@ -227,7 +229,9 @@ } void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, - raw_ostream &OS, unsigned Indent) const { + raw_ostream &OS, unsigned Indent, + DIDumpOptions DumpOpts, + const DWARFObject &Obj) const { uint64_t Value0, Value1; switch (Entry.Kind) { case dwarf::DW_LLE_base_address: @@ -248,6 +252,7 @@ OS.indent(Indent); OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", " << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')'; + DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); } Error DWARFDebugLoclists::visitLocationList( @@ -276,12 +281,13 @@ case dwarf::DW_LLE_offset_pair: E.Value0 = Data.getULEB128(C); E.Value1 = Data.getULEB128(C); + E.SectionIndex = SectionedAddress::UndefSection; break; case dwarf::DW_LLE_base_address: - E.Value0 = Data.getRelocatedAddress(C); + E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); break; case dwarf::DW_LLE_start_length: - E.Value0 = Data.getRelocatedAddress(C); + E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_startx_endx: @@ -310,7 +316,9 @@ } void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry, - raw_ostream &OS, unsigned Indent) const { + raw_ostream &OS, unsigned Indent, + DIDumpOptions DumpOpts, + const DWARFObject &Obj) const { size_t MaxEncodingStringLength = 0; #define HANDLE_DW_LLE(ID, NAME) \ MaxEncodingStringLength = std::max(MaxEncodingStringLength, \ @@ -339,10 +347,19 @@ break; } OS << ')'; + switch (Entry.Kind) { + case dwarf::DW_LLE_start_length: + case dwarf::DW_LLE_base_address: + DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); + break; + default: + break; + } } void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, const MCRegisterInfo *MRI, + const DWARFObject &Obj, DIDumpOptions DumpOpts) { if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) { OS << "Invalid dump range\n"; @@ -355,8 +372,8 @@ OS << Separator; Separator = "\n"; - CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, nullptr, - DumpOpts, /*Indent=*/12); + CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, + nullptr, DumpOpts, /*Indent=*/12); OS << '\n'; } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -96,7 +96,8 @@ return; } U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), - MRI, U, DumpOpts, Indent); + MRI, Ctx.getDWARFObj(), U, DumpOpts, + Indent); return; } diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-simple.test b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-simple.test --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-simple.test +++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-simple.test @@ -4,19 +4,19 @@ CHECK: .debug_info CHECK: DW_AT_name{{.*}}"f" CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]] -CHECK-NEXT: [0x00000000, 0x00000023): DW_OP_reg1 ECX -CHECK-NEXT: [0x00000023, 0x0000005d): DW_OP_breg5 EBP-16) +CHECK-NEXT: [0x00000000, 0x00000023) ".text": DW_OP_reg1 ECX +CHECK-NEXT: [0x00000023, 0x0000005d) ".text": DW_OP_breg5 EBP-16) CHECK: DW_AT_name{{.*}}"g" CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]] -CHECK-NEXT: [0x00000000, 0x00000020): DW_OP_reg0 EAX -CHECK-NEXT: [0x00000020, 0x0000005d): DW_OP_breg5 EBP-12) +CHECK-NEXT: [0x00000000, 0x00000020) ".text": DW_OP_reg0 EAX +CHECK-NEXT: [0x00000020, 0x0000005d) ".text": DW_OP_breg5 EBP-12) CHECK: .debug_loc contents: CHECK-NEXT: [[F_LOC]]: this is actually the wrong location due to PR14763, but that doesn't matter for the purposes of testing dwarfdump -CHECK-NEXT: (0x00000000, 0x00000023): DW_OP_reg1 ECX -CHECK-NEXT: (0x00000023, 0x0000005d): DW_OP_breg5 EBP-16 +CHECK-NEXT: (0x00000000, 0x00000023) ".text": DW_OP_reg1 ECX +CHECK-NEXT: (0x00000023, 0x0000005d) ".text": DW_OP_breg5 EBP-16 CHECK: [[G_LOC]]: -CHECK-NEXT: (0x00000000, 0x00000020): DW_OP_reg0 EAX -CHECK-NEXT: (0x00000020, 0x0000005d): DW_OP_breg5 EBP-12 +CHECK-NEXT: (0x00000000, 0x00000020) ".text": DW_OP_reg0 EAX +CHECK-NEXT: (0x00000020, 0x0000005d) ".text": DW_OP_breg5 EBP-12 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s @@ -1,13 +1,44 @@ # RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t -# RUN: llvm-dwarfdump %t | FileCheck %s +# RUN: llvm-dwarfdump -debug-info -debug-loclists %t \ +# RUN: | FileCheck %s --check-prefix=REGULAR --check-prefix=BOTH +# RUN: llvm-dwarfdump -debug-info -debug-loclists --verbose %t \ +# RUN: | FileCheck %s --check-prefix=VERBOSE --check-prefix=BOTH -# CHECK: DW_AT_location (0x0000000c -# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX -# CHECK-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX -# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX -# CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX -# CHECK-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg4 RSI) +# BOTH: DW_AT_location {{.*}}(0x0000000c + +# REGULAR-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX +# VERBOSE-NEXT: [0x0000000000000000, 0x0000000000000001) ".text": DW_OP_reg0 RAX + +# REGULAR-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX +# VERBOSE-NEXT: [0x0000000000000001, 0x0000000000000002) ".text": DW_OP_reg1 RDX + +# REGULAR-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX +# VERBOSE-NEXT: [0x0000000000000002, 0x0000000000000003) ".text": DW_OP_reg2 RCX + +# REGULAR-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX +# VERBOSE-NEXT: [0x0000000000000003, 0x0000000000000004) ".text": DW_OP_reg3 RBX + +# BOTH-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg4 RSI) + +# BOTH: locations list header: length = 0x00000034, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +# BOTH-NEXT: 0x0000000c: +# BOTH-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX +# BOTH-NEXT: DW_LLE_offset_pair (0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX + +# REGULAR-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX +# VERBOSE-NEXT: DW_LLE_start_length (0x0000000000000002, 0x0000000000000001) ".text" +# VERBOSE-NEXT: => [0x0000000000000002, 0x0000000000000003) ".text": DW_OP_reg2 RCX + +# VERBOSE-NEXT: DW_LLE_base_address (0x0000000000000003) ".text" + +# REGULAR-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX +# VERBOSE-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000001) +# VERBOSE-NEXT: => [0x0000000000000003, 0x0000000000000004) ".text": DW_OP_reg3 RBX + +# BOTH-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg4 RSI + +# VERBOSE-NEXT: DW_LLE_end_of_list () .text