Skip to content

Commit f946489

Browse files
Address comments
1 parent 174545c commit f946489

File tree

5 files changed

+167
-202
lines changed

5 files changed

+167
-202
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,57 @@
1111

1212
#include "llvm/BinaryFormat/Dwarf.h"
1313
#include "llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h"
14+
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
15+
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
1416
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
1517

1618
namespace llvm {
17-
class DWARFObject;
1819

19-
/// A DWARFDataExtractorSimple (typically for an in-memory copy of an
20-
/// object-file section) plus a relocation map for that section, if there is
21-
/// one.
22-
class DWARFDataExtractor : public DWARFDataExtractorSimple {
20+
/// A DWARFDataExtractor (typically for an in-memory copy of an object-file
21+
/// section) plus a relocation map for that section, if there is one.
22+
class DWARFDataExtractor : public DWARFDataExtractorBase<DWARFDataExtractor> {
2323
const DWARFObject *Obj = nullptr;
2424
const DWARFSection *Section = nullptr;
2525

2626
public:
27-
using DWARFDataExtractorSimple::DWARFDataExtractorSimple;
27+
using DWARFDataExtractorBase::DWARFDataExtractorBase;
2828

2929
/// Constructor for the normal case of extracting data from a DWARF section.
3030
/// The DWARFSection's lifetime must be at least as long as the extractor's.
3131
DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
3232
bool IsLittleEndian, uint8_t AddressSize)
33-
: DWARFDataExtractorSimple(Section.Data, IsLittleEndian, AddressSize),
33+
: DWARFDataExtractorBase(Section.Data, IsLittleEndian, AddressSize),
3434
Obj(&Obj), Section(&Section) {}
3535

3636
/// Truncating constructor
3737
DWARFDataExtractor(const DWARFDataExtractor &Other, size_t Length)
38-
: DWARFDataExtractorSimple(Other.getData().substr(0, Length),
39-
Other.isLittleEndian(),
40-
Other.getAddressSize()),
38+
: DWARFDataExtractorBase(Other.getData().substr(0, Length),
39+
Other.isLittleEndian(), Other.getAddressSize()),
4140
Obj(Other.Obj), Section(Other.Section) {}
4241

4342
/// Extracts a value and applies a relocation to the result if
4443
/// one exists for the given offset.
45-
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
46-
uint64_t *SectionIndex = nullptr,
47-
Error *Err = nullptr) const override;
44+
uint64_t getRelocatedValueImpl(uint32_t Size, uint64_t *Off, uint64_t *SecNdx,
45+
Error *Err) const {
46+
if (SecNdx)
47+
*SecNdx = object::SectionedAddress::UndefSection;
48+
if (!Section)
49+
return getUnsigned(Off, Size, Err);
4850

49-
uint64_t getRelocatedValue(Cursor &C, uint32_t Size,
50-
uint64_t *SectionIndex = nullptr) const override {
51-
return getRelocatedValue(Size, &getOffset(C), SectionIndex, &getError(C));
51+
ErrorAsOutParameter ErrAsOut(Err);
52+
std::optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
53+
uint64_t LocData = getUnsigned(Off, Size, Err);
54+
if (!E || (Err && *Err))
55+
return LocData;
56+
if (SecNdx)
57+
*SecNdx = E->SectionIndex;
58+
59+
uint64_t R = object::resolveRelocation(E->Resolver, E->Reloc,
60+
E->SymbolValue, LocData);
61+
if (E->Reloc2)
62+
R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2,
63+
R);
64+
return R;
5265
}
5366
};
5467

llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h

Lines changed: 138 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,42 @@
1414

1515
#include "llvm/BinaryFormat/Dwarf.h"
1616
#include "llvm/Support/DataExtractor.h"
17+
#include "llvm/Support/Errc.h"
18+
#include "llvm/Support/MathExtras.h"
1719

1820
namespace llvm {
1921

20-
/// A DataExtractor suitable use for parsing dwarf from memory with minimal
21-
/// dwarf context--no sections and no objects. getRelocated* functions
22-
/// return raw values.
22+
/// A DataExtractor suitable use for parsing dwarf from memory. Clients use
23+
/// Relocator::getRelocatedValueImpl to relocate values as appropriate.
2324

24-
class DWARFDataExtractorSimple : public DataExtractor {
25+
template <class Relocator> class DWARFDataExtractorBase : public DataExtractor {
2526

2627
public:
27-
DWARFDataExtractorSimple(StringRef Data, bool IsLittleEndian,
28-
uint8_t AddressSize)
28+
DWARFDataExtractorBase(StringRef Data, bool IsLittleEndian,
29+
uint8_t AddressSize)
2930
: DataExtractor(Data, IsLittleEndian, AddressSize) {}
30-
DWARFDataExtractorSimple(ArrayRef<uint8_t> Data, bool IsLittleEndian,
31-
uint8_t AddressSize)
31+
DWARFDataExtractorBase(ArrayRef<uint8_t> Data, bool IsLittleEndian,
32+
uint8_t AddressSize)
3233
: DataExtractor(
3334
StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()),
3435
IsLittleEndian, AddressSize) {}
3536

3637
/// Truncating constructor
37-
DWARFDataExtractorSimple(const DWARFDataExtractorSimple &Other, size_t Length)
38+
DWARFDataExtractorBase(const DWARFDataExtractorBase &Other, size_t Length)
3839
: DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(),
3940
Other.getAddressSize()) {}
4041

41-
virtual ~DWARFDataExtractorSimple() = default;
42+
~DWARFDataExtractorBase() {}
4243

43-
/// Extracts the DWARF "initial length" field, which can either be a 32-bit
44-
/// value smaller than 0xfffffff0, or the value 0xffffffff followed by a
45-
/// 64-bit length. Returns the actual length, and the DWARF format which is
46-
/// encoded in the field. In case of errors, it returns {0, DWARF32} and
47-
/// leaves the offset unchanged.
48-
std::pair<uint64_t, dwarf::DwarfFormat>
49-
getInitialLength(uint64_t *Off, Error *Err = nullptr) const;
50-
51-
std::pair<uint64_t, dwarf::DwarfFormat> getInitialLength(Cursor &C) const {
52-
return getInitialLength(&getOffset(C), &getError(C));
44+
/// Extracts a value and returns it as adjusted by the Relocator
45+
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
46+
uint64_t *SectionIndex = nullptr,
47+
Error *Err = nullptr) const {
48+
return static_cast<const Relocator *>(this)->getRelocatedValueImpl(
49+
Size, Off, SectionIndex, Err);
5350
}
54-
55-
/// Extracts a value and returns it unrelocated. Named such to implement the
56-
/// required interface.
57-
virtual uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
58-
uint64_t *SectionIndex = nullptr,
59-
Error *Err = nullptr) const {
60-
assert(SectionIndex == nullptr &&
61-
"DWARFDATAExtractorSimple cannot take section indices.");
62-
return getUnsigned(Off, Size, Err);
63-
}
64-
virtual uint64_t getRelocatedValue(Cursor &C, uint32_t Size,
65-
uint64_t *SectionIndex = nullptr) const {
51+
uint64_t getRelocatedValue(Cursor &C, uint32_t Size,
52+
uint64_t *SectionIndex = nullptr) const {
6653
return getRelocatedValue(Size, &getOffset(C), SectionIndex, &getError(C));
6754
}
6855

@@ -75,14 +62,131 @@ class DWARFDataExtractorSimple : public DataExtractor {
7562
&getError(C));
7663
}
7764

65+
/// Extracts the DWARF "initial length" field, which can either be a 32-bit
66+
/// value smaller than 0xfffffff0, or the value 0xffffffff followed by a
67+
/// 64-bit length. Returns the actual length, and the DWARF format which is
68+
/// encoded in the field. In case of errors, it returns {0, DWARF32} and
69+
/// leaves the offset unchanged.
70+
std::pair<uint64_t, dwarf::DwarfFormat>
71+
getInitialLength(uint64_t *Off, Error *Err = nullptr) const {
72+
ErrorAsOutParameter ErrAsOut(Err);
73+
if (Err && *Err)
74+
return {0, dwarf::DWARF32};
75+
76+
Cursor C(*Off);
77+
uint64_t Length = getRelocatedValue(C, 4);
78+
dwarf::DwarfFormat Format = dwarf::DWARF32;
79+
if (Length == dwarf::DW_LENGTH_DWARF64) {
80+
Length = getRelocatedValue(C, 8);
81+
Format = dwarf::DWARF64;
82+
} else if (Length >= dwarf::DW_LENGTH_lo_reserved) {
83+
cantFail(C.takeError());
84+
if (Err)
85+
*Err = createStringError(
86+
std::errc::invalid_argument,
87+
"unsupported reserved unit length of value 0x%8.8" PRIx64, Length);
88+
return {0, dwarf::DWARF32};
89+
}
90+
91+
if (C) {
92+
*Off = C.tell();
93+
return {Length, Format};
94+
}
95+
if (Err)
96+
*Err = C.takeError();
97+
else
98+
consumeError(C.takeError());
99+
return {0, dwarf::DWARF32};
100+
}
101+
102+
std::pair<uint64_t, dwarf::DwarfFormat> getInitialLength(Cursor &C) const {
103+
return getInitialLength(&getOffset(C), &getError(C));
104+
}
105+
78106
/// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
79107
/// There is a DWARF encoding that uses a PC-relative adjustment.
80108
/// For these values, \p AbsPosOffset is used to fix them, which should
81109
/// reflect the absolute address of this pointer.
82110
std::optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
83-
uint64_t AbsPosOffset = 0) const;
111+
uint64_t PCRelOffset) const {
112+
if (Encoding == dwarf::DW_EH_PE_omit)
113+
return std::nullopt;
114+
115+
uint64_t Result = 0;
116+
uint64_t OldOffset = *Offset;
117+
// First get value
118+
switch (Encoding & 0x0F) {
119+
case dwarf::DW_EH_PE_absptr:
120+
switch (getAddressSize()) {
121+
case 2:
122+
case 4:
123+
case 8:
124+
Result = getUnsigned(Offset, getAddressSize());
125+
break;
126+
default:
127+
return std::nullopt;
128+
}
129+
break;
130+
case dwarf::DW_EH_PE_uleb128:
131+
Result = getULEB128(Offset);
132+
break;
133+
case dwarf::DW_EH_PE_sleb128:
134+
Result = getSLEB128(Offset);
135+
break;
136+
case dwarf::DW_EH_PE_udata2:
137+
Result = getUnsigned(Offset, 2);
138+
break;
139+
case dwarf::DW_EH_PE_udata4:
140+
Result = getUnsigned(Offset, 4);
141+
break;
142+
case dwarf::DW_EH_PE_udata8:
143+
Result = getUnsigned(Offset, 8);
144+
break;
145+
case dwarf::DW_EH_PE_sdata2:
146+
Result = getSigned(Offset, 2);
147+
break;
148+
case dwarf::DW_EH_PE_sdata4:
149+
Result = SignExtend64<32>(getRelocatedValue(4, Offset));
150+
break;
151+
case dwarf::DW_EH_PE_sdata8:
152+
Result = getRelocatedValue(8, Offset);
153+
break;
154+
default:
155+
return std::nullopt;
156+
}
157+
// Then add relative offset, if required
158+
switch (Encoding & 0x70) {
159+
case dwarf::DW_EH_PE_absptr:
160+
// do nothing
161+
break;
162+
case dwarf::DW_EH_PE_pcrel:
163+
Result += PCRelOffset;
164+
break;
165+
case dwarf::DW_EH_PE_datarel:
166+
case dwarf::DW_EH_PE_textrel:
167+
case dwarf::DW_EH_PE_funcrel:
168+
case dwarf::DW_EH_PE_aligned:
169+
default:
170+
*Offset = OldOffset;
171+
return std::nullopt;
172+
}
173+
174+
return Result;
175+
}
84176
};
85177

86-
} // end namespace llvm
178+
class DWARFDataExtractorSimple
179+
: public DWARFDataExtractorBase<DWARFDataExtractorSimple> {
180+
using DWARFDataExtractorBase::DWARFDataExtractorBase;
181+
182+
uint64_t getRelocatedValueImpl(uint32_t Size, uint64_t *Off,
183+
uint64_t *SectionIndex = nullptr,
184+
Error *Err = nullptr) const {
185+
assert(SectionIndex == nullptr &&
186+
"DWARFDATAExtractorSimple cannot take section indices.");
187+
return getUnsigned(Off, Size, Err);
188+
}
189+
};
87190

191+
} // end namespace llvm
88192
#endif // LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTOR_H

llvm/lib/DebugInfo/DWARF/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ add_llvm_component_library(LLVMDebugInfoDWARF
44
DWARFAcceleratorTable.cpp
55
DWARFCompileUnit.cpp
66
DWARFContext.cpp
7-
DWARFDataExtractor.cpp
8-
DWARFDataExtractorSimple.cpp
97
DWARFDebugAbbrev.cpp
108
DWARFDebugAddr.cpp
119
DWARFDebugArangeSet.cpp

llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)