#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cstdint>
class MCRegisterInfo;
class raw_ostream;
+/// A single location within a location list. Entries are stored in the DWARF5
+/// form even if they originally come from a DWARF<=4 location list.
+struct DWARFLocationEntry {
+ /// The entry kind (DW_LLE_***).
+ uint8_t Kind;
+
+ /// The first value of the location entry (if applicable).
+ uint64_t Value0;
+
+ /// The second value of the location entry (if applicable).
+ uint64_t Value1;
+
+ /// The location expression itself (if applicable).
+ SmallVector<uint8_t, 4> Loc;
+};
+
+/// An abstract base class for various kinds of location tables (.debug_loc,
+/// .debug_loclists, and their dwo variants).
+class DWARFLocationTable {
+public:
+ DWARFLocationTable(DWARFDataExtractor Data) : Data(std::move(Data)) {}
+ virtual ~DWARFLocationTable() = default;
+
+ /// Call the user-provided callback for each entry (including the end-of-list
+ /// entry) in the location list starting at \p Offset. The callback can return
+ /// 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<bool(const DWARFLocationEntry &)> F) 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
+ /// can attempt to parse another list after the current one (\p Offset will be
+ /// updated to point past the end of the current list).
+ bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, uint64_t BaseAddr,
+ const MCRegisterInfo *MRI, DWARFUnit *U,
+ DIDumpOptions DumpOpts, unsigned Indent) const;
+
+protected:
+ DWARFDataExtractor Data;
+
+ virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
+ unsigned Indent) const = 0;
+};
+
class DWARFDebugLoc {
public:
/// A single location within a location list.
parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset);
};
-class DWARFDebugLoclists {
+class DWARFDebugLoclists final : public DWARFLocationTable {
public:
- // Unconstructible.
- DWARFDebugLoclists() = delete;
+ DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
+ : DWARFLocationTable(std::move(Data)), Version(Version) {}
- struct Entry {
- uint8_t Kind;
- uint64_t Offset;
- uint64_t Value0;
- uint64_t Value1;
- SmallVector<uint8_t, 4> Loc;
- void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian,
- unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
- DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const;
- };
+ Error visitLocationList(
+ uint64_t *Offset,
+ function_ref<bool(const DWARFLocationEntry &)> F) const override;
- /// Call the user-provided callback for each entry (including the end-of-list
- /// entry) in the location list starting at \p Offset. The callback can return
- /// 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.
- static Error visitLocationList(const DWARFDataExtractor &Data,
- uint64_t *Offset, uint16_t Version,
- llvm::function_ref<bool(const Entry &)> F);
+ /// Dump all location lists within the given range.
+ void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
+ uint64_t BaseAddr, const MCRegisterInfo *MRI,
+ DIDumpOptions DumpOpts);
- /// 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
- /// can attempt to parse another list after the current one (\p Offset will be
- /// updated to point past the end of the current list).
- static bool dumpLocationList(const DWARFDataExtractor &Data, uint64_t *Offset,
- uint16_t Version, raw_ostream &OS,
- uint64_t BaseAddr, const MCRegisterInfo *MRI,
- DWARFUnit *U, DIDumpOptions DumpOpts,
- unsigned Indent);
+protected:
+ void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
+ unsigned Indent) const override;
- /// Dump all location lists within the given range.
- static void dumpRange(const DWARFDataExtractor &Data, uint64_t StartOffset,
- uint64_t Size, uint16_t Version, raw_ostream &OS,
- uint64_t BaseAddr, const MCRegisterInfo *MRI,
- DIDumpOptions DumpOpts);
+private:
+ uint16_t Version;
};
} // end namespace llvm
--- /dev/null
+//===- DWARFLocationExpression.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
+#define LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
+
+namespace llvm {
+
+/// Represents a single DWARF expression, whose value is location-dependent.
+/// Typically used in DW_AT_location attributes to describe the location of
+/// objects.
+struct DWARFLocationExpression {
+ /// The address range in which this expression is valid. None denotes a
+ /// default entry which is valid in addresses not covered by other location
+ /// expressions, or everywhere if there are no other expressions.
+ Optional<DWARFAddressRange> Range;
+
+ /// The expression itself.
+ SmallVector<uint8_t, 4> Expr;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
Data.setAddressSize(Header.getAddrSize());
+ DWARFDebugLoclists Loc(Data, Header.getVersion());
if (DumpOffset) {
if (DumpOffset >= Offset && DumpOffset < EndOffset) {
Offset = *DumpOffset;
- DWARFDebugLoclists::dumpLocationList(Data, &Offset, Header.getVersion(),
- OS, /*BaseAddr=*/0, MRI, nullptr,
- DumpOpts, /*Indent=*/0);
+ Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/0, MRI, nullptr,
+ DumpOpts, /*Indent=*/0);
OS << "\n";
return;
}
} else {
- DWARFDebugLoclists::dumpRange(Data, Offset, EndOffset - Offset,
- Header.getVersion(), OS, 0, MRI, DumpOpts);
+ Loc.dumpRange(Offset, EndOffset - Offset, OS, /*BaseAddr=*/0, MRI,
+ DumpOpts);
}
Offset = EndOffset;
}
DObj->getLocDWOSection().Data)) {
DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
4);
+ DWARFDebugLoclists Loc(Data, /*Version=*/4);
if (*Off) {
uint64_t Offset = **Off;
- DWARFDebugLoclists::dumpLocationList(Data, &Offset, /*Version=*/4, OS,
- /*BaseAddr=*/0, getRegisterInfo(),
- nullptr, DumpOpts, /*Indent=*/0);
+ Loc.dumpLocationList(&Offset, OS,
+ /*BaseAddr=*/0, getRegisterInfo(), nullptr, DumpOpts,
+ /*Indent=*/0);
OS << "\n";
} else {
- DWARFDebugLoclists::dumpRange(Data, 0, Data.getData().size(),
- /*Version=*/4, OS, /*BaseAddr=*/0,
- getRegisterInfo(), DumpOpts);
+ Loc.dumpRange(0, Data.getData().size(), OS, /*BaseAddr=*/0,
+ getRegisterInfo(), DumpOpts);
}
}
#include <cstdint>
using namespace llvm;
+using object::SectionedAddress;
+
+namespace {
+class DWARFLocationInterpreter {
+ Optional<object::SectionedAddress> Base;
+ std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr;
+
+public:
+ DWARFLocationInterpreter(
+ Optional<object::SectionedAddress> Base,
+ std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr)
+ : Base(Base), LookupAddr(std::move(LookupAddr)) {}
+
+ Expected<Optional<DWARFLocationExpression>>
+ Interpret(const DWARFLocationEntry &E);
+};
+} // namespace
+
+static Error createResolverError(uint32_t Index, unsigned Kind) {
+ return createStringError(errc::invalid_argument,
+ "Unable to resolve indirect address %u for: %s",
+ Index, dwarf::LocListEncodingString(Kind).data());
+}
+
+Expected<Optional<DWARFLocationExpression>>
+DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) {
+ switch (E.Kind) {
+ case dwarf::DW_LLE_end_of_list:
+ return None;
+ case dwarf::DW_LLE_base_addressx: {
+ Base = LookupAddr(E.Value0);
+ if (!Base)
+ return createResolverError(E.Value0, E.Kind);
+ return None;
+ }
+ case dwarf::DW_LLE_startx_length: {
+ Optional<SectionedAddress> LowPC = LookupAddr(E.Value0);
+ if (!LowPC)
+ return createResolverError(E.Value0, E.Kind);
+ return DWARFLocationExpression{DWARFAddressRange{LowPC->Address,
+ LowPC->Address + E.Value1,
+ LowPC->SectionIndex},
+ E.Loc};
+ }
+ 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};
+ case dwarf::DW_LLE_base_address:
+ Base = SectionedAddress{E.Value0, SectionedAddress::UndefSection};
+ return None;
+ case dwarf::DW_LLE_start_length:
+ return DWARFLocationExpression{
+ DWARFAddressRange{E.Value0, E.Value0 + E.Value1,
+ SectionedAddress::UndefSection},
+ E.Loc};
+ default:
+ llvm_unreachable("unreachable locations list kind");
+ }
+}
// When directly dumping the .debug_loc without a compile unit, we have to guess
// at the DWARF version. This only affects DW_OP_call_ref, which is a rare
DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
}
+bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
+ uint64_t BaseAddr,
+ const MCRegisterInfo *MRI,
+ DWARFUnit *U, DIDumpOptions DumpOpts,
+ unsigned Indent) const {
+ DWARFLocationInterpreter Interp(
+ SectionedAddress{BaseAddr, SectionedAddress::UndefSection},
+ [U](uint32_t Index) -> Optional<SectionedAddress> {
+ if (U)
+ return U->getAddrOffsetSectionItem(Index);
+ return None;
+ });
+ OS << format("0x%8.8" PRIx64 ": ", *Offset);
+ Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) {
+ Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
+ if (!Loc || DumpOpts.Verbose)
+ dumpRawEntry(E, OS, Indent);
+ if (Loc && *Loc) {
+ OS << "\n";
+ OS.indent(Indent);
+ if (DumpOpts.Verbose)
+ OS << " => ";
+ Loc.get()->Range->dump(OS, Data.getAddressSize(), DumpOpts);
+ }
+ if (!Loc)
+ consumeError(Loc.takeError());
+
+ if (E.Kind != dwarf::DW_LLE_base_address &&
+ E.Kind != dwarf::DW_LLE_base_addressx &&
+ E.Kind != dwarf::DW_LLE_end_of_list) {
+ OS << ": ";
+ dumpExpression(OS, E.Loc, Data.isLittleEndian(), Data.getAddressSize(),
+ MRI, U);
+ }
+ return true;
+ });
+ if (E) {
+ OS << "\n";
+ OS.indent(Indent);
+ OS << "error: " << toString(std::move(E));
+ return false;
+ }
+ return true;
+}
+
void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress,
bool IsLittleEndian,
unsigned AddressSize,
}
Error DWARFDebugLoclists::visitLocationList(
- const DWARFDataExtractor &Data, uint64_t *Offset, uint16_t Version,
- llvm::function_ref<bool(const Entry &)> F) {
+ uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const {
DataExtractor::Cursor C(*Offset);
bool Continue = true;
while (Continue) {
- Entry E;
- E.Offset = C.tell();
+ DWARFLocationEntry E;
E.Kind = Data.getU8(C);
switch (E.Kind) {
case dwarf::DW_LLE_end_of_list:
return Error::success();
}
-bool DWARFDebugLoclists::dumpLocationList(const DWARFDataExtractor &Data,
- uint64_t *Offset, uint16_t Version,
- raw_ostream &OS, uint64_t BaseAddr,
- const MCRegisterInfo *MRI,
- DWARFUnit *U, DIDumpOptions DumpOpts,
- unsigned Indent) {
+void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry,
+ raw_ostream &OS, unsigned Indent) const {
size_t MaxEncodingStringLength = 0;
- if (DumpOpts.Verbose) {
#define HANDLE_DW_LLE(ID, NAME) \
MaxEncodingStringLength = std::max(MaxEncodingStringLength, \
dwarf::LocListEncodingString(ID).size());
#include "llvm/BinaryFormat/Dwarf.def"
- }
-
- OS << format("0x%8.8" PRIx64 ": ", *Offset);
- Error E = visitLocationList(Data, Offset, Version, [&](const Entry &E) {
- E.dump(OS, BaseAddr, Data.isLittleEndian(), Data.getAddressSize(), MRI, U,
- DumpOpts, Indent, MaxEncodingStringLength);
- return true;
- });
- if (E) {
- OS << "\n";
- OS.indent(Indent);
- OS << "error: " << toString(std::move(E));
- return false;
- }
- return true;
-}
-void DWARFDebugLoclists::Entry::dump(raw_ostream &OS, uint64_t &BaseAddr,
- bool IsLittleEndian, unsigned AddressSize,
- const MCRegisterInfo *MRI, DWARFUnit *U,
- DIDumpOptions DumpOpts, unsigned Indent,
- size_t MaxEncodingStringLength) const {
- if (DumpOpts.Verbose) {
- OS << "\n";
- OS.indent(Indent);
- auto EncodingString = dwarf::LocListEncodingString(Kind);
- // Unsupported encodings should have been reported during parsing.
- assert(!EncodingString.empty() && "Unknown loclist entry encoding");
- OS << format("%s%*c", EncodingString.data(),
- MaxEncodingStringLength - EncodingString.size() + 1, '(');
- switch (Kind) {
- case dwarf::DW_LLE_startx_length:
- case dwarf::DW_LLE_start_length:
- case dwarf::DW_LLE_offset_pair:
- OS << format("0x%*.*" PRIx64 ", 0x%*.*" PRIx64, AddressSize * 2,
- AddressSize * 2, Value0, AddressSize * 2, AddressSize * 2,
- Value1);
- break;
- case dwarf::DW_LLE_base_addressx:
- case dwarf::DW_LLE_base_address:
- OS << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2,
- Value0);
- break;
- case dwarf::DW_LLE_end_of_list:
- break;
- }
- OS << ')';
- }
- auto PrintPrefix = [&] {
- OS << "\n";
- OS.indent(Indent);
- if (DumpOpts.Verbose)
- OS << format("%*s", MaxEncodingStringLength, (const char *)"=> ");
- };
- switch (Kind) {
+ OS << "\n";
+ OS.indent(Indent);
+ StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind);
+ // Unsupported encodings should have been reported during parsing.
+ assert(!EncodingString.empty() && "Unknown loclist entry encoding");
+ OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data());
+ unsigned FieldSize = 2 + 2 * Data.getAddressSize();
+ switch (Entry.Kind) {
case dwarf::DW_LLE_startx_length:
- PrintPrefix();
- OS << "Addr idx " << Value0 << " (w/ length " << Value1 << "): ";
- break;
case dwarf::DW_LLE_start_length:
- PrintPrefix();
- DWARFAddressRange(Value0, Value0 + Value1)
- .dump(OS, AddressSize, DumpOpts);
- OS << ": ";
- break;
case dwarf::DW_LLE_offset_pair:
- PrintPrefix();
- DWARFAddressRange(BaseAddr + Value0, BaseAddr + Value1)
- .dump(OS, AddressSize, DumpOpts);
- OS << ": ";
+ OS << format_hex(Entry.Value0, FieldSize) << ", "
+ << format_hex(Entry.Value1, FieldSize);
break;
case dwarf::DW_LLE_base_addressx:
- if (!DumpOpts.Verbose)
- return;
+ case dwarf::DW_LLE_base_address:
+ OS << format_hex(Entry.Value0, FieldSize);
break;
case dwarf::DW_LLE_end_of_list:
- if (!DumpOpts.Verbose)
- return;
break;
- case dwarf::DW_LLE_base_address:
- BaseAddr = Value0;
- if (!DumpOpts.Verbose)
- return;
- break;
- default:
- llvm_unreachable("unreachable locations list kind");
}
-
- dumpExpression(OS, Loc, IsLittleEndian, AddressSize, MRI, U);
+ OS << ')';
}
-void DWARFDebugLoclists::dumpRange(const DWARFDataExtractor &Data,
- uint64_t StartOffset, uint64_t Size,
- uint16_t Version, raw_ostream &OS,
- uint64_t BaseAddr, const MCRegisterInfo *MRI,
+void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
+ raw_ostream &OS, uint64_t BaseAddr,
+ const MCRegisterInfo *MRI,
DIDumpOptions DumpOpts) {
if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) {
OS << "Invalid dump range\n";
OS << Separator;
Separator = "\n";
- CanContinue = dumpLocationList(Data, &Offset, Version, OS, BaseAddr, MRI,
- nullptr, DumpOpts, /*Indent=*/12);
+ CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, nullptr,
+ DumpOpts, /*Indent=*/12);
OS << '\n';
}
}
// Modern locations list (.debug_loclists) are used starting from v5.
// Ideally we should take the version from the .debug_loclists section
// header, but using CU's version for simplicity.
- DWARFDebugLoclists::dumpLocationList(
- Data, &Offset, UseLocLists ? U->getVersion() : 4, OS, BaseAddr, MRI,
- U, LLDumpOpts, Indent);
+ DWARFDebugLoclists(Data, UseLocLists ? U->getVersion() : 4)
+ .dumpLocationList(&Offset, OS, BaseAddr, MRI, U, LLDumpOpts, Indent);
}
return;
}
; CHECK: DW_TAG_variable
; FIXME: Use DW_FORM_loclistx to reduce relocations
; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x0000001d
-; CHECK-NEXT: Addr idx 0 (w/ length 3): DW_OP_consts +5, DW_OP_stack_value)
+; CHECK-NEXT: [0x0000000000000000, 0x0000000000000003): DW_OP_consts +5, DW_OP_stack_value)
; CHECK-NEXT: DW_AT_name {{.*}} "x"
; CHECK: DW_TAG_variable
; CHECK-NEXT: 0x0000000c:
; CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000)
-; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000003)
-; CHECK-NEXT: => [0x0000000000000000, 0x0000000000000003): DW_OP_consts +3, DW_OP_stack_value
-; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004)
-; CHECK-NEXT: => [0x0000000000000003, 0x0000000000000004): DW_OP_consts +4, DW_OP_stack_value
+; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000003): DW_OP_consts +3, DW_OP_stack_value
+; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004): DW_OP_consts +4, DW_OP_stack_value
; CHECK-NEXT: DW_LLE_end_of_list ()
; Show that startx_length can be used when the address range starts at the start of the function.
; CHECK: 0x0000001d:
-; CHECK-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000003)
-; CHECK-NEXT: => Addr idx 0 (w/ length 3): DW_OP_consts +5, DW_OP_stack_value
+; CHECK-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000003): DW_OP_consts +5, DW_OP_stack_value
; CHECK-NEXT: DW_LLE_end_of_list ()
; And use a base address when the range doesn't start at an existing/useful
; CHECK: 0x00000025:
; CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000)
-; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004)
-; CHECK-NEXT: => [0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX
+; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX
; CHECK-NEXT: DW_LLE_end_of_list ()
; Built with clang -O3 -ffunction-sections from source:
; if they've changed due to a bugfix, change in register allocation, etc.
; CHECK: [[A]]:
-; CHECK-NEXT: DW_LLE_startx_length (0x00000002, 0x0000000f)
-; CHECK-NEXT: => Addr idx 2 (w/ length 15): DW_OP_consts +0, DW_OP_stack_value
-; CHECK-NEXT: DW_LLE_startx_length (0x00000003, 0x0000000f)
-; CHECK-NEXT: => Addr idx 3 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT: DW_LLE_startx_length (0x00000004, 0x00000012)
-; CHECK-NEXT: => Addr idx 4 (w/ length 18): DW_OP_breg7 RSP-8
+; CHECK-NEXT: DW_LLE_startx_length (0x00000002, 0x0000000f): DW_OP_consts +0, DW_OP_stack_value
+; CHECK-NEXT: DW_LLE_startx_length (0x00000003, 0x0000000f): DW_OP_reg0 RAX
+; CHECK-NEXT: DW_LLE_startx_length (0x00000004, 0x00000012): DW_OP_breg7 RSP-8
; CHECK-NEXT: DW_LLE_end_of_list ()
; CHECK: [[E]]:
-; CHECK-NEXT: DW_LLE_startx_length (0x00000005, 0x00000009)
-; CHECK-NEXT: => Addr idx 5 (w/ length 9): DW_OP_reg0 RAX
-; CHECK-NEXT: DW_LLE_startx_length (0x00000006, 0x00000062)
-; CHECK-NEXT: => Addr idx 6 (w/ length 98): DW_OP_breg7 RSP-44
+; CHECK-NEXT: DW_LLE_startx_length (0x00000005, 0x00000009): DW_OP_reg0 RAX
+; CHECK-NEXT: DW_LLE_startx_length (0x00000006, 0x00000062): DW_OP_breg7 RSP-44
; CHECK-NEXT: DW_LLE_end_of_list ()
; CHECK: [[B]]:
-; CHECK-NEXT: DW_LLE_startx_length (0x00000007, 0x0000000f)
-; CHECK-NEXT: => Addr idx 7 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT: DW_LLE_startx_length (0x00000008, 0x00000042)
-; CHECK-NEXT: => Addr idx 8 (w/ length 66): DW_OP_breg7 RSP-32
+; CHECK-NEXT: DW_LLE_startx_length (0x00000007, 0x0000000f): DW_OP_reg0 RAX
+; CHECK-NEXT: DW_LLE_startx_length (0x00000008, 0x00000042): DW_OP_breg7 RSP-32
; CHECK-NEXT: DW_LLE_end_of_list ()
; CHECK: [[D]]:
-; CHECK-NEXT: DW_LLE_startx_length (0x00000009, 0x0000000f)
-; CHECK-NEXT: => Addr idx 9 (w/ length 15): DW_OP_reg0 RAX
-; CHECK-NEXT: DW_LLE_startx_length (0x0000000a, 0x0000002a)
-; CHECK-NEXT: => Addr idx 10 (w/ length 42): DW_OP_breg7 RSP-20
+; CHECK-NEXT: DW_LLE_startx_length (0x00000009, 0x0000000f): DW_OP_reg0 RAX
+; CHECK-NEXT: DW_LLE_startx_length (0x0000000a, 0x0000002a): DW_OP_breg7 RSP-20
; CHECK-NEXT: DW_LLE_end_of_list ()
; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)
; 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-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000006): 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)
+; CHECK-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000000): DW_OP_reg5 RDI)
target triple = "x86_64-unknown-linux-gnu"
# CHECK: .debug_loc.dwo contents:
# CHECK-NEXT: 0x00000000:
-# CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT: DW_LLE_startx_length (0x00000001, 0x00000010): DW_OP_reg5 RDI
.section .debug_loc.dwo,"",@progbits
# One location list. The pre-DWARF v5 implementation only recognizes
# CHECK: DW_AT_location (0x0000000c
-# CHECK-NEXT: Addr idx 0 (w/ length 1): DW_OP_reg0 RAX
+# 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: Addr idx 57005 (w/ length 1): DW_OP_reg4 RSI)
+# CHECK-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg4 RSI)
.text
# CHECK: .debug_loclists contents:
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
# CHECK-NEXT: 0x0000000c:
-# CHECK-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000010)
-# CHECK-NEXT: => Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000010): DW_OP_reg5 RDI
# CHECK-NEXT: DW_LLE_end_of_list ()
.section .debug_loclists,"",@progbits