Skip to content

Commit ebe2f56

Browse files
committed
DWARFDebugLoclists: add location list "interpretation" logic
Summary: This patch extracts the logic for computing the "absolute" locations, which was partially present in the debug_loclists dumper, completes it, and moves it into a separate function. This makes it possible to later reuse the same logic for uses other than dumping. The dumper is changed to reuse the location list interpreter, and its format is changed somewhat. In "verbose" mode it prints the "raw" value of a location list, the interpreted location (if available) and the expression itself. In non-verbose mode it prints only one of the location forms: it prefers the interpreted form, but falls back to the "raw" format if interpretation is not possible (for instance, because we were not given a base address, or the resolution of indirect addresses failed). This patch also undos some of the changes made in D69672, namely the part about making all functions static. The main reason for this is that I learned that the original approach (dumping only fully resolved locations) meant that it was impossible to rewrite one of the existing tests. To make that possible (and make the "inline location" dump work in more cases), I now reuse the same dumping mechanism as is used for section-based dumping. As this required having more objects know about the various location lists classes, it seemed like a good idea to create an interface abstracting the difference between them. Therefore, I now create a DWARFLocationTable class, which will serve as a base class for the location list classes. DWARFDebugLoclists is made to inherit from that. DWARFDebugLoc will follow. Another positive effect of this change is that section-based dumping code will not need to use templates (as originally) envisioned, and that the argument lists of the dumping functions become shorter. Reviewers: dblaikie, probinson, JDevlieghere, aprantl, SouraVX Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70081
1 parent a9018fd commit ebe2f56

File tree

11 files changed

+261
-179
lines changed

11 files changed

+261
-179
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/SmallVector.h"
1414
#include "llvm/DebugInfo/DIContext.h"
1515
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16+
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
1617
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
1718
#include <cstdint>
1819

@@ -21,6 +22,53 @@ class DWARFUnit;
2122
class MCRegisterInfo;
2223
class raw_ostream;
2324

25+
/// A single location within a location list. Entries are stored in the DWARF5
26+
/// form even if they originally come from a DWARF<=4 location list.
27+
struct DWARFLocationEntry {
28+
/// The entry kind (DW_LLE_***).
29+
uint8_t Kind;
30+
31+
/// The first value of the location entry (if applicable).
32+
uint64_t Value0;
33+
34+
/// The second value of the location entry (if applicable).
35+
uint64_t Value1;
36+
37+
/// The location expression itself (if applicable).
38+
SmallVector<uint8_t, 4> Loc;
39+
};
40+
41+
/// An abstract base class for various kinds of location tables (.debug_loc,
42+
/// .debug_loclists, and their dwo variants).
43+
class DWARFLocationTable {
44+
public:
45+
DWARFLocationTable(DWARFDataExtractor Data) : Data(std::move(Data)) {}
46+
virtual ~DWARFLocationTable() = default;
47+
48+
/// Call the user-provided callback for each entry (including the end-of-list
49+
/// entry) in the location list starting at \p Offset. The callback can return
50+
/// false to terminate the iteration early. Returns an error if it was unable
51+
/// to parse the entire location list correctly. Upon successful termination
52+
/// \p Offset will be updated point past the end of the list.
53+
virtual Error
54+
visitLocationList(uint64_t *Offset,
55+
function_ref<bool(const DWARFLocationEntry &)> F) const = 0;
56+
57+
/// Dump the location list at the given \p Offset. The function returns true
58+
/// iff it has successfully reched the end of the list. This means that one
59+
/// can attempt to parse another list after the current one (\p Offset will be
60+
/// updated to point past the end of the current list).
61+
bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, uint64_t BaseAddr,
62+
const MCRegisterInfo *MRI, DWARFUnit *U,
63+
DIDumpOptions DumpOpts, unsigned Indent) const;
64+
65+
protected:
66+
DWARFDataExtractor Data;
67+
68+
virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
69+
unsigned Indent) const = 0;
70+
};
71+
2472
class DWARFDebugLoc {
2573
public:
2674
/// A single location within a location list.
@@ -74,46 +122,26 @@ class DWARFDebugLoc {
74122
parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset);
75123
};
76124

77-
class DWARFDebugLoclists {
125+
class DWARFDebugLoclists final : public DWARFLocationTable {
78126
public:
79-
// Unconstructible.
80-
DWARFDebugLoclists() = delete;
127+
DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
128+
: DWARFLocationTable(std::move(Data)), Version(Version) {}
81129

82-
struct Entry {
83-
uint8_t Kind;
84-
uint64_t Offset;
85-
uint64_t Value0;
86-
uint64_t Value1;
87-
SmallVector<uint8_t, 4> Loc;
88-
void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian,
89-
unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
90-
DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const;
91-
};
130+
Error visitLocationList(
131+
uint64_t *Offset,
132+
function_ref<bool(const DWARFLocationEntry &)> F) const override;
92133

93-
/// Call the user-provided callback for each entry (including the end-of-list
94-
/// entry) in the location list starting at \p Offset. The callback can return
95-
/// false to terminate the iteration early. Returns an error if it was unable
96-
/// to parse the entire location list correctly. Upon successful termination
97-
/// \p Offset will be updated point past the end of the list.
98-
static Error visitLocationList(const DWARFDataExtractor &Data,
99-
uint64_t *Offset, uint16_t Version,
100-
llvm::function_ref<bool(const Entry &)> F);
134+
/// Dump all location lists within the given range.
135+
void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
136+
uint64_t BaseAddr, const MCRegisterInfo *MRI,
137+
DIDumpOptions DumpOpts);
101138

102-
/// Dump the location list at the given \p Offset. The function returns true
103-
/// iff it has successfully reched the end of the list. This means that one
104-
/// can attempt to parse another list after the current one (\p Offset will be
105-
/// updated to point past the end of the current list).
106-
static bool dumpLocationList(const DWARFDataExtractor &Data, uint64_t *Offset,
107-
uint16_t Version, raw_ostream &OS,
108-
uint64_t BaseAddr, const MCRegisterInfo *MRI,
109-
DWARFUnit *U, DIDumpOptions DumpOpts,
110-
unsigned Indent);
139+
protected:
140+
void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
141+
unsigned Indent) const override;
111142

112-
/// Dump all location lists within the given range.
113-
static void dumpRange(const DWARFDataExtractor &Data, uint64_t StartOffset,
114-
uint64_t Size, uint16_t Version, raw_ostream &OS,
115-
uint64_t BaseAddr, const MCRegisterInfo *MRI,
116-
DIDumpOptions DumpOpts);
143+
private:
144+
uint16_t Version;
117145
};
118146

119147
} // end namespace llvm
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===- DWARFLocationExpression.h --------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
10+
#define LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
11+
12+
#include "llvm/ADT/Optional.h"
13+
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
14+
15+
namespace llvm {
16+
17+
/// Represents a single DWARF expression, whose value is location-dependent.
18+
/// Typically used in DW_AT_location attributes to describe the location of
19+
/// objects.
20+
struct DWARFLocationExpression {
21+
/// The address range in which this expression is valid. None denotes a
22+
/// default entry which is valid in addresses not covered by other location
23+
/// expressions, or everywhere if there are no other expressions.
24+
Optional<DWARFAddressRange> Range;
25+
26+
/// The expression itself.
27+
SmallVector<uint8_t, 4> Expr;
28+
};
29+
30+
} // end namespace llvm
31+
32+
#endif // LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -302,18 +302,18 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
302302

303303
uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
304304
Data.setAddressSize(Header.getAddrSize());
305+
DWARFDebugLoclists Loc(Data, Header.getVersion());
305306
if (DumpOffset) {
306307
if (DumpOffset >= Offset && DumpOffset < EndOffset) {
307308
Offset = *DumpOffset;
308-
DWARFDebugLoclists::dumpLocationList(Data, &Offset, Header.getVersion(),
309-
OS, /*BaseAddr=*/0, MRI, nullptr,
310-
DumpOpts, /*Indent=*/0);
309+
Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/0, MRI, nullptr,
310+
DumpOpts, /*Indent=*/0);
311311
OS << "\n";
312312
return;
313313
}
314314
} else {
315-
DWARFDebugLoclists::dumpRange(Data, Offset, EndOffset - Offset,
316-
Header.getVersion(), OS, 0, MRI, DumpOpts);
315+
Loc.dumpRange(Offset, EndOffset - Offset, OS, /*BaseAddr=*/0, MRI,
316+
DumpOpts);
317317
}
318318
Offset = EndOffset;
319319
}
@@ -405,16 +405,16 @@ void DWARFContext::dump(
405405
DObj->getLocDWOSection().Data)) {
406406
DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
407407
4);
408+
DWARFDebugLoclists Loc(Data, /*Version=*/4);
408409
if (*Off) {
409410
uint64_t Offset = **Off;
410-
DWARFDebugLoclists::dumpLocationList(Data, &Offset, /*Version=*/4, OS,
411-
/*BaseAddr=*/0, getRegisterInfo(),
412-
nullptr, DumpOpts, /*Indent=*/0);
411+
Loc.dumpLocationList(&Offset, OS,
412+
/*BaseAddr=*/0, getRegisterInfo(), nullptr, DumpOpts,
413+
/*Indent=*/0);
413414
OS << "\n";
414415
} else {
415-
DWARFDebugLoclists::dumpRange(Data, 0, Data.getData().size(),
416-
/*Version=*/4, OS, /*BaseAddr=*/0,
417-
getRegisterInfo(), DumpOpts);
416+
Loc.dumpRange(0, Data.getData().size(), OS, /*BaseAddr=*/0,
417+
getRegisterInfo(), DumpOpts);
418418
}
419419
}
420420

0 commit comments

Comments
 (0)