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 @@ -50,9 +50,9 @@ /// false to terminate the iteration early. Returns an error if it was unable /// to parse the entire location list correctly. Upon successful termination /// \p Offset will be updated point past the end of the list. - virtual Error - visitLocationList(uint64_t *Offset, - function_ref F) const = 0; + virtual Error visitLocationList( + uint64_t *Offset, + function_ref Callback) const = 0; /// Dump the location list at the given \p Offset. The function returns true /// iff it has successfully reched the end of the list. This means that one @@ -70,30 +70,15 @@ unsigned Indent) const = 0; }; -class DWARFDebugLoc { +class DWARFDebugLoc final : public DWARFLocationTable { public: - /// 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. uint64_t Offset; /// All the locations in which the variable is stored. - SmallVector Entries; - /// Dump this list on OS. - void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian, - unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, - DIDumpOptions DumpOpts, - unsigned Indent) const; + SmallVector Entries; }; private: @@ -103,24 +88,29 @@ /// the locations in which the variable is stored. LocationLists Locations; - unsigned AddressSize; - - bool IsLittleEndian; - public: + DWARFDebugLoc(DWARFDataExtractor Data) + : DWARFLocationTable(std::move(Data)) {} + /// Print the location lists found within the debug_loc section. void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional Offset) const; - /// Parse the debug_loc section accessible via the 'data' parameter using the - /// address size also given in 'data' to interpret the address ranges. - void parse(const DWARFDataExtractor &data); + /// Parse the debug_loc section. + void parse(); /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - Expected - parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset); + Error visitLocationList( + uint64_t *Offset, + function_ref Callback) const override; + + Expected parseOneLocationList(uint64_t *Offset); + +protected: + void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, + unsigned Indent) const override; }; class DWARFDebugLoclists final : public DWARFLocationTable { @@ -130,7 +120,7 @@ Error visitLocationList( uint64_t *Offset, - function_ref F) const override; + function_ref Callback) const override; /// Dump all location lists within the given range. void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -201,11 +201,7 @@ const DWARFSection *RangeSection; uint64_t RangeSectionBase; - /// Section containing the location lists of this unit used for non-split - /// DWARF<=v4 units. - const DWARFSection *LocSection; - - /// Location table of this unit. Used for DWARF v5 and DWO units. + /// Location table of this unit. std::unique_ptr LocTable; const DWARFSection &LineSection; @@ -277,7 +273,6 @@ bool isDWOUnit() const { return IsDWO; } DWARFContext& getContext() const { return Context; } const DWARFSection &getInfoSection() const { return InfoSection; } - const DWARFSection *getLocSection() const { return LocSection; } uint64_t getOffset() const { return Header.getOffset(); } const dwarf::FormParams &getFormParams() const { return Header.getFormParams(); @@ -321,7 +316,7 @@ return DataExtractor(StringSection, false, 0); } - const DWARFLocationTable *getLocationTable() { return LocTable.get(); } + const DWARFLocationTable &getLocationTable() { return *LocTable; } /// Extract the range list referenced by this compile unit from the /// .debug_ranges section. If the extraction is unsuccessful, an error 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 @@ -734,13 +734,14 @@ if (Loc) return Loc.get(); - Loc.reset(new DWARFDebugLoc); // Assume all units have the same address byte size. - if (getNumCompileUnits()) { - DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), - getUnitAtIndex(0)->getAddressByteSize()); - Loc->parse(LocData); - } + auto LocData = + getNumCompileUnits() + ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(), + getUnitAtIndex(0)->getAddressByteSize()) + : DWARFDataExtractor("", isLittleEndian(), 0); + Loc.reset(new DWARFDebugLoc(std::move(LocData))); + Loc->parse(); return Loc.get(); } 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 @@ -145,25 +145,6 @@ return true; } -void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress, - bool IsLittleEndian, - unsigned AddressSize, - const MCRegisterInfo *MRI, DWARFUnit *U, - DIDumpOptions DumpOpts, - unsigned Indent) const { - for (const Entry &E : Entries) { - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, - BaseAddress + E.Begin); - OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, - BaseAddress + E.End); - OS << ": "; - - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); - } -} - DWARFDebugLoc::LocationList const * DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { auto It = partition_point( @@ -173,74 +154,84 @@ return nullptr; } -void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, - Optional Offset) const { - auto DumpLocationList = [&](const LocationList &L) { - OS << format("0x%8.8" PRIx64 ": ", L.Offset); - L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, 12); - OS << "\n"; - }; - - if (Offset) { - if (auto *L = getLocationListAtOffset(*Offset)) - DumpLocationList(*L); - return; - } - - for (const LocationList &L : Locations) { - DumpLocationList(L); - if (&L != &Locations.back()) +void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + DIDumpOptions DumpOpts, + Optional DumpOffset) const { + auto BaseAddr = None; + unsigned Indent = 12; + if (DumpOffset) { + dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, nullptr, DumpOpts, + Indent); + } else { + uint64_t Offset = 0; + StringRef Separator; + bool CanContinue = true; + while (CanContinue && Data.isValidOffset(Offset)) { + OS << Separator; + Separator = "\n"; + + CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, nullptr, + DumpOpts, Indent); OS << '\n'; + } } } -Expected -DWARFDebugLoc::parseOneLocationList(const DWARFDataExtractor &Data, - uint64_t *Offset) { - LocationList LL; - LL.Offset = *Offset; - AddressSize = Data.getAddressSize(); +Error DWARFDebugLoc::visitLocationList( + uint64_t *Offset, + function_ref Callback) const { DataExtractor::Cursor C(*Offset); - - // 2.6.2 Location Lists - // A location list entry consists of: while (true) { - Entry E; - - // 1. A beginning address offset. ... - E.Begin = Data.getRelocatedAddress(C); - - // 2. An ending address offset. ... - E.End = Data.getRelocatedAddress(C); + uint64_t Value0 = Data.getRelocatedAddress(C); + uint64_t Value1 = Data.getRelocatedAddress(C); - if (Error Err = C.takeError()) - return std::move(Err); + DWARFLocationEntry E; // 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) { - *Offset = C.tell(); - return LL; - } - - if (E.Begin != (AddressSize == 4 ? -1U : -1ULL)) { + // ending address offset. A beginning offset of 0xff...f marks the base + // address selection entry. + if (Value0 == 0 && Value1 == 0) { + E.Kind = dwarf::DW_LLE_end_of_list; + } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) { + E.Kind = dwarf::DW_LLE_base_address; + E.Value0 = Value1; + } else { + E.Kind = dwarf::DW_LLE_offset_pair; + E.Value0 = Value0; + E.Value1 = Value1; unsigned Bytes = Data.getU16(C); // A single location description describing the location of the object... Data.getU8(C, E.Loc, Bytes); } - LL.Entries.push_back(std::move(E)); + if (!C) + return C.takeError(); + if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list) + break; } + *Offset = C.tell(); + return Error::success(); } -void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { - IsLittleEndian = data.isLittleEndian(); - AddressSize = data.getAddressSize(); +Expected +DWARFDebugLoc::parseOneLocationList(uint64_t *Offset) { + LocationList LL; + LL.Offset = *Offset; + + Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) { + LL.Entries.push_back(E); + return true; + }); + if (E) + return std::move(E); + return std::move(LL); +} +void DWARFDebugLoc::parse() { uint64_t Offset = 0; - while (Offset < data.getData().size()) { - if (auto LL = parseOneLocationList(data, &Offset)) + while (Offset < Data.getData().size()) { + if (auto LL = parseOneLocationList(&Offset)) Locations.push_back(std::move(*LL)); else { logAllUnhandledErrors(LL.takeError(), WithColor::error()); @@ -249,6 +240,30 @@ } } +void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, + raw_ostream &OS, unsigned Indent) const { + uint64_t Value0, Value1; + switch (Entry.Kind) { + case dwarf::DW_LLE_base_address: + Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL; + Value1 = Entry.Value0; + break; + case dwarf::DW_LLE_offset_pair: + Value0 = Entry.Value0; + Value1 = Entry.Value1; + break; + case dwarf::DW_LLE_end_of_list: + Value0 = Value1 = 0; + return; + default: + llvm_unreachable("Not possible in DWARF4!"); + } + OS << '\n'; + OS.indent(Indent); + OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", " + << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')'; +} + Error DWARFDebugLoclists::visitLocationList( uint64_t *Offset, function_ref F) const { 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 @@ -79,7 +79,6 @@ DWARFUnit *U, unsigned Indent, DIDumpOptions DumpOpts) { DWARFContext &Ctx = U->getContext(); - const DWARFObject &Obj = Ctx.getDWARFObj(); const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); if (FormValue.isFormClass(DWARFFormValue::FC_Block) || FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { @@ -97,32 +96,8 @@ uint64_t Offset = *FormValue.getAsSectionOffset(); - if (const DWARFLocationTable *LT = U->getLocationTable()) { - LT->dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI, U, LLDumpOpts, - Indent); - return; - } - - DWARFDebugLoc DebugLoc; - DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), - Obj.getAddressSize()); - - FormValue.dump(OS, DumpOpts); - OS << ": "; - - if (Expected LL = - DebugLoc.parseOneLocationList(Data, &Offset)) { - uint64_t BaseAddr = 0; - if (Optional BA = U->getBaseAddress()) - BaseAddr = BA->Address; - LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, - LLDumpOpts, Indent); - } else { - OS << '\n'; - OS.indent(Indent); - OS << formatv("error extracting location list: {0}", - fmt_consume(LL.takeError())); - } + U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), + MRI, U, LLDumpOpts, Indent); return; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -175,9 +175,9 @@ const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector) : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), - RangeSection(RS), LocSection(LocSection), LineSection(LS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { + RangeSection(RS), LineSection(LS), StringSection(SS), + StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), + IsDWO(IsDWO), UnitVector(UnitVector) { clear(); if (IsDWO) { // If we are reading a package file, we need to adjust the location list @@ -195,6 +195,10 @@ Context.getDWARFObj().getLoclistsSection(), isLittleEndian, getAddressByteSize()), Header.getVersion()); + } else { + LocTable = std::make_unique( + DWARFDataExtractor(Context.getDWARFObj(), *LocSection, isLittleEndian, + getAddressByteSize())); } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -1302,7 +1302,7 @@ if (const DWARFDebugLoc *DebugLoc = DCtx.getDebugLoc()) { if (const DWARFDebugLoc::LocationList *LocList = DebugLoc->getLocationListAtOffset(*Offset)) { - if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) { + if (any_of(LocList->Entries, [&](const DWARFLocationEntry &E) { return ContainsInterestingOperators(E.Loc); })) return true; diff --git a/llvm/test/CodeGen/ARM/debug-info-sreg2.ll b/llvm/test/CodeGen/ARM/debug-info-sreg2.ll --- a/llvm/test/CodeGen/ARM/debug-info-sreg2.ll +++ b/llvm/test/CodeGen/ARM/debug-info-sreg2.ll @@ -7,7 +7,7 @@ ; of the size of the location description. ; CHECK: 0x00000000: -; CHECK-NEXT: [0x{{[0-9]*[a-f]*}}, 0x{{[0-9]*[a-f]*}}): DW_OP_regx D8 +; CHECK-NEXT: (0x{{[0-9]*[a-f]*}}, 0x{{[0-9]*[a-f]*}}): DW_OP_regx D8 define void @_Z3foov() optsize ssp !dbg !1 { entry: diff --git a/llvm/test/DebugInfo/Sparc/subreg.ll b/llvm/test/DebugInfo/Sparc/subreg.ll --- a/llvm/test/DebugInfo/Sparc/subreg.ll +++ b/llvm/test/DebugInfo/Sparc/subreg.ll @@ -1,6 +1,6 @@ ; RUN: llc -filetype=obj -O0 < %s -mtriple sparc64-unknown-linux-gnu | llvm-dwarfdump - --debug-loc | FileCheck %s ; The undescribable 128-bit register should be split into two 64-bit registers. -; CHECK: [{{.*}}, {{.*}}): DW_OP_regx D0, DW_OP_piece 0x8, DW_OP_regx D1, DW_OP_piece 0x8 +; CHECK: ({{.*}}, {{.*}}): DW_OP_regx D0, DW_OP_piece 0x8, DW_OP_regx D1, DW_OP_piece 0x8 target datalayout = "E-m:e-i64:64-n32:64-S128" target triple = "sparc64" diff --git a/llvm/test/DebugInfo/X86/PR26148.ll b/llvm/test/DebugInfo/X86/PR26148.ll --- a/llvm/test/DebugInfo/X86/PR26148.ll +++ b/llvm/test/DebugInfo/X86/PR26148.ll @@ -19,7 +19,7 @@ ; AS in 26163, we only expect one range as the first one is zero sized. ; ; -; CHECK: [0x0000000000000000, 0x000000000000000f): DW_OP_lit3, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_piece 0x4 +; CHECK: (0x0000000000000000, 0x000000000000000f): DW_OP_lit3, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_piece 0x4 source_filename = "test/DebugInfo/X86/PR26148.ll" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/DebugInfo/X86/debug-loc-offset.mir b/llvm/test/DebugInfo/X86/debug-loc-offset.mir --- a/llvm/test/DebugInfo/X86/debug-loc-offset.mir +++ b/llvm/test/DebugInfo/X86/debug-loc-offset.mir @@ -67,11 +67,11 @@ # # CHECK: .debug_loc contents: # CHECK: 0x00000000: -# CHECK-NEXT: [0x00000000, 0x0000000a): DW_OP_consts +0, DW_OP_stack_value -# CHECK-NEXT: [0x0000000a, 0x00000017): DW_OP_consts +1, DW_OP_stack_value +# CHECK-NEXT: (0x00000000, 0x0000000a): DW_OP_consts +0, DW_OP_stack_value +# CHECK-NEXT: (0x0000000a, 0x00000017): DW_OP_consts +1, DW_OP_stack_value # CHECK: 0x00000022: -# CHECK-NEXT: [0x00000009, 0x00000017): DW_OP_breg0 EAX+0, DW_OP_deref -# CHECK-NEXT: [0x00000017, 0x00000043): DW_OP_breg5 EBP-8, DW_OP_deref, DW_OP_deref +# CHECK-NEXT: (0x00000009, 0x00000017): DW_OP_breg0 EAX+0, DW_OP_deref +# CHECK-NEXT: (0x00000017, 0x00000043): DW_OP_breg5 EBP-8, DW_OP_deref, DW_OP_deref --- | target triple = "i386-unknown-linux-gnu" diff --git a/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll b/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll --- a/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll +++ b/llvm/test/DebugInfo/X86/dw_op_minus_direct.ll @@ -17,7 +17,7 @@ ; CHECK: .debug_loc contents: ; CHECK: 0x00000000: -; CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_lit1, DW_OP_minus, DW_OP_stack_value +; CHECK-NEXT: (0x0000000000000003, 0x0000000000000004): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_lit1, DW_OP_minus, DW_OP_stack_value ; rax+0, constu 0xffffffff, and, constu 0x00000001, minus, stack-value source_filename = "minus.c" diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases.s --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases.s @@ -21,7 +21,7 @@ # CHECK: error: unexpected end of data -# UNKNOWN-REG: [0x0000000000000000, 0x0000000000000001): DW_OP_regx 0xdeadbeef +# UNKNOWN-REG: (0x0000000000000000, 0x0000000000000001): DW_OP_regx 0xdeadbeef .section .debug_loc,"",@progbits .ifdef CASE1 diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s @@ -8,11 +8,11 @@ # CHECK: DW_AT_name ("x1") # CHECK-NEXT: DW_AT_location (0xdeadbeef -# CHECK-NEXT: error extracting location list: unexpected end of data) +# CHECK-NEXT: error: unexpected end of data) # CHECK: DW_AT_name ("x2") # CHECK-NEXT: DW_AT_location (0x00000036 -# CHECK-NEXT: error extracting location list: unexpected end of data) +# CHECK-NEXT: error: unexpected end of data) .type f,@function @@ -64,6 +64,10 @@ .byte 14 # DW_FORM_strp .byte 19 # DW_AT_language .byte 5 # DW_FORM_data2 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 .byte 0 # EOM(1) .byte 0 # EOM(2) .byte 2 # Abbreviation Code @@ -105,6 +109,8 @@ .byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit .long .Linfo_string0 # DW_AT_producer .short 12 # DW_AT_language + .quad 0 # DW_AT_low_pc + .long 0x100 # DW_AT_high_pc .byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram .long .Linfo_string3 # DW_AT_name .byte 3 # Abbrev [3] DW_TAG_formal_parameter 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 @@ -15,8 +15,8 @@ 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): DW_OP_reg1 ECX +CHECK-NEXT: (0x00000023, 0x0000005d): 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): DW_OP_reg0 EAX +CHECK-NEXT: (0x00000020, 0x0000005d): DW_OP_breg5 EBP-12 diff --git a/llvm/test/DebugInfo/X86/live-debug-variables.ll b/llvm/test/DebugInfo/X86/live-debug-variables.ll --- a/llvm/test/DebugInfo/X86/live-debug-variables.ll +++ b/llvm/test/DebugInfo/X86/live-debug-variables.ll @@ -25,7 +25,7 @@ ; CHECK: .debug_loc contents: ; CHECK-NEXT: 0x00000000: ; We currently emit an entry for the function prologue, too, which could be optimized away. -; CHECK: [0x0000000000000010, 0x0000000000000072): DW_OP_reg3 RBX +; CHECK: (0x0000000000000010, 0x0000000000000072): DW_OP_reg3 RBX ; We should only have one entry inside the function. ; CHECK-NOT: : diff --git a/llvm/test/DebugInfo/X86/pieces-1.ll b/llvm/test/DebugInfo/X86/pieces-1.ll --- a/llvm/test/DebugInfo/X86/pieces-1.ll +++ b/llvm/test/DebugInfo/X86/pieces-1.ll @@ -16,7 +16,7 @@ ; CHECK: .debug_loc contents: ; -; CHECK: [0x0000000000000000, 0x[[LTMP3:.*]]): DW_OP_reg5 RDI, DW_OP_piece 0x8, DW_OP_reg4 RSI, DW_OP_piece 0x4 +; CHECK: (0x0000000000000000, 0x[[LTMP3:.*]]): DW_OP_reg5 RDI, DW_OP_piece 0x8, DW_OP_reg4 RSI, DW_OP_piece 0x4 ; 0x0000000000000006 - 0x0000000000000008: rbp-8, piece 0x8, rax, piece 0x4 ) target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/DebugInfo/X86/sret.ll b/llvm/test/DebugInfo/X86/sret.ll --- a/llvm/test/DebugInfo/X86/sret.ll +++ b/llvm/test/DebugInfo/X86/sret.ll @@ -11,7 +11,6 @@ ; CHECK: _ZN1B9AInstanceEv ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000 -; CHECK-NEXT: [0xffffffffffffffff, {{.*}}): {{$}} ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg5 RDI+0 ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_breg6 RBP-24, DW_OP_deref) ; CHECK-NEXT: DW_AT_name {{.*}}"a" diff --git a/llvm/test/DebugInfo/X86/stack-value-piece.ll b/llvm/test/DebugInfo/X86/stack-value-piece.ll --- a/llvm/test/DebugInfo/X86/stack-value-piece.ll +++ b/llvm/test/DebugInfo/X86/stack-value-piece.ll @@ -1,4 +1,4 @@ -; RUN: llc %s -filetype=obj -o - | llvm-dwarfdump -v - | FileCheck %s +; RUN: llc %s -filetype=obj -o - | llvm-dwarfdump -debug-info -debug-loc - | FileCheck %s ; Test that DW_OP_piece is emitted for constants. ; ; // Generated from: @@ -16,25 +16,25 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_subprogram -; CHECK: DW_AT_name {{.*}} "i" +; CHECK: DW_AT_name ("i") ; CHECK: DW_TAG_variable -; CHECK-NEXT: DW_AT_location {{.*}} ([[I:0x[0-9a-f]+]] +; CHECK-NEXT: DW_AT_location ([[I:0x[0-9a-f]+]] ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4) -; CHECK-NEXT: DW_AT_name {{.*}} "r" +; CHECK-NEXT: DW_AT_name ("r") ; ; CHECK: DW_TAG_subprogram -; CHECK: DW_AT_name {{.*}} "f" +; CHECK: DW_AT_name ("f") ; CHECK: DW_TAG_variable -; CHECK-NEXT: DW_AT_location {{.*}} ([[F:0x[0-9a-f]+]] +; CHECK-NEXT: DW_AT_location ([[F:0x[0-9a-f]+]] ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4 ; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4) -; CHECK-NEXT: DW_AT_name {{.*}} "r" +; CHECK-NEXT: DW_AT_name ("r") ; ; CHECK: .debug_loc contents: ; CHECK: [[I]]: -; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4 +; CHECK-NEXT: ({{.*}}, {{.*}}): DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4 ; CHECK: [[F]]: -; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4 +; CHECK-NEXT: ({{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4 source_filename = "stack-value-piece.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test --- a/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test @@ -122,11 +122,11 @@ CHECK: .debug_loc contents: CHECK-NEXT: 0x00000000: -CHECK-NEXT: [0x0000000000000000, 0x000000000000000c): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000000, 0x000000000000000c): DW_OP_reg5 RDI, DW_OP_piece 0x4 CHECK-NOT: : CHECK: 0x00000025: -CHECK-NEXT: [0x0000000000000000, 0x000000000000000f): DW_OP_reg5 RDI, DW_OP_piece 0x4 -CHECK-NEXT: [0x0000000000000019, 0x000000000000001d): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000000, 0x000000000000000f): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000019, 0x000000000000001d): DW_OP_reg5 RDI, DW_OP_piece 0x4 CHECK: .debug_aranges contents: diff --git a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test --- a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test @@ -134,11 +134,11 @@ CHECK: .debug_loc contents: CHECK-NEXT: 0x00000000: -CHECK-NEXT: [0x0000000000000000, 0x000000000000000e): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000000, 0x000000000000000e): DW_OP_reg5 RDI, DW_OP_piece 0x4 CHECK-NOT: : CHECK: 0x00000025: -CHECK-NEXT: [0x0000000000000000, 0x000000000000000f): DW_OP_reg5 RDI, DW_OP_piece 0x4 -CHECK-NEXT: [0x0000000000000019, 0x000000000000001d): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000000, 0x000000000000000f): DW_OP_reg5 RDI, DW_OP_piece 0x4 +CHECK-NEXT: (0x0000000000000019, 0x000000000000001d): DW_OP_reg5 RDI, DW_OP_piece 0x4 CHECK: .debug_aranges contents: CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 diff --git a/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test b/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test --- a/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test +++ b/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test @@ -18,12 +18,9 @@ } CHECK: .debug_loc contents: -CHECK: [0xffffffffffffffff, 0x0000000100000f90): -CHECK: [0x0000000000000004, 0x0000000000000007): DW_OP_consts +3, DW_OP_stack_value -CHECK: [0x0000000000000007, 0x0000000000000009): DW_OP_consts +4, DW_OP_stack_value +CHECK: [0x0000000100000f94, 0x0000000100000f97): DW_OP_consts +3, DW_OP_stack_value +CHECK: [0x0000000100000f97, 0x0000000100000f99): DW_OP_consts +4, DW_OP_stack_value -CHECK: [0xffffffffffffffff, 0x0000000100000f90): -CHECK: [0x0000000000000004, 0x0000000000000007): DW_OP_consts +5, DW_OP_stack_value +CHECK: [0x0000000100000f94, 0x0000000100000f97): DW_OP_consts +5, DW_OP_stack_value -CHECK: [0xffffffffffffffff, 0x0000000100000f90): -CHECK: [0x0000000000000007, 0x0000000000000009): DW_OP_reg0 RAX +CHECK: [0x0000000100000f97, 0x0000000100000f99): DW_OP_reg0 RAX diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc-OP_addr.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc-OP_addr.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc-OP_addr.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc-OP_addr.s @@ -3,7 +3,7 @@ # CHECK: DW_TAG_variable # CHECK-NEXT: DW_AT_name ("a") # CHECK-NEXT: DW_AT_location -# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_addr 0xdeadbeefbaadf00d +# CHECK-NEXT: (0x0000000000000000, 0x0000000000000001): DW_OP_addr 0xdeadbeefbaadf00d .section .debug_str,"MS",@progbits,1 .Linfo_producer: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_base_address.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_base_address.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_base_address.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_base_address.s @@ -1,10 +1,11 @@ # RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o -# RUN: llvm-dwarfdump --debug-loc %t.o | FileCheck %s +# RUN: llvm-dwarfdump --debug-loc -v %t.o | FileCheck %s # CHECK: .debug_loc contents: # CHECK-NEXT: 0x00000000: -# CHECK-NEXT: [0xffffffffffffffff, 0x000000000000002a): -# CHECK-NEXT: [0x0000000000000003, 0x0000000000000007): DW_OP_consts +3, DW_OP_stack_value +# CHECK-NEXT: (0xffffffffffffffff, 0x000000000000002a) +# CHECK-NEXT: (0x0000000000000003, 0x0000000000000007) +# CHECK-NEXT: => [0x000000000000002d, 0x0000000000000031): DW_OP_consts +3, DW_OP_stack_value .section .debug_loc,"",@progbits .quad 0xffffffffffffffff diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test @@ -4,8 +4,8 @@ # CHECK-A: .debug_loc contents: # CHECK-A: 0x00000000: -# CHECK-A-NEXT: [0x0000000000000000, 0x0000000000000003): DW_OP_reg5 RDI -# CHECK-A-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX +# CHECK-A-NEXT: (0x0000000000000000, 0x0000000000000003): DW_OP_reg5 RDI +# CHECK-A-NEXT: (0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX RUN: llvm-mc %S/debugloc.s -filetype obj -triple x86_64-linux-elf -o - \ RUN: | llvm-dwarfdump --debug-loc=0x36 - \ @@ -13,5 +13,5 @@ # CHECK-B: .debug_loc contents: # CHECK-B: 0x00000036: -# CHECK-B-NEXT: [0x0000000000000010, 0x0000000000000013): DW_OP_reg5 RDI -# CHECK-B-NEXT: [0x0000000000000013, 0x0000000000000014): DW_OP_reg0 RAX +# CHECK-B-NEXT: (0x0000000000000010, 0x0000000000000013): DW_OP_reg5 RDI +# CHECK-B-NEXT: (0x0000000000000013, 0x0000000000000014): DW_OP_reg0 RAX diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debugloc.s b/llvm/test/tools/llvm-dwarfdump/X86/debugloc.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debugloc.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debugloc.s @@ -9,12 +9,12 @@ # CHECK: .debug_loc contents: # CHECK: 0x00000000: -# CHECK-NEXT: [0x0000000000000000, 0x0000000000000003): DW_OP_reg5 RDI -# CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX +# CHECK-NEXT: (0x0000000000000000, 0x0000000000000003): DW_OP_reg5 RDI +# CHECK-NEXT: (0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX # CHECK: 0x00000036: -# CHECK-NEXT: [0x0000000000000010, 0x0000000000000013): DW_OP_reg5 RDI -# CHECK-NEXT: [0x0000000000000013, 0x0000000000000014): DW_OP_reg0 RAX +# CHECK-NEXT: (0x0000000000000010, 0x0000000000000013): DW_OP_reg5 RDI +# CHECK-NEXT: (0x0000000000000013, 0x0000000000000014): DW_OP_reg0 RAX # VERIFY: Verifying .debug_info Unit Header Chain # VERIFY-NOT: DIE has invalid DW_AT_location encoding diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp --- a/llvm/tools/llvm-dwarfdump/Statistics.cpp +++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -249,15 +249,22 @@ // Get PC coverage. if (auto DebugLocOffset = FormValue->getAsSectionOffset()) { auto *DebugLoc = Die.getDwarfUnit()->getContext().getDebugLoc(); + // TODO: This code does not handle DWARF5 nor DWARF4 base address + // selection entries. This should use a higher-level API which abstracts + // these away. if (auto List = DebugLoc->getLocationListAtOffset(*DebugLocOffset)) { - for (auto Entry : List->Entries) { - uint64_t BytesEntryCovered = Entry.End - Entry.Begin; + ArrayRef Entries = List->Entries; + // Ignore end-of-list entries + Entries = Entries.drop_back(); + + for (auto Entry : Entries) { + uint64_t BytesEntryCovered = Entry.Value1 - Entry.Value0; BytesCovered += BytesEntryCovered; if (IsEntryValue(Entry.Loc)) BytesEntryValuesCovered += BytesEntryCovered; } - if (List->Entries.size()) { - uint64_t FirstDef = List->Entries[0].Begin; + if (Entries.size()) { + uint64_t FirstDef = Entries[0].Value0; uint64_t UnitOfs = UnitLowPC; // Ranges sometimes start before the lexical scope. if (UnitOfs + FirstDef >= ScopeLowPC)