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:
parent
09df29855e
commit
96888349a9
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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: :
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user