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