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
1820namespace 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
2627public:
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
0 commit comments