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