Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
39645 views
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 = ValueTypeTag();
29
}
30
31
bool DWARFFormValue::ExtractValue(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.value.uval =
48
data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
49
break;
50
case DW_FORM_block1:
51
m_value.value.uval = data.GetU8(offset_ptr);
52
is_block = true;
53
break;
54
case DW_FORM_block2:
55
m_value.value.uval = data.GetU16(offset_ptr);
56
is_block = true;
57
break;
58
case DW_FORM_block4:
59
m_value.value.uval = data.GetU32(offset_ptr);
60
is_block = true;
61
break;
62
case DW_FORM_data16:
63
m_value.value.uval = 16;
64
is_block = true;
65
break;
66
case DW_FORM_exprloc:
67
case DW_FORM_block:
68
m_value.value.uval = data.GetULEB128(offset_ptr);
69
is_block = true;
70
break;
71
case DW_FORM_string:
72
m_value.value.cstr = data.GetCStr(offset_ptr);
73
break;
74
case DW_FORM_sdata:
75
m_value.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.value.uval = data.GetMaxU64(offset_ptr, 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.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.value.uval = data.GetU16(offset_ptr);
94
break;
95
case DW_FORM_addrx3:
96
case DW_FORM_strx3:
97
m_value.value.uval = data.GetMaxU64(offset_ptr, 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.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.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.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.value.uval = data.GetMaxU64(offset_ptr, 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.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_ptr, m_value.value.uval);
142
if (m_value.data != nullptr) {
143
*offset_ptr += m_value.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
{0, 0}, // 0x00 unused
155
{0, 0}, // 0x01 DW_FORM_addr
156
{0, 0}, // 0x02 unused
157
{0, 0}, // 0x03 DW_FORM_block2
158
{0, 0}, // 0x04 DW_FORM_block4
159
{1, 2}, // 0x05 DW_FORM_data2
160
{1, 4}, // 0x06 DW_FORM_data4
161
{1, 8}, // 0x07 DW_FORM_data8
162
{0, 0}, // 0x08 DW_FORM_string
163
{0, 0}, // 0x09 DW_FORM_block
164
{0, 0}, // 0x0a DW_FORM_block1
165
{1, 1}, // 0x0b DW_FORM_data1
166
{1, 1}, // 0x0c DW_FORM_flag
167
{0, 0}, // 0x0d DW_FORM_sdata
168
{1, 4}, // 0x0e DW_FORM_strp
169
{0, 0}, // 0x0f DW_FORM_udata
170
{0, 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
{1, 1}, // 0x11 DW_FORM_ref1
173
{1, 2}, // 0x12 DW_FORM_ref2
174
{1, 4}, // 0x13 DW_FORM_ref4
175
{1, 8}, // 0x14 DW_FORM_ref8
176
{0, 0}, // 0x15 DW_FORM_ref_udata
177
{0, 0}, // 0x16 DW_FORM_indirect
178
{1, 4}, // 0x17 DW_FORM_sec_offset
179
{0, 0}, // 0x18 DW_FORM_exprloc
180
{1, 0}, // 0x19 DW_FORM_flag_present
181
{0, 0}, // 0x1a DW_FORM_strx (ULEB128)
182
{0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
183
{1, 4}, // 0x1c DW_FORM_ref_sup4
184
{0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
185
{1, 16}, // 0x1e DW_FORM_data16
186
{1, 4}, // 0x1f DW_FORM_line_strp
187
{1, 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(m_form, m_unit);
201
}
202
203
bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
204
lldb::offset_t *offset_ptr) const {
205
return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);
206
}
207
208
bool DWARFFormValue::SkipValue(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(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
// signed or unsigned LEB 128 values
310
case DW_FORM_addrx:
311
case DW_FORM_loclistx:
312
case DW_FORM_rnglistx:
313
case DW_FORM_sdata:
314
case DW_FORM_udata:
315
case DW_FORM_ref_udata:
316
case DW_FORM_GNU_addr_index:
317
case DW_FORM_GNU_str_index:
318
case DW_FORM_strx:
319
debug_info_data.Skip_LEB128(offset_ptr);
320
return true;
321
322
case DW_FORM_indirect: {
323
auto indirect_form =
324
static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr));
325
return DWARFFormValue::SkipValue(indirect_form, debug_info_data,
326
offset_ptr, unit);
327
}
328
329
default:
330
break;
331
}
332
return false;
333
}
334
335
void DWARFFormValue::Dump(Stream &s) const {
336
uint64_t uvalue = Unsigned();
337
bool unit_relative_offset = false;
338
339
switch (m_form) {
340
case DW_FORM_addr:
341
DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));
342
break;
343
case DW_FORM_flag:
344
case DW_FORM_data1:
345
s.PutHex8(uvalue);
346
break;
347
case DW_FORM_data2:
348
s.PutHex16(uvalue);
349
break;
350
case DW_FORM_sec_offset:
351
case DW_FORM_data4:
352
s.PutHex32(uvalue);
353
break;
354
case DW_FORM_ref_sig8:
355
case DW_FORM_data8:
356
s.PutHex64(uvalue);
357
break;
358
case DW_FORM_string:
359
s.QuotedCString(AsCString());
360
break;
361
case DW_FORM_exprloc:
362
case DW_FORM_block:
363
case DW_FORM_block1:
364
case DW_FORM_block2:
365
case DW_FORM_block4:
366
if (uvalue > 0) {
367
switch (m_form) {
368
case DW_FORM_exprloc:
369
case DW_FORM_block:
370
s.Printf("<0x%" PRIx64 "> ", uvalue);
371
break;
372
case DW_FORM_block1:
373
s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
374
break;
375
case DW_FORM_block2:
376
s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
377
break;
378
case DW_FORM_block4:
379
s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
380
break;
381
default:
382
break;
383
}
384
385
const uint8_t *data_ptr = m_value.data;
386
if (data_ptr) {
387
const uint8_t *end_data_ptr =
388
data_ptr + uvalue; // uvalue contains size of block
389
while (data_ptr < end_data_ptr) {
390
s.Printf("%2.2x ", *data_ptr);
391
++data_ptr;
392
}
393
} else
394
s.PutCString("NULL");
395
}
396
break;
397
398
case DW_FORM_sdata:
399
s.PutSLEB128(uvalue);
400
break;
401
case DW_FORM_udata:
402
s.PutULEB128(uvalue);
403
break;
404
case DW_FORM_strp:
405
case DW_FORM_line_strp: {
406
const char *dbg_str = AsCString();
407
if (dbg_str) {
408
s.QuotedCString(dbg_str);
409
} else {
410
s.PutHex32(uvalue);
411
}
412
} break;
413
414
case DW_FORM_ref_addr: {
415
assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
416
// will get this wrong
417
if (m_unit->GetVersion() <= 2)
418
DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2);
419
else
420
DumpAddress(s.AsRawOstream(), uvalue,
421
4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
422
// support DWARF64 yet
423
break;
424
}
425
case DW_FORM_ref1:
426
unit_relative_offset = true;
427
break;
428
case DW_FORM_ref2:
429
unit_relative_offset = true;
430
break;
431
case DW_FORM_ref4:
432
unit_relative_offset = true;
433
break;
434
case DW_FORM_ref8:
435
unit_relative_offset = true;
436
break;
437
case DW_FORM_ref_udata:
438
unit_relative_offset = true;
439
break;
440
441
// All DW_FORM_indirect attributes should be resolved prior to calling this
442
// function
443
case DW_FORM_indirect:
444
s.PutCString("DW_FORM_indirect");
445
break;
446
case DW_FORM_flag_present:
447
break;
448
default:
449
s.Printf("DW_FORM(0x%4.4x)", m_form);
450
break;
451
}
452
453
if (unit_relative_offset) {
454
assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
455
// unit relative or we will get this wrong
456
s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());
457
}
458
}
459
460
const char *DWARFFormValue::AsCString() const {
461
DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();
462
463
if (m_form == DW_FORM_string)
464
return m_value.value.cstr;
465
if (m_form == DW_FORM_strp)
466
return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
467
468
if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||
469
m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||
470
m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {
471
472
std::optional<uint64_t> offset =
473
m_unit->GetStringOffsetSectionItem(m_value.value.uval);
474
if (!offset)
475
return nullptr;
476
return context.getOrLoadStrData().PeekCStr(*offset);
477
}
478
479
if (m_form == DW_FORM_line_strp)
480
return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
481
482
return nullptr;
483
}
484
485
dw_addr_t DWARFFormValue::Address() const {
486
SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
487
488
if (m_form == DW_FORM_addr)
489
return Unsigned();
490
491
assert(m_unit);
492
assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
493
m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
494
m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
495
496
uint32_t index_size = m_unit->GetAddressByteSize();
497
dw_offset_t addr_base = m_unit->GetAddrBase();
498
lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
499
return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
500
&offset, index_size);
501
}
502
503
std::pair<DWARFUnit *, uint64_t>
504
DWARFFormValue::ReferencedUnitAndOffset() const {
505
uint64_t value = m_value.value.uval;
506
switch (m_form) {
507
case DW_FORM_ref1:
508
case DW_FORM_ref2:
509
case DW_FORM_ref4:
510
case DW_FORM_ref8:
511
case DW_FORM_ref_udata:
512
assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
513
// unit relative or we will get this wrong
514
value += m_unit->GetOffset();
515
if (!m_unit->ContainsDIEOffset(value)) {
516
m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
517
"DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);
518
return {nullptr, 0};
519
}
520
return {const_cast<DWARFUnit *>(m_unit), value};
521
522
case DW_FORM_ref_addr: {
523
DWARFUnit *ref_cu =
524
m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
525
DIERef::Section::DebugInfo, value);
526
if (!ref_cu) {
527
m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
528
"DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);
529
return {nullptr, 0};
530
}
531
return {ref_cu, value};
532
}
533
534
case DW_FORM_ref_sig8: {
535
DWARFTypeUnit *tu =
536
m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);
537
if (!tu)
538
return {nullptr, 0};
539
return {tu, tu->GetTypeOffset()};
540
}
541
542
default:
543
return {nullptr, 0};
544
}
545
}
546
547
DWARFDIE DWARFFormValue::Reference() const {
548
auto [unit, offset] = ReferencedUnitAndOffset();
549
return unit ? unit->GetDIE(offset) : DWARFDIE();
550
}
551
552
uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
553
uint64_t value = m_value.value.uval;
554
switch (m_form) {
555
case DW_FORM_ref1:
556
case DW_FORM_ref2:
557
case DW_FORM_ref4:
558
case DW_FORM_ref8:
559
case DW_FORM_ref_udata:
560
return value + base_offset;
561
562
case DW_FORM_ref_addr:
563
case DW_FORM_ref_sig8:
564
case DW_FORM_GNU_ref_alt:
565
return value;
566
567
default:
568
return DW_INVALID_OFFSET;
569
}
570
}
571
572
const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
573
574
bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
575
switch (form) {
576
case DW_FORM_exprloc:
577
case DW_FORM_block:
578
case DW_FORM_block1:
579
case DW_FORM_block2:
580
case DW_FORM_block4:
581
return true;
582
default:
583
return false;
584
}
585
llvm_unreachable("All cases handled above!");
586
}
587
588
bool DWARFFormValue::IsDataForm(const dw_form_t form) {
589
switch (form) {
590
case DW_FORM_sdata:
591
case DW_FORM_udata:
592
case DW_FORM_data1:
593
case DW_FORM_data2:
594
case DW_FORM_data4:
595
case DW_FORM_data8:
596
return true;
597
default:
598
return false;
599
}
600
llvm_unreachable("All cases handled above!");
601
}
602
603
bool DWARFFormValue::FormIsSupported(dw_form_t form) {
604
switch (form) {
605
case DW_FORM_addr:
606
case DW_FORM_addrx:
607
case DW_FORM_loclistx:
608
case DW_FORM_rnglistx:
609
case DW_FORM_block2:
610
case DW_FORM_block4:
611
case DW_FORM_data2:
612
case DW_FORM_data4:
613
case DW_FORM_data8:
614
case DW_FORM_string:
615
case DW_FORM_block:
616
case DW_FORM_block1:
617
case DW_FORM_data1:
618
case DW_FORM_flag:
619
case DW_FORM_sdata:
620
case DW_FORM_strp:
621
case DW_FORM_line_strp:
622
case DW_FORM_strx:
623
case DW_FORM_strx1:
624
case DW_FORM_strx2:
625
case DW_FORM_strx3:
626
case DW_FORM_strx4:
627
case DW_FORM_udata:
628
case DW_FORM_ref_addr:
629
case DW_FORM_ref1:
630
case DW_FORM_ref2:
631
case DW_FORM_ref4:
632
case DW_FORM_ref8:
633
case DW_FORM_ref_udata:
634
case DW_FORM_indirect:
635
case DW_FORM_sec_offset:
636
case DW_FORM_exprloc:
637
case DW_FORM_flag_present:
638
case DW_FORM_ref_sig8:
639
case DW_FORM_GNU_str_index:
640
case DW_FORM_GNU_addr_index:
641
case DW_FORM_implicit_const:
642
return true;
643
default:
644
break;
645
}
646
return false;
647
}
648
649