/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
78 | | }; |
79 | | |
80 | 8 | DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { |
81 | 8 | return DWARFFormValue(F, ValueType(V)); |
82 | 8 | } |
83 | | |
84 | 12 | DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) { |
85 | 12 | return DWARFFormValue(F, ValueType(V)); |
86 | 12 | } |
87 | | |
88 | 1.94k | DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) { |
89 | 1.94k | return DWARFFormValue(F, ValueType(V)); |
90 | 1.94k | } |
91 | | |
92 | | DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, |
93 | 1 | ArrayRef<uint8_t> D) { |
94 | 1 | ValueType V; |
95 | 1 | V.uval = D.size(); |
96 | 1 | V.data = D.data(); |
97 | 1 | return DWARFFormValue(F, V); |
98 | 1 | } |
99 | | |
100 | | DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, |
101 | 32.2k | uint32_t *OffsetPtr) { |
102 | 32.2k | DWARFFormValue FormValue(F); |
103 | 32.2k | FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, |
104 | 32.2k | U->getFormParams(), U); |
105 | 32.2k | return FormValue; |
106 | 32.2k | } |
107 | | |
108 | | bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, |
109 | | uint32_t *OffsetPtr, |
110 | 19.3k | const dwarf::FormParams Params) { |
111 | 19.3k | bool Indirect = false; |
112 | 19.3k | do { |
113 | 19.3k | switch (Form) { |
114 | 19.3k | // Blocks of inlined data that have a length field and the data bytes |
115 | 19.3k | // inlined in the .debug_info. |
116 | 19.3k | case DW_FORM_exprloc: |
117 | 3.94k | case DW_FORM_block: { |
118 | 3.94k | uint64_t size = DebugInfoData.getULEB128(OffsetPtr); |
119 | 3.94k | *OffsetPtr += size; |
120 | 3.94k | return true; |
121 | 3.94k | } |
122 | 3.94k | case DW_FORM_block1: { |
123 | 2.91k | uint8_t size = DebugInfoData.getU8(OffsetPtr); |
124 | 2.91k | *OffsetPtr += size; |
125 | 2.91k | return true; |
126 | 3.94k | } |
127 | 3.94k | case DW_FORM_block2: { |
128 | 209 | uint16_t size = DebugInfoData.getU16(OffsetPtr); |
129 | 209 | *OffsetPtr += size; |
130 | 209 | return true; |
131 | 3.94k | } |
132 | 3.94k | case DW_FORM_block4: { |
133 | 204 | uint32_t size = DebugInfoData.getU32(OffsetPtr); |
134 | 204 | *OffsetPtr += size; |
135 | 204 | return true; |
136 | 3.94k | } |
137 | 3.94k | |
138 | 3.94k | // Inlined NULL terminated C-strings. |
139 | 3.94k | case DW_FORM_string: |
140 | 746 | DebugInfoData.getCStr(OffsetPtr); |
141 | 746 | return true; |
142 | 3.94k | |
143 | 8.90k | case DW_FORM_addr: |
144 | 8.90k | case DW_FORM_ref_addr: |
145 | 8.90k | case DW_FORM_flag_present: |
146 | 8.90k | case DW_FORM_data1: |
147 | 8.90k | case DW_FORM_data2: |
148 | 8.90k | case DW_FORM_data4: |
149 | 8.90k | case DW_FORM_data8: |
150 | 8.90k | case DW_FORM_data16: |
151 | 8.90k | case DW_FORM_flag: |
152 | 8.90k | case DW_FORM_ref1: |
153 | 8.90k | case DW_FORM_ref2: |
154 | 8.90k | case DW_FORM_ref4: |
155 | 8.90k | case DW_FORM_ref8: |
156 | 8.90k | case DW_FORM_ref_sig8: |
157 | 8.90k | case DW_FORM_ref_sup4: |
158 | 8.90k | case DW_FORM_ref_sup8: |
159 | 8.90k | case DW_FORM_strx1: |
160 | 8.90k | case DW_FORM_strx2: |
161 | 8.90k | case DW_FORM_strx4: |
162 | 8.90k | case DW_FORM_addrx1: |
163 | 8.90k | case DW_FORM_addrx2: |
164 | 8.90k | case DW_FORM_addrx4: |
165 | 8.90k | case DW_FORM_sec_offset: |
166 | 8.90k | case DW_FORM_strp: |
167 | 8.90k | case DW_FORM_strp_sup: |
168 | 8.90k | case DW_FORM_line_strp: |
169 | 8.90k | case DW_FORM_GNU_ref_alt: |
170 | 8.90k | case DW_FORM_GNU_strp_alt: |
171 | 8.90k | if (Optional<uint8_t> FixedSize = |
172 | 8.90k | dwarf::getFixedFormByteSize(Form, Params)) { |
173 | 8.90k | *OffsetPtr += *FixedSize; |
174 | 8.90k | return true; |
175 | 8.90k | } |
176 | 1 | return false; |
177 | 1 | |
178 | 1 | // signed or unsigned LEB 128 values. |
179 | 413 | case DW_FORM_sdata: |
180 | 413 | DebugInfoData.getSLEB128(OffsetPtr); |
181 | 413 | return true; |
182 | 1 | |
183 | 1.97k | case DW_FORM_udata: |
184 | 1.97k | case DW_FORM_ref_udata: |
185 | 1.97k | case DW_FORM_strx: |
186 | 1.97k | case DW_FORM_addrx: |
187 | 1.97k | case DW_FORM_loclistx: |
188 | 1.97k | case DW_FORM_rnglistx: |
189 | 1.97k | case DW_FORM_GNU_addr_index: |
190 | 1.97k | case DW_FORM_GNU_str_index: |
191 | 1.97k | DebugInfoData.getULEB128(OffsetPtr); |
192 | 1.97k | return true; |
193 | 1.97k | |
194 | 1.97k | case DW_FORM_indirect: |
195 | 0 | Indirect = true; |
196 | 0 | Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr)); |
197 | 0 | break; |
198 | 1.97k | |
199 | 1.97k | default: |
200 | 0 | return false; |
201 | 0 | } |
202 | 0 | } while (Indirect); |
203 | 19.3k | return true0 ; |
204 | 19.3k | } |
205 | | |
206 | 128k | bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { |
207 | 128k | // First, check DWARF5 form classes. |
208 | 128k | if (Form < makeArrayRef(DWARF5FormClasses).size() && |
209 | 128k | DWARF5FormClasses[Form] == FC127k ) |
210 | 74.5k | return true; |
211 | 54.3k | // Check more forms from extensions and proposals. |
212 | 54.3k | switch (Form) { |
213 | 54.3k | case DW_FORM_GNU_ref_alt: |
214 | 9 | return (FC == FC_Reference); |
215 | 54.3k | case DW_FORM_GNU_addr_index: |
216 | 182 | return (FC == FC_Address); |
217 | 54.3k | case DW_FORM_GNU_str_index: |
218 | 1.55k | case DW_FORM_GNU_strp_alt: |
219 | 1.55k | return (FC == FC_String); |
220 | 52.5k | default: |
221 | 52.5k | break; |
222 | 52.5k | } |
223 | 52.5k | |
224 | 52.5k | if (FC == FC_SectionOffset) { |
225 | 3.69k | if (Form == DW_FORM_strp || Form == DW_FORM_line_strp3.10k ) |
226 | 593 | return true; |
227 | 3.10k | // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section |
228 | 3.10k | // offset. If we don't have a DWARFUnit, default to the old behavior. |
229 | 3.10k | if (Form == DW_FORM_data4 || Form == DW_FORM_data81.43k ) |
230 | 1.67k | return !U || U->getVersion() <= 31.66k ; |
231 | 50.3k | } |
232 | 50.3k | |
233 | 50.3k | return false; |
234 | 50.3k | } |
235 | | |
236 | | bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, |
237 | | uint32_t *OffsetPtr, dwarf::FormParams FP, |
238 | | const DWARFContext *Ctx, |
239 | 70.9k | const DWARFUnit *CU) { |
240 | 70.9k | if (!Ctx && CU70.4k ) |
241 | 66.5k | Ctx = &CU->getContext(); |
242 | 70.9k | C = Ctx; |
243 | 70.9k | U = CU; |
244 | 70.9k | bool Indirect = false; |
245 | 70.9k | bool IsBlock = false; |
246 | 70.9k | Value.data = nullptr; |
247 | 70.9k | // Read the value for the form into value and follow and DW_FORM_indirect |
248 | 70.9k | // instances we run into |
249 | 70.9k | do { |
250 | 70.9k | Indirect = false; |
251 | 70.9k | switch (Form) { |
252 | 70.9k | case DW_FORM_addr: |
253 | 6.48k | case DW_FORM_ref_addr: { |
254 | 6.48k | uint16_t Size = |
255 | 6.48k | (Form == DW_FORM_addr) ? FP.AddrSize5.90k : FP.getRefAddrByteSize()583 ; |
256 | 6.48k | Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex); |
257 | 6.48k | break; |
258 | 6.48k | } |
259 | 6.48k | case DW_FORM_exprloc: |
260 | 1.75k | case DW_FORM_block: |
261 | 1.75k | Value.uval = Data.getULEB128(OffsetPtr); |
262 | 1.75k | IsBlock = true; |
263 | 1.75k | break; |
264 | 1.75k | case DW_FORM_block1: |
265 | 1.52k | Value.uval = Data.getU8(OffsetPtr); |
266 | 1.52k | IsBlock = true; |
267 | 1.52k | break; |
268 | 1.75k | case DW_FORM_block2: |
269 | 9 | Value.uval = Data.getU16(OffsetPtr); |
270 | 9 | IsBlock = true; |
271 | 9 | break; |
272 | 1.75k | case DW_FORM_block4: |
273 | 14 | Value.uval = Data.getU32(OffsetPtr); |
274 | 14 | IsBlock = true; |
275 | 14 | break; |
276 | 16.1k | case DW_FORM_data1: |
277 | 16.1k | case DW_FORM_ref1: |
278 | 16.1k | case DW_FORM_flag: |
279 | 16.1k | case DW_FORM_strx1: |
280 | 16.1k | case DW_FORM_addrx1: |
281 | 16.1k | Value.uval = Data.getU8(OffsetPtr); |
282 | 16.1k | break; |
283 | 16.1k | case DW_FORM_data2: |
284 | 2.62k | case DW_FORM_ref2: |
285 | 2.62k | case DW_FORM_strx2: |
286 | 2.62k | case DW_FORM_addrx2: |
287 | 2.62k | Value.uval = Data.getU16(OffsetPtr); |
288 | 2.62k | break; |
289 | 2.62k | case DW_FORM_strx3: |
290 | 5 | Value.uval = Data.getU24(OffsetPtr); |
291 | 5 | break; |
292 | 14.5k | case DW_FORM_data4: |
293 | 14.5k | case DW_FORM_ref4: |
294 | 14.5k | case DW_FORM_ref_sup4: |
295 | 14.5k | case DW_FORM_strx4: |
296 | 14.5k | case DW_FORM_addrx4: |
297 | 14.5k | Value.uval = Data.getRelocatedValue(4, OffsetPtr); |
298 | 14.5k | break; |
299 | 14.5k | case DW_FORM_data8: |
300 | 374 | case DW_FORM_ref8: |
301 | 374 | case DW_FORM_ref_sup8: |
302 | 374 | Value.uval = Data.getRelocatedValue(8, OffsetPtr); |
303 | 374 | break; |
304 | 374 | case DW_FORM_data16: |
305 | 63 | // Treat this like a 16-byte block. |
306 | 63 | Value.uval = 16; |
307 | 63 | IsBlock = true; |
308 | 63 | break; |
309 | 374 | case DW_FORM_sdata: |
310 | 373 | Value.sval = Data.getSLEB128(OffsetPtr); |
311 | 373 | break; |
312 | 582 | case DW_FORM_udata: |
313 | 582 | case DW_FORM_ref_udata: |
314 | 582 | case DW_FORM_rnglistx: |
315 | 582 | Value.uval = Data.getULEB128(OffsetPtr); |
316 | 582 | break; |
317 | 582 | case DW_FORM_string: |
318 | 313 | Value.cstr = Data.getCStr(OffsetPtr); |
319 | 313 | break; |
320 | 582 | case DW_FORM_indirect: |
321 | 0 | Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr)); |
322 | 0 | Indirect = true; |
323 | 0 | break; |
324 | 22.8k | case DW_FORM_strp: |
325 | 22.8k | case DW_FORM_sec_offset: |
326 | 22.8k | case DW_FORM_GNU_ref_alt: |
327 | 22.8k | case DW_FORM_GNU_strp_alt: |
328 | 22.8k | case DW_FORM_line_strp: |
329 | 22.8k | case DW_FORM_strp_sup: { |
330 | 22.8k | Value.uval = |
331 | 22.8k | Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), OffsetPtr); |
332 | 22.8k | break; |
333 | 22.8k | } |
334 | 22.8k | case DW_FORM_flag_present: |
335 | 2.19k | Value.uval = 1; |
336 | 2.19k | break; |
337 | 22.8k | case DW_FORM_ref_sig8: |
338 | 66 | Value.uval = Data.getU64(OffsetPtr); |
339 | 66 | break; |
340 | 22.8k | case DW_FORM_GNU_addr_index: |
341 | 963 | case DW_FORM_GNU_str_index: |
342 | 963 | case DW_FORM_addrx: |
343 | 963 | case DW_FORM_strx: |
344 | 963 | Value.uval = Data.getULEB128(OffsetPtr); |
345 | 963 | break; |
346 | 963 | default: |
347 | 0 | // DWARFFormValue::skipValue() will have caught this and caused all |
348 | 0 | // DWARF DIEs to fail to be parsed, so this code is not be reachable. |
349 | 0 | llvm_unreachable("unsupported form"); |
350 | 70.9k | } |
351 | 70.9k | } while (Indirect); |
352 | 70.9k | |
353 | 70.9k | if (IsBlock) { |
354 | 3.36k | StringRef Str = Data.getData().substr(*OffsetPtr, Value.uval); |
355 | 3.36k | Value.data = nullptr; |
356 | 3.36k | if (!Str.empty()) { |
357 | 3.35k | Value.data = Str.bytes_begin(); |
358 | 3.35k | *OffsetPtr += Value.uval; |
359 | 3.35k | } |
360 | 3.36k | } |
361 | 70.9k | |
362 | 70.9k | return true; |
363 | 70.9k | } |
364 | | |
365 | | void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, |
366 | | DIDumpOptions DumpOpts, |
367 | 2.04k | object::SectionedAddress SA) const { |
368 | 2.04k | OS << format("0x%016" PRIx64, SA.Address); |
369 | 2.04k | dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, |
370 | 2.04k | SA.SectionIndex); |
371 | 2.04k | } |
372 | | |
373 | | void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, |
374 | | DIDumpOptions DumpOpts, |
375 | 2.19k | uint64_t SectionIndex) { |
376 | 2.19k | if (!DumpOpts.Verbose || SectionIndex == -1ULL1.25k ) |
377 | 1.85k | return; |
378 | 334 | ArrayRef<SectionName> SectionNames = Obj.getSectionNames(); |
379 | 334 | const auto &SecRef = SectionNames[SectionIndex]; |
380 | 334 | |
381 | 334 | OS << " \"" << SecRef.Name << '\"'; |
382 | 334 | |
383 | 334 | // Print section index if name is not unique. |
384 | 334 | if (!SecRef.IsNameUnique) |
385 | 2 | OS << format(" [%" PRIu64 "]", SectionIndex); |
386 | 334 | } |
387 | | |
388 | 22.4k | void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { |
389 | 22.4k | uint64_t UValue = Value.uval; |
390 | 22.4k | bool CURelativeOffset = false; |
391 | 22.4k | raw_ostream &AddrOS = DumpOpts.ShowAddresses |
392 | 22.4k | ? WithColor(OS, HighlightColor::Address).get()22.4k |
393 | 22.4k | : nulls()72 ; |
394 | 22.4k | switch (Form) { |
395 | 22.4k | case DW_FORM_addr: |
396 | 1.94k | dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex}); |
397 | 1.94k | break; |
398 | 22.4k | case DW_FORM_addrx: |
399 | 118 | case DW_FORM_addrx1: |
400 | 118 | case DW_FORM_addrx2: |
401 | 118 | case DW_FORM_addrx3: |
402 | 118 | case DW_FORM_addrx4: |
403 | 118 | case DW_FORM_GNU_addr_index: { |
404 | 118 | if (U == nullptr) { |
405 | 0 | OS << "<invalid dwarf unit>"; |
406 | 0 | break; |
407 | 0 | } |
408 | 118 | Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); |
409 | 118 | if (!A || DumpOpts.Verbose100 ) |
410 | 84 | AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); |
411 | 118 | if (A) |
412 | 100 | dumpSectionedAddress(AddrOS, DumpOpts, *A); |
413 | 18 | else |
414 | 18 | OS << "<no .debug_addr section>"; |
415 | 118 | break; |
416 | 118 | } |
417 | 1.87k | case DW_FORM_flag_present: |
418 | 1.87k | OS << "true"; |
419 | 1.87k | break; |
420 | 2.83k | case DW_FORM_flag: |
421 | 2.83k | case DW_FORM_data1: |
422 | 2.83k | OS << format("0x%02x", (uint8_t)UValue); |
423 | 2.83k | break; |
424 | 2.83k | case DW_FORM_data2: |
425 | 549 | OS << format("0x%04x", (uint16_t)UValue); |
426 | 549 | break; |
427 | 2.83k | case DW_FORM_data4: |
428 | 1.90k | OS << format("0x%08x", (uint32_t)UValue); |
429 | 1.90k | break; |
430 | 2.83k | case DW_FORM_ref_sig8: |
431 | 61 | AddrOS << format("0x%016" PRIx64, UValue); |
432 | 61 | break; |
433 | 2.83k | case DW_FORM_data8: |
434 | 111 | OS << format("0x%016" PRIx64, UValue); |
435 | 111 | break; |
436 | 2.83k | case DW_FORM_data16: |
437 | 1 | OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), None, 16, 16); |
438 | 1 | break; |
439 | 2.83k | case DW_FORM_string: |
440 | 585 | OS << '"'; |
441 | 585 | OS.write_escaped(Value.cstr); |
442 | 585 | OS << '"'; |
443 | 585 | break; |
444 | 2.83k | case DW_FORM_exprloc: |
445 | 1 | case DW_FORM_block: |
446 | 1 | case DW_FORM_block1: |
447 | 1 | case DW_FORM_block2: |
448 | 1 | case DW_FORM_block4: |
449 | 1 | if (UValue > 0) { |
450 | 0 | switch (Form) { |
451 | 0 | case DW_FORM_exprloc: |
452 | 0 | case DW_FORM_block: |
453 | 0 | AddrOS << format("<0x%" PRIx64 "> ", UValue); |
454 | 0 | break; |
455 | 0 | case DW_FORM_block1: |
456 | 0 | AddrOS << format("<0x%2.2x> ", (uint8_t)UValue); |
457 | 0 | break; |
458 | 0 | case DW_FORM_block2: |
459 | 0 | AddrOS << format("<0x%4.4x> ", (uint16_t)UValue); |
460 | 0 | break; |
461 | 0 | case DW_FORM_block4: |
462 | 0 | AddrOS << format("<0x%8.8x> ", (uint32_t)UValue); |
463 | 0 | break; |
464 | 0 | default: |
465 | 0 | break; |
466 | 0 | } |
467 | 0 | |
468 | 0 | const uint8_t *DataPtr = Value.data; |
469 | 0 | if (DataPtr) { |
470 | 0 | // UValue contains size of block |
471 | 0 | const uint8_t *EndDataPtr = DataPtr + UValue; |
472 | 0 | while (DataPtr < EndDataPtr) { |
473 | 0 | AddrOS << format("%2.2x ", *DataPtr); |
474 | 0 | ++DataPtr; |
475 | 0 | } |
476 | 0 | } else |
477 | 0 | OS << "NULL"; |
478 | 0 | } |
479 | 1 | break; |
480 | 1 | |
481 | 355 | case DW_FORM_sdata: |
482 | 355 | OS << Value.sval; |
483 | 355 | break; |
484 | 423 | case DW_FORM_udata: |
485 | 423 | OS << Value.uval; |
486 | 423 | break; |
487 | 5.69k | case DW_FORM_strp: |
488 | 5.69k | if (DumpOpts.Verbose) |
489 | 3.43k | OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue); |
490 | 5.69k | dumpString(OS); |
491 | 5.69k | break; |
492 | 105 | case DW_FORM_line_strp: |
493 | 105 | if (DumpOpts.Verbose) |
494 | 79 | OS << format(" .debug_line_str[0x%8.8x] = ", (uint32_t)UValue); |
495 | 105 | dumpString(OS); |
496 | 105 | break; |
497 | 1.06k | case DW_FORM_strx: |
498 | 1.06k | case DW_FORM_strx1: |
499 | 1.06k | case DW_FORM_strx2: |
500 | 1.06k | case DW_FORM_strx3: |
501 | 1.06k | case DW_FORM_strx4: |
502 | 1.06k | case DW_FORM_GNU_str_index: |
503 | 1.06k | if (DumpOpts.Verbose) |
504 | 889 | OS << format("indexed (%8.8x) string = ", (uint32_t)UValue); |
505 | 1.06k | dumpString(OS); |
506 | 1.06k | break; |
507 | 1.06k | case DW_FORM_GNU_strp_alt: |
508 | 0 | if (DumpOpts.Verbose) |
509 | 0 | OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue); |
510 | 0 | dumpString(OS); |
511 | 0 | break; |
512 | 1.06k | case DW_FORM_ref_addr: |
513 | 235 | AddrOS << format("0x%016" PRIx64, UValue); |
514 | 235 | break; |
515 | 1.06k | case DW_FORM_ref1: |
516 | 0 | CURelativeOffset = true; |
517 | 0 | if (DumpOpts.Verbose) |
518 | 0 | AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue); |
519 | 0 | break; |
520 | 1.06k | case DW_FORM_ref2: |
521 | 0 | CURelativeOffset = true; |
522 | 0 | if (DumpOpts.Verbose) |
523 | 0 | AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue); |
524 | 0 | break; |
525 | 3.77k | case DW_FORM_ref4: |
526 | 3.77k | CURelativeOffset = true; |
527 | 3.77k | if (DumpOpts.Verbose) |
528 | 2.25k | AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue); |
529 | 3.77k | break; |
530 | 1.06k | case DW_FORM_ref8: |
531 | 0 | CURelativeOffset = true; |
532 | 0 | if (DumpOpts.Verbose) |
533 | 0 | AddrOS << format("cu + 0x%8.8" PRIx64, UValue); |
534 | 0 | break; |
535 | 1.06k | case DW_FORM_ref_udata: |
536 | 0 | CURelativeOffset = true; |
537 | 0 | if (DumpOpts.Verbose) |
538 | 0 | AddrOS << format("cu + 0x%" PRIx64, UValue); |
539 | 0 | break; |
540 | 1.06k | case DW_FORM_GNU_ref_alt: |
541 | 0 | AddrOS << format("<alt 0x%" PRIx64 ">", UValue); |
542 | 0 | break; |
543 | 1.06k | |
544 | 1.06k | // All DW_FORM_indirect attributes should be resolved prior to calling |
545 | 1.06k | // this function |
546 | 1.06k | case DW_FORM_indirect: |
547 | 0 | OS << "DW_FORM_indirect"; |
548 | 0 | break; |
549 | 1.06k | |
550 | 1.06k | case DW_FORM_rnglistx: |
551 | 10 | OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue); |
552 | 10 | break; |
553 | 1.06k | |
554 | 1.06k | // Should be formatted to 64-bit for DWARF64. |
555 | 1.06k | case DW_FORM_sec_offset: |
556 | 838 | AddrOS << format("0x%08x", (uint32_t)UValue); |
557 | 838 | break; |
558 | 1.06k | |
559 | 1.06k | default: |
560 | 0 | OS << format("DW_FORM(0x%4.4x)", Form); |
561 | 0 | break; |
562 | 22.4k | } |
563 | 22.4k | |
564 | 22.4k | if (CURelativeOffset) { |
565 | 3.77k | if (DumpOpts.Verbose) |
566 | 2.25k | OS << " => {"; |
567 | 3.77k | if (DumpOpts.ShowAddresses) |
568 | 3.76k | WithColor(OS, HighlightColor::Address).get() |
569 | 3.76k | << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset()3.37k : 0394 )); |
570 | 3.77k | if (DumpOpts.Verbose) |
571 | 2.25k | OS << "}"; |
572 | 3.77k | } |
573 | 22.4k | } |
574 | | |
575 | 6.85k | void DWARFFormValue::dumpString(raw_ostream &OS) const { |
576 | 6.85k | Optional<const char *> DbgStr = getAsCString(); |
577 | 6.85k | if (DbgStr.hasValue()) { |
578 | 6.83k | auto COS = WithColor(OS, HighlightColor::String); |
579 | 6.83k | COS.get() << '"'; |
580 | 6.83k | COS.get().write_escaped(DbgStr.getValue()); |
581 | 6.83k | COS.get() << '"'; |
582 | 6.83k | } |
583 | 6.85k | } |
584 | | |
585 | 25.0k | Optional<const char *> DWARFFormValue::getAsCString() const { |
586 | 25.0k | if (!isFormClass(FC_String)) |
587 | 857 | return None; |
588 | 24.1k | if (Form == DW_FORM_string) |
589 | 4.52k | return Value.cstr; |
590 | 19.6k | // FIXME: Add support for DW_FORM_GNU_strp_alt |
591 | 19.6k | if (Form == DW_FORM_GNU_strp_alt || C == nullptr) |
592 | 0 | return None; |
593 | 19.6k | uint32_t Offset = Value.uval; |
594 | 19.6k | if (Form == DW_FORM_line_strp) { |
595 | 392 | // .debug_line_str is tracked in the Context. |
596 | 392 | if (const char *Str = C->getLineStringExtractor().getCStr(&Offset)) |
597 | 392 | return Str; |
598 | 0 | return None; |
599 | 0 | } |
600 | 19.2k | if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx18.5k || |
601 | 19.2k | Form == DW_FORM_strx118.5k || Form == DW_FORM_strx217.7k || Form == DW_FORM_strx317.7k || |
602 | 19.2k | Form == DW_FORM_strx417.7k ) { |
603 | 1.57k | if (!U) |
604 | 0 | return None; |
605 | 1.57k | Optional<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset); |
606 | 1.57k | if (!StrOffset) |
607 | 2 | return None; |
608 | 1.57k | Offset = *StrOffset; |
609 | 1.57k | } |
610 | 19.2k | // Prefer the Unit's string extractor, because for .dwo it will point to |
611 | 19.2k | // .debug_str.dwo, while the Context's extractor always uses .debug_str. |
612 | 19.2k | if (19.2k U19.2k ) { |
613 | 19.2k | if (const char *Str = U->getStringExtractor().getCStr(&Offset)) |
614 | 19.2k | return Str; |
615 | 32 | return None; |
616 | 32 | } |
617 | 2 | if (const char *Str = C->getStringExtractor().getCStr(&Offset)) |
618 | 2 | return Str; |
619 | 0 | return None; |
620 | 0 | } |
621 | | |
622 | 3.43k | Optional<uint64_t> DWARFFormValue::getAsAddress() const { |
623 | 3.43k | if (auto SA = getAsSectionedAddress()) |
624 | 2.29k | return SA->Address; |
625 | 1.14k | return None; |
626 | 1.14k | } |
627 | | Optional<object::SectionedAddress> |
628 | 4.93k | DWARFFormValue::getAsSectionedAddress() const { |
629 | 4.93k | if (!isFormClass(FC_Address)) |
630 | 1.14k | return None; |
631 | 3.79k | if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx3.74k ) { |
632 | 104 | uint32_t Index = Value.uval; |
633 | 104 | if (!U) |
634 | 0 | return None; |
635 | 104 | Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); |
636 | 104 | if (!SA) |
637 | 23 | return None; |
638 | 81 | return SA; |
639 | 81 | } |
640 | 3.68k | return {{Value.uval, Value.SectionIndex}}; |
641 | 3.68k | } |
642 | | |
643 | 3.77k | Optional<uint64_t> DWARFFormValue::getAsReference() const { |
644 | 3.77k | if (auto R = getAsRelativeReference()) |
645 | 3.76k | return R->Unit ? R->Unit->getOffset() + R->Offset3.40k : R->Offset363 ; |
646 | 10 | return None; |
647 | 10 | } |
648 | | |
649 | 9.20k | Optional<DWARFFormValue::UnitOffset> DWARFFormValue::getAsRelativeReference() const { |
650 | 9.20k | if (!isFormClass(FC_Reference)) |
651 | 10 | return None; |
652 | 9.19k | switch (Form) { |
653 | 9.19k | case DW_FORM_ref1: |
654 | 8.51k | case DW_FORM_ref2: |
655 | 8.51k | case DW_FORM_ref4: |
656 | 8.51k | case DW_FORM_ref8: |
657 | 8.51k | case DW_FORM_ref_udata: |
658 | 8.51k | if (!U) |
659 | 0 | return None; |
660 | 8.51k | return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; |
661 | 8.51k | case DW_FORM_ref_addr: |
662 | 679 | case DW_FORM_ref_sig8: |
663 | 679 | case DW_FORM_GNU_ref_alt: |
664 | 679 | return UnitOffset{nullptr, Value.uval}; |
665 | 679 | default: |
666 | 0 | return None; |
667 | 9.19k | } |
668 | 9.19k | } |
669 | | |
670 | 5.96k | Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { |
671 | 5.96k | if (!isFormClass(FC_SectionOffset)) |
672 | 51 | return None; |
673 | 5.91k | return Value.uval; |
674 | 5.91k | } |
675 | | |
676 | 42.0k | Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { |
677 | 42.0k | if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)18.9k ) || |
678 | 42.0k | Form == DW_FORM_sdata26.3k ) |
679 | 16.0k | return None; |
680 | 25.9k | return Value.uval; |
681 | 25.9k | } |
682 | | |
683 | 43 | Optional<int64_t> DWARFFormValue::getAsSignedConstant() const { |
684 | 43 | if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)8 ) || |
685 | 43 | (35 Form == DW_FORM_udata35 && |
686 | 35 | uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval6 )) |
687 | 9 | return None; |
688 | 34 | switch (Form) { |
689 | 34 | case DW_FORM_data4: |
690 | 2 | return int32_t(Value.uval); |
691 | 34 | case DW_FORM_data2: |
692 | 2 | return int16_t(Value.uval); |
693 | 34 | case DW_FORM_data1: |
694 | 2 | return int8_t(Value.uval); |
695 | 34 | case DW_FORM_sdata: |
696 | 16 | case DW_FORM_data8: |
697 | 28 | default: |
698 | 28 | return Value.sval; |
699 | 34 | } |
700 | 34 | } |
701 | | |
702 | 3.38k | Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { |
703 | 3.38k | if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)1.86k && |
704 | 3.38k | Form != DW_FORM_data16206 ) |
705 | 24 | return None; |
706 | 3.36k | return makeArrayRef(Value.data, Value.uval); |
707 | 3.36k | } |
708 | | |
709 | 30 | Optional<uint64_t> DWARFFormValue::getAsCStringOffset() const { |
710 | 30 | if (!isFormClass(FC_String) && Form == DW_FORM_string5 ) |
711 | 0 | return None; |
712 | 30 | return Value.uval; |
713 | 30 | } |
714 | | |
715 | 754 | Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const { |
716 | 754 | if (!isFormClass(FC_Reference)) |
717 | 0 | return None; |
718 | 754 | return Value.uval; |
719 | 754 | } |