File: | build/source/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp |
Warning: | line 219, column 31 The left operand of '==' is a garbage value due to array index out of bounds |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- DWARFFormValue.cpp -------------------------------------------------===// | |||
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 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" | |||
10 | #include "llvm/ADT/ArrayRef.h" | |||
11 | #include "llvm/ADT/StringRef.h" | |||
12 | #include "llvm/BinaryFormat/Dwarf.h" | |||
13 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | |||
14 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" | |||
15 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" | |||
16 | #include "llvm/DebugInfo/DWARF/DWARFObject.h" | |||
17 | #include "llvm/DebugInfo/DWARF/DWARFSection.h" | |||
18 | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" | |||
19 | #include "llvm/Support/ErrorHandling.h" | |||
20 | #include "llvm/Support/Format.h" | |||
21 | #include "llvm/Support/WithColor.h" | |||
22 | #include "llvm/Support/raw_ostream.h" | |||
23 | #include <cinttypes> | |||
24 | #include <cstdint> | |||
25 | #include <limits> | |||
26 | #include <optional> | |||
27 | ||||
28 | using namespace llvm; | |||
29 | using namespace dwarf; | |||
30 | ||||
31 | static const DWARFFormValue::FormClass DWARF5FormClasses[] = { | |||
32 | DWARFFormValue::FC_Unknown, // 0x0 | |||
33 | DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr | |||
34 | DWARFFormValue::FC_Unknown, // 0x02 unused | |||
35 | DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2 | |||
36 | DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4 | |||
37 | DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2 | |||
38 | // --- These can be FC_SectionOffset in DWARF3 and below: | |||
39 | DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4 | |||
40 | DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8 | |||
41 | // --- | |||
42 | DWARFFormValue::FC_String, // 0x08 DW_FORM_string | |||
43 | DWARFFormValue::FC_Block, // 0x09 DW_FORM_block | |||
44 | DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1 | |||
45 | DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1 | |||
46 | DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag | |||
47 | DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata | |||
48 | DWARFFormValue::FC_String, // 0x0e DW_FORM_strp | |||
49 | DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata | |||
50 | DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr | |||
51 | DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1 | |||
52 | DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2 | |||
53 | DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4 | |||
54 | DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8 | |||
55 | DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata | |||
56 | DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect | |||
57 | DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset | |||
58 | DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc | |||
59 | DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present | |||
60 | DWARFFormValue::FC_String, // 0x1a DW_FORM_strx | |||
61 | DWARFFormValue::FC_Address, // 0x1b DW_FORM_addrx | |||
62 | DWARFFormValue::FC_Reference, // 0x1c DW_FORM_ref_sup4 | |||
63 | DWARFFormValue::FC_String, // 0x1d DW_FORM_strp_sup | |||
64 | DWARFFormValue::FC_Constant, // 0x1e DW_FORM_data16 | |||
65 | DWARFFormValue::FC_String, // 0x1f DW_FORM_line_strp | |||
66 | DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig8 | |||
67 | DWARFFormValue::FC_Constant, // 0x21 DW_FORM_implicit_const | |||
68 | DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx | |||
69 | DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx | |||
70 | DWARFFormValue::FC_Reference, // 0x24 DW_FORM_ref_sup8 | |||
71 | DWARFFormValue::FC_String, // 0x25 DW_FORM_strx1 | |||
72 | DWARFFormValue::FC_String, // 0x26 DW_FORM_strx2 | |||
73 | DWARFFormValue::FC_String, // 0x27 DW_FORM_strx3 | |||
74 | DWARFFormValue::FC_String, // 0x28 DW_FORM_strx4 | |||
75 | DWARFFormValue::FC_Address, // 0x29 DW_FORM_addrx1 | |||
76 | DWARFFormValue::FC_Address, // 0x2a DW_FORM_addrx2 | |||
77 | DWARFFormValue::FC_Address, // 0x2b DW_FORM_addrx3 | |||
78 | DWARFFormValue::FC_Address, // 0x2c DW_FORM_addrx4 | |||
79 | DWARFFormValue::FC_Address, // 0x2001 DW_FORM_addrx_offset | |||
80 | }; | |||
81 | ||||
82 | DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { | |||
83 | return DWARFFormValue(F, ValueType(V)); | |||
84 | } | |||
85 | ||||
86 | DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) { | |||
87 | return DWARFFormValue(F, ValueType(V)); | |||
88 | } | |||
89 | ||||
90 | DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) { | |||
91 | return DWARFFormValue(F, ValueType(V)); | |||
92 | } | |||
93 | ||||
94 | DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, | |||
95 | ArrayRef<uint8_t> D) { | |||
96 | ValueType V; | |||
97 | V.uval = D.size(); | |||
98 | V.data = D.data(); | |||
99 | return DWARFFormValue(F, V); | |||
100 | } | |||
101 | ||||
102 | DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, | |||
103 | uint64_t *OffsetPtr) { | |||
104 | DWARFFormValue FormValue(F); | |||
105 | FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, | |||
106 | U->getFormParams(), U); | |||
107 | return FormValue; | |||
108 | } | |||
109 | ||||
110 | bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, | |||
111 | uint64_t *OffsetPtr, | |||
112 | const dwarf::FormParams Params) { | |||
113 | bool Indirect = false; | |||
114 | do { | |||
115 | switch (Form) { | |||
116 | // Blocks of inlined data that have a length field and the data bytes | |||
117 | // inlined in the .debug_info. | |||
118 | case DW_FORM_exprloc: | |||
119 | case DW_FORM_block: { | |||
120 | uint64_t size = DebugInfoData.getULEB128(OffsetPtr); | |||
121 | *OffsetPtr += size; | |||
122 | return true; | |||
123 | } | |||
124 | case DW_FORM_block1: { | |||
125 | uint8_t size = DebugInfoData.getU8(OffsetPtr); | |||
126 | *OffsetPtr += size; | |||
127 | return true; | |||
128 | } | |||
129 | case DW_FORM_block2: { | |||
130 | uint16_t size = DebugInfoData.getU16(OffsetPtr); | |||
131 | *OffsetPtr += size; | |||
132 | return true; | |||
133 | } | |||
134 | case DW_FORM_block4: { | |||
135 | uint32_t size = DebugInfoData.getU32(OffsetPtr); | |||
136 | *OffsetPtr += size; | |||
137 | return true; | |||
138 | } | |||
139 | ||||
140 | // Inlined NULL terminated C-strings. | |||
141 | case DW_FORM_string: | |||
142 | DebugInfoData.getCStr(OffsetPtr); | |||
143 | return true; | |||
144 | ||||
145 | case DW_FORM_addr: | |||
146 | case DW_FORM_ref_addr: | |||
147 | case DW_FORM_flag_present: | |||
148 | case DW_FORM_data1: | |||
149 | case DW_FORM_data2: | |||
150 | case DW_FORM_data4: | |||
151 | case DW_FORM_data8: | |||
152 | case DW_FORM_data16: | |||
153 | case DW_FORM_flag: | |||
154 | case DW_FORM_ref1: | |||
155 | case DW_FORM_ref2: | |||
156 | case DW_FORM_ref4: | |||
157 | case DW_FORM_ref8: | |||
158 | case DW_FORM_ref_sig8: | |||
159 | case DW_FORM_ref_sup4: | |||
160 | case DW_FORM_ref_sup8: | |||
161 | case DW_FORM_strx1: | |||
162 | case DW_FORM_strx2: | |||
163 | case DW_FORM_strx3: | |||
164 | case DW_FORM_strx4: | |||
165 | case DW_FORM_addrx1: | |||
166 | case DW_FORM_addrx2: | |||
167 | case DW_FORM_addrx3: | |||
168 | case DW_FORM_addrx4: | |||
169 | case DW_FORM_sec_offset: | |||
170 | case DW_FORM_strp: | |||
171 | case DW_FORM_strp_sup: | |||
172 | case DW_FORM_line_strp: | |||
173 | case DW_FORM_GNU_ref_alt: | |||
174 | case DW_FORM_GNU_strp_alt: | |||
175 | case DW_FORM_implicit_const: | |||
176 | if (std::optional<uint8_t> FixedSize = | |||
177 | dwarf::getFixedFormByteSize(Form, Params)) { | |||
178 | *OffsetPtr += *FixedSize; | |||
179 | return true; | |||
180 | } | |||
181 | return false; | |||
182 | ||||
183 | // signed or unsigned LEB 128 values. | |||
184 | case DW_FORM_sdata: | |||
185 | DebugInfoData.getSLEB128(OffsetPtr); | |||
186 | return true; | |||
187 | ||||
188 | case DW_FORM_udata: | |||
189 | case DW_FORM_ref_udata: | |||
190 | case DW_FORM_strx: | |||
191 | case DW_FORM_addrx: | |||
192 | case DW_FORM_loclistx: | |||
193 | case DW_FORM_rnglistx: | |||
194 | case DW_FORM_GNU_addr_index: | |||
195 | case DW_FORM_GNU_str_index: | |||
196 | DebugInfoData.getULEB128(OffsetPtr); | |||
197 | return true; | |||
198 | ||||
199 | case DW_FORM_LLVM_addrx_offset: | |||
200 | DebugInfoData.getULEB128(OffsetPtr); | |||
201 | *OffsetPtr += 4; | |||
202 | return true; | |||
203 | ||||
204 | case DW_FORM_indirect: | |||
205 | Indirect = true; | |||
206 | Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr)); | |||
207 | break; | |||
208 | ||||
209 | default: | |||
210 | return false; | |||
211 | } | |||
212 | } while (Indirect); | |||
213 | return true; | |||
214 | } | |||
215 | ||||
216 | bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { | |||
217 | // First, check DWARF5 form classes. | |||
218 | if (Form < ArrayRef(DWARF5FormClasses).size() && | |||
219 | DWARF5FormClasses[Form] == FC) | |||
| ||||
220 | return true; | |||
221 | // Check more forms from extensions and proposals. | |||
222 | switch (Form) { | |||
223 | case DW_FORM_GNU_ref_alt: | |||
224 | return (FC == FC_Reference); | |||
225 | case DW_FORM_GNU_addr_index: | |||
226 | return (FC == FC_Address); | |||
227 | case DW_FORM_GNU_str_index: | |||
228 | case DW_FORM_GNU_strp_alt: | |||
229 | return (FC == FC_String); | |||
230 | case DW_FORM_LLVM_addrx_offset: | |||
231 | return (FC == FC_Address); | |||
232 | default: | |||
233 | break; | |||
234 | } | |||
235 | ||||
236 | if (FC == FC_SectionOffset) { | |||
237 | if (Form == DW_FORM_strp || Form == DW_FORM_line_strp) | |||
238 | return true; | |||
239 | // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section | |||
240 | // offset. If we don't have a DWARFUnit, default to the old behavior. | |||
241 | if (Form == DW_FORM_data4 || Form == DW_FORM_data8) | |||
242 | return !U || U->getVersion() <= 3; | |||
243 | } | |||
244 | ||||
245 | return false; | |||
246 | } | |||
247 | ||||
248 | bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, | |||
249 | uint64_t *OffsetPtr, dwarf::FormParams FP, | |||
250 | const DWARFContext *Ctx, | |||
251 | const DWARFUnit *CU) { | |||
252 | if (!Ctx && CU) | |||
253 | Ctx = &CU->getContext(); | |||
254 | C = Ctx; | |||
255 | U = CU; | |||
256 | Format = FP.Format; | |||
257 | bool Indirect = false; | |||
258 | bool IsBlock = false; | |||
259 | Value.data = nullptr; | |||
260 | // Read the value for the form into value and follow and DW_FORM_indirect | |||
261 | // instances we run into | |||
262 | Error Err = Error::success(); | |||
263 | do { | |||
264 | Indirect = false; | |||
265 | switch (Form) { | |||
266 | case DW_FORM_addr: | |||
267 | case DW_FORM_ref_addr: { | |||
268 | uint16_t Size = | |||
269 | (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize(); | |||
270 | Value.uval = | |||
271 | Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err); | |||
272 | break; | |||
273 | } | |||
274 | case DW_FORM_exprloc: | |||
275 | case DW_FORM_block: | |||
276 | Value.uval = Data.getULEB128(OffsetPtr, &Err); | |||
277 | IsBlock = true; | |||
278 | break; | |||
279 | case DW_FORM_block1: | |||
280 | Value.uval = Data.getU8(OffsetPtr, &Err); | |||
281 | IsBlock = true; | |||
282 | break; | |||
283 | case DW_FORM_block2: | |||
284 | Value.uval = Data.getU16(OffsetPtr, &Err); | |||
285 | IsBlock = true; | |||
286 | break; | |||
287 | case DW_FORM_block4: | |||
288 | Value.uval = Data.getU32(OffsetPtr, &Err); | |||
289 | IsBlock = true; | |||
290 | break; | |||
291 | case DW_FORM_data1: | |||
292 | case DW_FORM_ref1: | |||
293 | case DW_FORM_flag: | |||
294 | case DW_FORM_strx1: | |||
295 | case DW_FORM_addrx1: | |||
296 | Value.uval = Data.getU8(OffsetPtr, &Err); | |||
297 | break; | |||
298 | case DW_FORM_data2: | |||
299 | case DW_FORM_ref2: | |||
300 | case DW_FORM_strx2: | |||
301 | case DW_FORM_addrx2: | |||
302 | Value.uval = Data.getU16(OffsetPtr, &Err); | |||
303 | break; | |||
304 | case DW_FORM_strx3: | |||
305 | case DW_FORM_addrx3: | |||
306 | Value.uval = Data.getU24(OffsetPtr, &Err); | |||
307 | break; | |||
308 | case DW_FORM_data4: | |||
309 | case DW_FORM_ref4: | |||
310 | case DW_FORM_ref_sup4: | |||
311 | case DW_FORM_strx4: | |||
312 | case DW_FORM_addrx4: | |||
313 | Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err); | |||
314 | break; | |||
315 | case DW_FORM_data8: | |||
316 | case DW_FORM_ref8: | |||
317 | case DW_FORM_ref_sup8: | |||
318 | Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err); | |||
319 | break; | |||
320 | case DW_FORM_data16: | |||
321 | // Treat this like a 16-byte block. | |||
322 | Value.uval = 16; | |||
323 | IsBlock = true; | |||
324 | break; | |||
325 | case DW_FORM_sdata: | |||
326 | Value.sval = Data.getSLEB128(OffsetPtr, &Err); | |||
327 | break; | |||
328 | case DW_FORM_udata: | |||
329 | case DW_FORM_ref_udata: | |||
330 | case DW_FORM_rnglistx: | |||
331 | case DW_FORM_loclistx: | |||
332 | case DW_FORM_GNU_addr_index: | |||
333 | case DW_FORM_GNU_str_index: | |||
334 | case DW_FORM_addrx: | |||
335 | case DW_FORM_strx: | |||
336 | Value.uval = Data.getULEB128(OffsetPtr, &Err); | |||
337 | break; | |||
338 | case DW_FORM_LLVM_addrx_offset: | |||
339 | Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32; | |||
340 | Value.uval |= Data.getU32(OffsetPtr, &Err); | |||
341 | break; | |||
342 | case DW_FORM_string: | |||
343 | Value.cstr = Data.getCStr(OffsetPtr, &Err); | |||
344 | break; | |||
345 | case DW_FORM_indirect: | |||
346 | Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err)); | |||
347 | Indirect = true; | |||
348 | break; | |||
349 | case DW_FORM_strp: | |||
350 | case DW_FORM_sec_offset: | |||
351 | case DW_FORM_GNU_ref_alt: | |||
352 | case DW_FORM_GNU_strp_alt: | |||
353 | case DW_FORM_line_strp: | |||
354 | case DW_FORM_strp_sup: { | |||
355 | Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), | |||
356 | OffsetPtr, nullptr, &Err); | |||
357 | break; | |||
358 | } | |||
359 | case DW_FORM_flag_present: | |||
360 | Value.uval = 1; | |||
361 | break; | |||
362 | case DW_FORM_ref_sig8: | |||
363 | Value.uval = Data.getU64(OffsetPtr, &Err); | |||
364 | break; | |||
365 | case DW_FORM_implicit_const: | |||
366 | // Value has been already set by DWARFFormValue::createFromSValue. | |||
367 | break; | |||
368 | default: | |||
369 | // DWARFFormValue::skipValue() will have caught this and caused all | |||
370 | // DWARF DIEs to fail to be parsed, so this code is not be reachable. | |||
371 | llvm_unreachable("unsupported form")::llvm::llvm_unreachable_internal("unsupported form", "llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp" , 371); | |||
372 | } | |||
373 | } while (Indirect && !Err); | |||
374 | ||||
375 | if (IsBlock) | |||
376 | Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin(); | |||
377 | ||||
378 | return !errorToBool(std::move(Err)); | |||
379 | } | |||
380 | ||||
381 | void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize, | |||
382 | uint64_t Address) { | |||
383 | uint8_t HexDigits = AddressSize * 2; | |||
384 | OS << format("0x%*.*" PRIx64"l" "x", HexDigits, HexDigits, Address); | |||
385 | } | |||
386 | ||||
387 | void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, | |||
388 | DIDumpOptions DumpOpts, | |||
389 | object::SectionedAddress SA) const { | |||
390 | dumpAddress(OS, U->getAddressByteSize(), SA.Address); | |||
391 | dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, | |||
392 | SA.SectionIndex); | |||
393 | } | |||
394 | ||||
395 | void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, | |||
396 | DIDumpOptions DumpOpts, | |||
397 | uint64_t SectionIndex) { | |||
398 | if (!DumpOpts.Verbose || SectionIndex == -1ULL) | |||
399 | return; | |||
400 | ArrayRef<SectionName> SectionNames = Obj.getSectionNames(); | |||
401 | const auto &SecRef = SectionNames[SectionIndex]; | |||
402 | ||||
403 | OS << " \"" << SecRef.Name << '\"'; | |||
404 | ||||
405 | // Print section index if name is not unique. | |||
406 | if (!SecRef.IsNameUnique) | |||
407 | OS << format(" [%" PRIu64"l" "u" "]", SectionIndex); | |||
408 | } | |||
409 | ||||
410 | void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { | |||
411 | uint64_t UValue = Value.uval; | |||
412 | bool CURelativeOffset = false; | |||
413 | raw_ostream &AddrOS = DumpOpts.ShowAddresses | |||
414 | ? WithColor(OS, HighlightColor::Address).get() | |||
415 | : nulls(); | |||
416 | int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format); | |||
417 | switch (Form) { | |||
418 | case DW_FORM_addr: | |||
419 | dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex}); | |||
420 | break; | |||
421 | case DW_FORM_addrx: | |||
422 | case DW_FORM_addrx1: | |||
423 | case DW_FORM_addrx2: | |||
424 | case DW_FORM_addrx3: | |||
425 | case DW_FORM_addrx4: | |||
426 | case DW_FORM_GNU_addr_index: | |||
427 | case DW_FORM_LLVM_addrx_offset: { | |||
428 | if (U == nullptr) { | |||
429 | OS << "<invalid dwarf unit>"; | |||
430 | break; | |||
431 | } | |||
432 | std::optional<object::SectionedAddress> A = getAsSectionedAddress(); | |||
433 | if (!A || DumpOpts.Verbose) { | |||
434 | if (Form == DW_FORM_LLVM_addrx_offset) { | |||
435 | uint32_t Index = UValue >> 32; | |||
436 | uint32_t Offset = UValue & 0xffffffff; | |||
437 | AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset); | |||
438 | } else | |||
439 | AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); | |||
440 | } | |||
441 | if (A) | |||
442 | dumpSectionedAddress(AddrOS, DumpOpts, *A); | |||
443 | else | |||
444 | OS << "<unresolved>"; | |||
445 | break; | |||
446 | } | |||
447 | case DW_FORM_flag_present: | |||
448 | OS << "true"; | |||
449 | break; | |||
450 | case DW_FORM_flag: | |||
451 | case DW_FORM_data1: | |||
452 | OS << format("0x%02x", (uint8_t)UValue); | |||
453 | break; | |||
454 | case DW_FORM_data2: | |||
455 | OS << format("0x%04x", (uint16_t)UValue); | |||
456 | break; | |||
457 | case DW_FORM_data4: | |||
458 | OS << format("0x%08x", (uint32_t)UValue); | |||
459 | break; | |||
460 | case DW_FORM_ref_sig8: | |||
461 | AddrOS << format("0x%016" PRIx64"l" "x", UValue); | |||
462 | break; | |||
463 | case DW_FORM_data8: | |||
464 | OS << format("0x%016" PRIx64"l" "x", UValue); | |||
465 | break; | |||
466 | case DW_FORM_data16: | |||
467 | OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16); | |||
468 | break; | |||
469 | case DW_FORM_string: | |||
470 | OS << '"'; | |||
471 | OS.write_escaped(Value.cstr); | |||
472 | OS << '"'; | |||
473 | break; | |||
474 | case DW_FORM_exprloc: | |||
475 | case DW_FORM_block: | |||
476 | case DW_FORM_block1: | |||
477 | case DW_FORM_block2: | |||
478 | case DW_FORM_block4: | |||
479 | if (UValue > 0) { | |||
480 | switch (Form) { | |||
481 | case DW_FORM_exprloc: | |||
482 | case DW_FORM_block: | |||
483 | AddrOS << format("<0x%" PRIx64"l" "x" "> ", UValue); | |||
484 | break; | |||
485 | case DW_FORM_block1: | |||
486 | AddrOS << format("<0x%2.2x> ", (uint8_t)UValue); | |||
487 | break; | |||
488 | case DW_FORM_block2: | |||
489 | AddrOS << format("<0x%4.4x> ", (uint16_t)UValue); | |||
490 | break; | |||
491 | case DW_FORM_block4: | |||
492 | AddrOS << format("<0x%8.8x> ", (uint32_t)UValue); | |||
493 | break; | |||
494 | default: | |||
495 | break; | |||
496 | } | |||
497 | ||||
498 | const uint8_t *DataPtr = Value.data; | |||
499 | if (DataPtr) { | |||
500 | // UValue contains size of block | |||
501 | const uint8_t *EndDataPtr = DataPtr + UValue; | |||
502 | while (DataPtr < EndDataPtr) { | |||
503 | AddrOS << format("%2.2x ", *DataPtr); | |||
504 | ++DataPtr; | |||
505 | } | |||
506 | } else | |||
507 | OS << "NULL"; | |||
508 | } | |||
509 | break; | |||
510 | ||||
511 | case DW_FORM_sdata: | |||
512 | case DW_FORM_implicit_const: | |||
513 | OS << Value.sval; | |||
514 | break; | |||
515 | case DW_FORM_udata: | |||
516 | OS << Value.uval; | |||
517 | break; | |||
518 | case DW_FORM_strp: | |||
519 | if (DumpOpts.Verbose) | |||
520 | OS << format(" .debug_str[0x%0*" PRIx64"l" "x" "] = ", OffsetDumpWidth, UValue); | |||
521 | dumpString(OS); | |||
522 | break; | |||
523 | case DW_FORM_line_strp: | |||
524 | if (DumpOpts.Verbose) | |||
525 | OS << format(" .debug_line_str[0x%0*" PRIx64"l" "x" "] = ", OffsetDumpWidth, | |||
526 | UValue); | |||
527 | dumpString(OS); | |||
528 | break; | |||
529 | case DW_FORM_strx: | |||
530 | case DW_FORM_strx1: | |||
531 | case DW_FORM_strx2: | |||
532 | case DW_FORM_strx3: | |||
533 | case DW_FORM_strx4: | |||
534 | case DW_FORM_GNU_str_index: | |||
535 | if (DumpOpts.Verbose) | |||
536 | OS << format("indexed (%8.8x) string = ", (uint32_t)UValue); | |||
537 | dumpString(OS); | |||
538 | break; | |||
539 | case DW_FORM_GNU_strp_alt: | |||
540 | if (DumpOpts.Verbose) | |||
541 | OS << format("alt indirect string, offset: 0x%" PRIx64"l" "x" "", UValue); | |||
542 | dumpString(OS); | |||
543 | break; | |||
544 | case DW_FORM_ref_addr: | |||
545 | AddrOS << format("0x%016" PRIx64"l" "x", UValue); | |||
546 | break; | |||
547 | case DW_FORM_ref1: | |||
548 | CURelativeOffset = true; | |||
549 | if (DumpOpts.Verbose) | |||
550 | AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue); | |||
551 | break; | |||
552 | case DW_FORM_ref2: | |||
553 | CURelativeOffset = true; | |||
554 | if (DumpOpts.Verbose) | |||
555 | AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue); | |||
556 | break; | |||
557 | case DW_FORM_ref4: | |||
558 | CURelativeOffset = true; | |||
559 | if (DumpOpts.Verbose) | |||
560 | AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue); | |||
561 | break; | |||
562 | case DW_FORM_ref8: | |||
563 | CURelativeOffset = true; | |||
564 | if (DumpOpts.Verbose) | |||
565 | AddrOS << format("cu + 0x%8.8" PRIx64"l" "x", UValue); | |||
566 | break; | |||
567 | case DW_FORM_ref_udata: | |||
568 | CURelativeOffset = true; | |||
569 | if (DumpOpts.Verbose) | |||
570 | AddrOS << format("cu + 0x%" PRIx64"l" "x", UValue); | |||
571 | break; | |||
572 | case DW_FORM_GNU_ref_alt: | |||
573 | AddrOS << format("<alt 0x%" PRIx64"l" "x" ">", UValue); | |||
574 | break; | |||
575 | ||||
576 | // All DW_FORM_indirect attributes should be resolved prior to calling | |||
577 | // this function | |||
578 | case DW_FORM_indirect: | |||
579 | OS << "DW_FORM_indirect"; | |||
580 | break; | |||
581 | ||||
582 | case DW_FORM_rnglistx: | |||
583 | OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue); | |||
584 | break; | |||
585 | ||||
586 | case DW_FORM_loclistx: | |||
587 | OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue); | |||
588 | break; | |||
589 | ||||
590 | case DW_FORM_sec_offset: | |||
591 | AddrOS << format("0x%0*" PRIx64"l" "x", OffsetDumpWidth, UValue); | |||
592 | break; | |||
593 | ||||
594 | default: | |||
595 | OS << format("DW_FORM(0x%4.4x)", Form); | |||
596 | break; | |||
597 | } | |||
598 | ||||
599 | if (CURelativeOffset) { | |||
600 | if (DumpOpts.Verbose) | |||
601 | OS << " => {"; | |||
602 | if (DumpOpts.ShowAddresses) | |||
603 | WithColor(OS, HighlightColor::Address).get() | |||
604 | << format("0x%8.8" PRIx64"l" "x", UValue + (U ? U->getOffset() : 0)); | |||
605 | if (DumpOpts.Verbose) | |||
606 | OS << "}"; | |||
607 | } | |||
608 | } | |||
609 | ||||
610 | void DWARFFormValue::dumpString(raw_ostream &OS) const { | |||
611 | if (auto DbgStr = dwarf::toString(*this)) { | |||
612 | auto COS = WithColor(OS, HighlightColor::String); | |||
613 | COS.get() << '"'; | |||
614 | COS.get().write_escaped(*DbgStr); | |||
615 | COS.get() << '"'; | |||
616 | } | |||
617 | } | |||
618 | ||||
619 | Expected<const char *> DWARFFormValue::getAsCString() const { | |||
620 | if (!isFormClass(FC_String)) | |||
621 | return make_error<StringError>("Invalid form for string attribute", | |||
622 | inconvertibleErrorCode()); | |||
623 | if (Form == DW_FORM_string) | |||
624 | return Value.cstr; | |||
625 | // FIXME: Add support for DW_FORM_GNU_strp_alt | |||
626 | if (Form == DW_FORM_GNU_strp_alt || C == nullptr) | |||
627 | return make_error<StringError>("Unsupported form for string attribute", | |||
628 | inconvertibleErrorCode()); | |||
629 | uint64_t Offset = Value.uval; | |||
630 | std::optional<uint32_t> Index; | |||
631 | if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx || | |||
632 | Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || | |||
633 | Form == DW_FORM_strx4) { | |||
634 | if (!U) | |||
635 | return make_error<StringError>("API limitation - string extraction not " | |||
636 | "available without a DWARFUnit", | |||
637 | inconvertibleErrorCode()); | |||
638 | Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset); | |||
639 | Index = Offset; | |||
640 | if (!StrOffset) | |||
641 | return StrOffset.takeError(); | |||
642 | Offset = *StrOffset; | |||
643 | } | |||
644 | // Prefer the Unit's string extractor, because for .dwo it will point to | |||
645 | // .debug_str.dwo, while the Context's extractor always uses .debug_str. | |||
646 | DataExtractor StrData = Form == DW_FORM_line_strp | |||
647 | ? C->getLineStringExtractor() | |||
648 | : U ? U->getStringExtractor() | |||
649 | : C->getStringExtractor(); | |||
650 | if (const char *Str = StrData.getCStr(&Offset)) | |||
651 | return Str; | |||
652 | std::string Msg = FormEncodingString(Form).str(); | |||
653 | if (Index) | |||
654 | Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str(); | |||
655 | Msg += (" offset " + Twine(Offset) + " is beyond .debug_str bounds").str(); | |||
656 | return make_error<StringError>(Msg, | |||
657 | inconvertibleErrorCode()); | |||
658 | } | |||
659 | ||||
660 | std::optional<uint64_t> DWARFFormValue::getAsAddress() const { | |||
661 | if (auto SA = getAsSectionedAddress()) | |||
662 | return SA->Address; | |||
663 | return std::nullopt; | |||
664 | } | |||
665 | ||||
666 | std::optional<object::SectionedAddress> | |||
667 | DWARFFormValue::getAsSectionedAddress() const { | |||
668 | if (!isFormClass(FC_Address)) | |||
669 | return std::nullopt; | |||
670 | bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset; | |||
671 | if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx || | |||
672 | Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 || | |||
673 | Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) { | |||
674 | ||||
675 | uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval; | |||
676 | if (!U) | |||
677 | return std::nullopt; | |||
678 | std::optional<object::SectionedAddress> SA = | |||
679 | U->getAddrOffsetSectionItem(Index); | |||
680 | if (!SA) | |||
681 | return std::nullopt; | |||
682 | if (AddrOffset) | |||
683 | SA->Address += (Value.uval & 0xffffffff); | |||
684 | return SA; | |||
685 | } | |||
686 | return {{Value.uval, Value.SectionIndex}}; | |||
687 | } | |||
688 | ||||
689 | std::optional<uint64_t> DWARFFormValue::getAsReference() const { | |||
690 | if (auto R = getAsRelativeReference()) | |||
691 | return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset; | |||
692 | return std::nullopt; | |||
693 | } | |||
694 | ||||
695 | std::optional<DWARFFormValue::UnitOffset> | |||
696 | DWARFFormValue::getAsRelativeReference() const { | |||
697 | if (!isFormClass(FC_Reference)) | |||
698 | return std::nullopt; | |||
699 | switch (Form) { | |||
700 | case DW_FORM_ref1: | |||
701 | case DW_FORM_ref2: | |||
702 | case DW_FORM_ref4: | |||
703 | case DW_FORM_ref8: | |||
704 | case DW_FORM_ref_udata: | |||
705 | if (!U) | |||
706 | return std::nullopt; | |||
707 | return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; | |||
708 | case DW_FORM_ref_addr: | |||
709 | case DW_FORM_ref_sig8: | |||
710 | case DW_FORM_GNU_ref_alt: | |||
711 | return UnitOffset{nullptr, Value.uval}; | |||
712 | default: | |||
713 | return std::nullopt; | |||
714 | } | |||
715 | } | |||
716 | ||||
717 | std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { | |||
718 | if (!isFormClass(FC_SectionOffset)) | |||
719 | return std::nullopt; | |||
720 | return Value.uval; | |||
721 | } | |||
722 | ||||
723 | std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { | |||
724 | if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || | |||
725 | Form == DW_FORM_sdata) | |||
726 | return std::nullopt; | |||
727 | return Value.uval; | |||
728 | } | |||
729 | ||||
730 | std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const { | |||
731 | if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || | |||
732 | (Form == DW_FORM_udata && | |||
733 | uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval)) | |||
734 | return std::nullopt; | |||
735 | switch (Form) { | |||
736 | case DW_FORM_data4: | |||
737 | return int32_t(Value.uval); | |||
738 | case DW_FORM_data2: | |||
739 | return int16_t(Value.uval); | |||
740 | case DW_FORM_data1: | |||
741 | return int8_t(Value.uval); | |||
742 | case DW_FORM_sdata: | |||
743 | case DW_FORM_data8: | |||
744 | default: | |||
745 | return Value.sval; | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { | |||
750 | if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) && | |||
| ||||
751 | Form != DW_FORM_data16) | |||
752 | return std::nullopt; | |||
753 | return ArrayRef(Value.data, Value.uval); | |||
754 | } | |||
755 | ||||
756 | std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const { | |||
757 | if (!isFormClass(FC_String) && Form == DW_FORM_string) | |||
758 | return std::nullopt; | |||
759 | return Value.uval; | |||
760 | } | |||
761 | ||||
762 | std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const { | |||
763 | if (!isFormClass(FC_Reference)) | |||
764 | return std::nullopt; | |||
765 | return Value.uval; | |||
766 | } | |||
767 | ||||
768 | std::optional<std::string> | |||
769 | DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { | |||
770 | if (U == nullptr || !isFormClass(FC_Constant)) | |||
771 | return std::nullopt; | |||
772 | DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit(); | |||
773 | if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) { | |||
774 | std::string FileName; | |||
775 | if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind, | |||
776 | FileName)) | |||
777 | return FileName; | |||
778 | } | |||
779 | return std::nullopt; | |||
780 | } |