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