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 <cassert> |
10 | #include <optional> |
11 | |
12 | #include "lldb/Core/Module.h" |
13 | #include "lldb/Core/dwarf.h" |
14 | #include "lldb/Symbol/ObjectFile.h" |
15 | #include "lldb/Utility/Stream.h" |
16 | |
17 | #include "DWARFDebugInfo.h" |
18 | #include "DWARFFormValue.h" |
19 | #include "DWARFUnit.h" |
20 | |
21 | using namespace lldb_private; |
22 | using namespace lldb_private::dwarf; |
23 | using namespace lldb_private::plugin::dwarf; |
24 | |
25 | void DWARFFormValue::Clear() { |
26 | m_unit = nullptr; |
27 | m_form = dw_form_t(0); |
28 | m_value = ValueType(); |
29 | } |
30 | |
31 | bool DWARFFormValue::(const DWARFDataExtractor &data, |
32 | lldb::offset_t *offset_ptr) { |
33 | if (m_form == DW_FORM_implicit_const) |
34 | return true; |
35 | |
36 | bool indirect = false; |
37 | bool is_block = false; |
38 | m_value.data = nullptr; |
39 | uint8_t ref_addr_size; |
40 | // Read the value for the form into value and follow and DW_FORM_indirect |
41 | // instances we run into |
42 | do { |
43 | indirect = false; |
44 | switch (m_form) { |
45 | case DW_FORM_addr: |
46 | assert(m_unit); |
47 | m_value.uval = |
48 | data.GetMaxU64(offset_ptr, byte_size: DWARFUnit::GetAddressByteSize(cu: m_unit)); |
49 | break; |
50 | case DW_FORM_block1: |
51 | m_value.uval = data.GetU8(offset_ptr); |
52 | is_block = true; |
53 | break; |
54 | case DW_FORM_block2: |
55 | m_value.uval = data.GetU16(offset_ptr); |
56 | is_block = true; |
57 | break; |
58 | case DW_FORM_block4: |
59 | m_value.uval = data.GetU32(offset_ptr); |
60 | is_block = true; |
61 | break; |
62 | case DW_FORM_data16: |
63 | m_value.uval = 16; |
64 | is_block = true; |
65 | break; |
66 | case DW_FORM_exprloc: |
67 | case DW_FORM_block: |
68 | m_value.uval = data.GetULEB128(offset_ptr); |
69 | is_block = true; |
70 | break; |
71 | case DW_FORM_string: |
72 | m_value.cstr = data.GetCStr(offset_ptr); |
73 | break; |
74 | case DW_FORM_sdata: |
75 | m_value.sval = data.GetSLEB128(offset_ptr); |
76 | break; |
77 | case DW_FORM_strp: |
78 | case DW_FORM_line_strp: |
79 | case DW_FORM_sec_offset: |
80 | m_value.uval = data.GetMaxU64(offset_ptr, byte_size: 4); |
81 | break; |
82 | case DW_FORM_addrx1: |
83 | case DW_FORM_strx1: |
84 | case DW_FORM_ref1: |
85 | case DW_FORM_data1: |
86 | case DW_FORM_flag: |
87 | m_value.uval = data.GetU8(offset_ptr); |
88 | break; |
89 | case DW_FORM_addrx2: |
90 | case DW_FORM_strx2: |
91 | case DW_FORM_ref2: |
92 | case DW_FORM_data2: |
93 | m_value.uval = data.GetU16(offset_ptr); |
94 | break; |
95 | case DW_FORM_addrx3: |
96 | case DW_FORM_strx3: |
97 | m_value.uval = data.GetMaxU64(offset_ptr, byte_size: 3); |
98 | break; |
99 | case DW_FORM_addrx4: |
100 | case DW_FORM_strx4: |
101 | case DW_FORM_ref4: |
102 | case DW_FORM_data4: |
103 | m_value.uval = data.GetU32(offset_ptr); |
104 | break; |
105 | case DW_FORM_data8: |
106 | case DW_FORM_ref8: |
107 | case DW_FORM_ref_sig8: |
108 | m_value.uval = data.GetU64(offset_ptr); |
109 | break; |
110 | case DW_FORM_addrx: |
111 | case DW_FORM_loclistx: |
112 | case DW_FORM_rnglistx: |
113 | case DW_FORM_strx: |
114 | case DW_FORM_udata: |
115 | case DW_FORM_ref_udata: |
116 | case DW_FORM_GNU_str_index: |
117 | case DW_FORM_GNU_addr_index: |
118 | m_value.uval = data.GetULEB128(offset_ptr); |
119 | break; |
120 | case DW_FORM_ref_addr: |
121 | assert(m_unit); |
122 | if (m_unit->GetVersion() <= 2) |
123 | ref_addr_size = m_unit->GetAddressByteSize(); |
124 | else |
125 | ref_addr_size = 4; |
126 | m_value.uval = data.GetMaxU64(offset_ptr, byte_size: ref_addr_size); |
127 | break; |
128 | case DW_FORM_indirect: |
129 | m_form = static_cast<dw_form_t>(data.GetULEB128(offset_ptr)); |
130 | indirect = true; |
131 | break; |
132 | case DW_FORM_flag_present: |
133 | m_value.uval = 1; |
134 | break; |
135 | default: |
136 | return false; |
137 | } |
138 | } while (indirect); |
139 | |
140 | if (is_block) { |
141 | m_value.data = data.PeekData(offset: *offset_ptr, length: m_value.uval); |
142 | if (m_value.data != nullptr) { |
143 | *offset_ptr += m_value.uval; |
144 | } |
145 | } |
146 | |
147 | return true; |
148 | } |
149 | |
150 | struct FormSize { |
151 | uint8_t valid:1, size:7; |
152 | }; |
153 | static FormSize g_form_sizes[] = { |
154 | {.valid: 0, .size: 0}, // 0x00 unused |
155 | {.valid: 0, .size: 0}, // 0x01 DW_FORM_addr |
156 | {.valid: 0, .size: 0}, // 0x02 unused |
157 | {.valid: 0, .size: 0}, // 0x03 DW_FORM_block2 |
158 | {.valid: 0, .size: 0}, // 0x04 DW_FORM_block4 |
159 | {.valid: 1, .size: 2}, // 0x05 DW_FORM_data2 |
160 | {.valid: 1, .size: 4}, // 0x06 DW_FORM_data4 |
161 | {.valid: 1, .size: 8}, // 0x07 DW_FORM_data8 |
162 | {.valid: 0, .size: 0}, // 0x08 DW_FORM_string |
163 | {.valid: 0, .size: 0}, // 0x09 DW_FORM_block |
164 | {.valid: 0, .size: 0}, // 0x0a DW_FORM_block1 |
165 | {.valid: 1, .size: 1}, // 0x0b DW_FORM_data1 |
166 | {.valid: 1, .size: 1}, // 0x0c DW_FORM_flag |
167 | {.valid: 0, .size: 0}, // 0x0d DW_FORM_sdata |
168 | {.valid: 1, .size: 4}, // 0x0e DW_FORM_strp |
169 | {.valid: 0, .size: 0}, // 0x0f DW_FORM_udata |
170 | {.valid: 0, .size: 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes |
171 | // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later |
172 | {.valid: 1, .size: 1}, // 0x11 DW_FORM_ref1 |
173 | {.valid: 1, .size: 2}, // 0x12 DW_FORM_ref2 |
174 | {.valid: 1, .size: 4}, // 0x13 DW_FORM_ref4 |
175 | {.valid: 1, .size: 8}, // 0x14 DW_FORM_ref8 |
176 | {.valid: 0, .size: 0}, // 0x15 DW_FORM_ref_udata |
177 | {.valid: 0, .size: 0}, // 0x16 DW_FORM_indirect |
178 | {.valid: 1, .size: 4}, // 0x17 DW_FORM_sec_offset |
179 | {.valid: 0, .size: 0}, // 0x18 DW_FORM_exprloc |
180 | {.valid: 1, .size: 0}, // 0x19 DW_FORM_flag_present |
181 | {.valid: 0, .size: 0}, // 0x1a DW_FORM_strx (ULEB128) |
182 | {.valid: 0, .size: 0}, // 0x1b DW_FORM_addrx (ULEB128) |
183 | {.valid: 1, .size: 4}, // 0x1c DW_FORM_ref_sup4 |
184 | {.valid: 0, .size: 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64) |
185 | {.valid: 1, .size: 16}, // 0x1e DW_FORM_data16 |
186 | {.valid: 1, .size: 4}, // 0x1f DW_FORM_line_strp |
187 | {.valid: 1, .size: 8}, // 0x20 DW_FORM_ref_sig8 |
188 | }; |
189 | |
190 | std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form, |
191 | const DWARFUnit *u) { |
192 | if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid) |
193 | return static_cast<uint8_t>(g_form_sizes[form].size); |
194 | if (form == DW_FORM_addr && u) |
195 | return u->GetAddressByteSize(); |
196 | return std::nullopt; |
197 | } |
198 | |
199 | std::optional<uint8_t> DWARFFormValue::GetFixedSize() const { |
200 | return GetFixedSize(form: m_form, u: m_unit); |
201 | } |
202 | |
203 | bool DWARFFormValue::(const DWARFDataExtractor &debug_info_data, |
204 | lldb::offset_t *offset_ptr) const { |
205 | return DWARFFormValue::SkipValue(form: m_form, debug_info_data, offset_ptr, unit: m_unit); |
206 | } |
207 | |
208 | bool DWARFFormValue::(dw_form_t form, |
209 | const DWARFDataExtractor &debug_info_data, |
210 | lldb::offset_t *offset_ptr, |
211 | const DWARFUnit *unit) { |
212 | uint8_t ref_addr_size; |
213 | switch (form) { |
214 | // Blocks if inlined data that have a length field and the data bytes inlined |
215 | // in the .debug_info |
216 | case DW_FORM_exprloc: |
217 | case DW_FORM_block: { |
218 | uint64_t size = debug_info_data.GetULEB128(offset_ptr); |
219 | *offset_ptr += size; |
220 | } |
221 | return true; |
222 | case DW_FORM_block1: { |
223 | uint8_t size = debug_info_data.GetU8(offset_ptr); |
224 | *offset_ptr += size; |
225 | } |
226 | return true; |
227 | case DW_FORM_block2: { |
228 | uint16_t size = debug_info_data.GetU16(offset_ptr); |
229 | *offset_ptr += size; |
230 | } |
231 | return true; |
232 | case DW_FORM_block4: { |
233 | uint32_t size = debug_info_data.GetU32(offset_ptr); |
234 | *offset_ptr += size; |
235 | } |
236 | return true; |
237 | |
238 | // Inlined NULL terminated C-strings |
239 | case DW_FORM_string: |
240 | debug_info_data.GetCStr(offset_ptr); |
241 | return true; |
242 | |
243 | // Compile unit address sized values |
244 | case DW_FORM_addr: |
245 | *offset_ptr += DWARFUnit::GetAddressByteSize(cu: unit); |
246 | return true; |
247 | |
248 | case DW_FORM_ref_addr: |
249 | ref_addr_size = 4; |
250 | assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will |
251 | // get this wrong |
252 | if (unit->GetVersion() <= 2) |
253 | ref_addr_size = unit->GetAddressByteSize(); |
254 | else |
255 | ref_addr_size = 4; |
256 | *offset_ptr += ref_addr_size; |
257 | return true; |
258 | |
259 | // 0 bytes values (implied from DW_FORM) |
260 | case DW_FORM_flag_present: |
261 | case DW_FORM_implicit_const: |
262 | return true; |
263 | |
264 | // 1 byte values |
265 | case DW_FORM_addrx1: |
266 | case DW_FORM_data1: |
267 | case DW_FORM_flag: |
268 | case DW_FORM_ref1: |
269 | case DW_FORM_strx1: |
270 | *offset_ptr += 1; |
271 | return true; |
272 | |
273 | // 2 byte values |
274 | case DW_FORM_addrx2: |
275 | case DW_FORM_data2: |
276 | case DW_FORM_ref2: |
277 | case DW_FORM_strx2: |
278 | *offset_ptr += 2; |
279 | return true; |
280 | |
281 | // 3 byte values |
282 | case DW_FORM_addrx3: |
283 | case DW_FORM_strx3: |
284 | *offset_ptr += 3; |
285 | return true; |
286 | |
287 | // 32 bit for DWARF 32, 64 for DWARF 64 |
288 | case DW_FORM_sec_offset: |
289 | case DW_FORM_strp: |
290 | case DW_FORM_line_strp: |
291 | *offset_ptr += 4; |
292 | return true; |
293 | |
294 | // 4 byte values |
295 | case DW_FORM_addrx4: |
296 | case DW_FORM_data4: |
297 | case DW_FORM_ref4: |
298 | case DW_FORM_strx4: |
299 | *offset_ptr += 4; |
300 | return true; |
301 | |
302 | // 8 byte values |
303 | case DW_FORM_data8: |
304 | case DW_FORM_ref8: |
305 | case DW_FORM_ref_sig8: |
306 | *offset_ptr += 8; |
307 | return true; |
308 | |
309 | // 16 byte values |
310 | case DW_FORM_data16: |
311 | *offset_ptr += 16; |
312 | return true; |
313 | |
314 | // signed or unsigned LEB 128 values |
315 | case DW_FORM_addrx: |
316 | case DW_FORM_loclistx: |
317 | case DW_FORM_rnglistx: |
318 | case DW_FORM_sdata: |
319 | case DW_FORM_udata: |
320 | case DW_FORM_ref_udata: |
321 | case DW_FORM_GNU_addr_index: |
322 | case DW_FORM_GNU_str_index: |
323 | case DW_FORM_strx: |
324 | debug_info_data.Skip_LEB128(offset_ptr); |
325 | return true; |
326 | |
327 | case DW_FORM_indirect: { |
328 | auto indirect_form = |
329 | static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr)); |
330 | return DWARFFormValue::SkipValue(form: indirect_form, debug_info_data, |
331 | offset_ptr, unit); |
332 | } |
333 | |
334 | default: |
335 | break; |
336 | } |
337 | return false; |
338 | } |
339 | |
340 | void DWARFFormValue::Dump(Stream &s) const { |
341 | uint64_t uvalue = Unsigned(); |
342 | bool unit_relative_offset = false; |
343 | |
344 | switch (m_form) { |
345 | case DW_FORM_addr: |
346 | DumpAddress(s&: s.AsRawOstream(), addr: uvalue, addr_size: sizeof(uint64_t)); |
347 | break; |
348 | case DW_FORM_flag: |
349 | case DW_FORM_data1: |
350 | s.PutHex8(uvalue); |
351 | break; |
352 | case DW_FORM_data2: |
353 | s.PutHex16(uvalue); |
354 | break; |
355 | case DW_FORM_sec_offset: |
356 | case DW_FORM_data4: |
357 | s.PutHex32(uvalue); |
358 | break; |
359 | case DW_FORM_ref_sig8: |
360 | case DW_FORM_data8: |
361 | s.PutHex64(uvalue); |
362 | break; |
363 | case DW_FORM_string: |
364 | s.QuotedCString(cstr: AsCString()); |
365 | break; |
366 | case DW_FORM_exprloc: |
367 | case DW_FORM_block: |
368 | case DW_FORM_block1: |
369 | case DW_FORM_block2: |
370 | case DW_FORM_block4: |
371 | if (uvalue > 0) { |
372 | switch (m_form) { |
373 | case DW_FORM_exprloc: |
374 | case DW_FORM_block: |
375 | s.Printf(format: "<0x%" PRIx64 "> " , uvalue); |
376 | break; |
377 | case DW_FORM_block1: |
378 | s.Printf(format: "<0x%2.2x> " , (uint8_t)uvalue); |
379 | break; |
380 | case DW_FORM_block2: |
381 | s.Printf(format: "<0x%4.4x> " , (uint16_t)uvalue); |
382 | break; |
383 | case DW_FORM_block4: |
384 | s.Printf(format: "<0x%8.8x> " , (uint32_t)uvalue); |
385 | break; |
386 | default: |
387 | break; |
388 | } |
389 | |
390 | const uint8_t *data_ptr = m_value.data; |
391 | if (data_ptr) { |
392 | const uint8_t *end_data_ptr = |
393 | data_ptr + uvalue; // uvalue contains size of block |
394 | while (data_ptr < end_data_ptr) { |
395 | s.Printf(format: "%2.2x " , *data_ptr); |
396 | ++data_ptr; |
397 | } |
398 | } else |
399 | s.PutCString(cstr: "NULL" ); |
400 | } |
401 | break; |
402 | |
403 | case DW_FORM_sdata: |
404 | s.PutSLEB128(uval: uvalue); |
405 | break; |
406 | case DW_FORM_udata: |
407 | s.PutULEB128(uval: uvalue); |
408 | break; |
409 | case DW_FORM_strp: |
410 | case DW_FORM_line_strp: { |
411 | const char *dbg_str = AsCString(); |
412 | if (dbg_str) { |
413 | s.QuotedCString(cstr: dbg_str); |
414 | } else { |
415 | s.PutHex32(uvalue); |
416 | } |
417 | } break; |
418 | |
419 | case DW_FORM_ref_addr: { |
420 | assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we |
421 | // will get this wrong |
422 | if (m_unit->GetVersion() <= 2) |
423 | DumpAddress(s&: s.AsRawOstream(), addr: uvalue, addr_size: sizeof(uint64_t) * 2); |
424 | else |
425 | DumpAddress(s&: s.AsRawOstream(), addr: uvalue, |
426 | addr_size: 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't |
427 | // support DWARF64 yet |
428 | break; |
429 | } |
430 | case DW_FORM_ref1: |
431 | unit_relative_offset = true; |
432 | break; |
433 | case DW_FORM_ref2: |
434 | unit_relative_offset = true; |
435 | break; |
436 | case DW_FORM_ref4: |
437 | unit_relative_offset = true; |
438 | break; |
439 | case DW_FORM_ref8: |
440 | unit_relative_offset = true; |
441 | break; |
442 | case DW_FORM_ref_udata: |
443 | unit_relative_offset = true; |
444 | break; |
445 | |
446 | // All DW_FORM_indirect attributes should be resolved prior to calling this |
447 | // function |
448 | case DW_FORM_indirect: |
449 | s.PutCString(cstr: "DW_FORM_indirect" ); |
450 | break; |
451 | case DW_FORM_flag_present: |
452 | break; |
453 | default: |
454 | s.Printf(format: "DW_FORM(0x%4.4x)" , m_form); |
455 | break; |
456 | } |
457 | |
458 | if (unit_relative_offset) { |
459 | assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile |
460 | // unit relative or we will get this wrong |
461 | s.Printf(format: "{0x%8.8" PRIx64 "}" , uvalue + m_unit->GetOffset()); |
462 | } |
463 | } |
464 | |
465 | const char *DWARFFormValue::AsCString() const { |
466 | DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext(); |
467 | |
468 | if (m_form == DW_FORM_string) |
469 | return m_value.cstr; |
470 | if (m_form == DW_FORM_strp) |
471 | return context.getOrLoadStrData().PeekCStr(offset: m_value.uval); |
472 | |
473 | if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx || |
474 | m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 || |
475 | m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) { |
476 | |
477 | std::optional<uint64_t> offset = |
478 | m_unit->GetStringOffsetSectionItem(index: m_value.uval); |
479 | if (!offset) |
480 | return nullptr; |
481 | return context.getOrLoadStrData().PeekCStr(offset: *offset); |
482 | } |
483 | |
484 | if (m_form == DW_FORM_line_strp) |
485 | return context.getOrLoadLineStrData().PeekCStr(offset: m_value.uval); |
486 | |
487 | return nullptr; |
488 | } |
489 | |
490 | dw_addr_t DWARFFormValue::Address() const { |
491 | SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); |
492 | |
493 | if (m_form == DW_FORM_addr) |
494 | return Unsigned(); |
495 | |
496 | assert(m_unit); |
497 | assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || |
498 | m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || |
499 | m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); |
500 | |
501 | uint32_t index_size = m_unit->GetAddressByteSize(); |
502 | dw_offset_t addr_base = m_unit->GetAddrBase(); |
503 | lldb::offset_t offset = addr_base + m_value.uval * index_size; |
504 | return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( |
505 | offset_ptr: &offset, byte_size: index_size); |
506 | } |
507 | |
508 | std::pair<DWARFUnit *, uint64_t> |
509 | DWARFFormValue::ReferencedUnitAndOffset() const { |
510 | uint64_t value = m_value.uval; |
511 | switch (m_form) { |
512 | case DW_FORM_ref1: |
513 | case DW_FORM_ref2: |
514 | case DW_FORM_ref4: |
515 | case DW_FORM_ref8: |
516 | case DW_FORM_ref_udata: |
517 | assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile |
518 | // unit relative or we will get this wrong |
519 | value += m_unit->GetOffset(); |
520 | if (!m_unit->ContainsDIEOffset(die_offset: value)) { |
521 | m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( |
522 | format: "DW_FORM_ref* DIE reference {0:x16} is outside of its CU" , args&: value); |
523 | return {nullptr, 0}; |
524 | } |
525 | return {const_cast<DWARFUnit *>(m_unit), value}; |
526 | |
527 | case DW_FORM_ref_addr: { |
528 | DWARFUnit *ref_cu = |
529 | m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset( |
530 | section: DIERef::Section::DebugInfo, die_offset: value); |
531 | if (!ref_cu) { |
532 | m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( |
533 | format: "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU" , args&: value); |
534 | return {nullptr, 0}; |
535 | } |
536 | return {ref_cu, value}; |
537 | } |
538 | |
539 | case DW_FORM_ref_sig8: { |
540 | DWARFTypeUnit *tu = |
541 | m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(hash: value); |
542 | if (!tu) |
543 | return {nullptr, 0}; |
544 | return {tu, tu->GetTypeOffset()}; |
545 | } |
546 | |
547 | default: |
548 | return {nullptr, 0}; |
549 | } |
550 | } |
551 | |
552 | DWARFDIE DWARFFormValue::Reference() const { |
553 | auto [unit, offset] = ReferencedUnitAndOffset(); |
554 | return unit ? unit->GetDIE(die_offset: offset) : DWARFDIE(); |
555 | } |
556 | |
557 | uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const { |
558 | uint64_t value = m_value.uval; |
559 | switch (m_form) { |
560 | case DW_FORM_ref1: |
561 | case DW_FORM_ref2: |
562 | case DW_FORM_ref4: |
563 | case DW_FORM_ref8: |
564 | case DW_FORM_ref_udata: |
565 | return value + base_offset; |
566 | |
567 | case DW_FORM_ref_addr: |
568 | case DW_FORM_ref_sig8: |
569 | case DW_FORM_GNU_ref_alt: |
570 | return value; |
571 | |
572 | default: |
573 | return DW_INVALID_OFFSET; |
574 | } |
575 | } |
576 | |
577 | std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { |
578 | if ((!IsDataForm(form: m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata) |
579 | return std::nullopt; |
580 | return m_value.uval; |
581 | } |
582 | |
583 | std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const { |
584 | if ((!IsDataForm(form: m_form)) || |
585 | (m_form == lldb_private::dwarf::DW_FORM_udata && |
586 | uint64_t(std::numeric_limits<int64_t>::max()) < m_value.uval)) |
587 | return std::nullopt; |
588 | switch (m_form) { |
589 | case lldb_private::dwarf::DW_FORM_data4: |
590 | return int32_t(m_value.uval); |
591 | case lldb_private::dwarf::DW_FORM_data2: |
592 | return int16_t(m_value.uval); |
593 | case lldb_private::dwarf::DW_FORM_data1: |
594 | return int8_t(m_value.uval); |
595 | case lldb_private::dwarf::DW_FORM_sdata: |
596 | case lldb_private::dwarf::DW_FORM_data8: |
597 | default: |
598 | return m_value.sval; |
599 | } |
600 | } |
601 | |
602 | const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; } |
603 | |
604 | bool DWARFFormValue::IsBlockForm(const dw_form_t form) { |
605 | switch (form) { |
606 | case DW_FORM_exprloc: |
607 | case DW_FORM_block: |
608 | case DW_FORM_block1: |
609 | case DW_FORM_block2: |
610 | case DW_FORM_block4: |
611 | case DW_FORM_data16: |
612 | return true; |
613 | default: |
614 | return false; |
615 | } |
616 | llvm_unreachable("All cases handled above!" ); |
617 | } |
618 | |
619 | bool DWARFFormValue::IsDataForm(const dw_form_t form) { |
620 | switch (form) { |
621 | case DW_FORM_sdata: |
622 | case DW_FORM_udata: |
623 | case DW_FORM_data1: |
624 | case DW_FORM_data2: |
625 | case DW_FORM_data4: |
626 | case DW_FORM_data8: |
627 | return true; |
628 | default: |
629 | return false; |
630 | } |
631 | llvm_unreachable("All cases handled above!" ); |
632 | } |
633 | |
634 | bool DWARFFormValue::FormIsSupported(dw_form_t form) { |
635 | switch (form) { |
636 | case DW_FORM_addr: |
637 | case DW_FORM_addrx: |
638 | case DW_FORM_loclistx: |
639 | case DW_FORM_rnglistx: |
640 | case DW_FORM_block2: |
641 | case DW_FORM_block4: |
642 | case DW_FORM_data2: |
643 | case DW_FORM_data4: |
644 | case DW_FORM_data8: |
645 | case DW_FORM_data16: |
646 | case DW_FORM_string: |
647 | case DW_FORM_block: |
648 | case DW_FORM_block1: |
649 | case DW_FORM_data1: |
650 | case DW_FORM_flag: |
651 | case DW_FORM_sdata: |
652 | case DW_FORM_strp: |
653 | case DW_FORM_line_strp: |
654 | case DW_FORM_strx: |
655 | case DW_FORM_strx1: |
656 | case DW_FORM_strx2: |
657 | case DW_FORM_strx3: |
658 | case DW_FORM_strx4: |
659 | case DW_FORM_udata: |
660 | case DW_FORM_ref_addr: |
661 | case DW_FORM_ref1: |
662 | case DW_FORM_ref2: |
663 | case DW_FORM_ref4: |
664 | case DW_FORM_ref8: |
665 | case DW_FORM_ref_udata: |
666 | case DW_FORM_indirect: |
667 | case DW_FORM_sec_offset: |
668 | case DW_FORM_exprloc: |
669 | case DW_FORM_flag_present: |
670 | case DW_FORM_ref_sig8: |
671 | case DW_FORM_GNU_str_index: |
672 | case DW_FORM_GNU_addr_index: |
673 | case DW_FORM_implicit_const: |
674 | return true; |
675 | default: |
676 | break; |
677 | } |
678 | return false; |
679 | } |
680 | |