1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

DWARFDebugLoc(v4): Add an incremental parsing function

Summary:
This adds a visitLocationList function to the DWARF v4 location lists,
similar to what already exists for DWARF v5. It follows the approach
outlined in previous patches (D69672), where the parsed form is always
stored in the DWARF v5 format, which makes it easier for generic code to
be built on top of that. v4 location lists are "upgraded" during
parsing, and then this upgrade is undone while dumping.

Both "inline" and section-based dumping is rewritten to reuse the
existing "generic" location list dumper. This means that the output
format is consistent for all location lists (the only thing one needs to
implement is the function which prints the "raw" form of a location
list), and that debug_loc dumping correctly processes base address
selection entries, etc.

The previous existing debug_loc functionality (e.g.,
parseOneLocationList) is rewritten on top of the new API, but it is not
removed as there is still code which uses them. This will be done in
follow-up patches, after I build the API to access the "interpreted"
location lists in a generic way (as that is what those users really
want).

Reviewers: dblaikie, probinson, JDevlieghere, aprantl, SouraVX

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69847
This commit is contained in:
Pavel Labath 2019-11-05 14:46:54 +01:00
parent 09df29855e
commit 96888349a9
27 changed files with 186 additions and 196 deletions

View File

@ -50,9 +50,9 @@ public:
/// 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;
virtual Error visitLocationList(
uint64_t *Offset,
function_ref<bool(const DWARFLocationEntry &)> 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 @@ protected:
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<uint8_t, 4> 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<Entry, 2> 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<DWARFLocationEntry, 2> Entries;
};
private:
@ -103,24 +88,29 @@ private:
/// 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<uint64_t> 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<LocationList>
parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset);
Error visitLocationList(
uint64_t *Offset,
function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
Expected<LocationList> 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 @@ public:
Error visitLocationList(
uint64_t *Offset,
function_ref<bool(const DWARFLocationEntry &)> F) const override;
function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
/// Dump all location lists within the given range.
void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,

View File

@ -201,11 +201,7 @@ class DWARFUnit {
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<DWARFLocationTable> LocTable;
const DWARFSection &LineSection;
@ -277,7 +273,6 @@ public:
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 @@ public:
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

View File

@ -734,13 +734,14 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() {
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();
}

View File

@ -145,25 +145,6 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
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 @@ DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
return nullptr;
}
void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts,
Optional<uint64_t> 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";
};
void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
DIDumpOptions DumpOpts,
Optional<uint64_t> 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";
if (Offset) {
if (auto *L = getLocationListAtOffset(*Offset))
DumpLocationList(*L);
return;
}
for (const LocationList &L : Locations) {
DumpLocationList(L);
if (&L != &Locations.back())
CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, nullptr,
DumpOpts, Indent);
OS << '\n';
}
}
}
Expected<DWARFDebugLoc::LocationList>
DWARFDebugLoc::parseOneLocationList(const DWARFDataExtractor &Data,
uint64_t *Offset) {
LocationList LL;
LL.Offset = *Offset;
AddressSize = Data.getAddressSize();
Error DWARFDebugLoc::visitLocationList(
uint64_t *Offset,
function_ref<bool(const DWARFLocationEntry &)> Callback) const {
DataExtractor::Cursor C(*Offset);
// 2.6.2 Location Lists
// A location list entry consists of:
while (true) {
Entry E;
uint64_t Value0 = Data.getRelocatedAddress(C);
uint64_t Value1 = Data.getRelocatedAddress(C);
// 1. A beginning address offset. ...
E.Begin = Data.getRelocatedAddress(C);
// 2. An ending address offset. ...
E.End = 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::LocationList>
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::parse(const DWARFDataExtractor &data) {
}
}
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<bool(const DWARFLocationEntry &)> F) const {

View File

@ -79,7 +79,6 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
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 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
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<DWARFDebugLoc::LocationList> LL =
DebugLoc.parseOneLocationList(Data, &Offset)) {
uint64_t BaseAddr = 0;
if (Optional<object::SectionedAddress> 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;
}

View File

@ -175,9 +175,9 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
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 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
Context.getDWARFObj().getLoclistsSection(),
isLittleEndian, getAddressByteSize()),
Header.getVersion());
} else {
LocTable = std::make_unique<DWARFDebugLoc>(
DWARFDataExtractor(Context.getDWARFObj(), *LocSection, isLittleEndian,
getAddressByteSize()));
}
}

View File

@ -1302,7 +1302,7 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) {
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;

View File

@ -7,7 +7,7 @@ target triple = "thumbv7-apple-macosx10.6.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:

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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 @@ f: # @f
.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 @@ f: # @f
.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

View File

@ -15,8 +15,8 @@ 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): 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

View File

@ -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: :

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -122,11 +122,11 @@ CHECK: NULL
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:

View File

@ -134,11 +134,11 @@ CHECK: NULL
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

View File

@ -18,12 +18,9 @@ int main() {
}
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

View File

@ -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:

View File

@ -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

View File

@ -4,8 +4,8 @@ RUN: | FileCheck %s --check-prefix=CHECK-A
# 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 @@ RUN: | FileCheck %s --check-prefix=CHECK-B
# 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

View File

@ -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

View File

@ -249,15 +249,22 @@ static void collectStatsForDie(DWARFDie Die, uint64_t UnitLowPC, std::string FnP
// 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<DWARFLocationEntry> 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)