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