Skip to content

Commit 174545c

Browse files
[NFC] Split portions of DWARFDataExtractor into DWARFDataExtractorSimple.
Currently, DWARFDataExtractor can extract data without performing relocations, but is coded such that it still depends on all the relocation machinery, like DWARFSections and similar. Extract most functionality into a new base class, DWARFDataExtractorSimple, and have DWARFDataExtractor add the relocation dependent pieces as overrides. This will allow moving DWARFDataExtractorSimple into a new lower-level, lighter-weight library with fewer external dependencies. This is another in a series of refactoring changes to create a new better-layered, lo-level Dwarf library that can be called from lower-level code without circular dependencies.
1 parent 8b53ada commit 174545c

File tree

5 files changed

+217
-148
lines changed

5 files changed

+217
-148
lines changed

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

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,79 +10,46 @@
1010
#define LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTOR_H
1111

1212
#include "llvm/BinaryFormat/Dwarf.h"
13+
#include "llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h"
1314
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
14-
#include "llvm/Support/DataExtractor.h"
1515

1616
namespace llvm {
1717
class DWARFObject;
1818

19-
/// A DataExtractor (typically for an in-memory copy of an object-file section)
20-
/// plus a relocation map for that section, if there is one.
21-
class DWARFDataExtractor : public DataExtractor {
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 {
2223
const DWARFObject *Obj = nullptr;
2324
const DWARFSection *Section = nullptr;
2425

2526
public:
27+
using DWARFDataExtractorSimple::DWARFDataExtractorSimple;
28+
2629
/// Constructor for the normal case of extracting data from a DWARF section.
2730
/// The DWARFSection's lifetime must be at least as long as the extractor's.
2831
DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
2932
bool IsLittleEndian, uint8_t AddressSize)
30-
: DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj),
31-
Section(&Section) {}
32-
33-
/// Constructor for cases when there are no relocations.
34-
DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
35-
: DataExtractor(Data, IsLittleEndian, AddressSize) {}
36-
DWARFDataExtractor(ArrayRef<uint8_t> Data, bool IsLittleEndian,
37-
uint8_t AddressSize)
38-
: DataExtractor(
39-
StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()),
40-
IsLittleEndian, AddressSize) {}
33+
: DWARFDataExtractorSimple(Section.Data, IsLittleEndian, AddressSize),
34+
Obj(&Obj), Section(&Section) {}
4135

4236
/// Truncating constructor
4337
DWARFDataExtractor(const DWARFDataExtractor &Other, size_t Length)
44-
: DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(),
45-
Other.getAddressSize()),
38+
: DWARFDataExtractorSimple(Other.getData().substr(0, Length),
39+
Other.isLittleEndian(),
40+
Other.getAddressSize()),
4641
Obj(Other.Obj), Section(Other.Section) {}
4742

48-
/// Extracts the DWARF "initial length" field, which can either be a 32-bit
49-
/// value smaller than 0xfffffff0, or the value 0xffffffff followed by a
50-
/// 64-bit length. Returns the actual length, and the DWARF format which is
51-
/// encoded in the field. In case of errors, it returns {0, DWARF32} and
52-
/// leaves the offset unchanged.
53-
std::pair<uint64_t, dwarf::DwarfFormat>
54-
getInitialLength(uint64_t *Off, Error *Err = nullptr) const;
55-
56-
std::pair<uint64_t, dwarf::DwarfFormat> getInitialLength(Cursor &C) const {
57-
return getInitialLength(&getOffset(C), &getError(C));
58-
}
59-
6043
/// Extracts a value and applies a relocation to the result if
6144
/// one exists for the given offset.
6245
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
6346
uint64_t *SectionIndex = nullptr,
64-
Error *Err = nullptr) const;
47+
Error *Err = nullptr) const override;
48+
6549
uint64_t getRelocatedValue(Cursor &C, uint32_t Size,
66-
uint64_t *SectionIndex = nullptr) const {
50+
uint64_t *SectionIndex = nullptr) const override {
6751
return getRelocatedValue(Size, &getOffset(C), SectionIndex, &getError(C));
6852
}
69-
70-
/// Extracts an address-sized value and applies a relocation to the result if
71-
/// one exists for the given offset.
72-
uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const {
73-
return getRelocatedValue(getAddressSize(), Off, SecIx);
74-
}
75-
uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const {
76-
return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx,
77-
&getError(C));
78-
}
79-
80-
/// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
81-
/// There is a DWARF encoding that uses a PC-relative adjustment.
82-
/// For these values, \p AbsPosOffset is used to fix them, which should
83-
/// reflect the absolute address of this pointer.
84-
std::optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
85-
uint64_t AbsPosOffset = 0) const;
8653
};
8754

8855
} // end namespace llvm
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//===- DWARFDataExtractorSimple.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+
// Non relocating, low-level dwarf-data extractor. Suitable for use from
10+
// libraries that cannot have build-time dependencies on relocation providers.
11+
12+
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTORSIMPLE_H
13+
#define LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTORSIMPLE_H
14+
15+
#include "llvm/BinaryFormat/Dwarf.h"
16+
#include "llvm/Support/DataExtractor.h"
17+
18+
namespace llvm {
19+
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.
23+
24+
class DWARFDataExtractorSimple : public DataExtractor {
25+
26+
public:
27+
DWARFDataExtractorSimple(StringRef Data, bool IsLittleEndian,
28+
uint8_t AddressSize)
29+
: DataExtractor(Data, IsLittleEndian, AddressSize) {}
30+
DWARFDataExtractorSimple(ArrayRef<uint8_t> Data, bool IsLittleEndian,
31+
uint8_t AddressSize)
32+
: DataExtractor(
33+
StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()),
34+
IsLittleEndian, AddressSize) {}
35+
36+
/// Truncating constructor
37+
DWARFDataExtractorSimple(const DWARFDataExtractorSimple &Other, size_t Length)
38+
: DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(),
39+
Other.getAddressSize()) {}
40+
41+
virtual ~DWARFDataExtractorSimple() = default;
42+
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));
53+
}
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 {
66+
return getRelocatedValue(Size, &getOffset(C), SectionIndex, &getError(C));
67+
}
68+
69+
/// Extracts an address-sized value.
70+
uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const {
71+
return getRelocatedValue(getAddressSize(), Off, SecIx);
72+
}
73+
uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const {
74+
return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx,
75+
&getError(C));
76+
}
77+
78+
/// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
79+
/// There is a DWARF encoding that uses a PC-relative adjustment.
80+
/// For these values, \p AbsPosOffset is used to fix them, which should
81+
/// reflect the absolute address of this pointer.
82+
std::optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
83+
uint64_t AbsPosOffset = 0) const;
84+
};
85+
86+
} // end namespace llvm
87+
88+
#endif // LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTOR_H

llvm/lib/DebugInfo/DWARF/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMDebugInfoDWARF
55
DWARFCompileUnit.cpp
66
DWARFContext.cpp
77
DWARFDataExtractor.cpp
8+
DWARFDataExtractorSimple.cpp
89
DWARFDebugAbbrev.cpp
910
DWARFDebugAddr.cpp
1011
DWARFDebugArangeSet.cpp

llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,6 @@
1313

1414
using namespace llvm;
1515

16-
std::pair<uint64_t, dwarf::DwarfFormat>
17-
DWARFDataExtractor::getInitialLength(uint64_t *Off, Error *Err) const {
18-
ErrorAsOutParameter ErrAsOut(Err);
19-
if (Err && *Err)
20-
return {0, dwarf::DWARF32};
21-
22-
Cursor C(*Off);
23-
uint64_t Length = getRelocatedValue(C, 4);
24-
dwarf::DwarfFormat Format = dwarf::DWARF32;
25-
if (Length == dwarf::DW_LENGTH_DWARF64) {
26-
Length = getRelocatedValue(C, 8);
27-
Format = dwarf::DWARF64;
28-
} else if (Length >= dwarf::DW_LENGTH_lo_reserved) {
29-
cantFail(C.takeError());
30-
if (Err)
31-
*Err = createStringError(
32-
errc::invalid_argument,
33-
"unsupported reserved unit length of value 0x%8.8" PRIx64, Length);
34-
return {0, dwarf::DWARF32};
35-
}
36-
37-
if (C) {
38-
*Off = C.tell();
39-
return {Length, Format};
40-
}
41-
if (Err)
42-
*Err = C.takeError();
43-
else
44-
consumeError(C.takeError());
45-
return {0, dwarf::DWARF32};
46-
}
47-
4816
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
4917
uint64_t *SecNdx,
5018
Error *Err) const {
@@ -67,71 +35,3 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
6735
R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R);
6836
return R;
6937
}
70-
71-
std::optional<uint64_t>
72-
DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
73-
uint64_t PCRelOffset) const {
74-
if (Encoding == dwarf::DW_EH_PE_omit)
75-
return std::nullopt;
76-
77-
uint64_t Result = 0;
78-
uint64_t OldOffset = *Offset;
79-
// First get value
80-
switch (Encoding & 0x0F) {
81-
case dwarf::DW_EH_PE_absptr:
82-
switch (getAddressSize()) {
83-
case 2:
84-
case 4:
85-
case 8:
86-
Result = getUnsigned(Offset, getAddressSize());
87-
break;
88-
default:
89-
return std::nullopt;
90-
}
91-
break;
92-
case dwarf::DW_EH_PE_uleb128:
93-
Result = getULEB128(Offset);
94-
break;
95-
case dwarf::DW_EH_PE_sleb128:
96-
Result = getSLEB128(Offset);
97-
break;
98-
case dwarf::DW_EH_PE_udata2:
99-
Result = getUnsigned(Offset, 2);
100-
break;
101-
case dwarf::DW_EH_PE_udata4:
102-
Result = getUnsigned(Offset, 4);
103-
break;
104-
case dwarf::DW_EH_PE_udata8:
105-
Result = getUnsigned(Offset, 8);
106-
break;
107-
case dwarf::DW_EH_PE_sdata2:
108-
Result = getSigned(Offset, 2);
109-
break;
110-
case dwarf::DW_EH_PE_sdata4:
111-
Result = SignExtend64<32>(getRelocatedValue(4, Offset));
112-
break;
113-
case dwarf::DW_EH_PE_sdata8:
114-
Result = getRelocatedValue(8, Offset);
115-
break;
116-
default:
117-
return std::nullopt;
118-
}
119-
// Then add relative offset, if required
120-
switch (Encoding & 0x70) {
121-
case dwarf::DW_EH_PE_absptr:
122-
// do nothing
123-
break;
124-
case dwarf::DW_EH_PE_pcrel:
125-
Result += PCRelOffset;
126-
break;
127-
case dwarf::DW_EH_PE_datarel:
128-
case dwarf::DW_EH_PE_textrel:
129-
case dwarf::DW_EH_PE_funcrel:
130-
case dwarf::DW_EH_PE_aligned:
131-
default:
132-
*Offset = OldOffset;
133-
return std::nullopt;
134-
}
135-
136-
return Result;
137-
}

0 commit comments

Comments
 (0)