xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- DWARFFormValue.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
100b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
110b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
130b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h"
1481ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
1581ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
1681ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFObject.h"
1781ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFSection.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
190b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
200b57cec5SDimitry Andric #include "llvm/Support/Format.h"
210b57cec5SDimitry Andric #include "llvm/Support/WithColor.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric #include <cinttypes>
240b57cec5SDimitry Andric #include <cstdint>
250b57cec5SDimitry Andric #include <limits>
26bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric using namespace dwarf;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static const DWARFFormValue::FormClass DWARF5FormClasses[] = {
320b57cec5SDimitry Andric     DWARFFormValue::FC_Unknown,  // 0x0
330b57cec5SDimitry Andric     DWARFFormValue::FC_Address,  // 0x01 DW_FORM_addr
340b57cec5SDimitry Andric     DWARFFormValue::FC_Unknown,  // 0x02 unused
350b57cec5SDimitry Andric     DWARFFormValue::FC_Block,    // 0x03 DW_FORM_block2
360b57cec5SDimitry Andric     DWARFFormValue::FC_Block,    // 0x04 DW_FORM_block4
370b57cec5SDimitry Andric     DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
380b57cec5SDimitry Andric     // --- These can be FC_SectionOffset in DWARF3 and below:
390b57cec5SDimitry Andric     DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
400b57cec5SDimitry Andric     DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
410b57cec5SDimitry Andric     // ---
420b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
430b57cec5SDimitry Andric     DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
440b57cec5SDimitry Andric     DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
450b57cec5SDimitry Andric     DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
460b57cec5SDimitry Andric     DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
470b57cec5SDimitry Andric     DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
480b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
490b57cec5SDimitry Andric     DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
500b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
510b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
520b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
530b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
540b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
550b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
560b57cec5SDimitry Andric     DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
570b57cec5SDimitry Andric     DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
580b57cec5SDimitry Andric     DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
590b57cec5SDimitry Andric     DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
600b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x1a DW_FORM_strx
610b57cec5SDimitry Andric     DWARFFormValue::FC_Address,       // 0x1b DW_FORM_addrx
620b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x1c DW_FORM_ref_sup4
630b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x1d DW_FORM_strp_sup
640b57cec5SDimitry Andric     DWARFFormValue::FC_Constant,      // 0x1e DW_FORM_data16
650b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x1f DW_FORM_line_strp
660b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x20 DW_FORM_ref_sig8
670b57cec5SDimitry Andric     DWARFFormValue::FC_Constant,      // 0x21 DW_FORM_implicit_const
680b57cec5SDimitry Andric     DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx
690b57cec5SDimitry Andric     DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx
700b57cec5SDimitry Andric     DWARFFormValue::FC_Reference,     // 0x24 DW_FORM_ref_sup8
710b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x25 DW_FORM_strx1
720b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x26 DW_FORM_strx2
730b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x27 DW_FORM_strx3
740b57cec5SDimitry Andric     DWARFFormValue::FC_String,        // 0x28 DW_FORM_strx4
750b57cec5SDimitry Andric     DWARFFormValue::FC_Address,       // 0x29 DW_FORM_addrx1
760b57cec5SDimitry Andric     DWARFFormValue::FC_Address,       // 0x2a DW_FORM_addrx2
770b57cec5SDimitry Andric     DWARFFormValue::FC_Address,       // 0x2b DW_FORM_addrx3
780b57cec5SDimitry Andric     DWARFFormValue::FC_Address,       // 0x2c DW_FORM_addrx4
79fe6060f1SDimitry Andric     DWARFFormValue::FC_Address,       // 0x2001 DW_FORM_addrx_offset
800b57cec5SDimitry Andric };
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {
830b57cec5SDimitry Andric   return DWARFFormValue(F, ValueType(V));
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) {
870b57cec5SDimitry Andric   return DWARFFormValue(F, ValueType(V));
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) {
910b57cec5SDimitry Andric   return DWARFFormValue(F, ValueType(V));
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,
950b57cec5SDimitry Andric                                                     ArrayRef<uint8_t> D) {
960b57cec5SDimitry Andric   ValueType V;
970b57cec5SDimitry Andric   V.uval = D.size();
980b57cec5SDimitry Andric   V.data = D.data();
990b57cec5SDimitry Andric   return DWARFFormValue(F, V);
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,
1038bcb0991SDimitry Andric                                               uint64_t *OffsetPtr) {
1040b57cec5SDimitry Andric   DWARFFormValue FormValue(F);
1050b57cec5SDimitry Andric   FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
1060b57cec5SDimitry Andric                          U->getFormParams(), U);
1070b57cec5SDimitry Andric   return FormValue;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
1118bcb0991SDimitry Andric                                uint64_t *OffsetPtr,
1120b57cec5SDimitry Andric                                const dwarf::FormParams Params) {
1130b57cec5SDimitry Andric   bool Indirect = false;
1140b57cec5SDimitry Andric   do {
1150b57cec5SDimitry Andric     switch (Form) {
1160b57cec5SDimitry Andric     // Blocks of inlined data that have a length field and the data bytes
1170b57cec5SDimitry Andric     // inlined in the .debug_info.
1180b57cec5SDimitry Andric     case DW_FORM_exprloc:
1190b57cec5SDimitry Andric     case DW_FORM_block: {
1200b57cec5SDimitry Andric       uint64_t size = DebugInfoData.getULEB128(OffsetPtr);
1210b57cec5SDimitry Andric       *OffsetPtr += size;
1220b57cec5SDimitry Andric       return true;
1230b57cec5SDimitry Andric     }
1240b57cec5SDimitry Andric     case DW_FORM_block1: {
1250b57cec5SDimitry Andric       uint8_t size = DebugInfoData.getU8(OffsetPtr);
1260b57cec5SDimitry Andric       *OffsetPtr += size;
1270b57cec5SDimitry Andric       return true;
1280b57cec5SDimitry Andric     }
1290b57cec5SDimitry Andric     case DW_FORM_block2: {
1300b57cec5SDimitry Andric       uint16_t size = DebugInfoData.getU16(OffsetPtr);
1310b57cec5SDimitry Andric       *OffsetPtr += size;
1320b57cec5SDimitry Andric       return true;
1330b57cec5SDimitry Andric     }
1340b57cec5SDimitry Andric     case DW_FORM_block4: {
1350b57cec5SDimitry Andric       uint32_t size = DebugInfoData.getU32(OffsetPtr);
1360b57cec5SDimitry Andric       *OffsetPtr += size;
1370b57cec5SDimitry Andric       return true;
1380b57cec5SDimitry Andric     }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     // Inlined NULL terminated C-strings.
1410b57cec5SDimitry Andric     case DW_FORM_string:
1420b57cec5SDimitry Andric       DebugInfoData.getCStr(OffsetPtr);
1430b57cec5SDimitry Andric       return true;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     case DW_FORM_addr:
1460b57cec5SDimitry Andric     case DW_FORM_ref_addr:
1470b57cec5SDimitry Andric     case DW_FORM_flag_present:
1480b57cec5SDimitry Andric     case DW_FORM_data1:
1490b57cec5SDimitry Andric     case DW_FORM_data2:
1500b57cec5SDimitry Andric     case DW_FORM_data4:
1510b57cec5SDimitry Andric     case DW_FORM_data8:
1520b57cec5SDimitry Andric     case DW_FORM_data16:
1530b57cec5SDimitry Andric     case DW_FORM_flag:
1540b57cec5SDimitry Andric     case DW_FORM_ref1:
1550b57cec5SDimitry Andric     case DW_FORM_ref2:
1560b57cec5SDimitry Andric     case DW_FORM_ref4:
1570b57cec5SDimitry Andric     case DW_FORM_ref8:
1580b57cec5SDimitry Andric     case DW_FORM_ref_sig8:
1590b57cec5SDimitry Andric     case DW_FORM_ref_sup4:
1600b57cec5SDimitry Andric     case DW_FORM_ref_sup8:
1610b57cec5SDimitry Andric     case DW_FORM_strx1:
1620b57cec5SDimitry Andric     case DW_FORM_strx2:
16306c3fb27SDimitry Andric     case DW_FORM_strx3:
1640b57cec5SDimitry Andric     case DW_FORM_strx4:
1650b57cec5SDimitry Andric     case DW_FORM_addrx1:
1660b57cec5SDimitry Andric     case DW_FORM_addrx2:
16706c3fb27SDimitry Andric     case DW_FORM_addrx3:
1680b57cec5SDimitry Andric     case DW_FORM_addrx4:
1690b57cec5SDimitry Andric     case DW_FORM_sec_offset:
1700b57cec5SDimitry Andric     case DW_FORM_strp:
1710b57cec5SDimitry Andric     case DW_FORM_strp_sup:
1720b57cec5SDimitry Andric     case DW_FORM_line_strp:
1730b57cec5SDimitry Andric     case DW_FORM_GNU_ref_alt:
1740b57cec5SDimitry Andric     case DW_FORM_GNU_strp_alt:
1754652422eSDimitry Andric     case DW_FORM_implicit_const:
176bdd1243dSDimitry Andric       if (std::optional<uint8_t> FixedSize =
1770b57cec5SDimitry Andric               dwarf::getFixedFormByteSize(Form, Params)) {
1780b57cec5SDimitry Andric         *OffsetPtr += *FixedSize;
1790b57cec5SDimitry Andric         return true;
1800b57cec5SDimitry Andric       }
1810b57cec5SDimitry Andric       return false;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric     // signed or unsigned LEB 128 values.
1840b57cec5SDimitry Andric     case DW_FORM_sdata:
1850b57cec5SDimitry Andric       DebugInfoData.getSLEB128(OffsetPtr);
1860b57cec5SDimitry Andric       return true;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric     case DW_FORM_udata:
1890b57cec5SDimitry Andric     case DW_FORM_ref_udata:
1900b57cec5SDimitry Andric     case DW_FORM_strx:
1910b57cec5SDimitry Andric     case DW_FORM_addrx:
1920b57cec5SDimitry Andric     case DW_FORM_loclistx:
1930b57cec5SDimitry Andric     case DW_FORM_rnglistx:
1940b57cec5SDimitry Andric     case DW_FORM_GNU_addr_index:
1950b57cec5SDimitry Andric     case DW_FORM_GNU_str_index:
1960b57cec5SDimitry Andric       DebugInfoData.getULEB128(OffsetPtr);
1970b57cec5SDimitry Andric       return true;
1980b57cec5SDimitry Andric 
199fe6060f1SDimitry Andric     case DW_FORM_LLVM_addrx_offset:
200fe6060f1SDimitry Andric       DebugInfoData.getULEB128(OffsetPtr);
201fe6060f1SDimitry Andric       *OffsetPtr += 4;
202fe6060f1SDimitry Andric       return true;
203fe6060f1SDimitry Andric 
2040b57cec5SDimitry Andric     case DW_FORM_indirect:
2050b57cec5SDimitry Andric       Indirect = true;
2060b57cec5SDimitry Andric       Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
2070b57cec5SDimitry Andric       break;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     default:
2100b57cec5SDimitry Andric       return false;
2110b57cec5SDimitry Andric     }
2120b57cec5SDimitry Andric   } while (Indirect);
2130b57cec5SDimitry Andric   return true;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
21706c3fb27SDimitry Andric   return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3);
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
2218bcb0991SDimitry Andric                                   uint64_t *OffsetPtr, dwarf::FormParams FP,
2220b57cec5SDimitry Andric                                   const DWARFContext *Ctx,
2230b57cec5SDimitry Andric                                   const DWARFUnit *CU) {
2240b57cec5SDimitry Andric   if (!Ctx && CU)
2250b57cec5SDimitry Andric     Ctx = &CU->getContext();
2260b57cec5SDimitry Andric   C = Ctx;
2270b57cec5SDimitry Andric   U = CU;
2285ffd83dbSDimitry Andric   Format = FP.Format;
2290b57cec5SDimitry Andric   bool Indirect = false;
2300b57cec5SDimitry Andric   bool IsBlock = false;
2310b57cec5SDimitry Andric   Value.data = nullptr;
2320b57cec5SDimitry Andric   // Read the value for the form into value and follow and DW_FORM_indirect
2330b57cec5SDimitry Andric   // instances we run into
2345ffd83dbSDimitry Andric   Error Err = Error::success();
2350b57cec5SDimitry Andric   do {
2360b57cec5SDimitry Andric     Indirect = false;
2370b57cec5SDimitry Andric     switch (Form) {
2380b57cec5SDimitry Andric     case DW_FORM_addr:
2390b57cec5SDimitry Andric     case DW_FORM_ref_addr: {
2400b57cec5SDimitry Andric       uint16_t Size =
2410b57cec5SDimitry Andric           (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();
2425ffd83dbSDimitry Andric       Value.uval =
2435ffd83dbSDimitry Andric           Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err);
2440b57cec5SDimitry Andric       break;
2450b57cec5SDimitry Andric     }
2460b57cec5SDimitry Andric     case DW_FORM_exprloc:
2470b57cec5SDimitry Andric     case DW_FORM_block:
2485ffd83dbSDimitry Andric       Value.uval = Data.getULEB128(OffsetPtr, &Err);
2490b57cec5SDimitry Andric       IsBlock = true;
2500b57cec5SDimitry Andric       break;
2510b57cec5SDimitry Andric     case DW_FORM_block1:
2525ffd83dbSDimitry Andric       Value.uval = Data.getU8(OffsetPtr, &Err);
2530b57cec5SDimitry Andric       IsBlock = true;
2540b57cec5SDimitry Andric       break;
2550b57cec5SDimitry Andric     case DW_FORM_block2:
2565ffd83dbSDimitry Andric       Value.uval = Data.getU16(OffsetPtr, &Err);
2570b57cec5SDimitry Andric       IsBlock = true;
2580b57cec5SDimitry Andric       break;
2590b57cec5SDimitry Andric     case DW_FORM_block4:
2605ffd83dbSDimitry Andric       Value.uval = Data.getU32(OffsetPtr, &Err);
2610b57cec5SDimitry Andric       IsBlock = true;
2620b57cec5SDimitry Andric       break;
2630b57cec5SDimitry Andric     case DW_FORM_data1:
2640b57cec5SDimitry Andric     case DW_FORM_ref1:
2650b57cec5SDimitry Andric     case DW_FORM_flag:
2660b57cec5SDimitry Andric     case DW_FORM_strx1:
2670b57cec5SDimitry Andric     case DW_FORM_addrx1:
2685ffd83dbSDimitry Andric       Value.uval = Data.getU8(OffsetPtr, &Err);
2690b57cec5SDimitry Andric       break;
2700b57cec5SDimitry Andric     case DW_FORM_data2:
2710b57cec5SDimitry Andric     case DW_FORM_ref2:
2720b57cec5SDimitry Andric     case DW_FORM_strx2:
2730b57cec5SDimitry Andric     case DW_FORM_addrx2:
2745ffd83dbSDimitry Andric       Value.uval = Data.getU16(OffsetPtr, &Err);
2750b57cec5SDimitry Andric       break;
2760b57cec5SDimitry Andric     case DW_FORM_strx3:
27706c3fb27SDimitry Andric     case DW_FORM_addrx3:
2785ffd83dbSDimitry Andric       Value.uval = Data.getU24(OffsetPtr, &Err);
2790b57cec5SDimitry Andric       break;
2800b57cec5SDimitry Andric     case DW_FORM_data4:
2810b57cec5SDimitry Andric     case DW_FORM_ref4:
2820b57cec5SDimitry Andric     case DW_FORM_ref_sup4:
2830b57cec5SDimitry Andric     case DW_FORM_strx4:
2840b57cec5SDimitry Andric     case DW_FORM_addrx4:
2855ffd83dbSDimitry Andric       Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err);
2860b57cec5SDimitry Andric       break;
2870b57cec5SDimitry Andric     case DW_FORM_data8:
2880b57cec5SDimitry Andric     case DW_FORM_ref8:
2890b57cec5SDimitry Andric     case DW_FORM_ref_sup8:
2905ffd83dbSDimitry Andric       Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err);
2910b57cec5SDimitry Andric       break;
2920b57cec5SDimitry Andric     case DW_FORM_data16:
2930b57cec5SDimitry Andric       // Treat this like a 16-byte block.
2940b57cec5SDimitry Andric       Value.uval = 16;
2950b57cec5SDimitry Andric       IsBlock = true;
2960b57cec5SDimitry Andric       break;
2970b57cec5SDimitry Andric     case DW_FORM_sdata:
2985ffd83dbSDimitry Andric       Value.sval = Data.getSLEB128(OffsetPtr, &Err);
2990b57cec5SDimitry Andric       break;
3000b57cec5SDimitry Andric     case DW_FORM_udata:
3010b57cec5SDimitry Andric     case DW_FORM_ref_udata:
3020b57cec5SDimitry Andric     case DW_FORM_rnglistx:
303480093f4SDimitry Andric     case DW_FORM_loclistx:
3045ffd83dbSDimitry Andric     case DW_FORM_GNU_addr_index:
3055ffd83dbSDimitry Andric     case DW_FORM_GNU_str_index:
3065ffd83dbSDimitry Andric     case DW_FORM_addrx:
3075ffd83dbSDimitry Andric     case DW_FORM_strx:
3085ffd83dbSDimitry Andric       Value.uval = Data.getULEB128(OffsetPtr, &Err);
3090b57cec5SDimitry Andric       break;
310fe6060f1SDimitry Andric     case DW_FORM_LLVM_addrx_offset:
311fe6060f1SDimitry Andric       Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;
312349cc55cSDimitry Andric       Value.uval |= Data.getU32(OffsetPtr, &Err);
313fe6060f1SDimitry Andric       break;
3140b57cec5SDimitry Andric     case DW_FORM_string:
3155ffd83dbSDimitry Andric       Value.cstr = Data.getCStr(OffsetPtr, &Err);
3160b57cec5SDimitry Andric       break;
3170b57cec5SDimitry Andric     case DW_FORM_indirect:
3185ffd83dbSDimitry Andric       Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err));
3190b57cec5SDimitry Andric       Indirect = true;
3200b57cec5SDimitry Andric       break;
3210b57cec5SDimitry Andric     case DW_FORM_strp:
3220b57cec5SDimitry Andric     case DW_FORM_sec_offset:
3230b57cec5SDimitry Andric     case DW_FORM_GNU_ref_alt:
3240b57cec5SDimitry Andric     case DW_FORM_GNU_strp_alt:
3250b57cec5SDimitry Andric     case DW_FORM_line_strp:
3260b57cec5SDimitry Andric     case DW_FORM_strp_sup: {
3275ffd83dbSDimitry Andric       Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(),
3285ffd83dbSDimitry Andric                                           OffsetPtr, nullptr, &Err);
3290b57cec5SDimitry Andric       break;
3300b57cec5SDimitry Andric     }
3310b57cec5SDimitry Andric     case DW_FORM_flag_present:
3320b57cec5SDimitry Andric       Value.uval = 1;
3330b57cec5SDimitry Andric       break;
3340b57cec5SDimitry Andric     case DW_FORM_ref_sig8:
3355ffd83dbSDimitry Andric       Value.uval = Data.getU64(OffsetPtr, &Err);
3360b57cec5SDimitry Andric       break;
3374652422eSDimitry Andric     case DW_FORM_implicit_const:
3384652422eSDimitry Andric       // Value has been already set by DWARFFormValue::createFromSValue.
3394652422eSDimitry Andric       break;
3400b57cec5SDimitry Andric     default:
3410b57cec5SDimitry Andric       // DWARFFormValue::skipValue() will have caught this and caused all
3420b57cec5SDimitry Andric       // DWARF DIEs to fail to be parsed, so this code is not be reachable.
3430b57cec5SDimitry Andric       llvm_unreachable("unsupported form");
3440b57cec5SDimitry Andric     }
3455ffd83dbSDimitry Andric   } while (Indirect && !Err);
3460b57cec5SDimitry Andric 
3475ffd83dbSDimitry Andric   if (IsBlock)
3485ffd83dbSDimitry Andric     Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin();
3490b57cec5SDimitry Andric 
3505ffd83dbSDimitry Andric   return !errorToBool(std::move(Err));
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
353e8d8bef9SDimitry Andric void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize,
354e8d8bef9SDimitry Andric                                  uint64_t Address) {
355e8d8bef9SDimitry Andric   uint8_t HexDigits = AddressSize * 2;
356e8d8bef9SDimitry Andric   OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address);
357e8d8bef9SDimitry Andric }
358e8d8bef9SDimitry Andric 
3590b57cec5SDimitry Andric void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,
3600b57cec5SDimitry Andric                                           DIDumpOptions DumpOpts,
3610b57cec5SDimitry Andric                                           object::SectionedAddress SA) const {
362e8d8bef9SDimitry Andric   dumpAddress(OS, U->getAddressByteSize(), SA.Address);
3630b57cec5SDimitry Andric   dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,
3640b57cec5SDimitry Andric                      SA.SectionIndex);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
3680b57cec5SDimitry Andric                                         DIDumpOptions DumpOpts,
3690b57cec5SDimitry Andric                                         uint64_t SectionIndex) {
3700b57cec5SDimitry Andric   if (!DumpOpts.Verbose || SectionIndex == -1ULL)
3710b57cec5SDimitry Andric     return;
3720b57cec5SDimitry Andric   ArrayRef<SectionName> SectionNames = Obj.getSectionNames();
3730b57cec5SDimitry Andric   const auto &SecRef = SectionNames[SectionIndex];
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   OS << " \"" << SecRef.Name << '\"';
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   // Print section index if name is not unique.
3780b57cec5SDimitry Andric   if (!SecRef.IsNameUnique)
3790b57cec5SDimitry Andric     OS << format(" [%" PRIu64 "]", SectionIndex);
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
3830b57cec5SDimitry Andric   uint64_t UValue = Value.uval;
3840b57cec5SDimitry Andric   bool CURelativeOffset = false;
3850b57cec5SDimitry Andric   raw_ostream &AddrOS = DumpOpts.ShowAddresses
3860b57cec5SDimitry Andric                             ? WithColor(OS, HighlightColor::Address).get()
3870b57cec5SDimitry Andric                             : nulls();
3885ffd83dbSDimitry Andric   int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
3890b57cec5SDimitry Andric   switch (Form) {
3900b57cec5SDimitry Andric   case DW_FORM_addr:
3910b57cec5SDimitry Andric     dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});
3920b57cec5SDimitry Andric     break;
3930b57cec5SDimitry Andric   case DW_FORM_addrx:
3940b57cec5SDimitry Andric   case DW_FORM_addrx1:
3950b57cec5SDimitry Andric   case DW_FORM_addrx2:
3960b57cec5SDimitry Andric   case DW_FORM_addrx3:
3970b57cec5SDimitry Andric   case DW_FORM_addrx4:
39806c3fb27SDimitry Andric   case DW_FORM_GNU_addr_index:
399fe6060f1SDimitry Andric   case DW_FORM_LLVM_addrx_offset: {
400fe6060f1SDimitry Andric     if (U == nullptr) {
401fe6060f1SDimitry Andric       OS << "<invalid dwarf unit>";
402fe6060f1SDimitry Andric       break;
403fe6060f1SDimitry Andric     }
40406c3fb27SDimitry Andric     std::optional<object::SectionedAddress> A = getAsSectionedAddress();
40506c3fb27SDimitry Andric     if (!A || DumpOpts.Verbose) {
40606c3fb27SDimitry Andric       if (Form == DW_FORM_LLVM_addrx_offset) {
407fe6060f1SDimitry Andric         uint32_t Index = UValue >> 32;
408fe6060f1SDimitry Andric         uint32_t Offset = UValue & 0xffffffff;
409fe6060f1SDimitry Andric         AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);
410fe6060f1SDimitry Andric       } else
41106c3fb27SDimitry Andric         AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
41206c3fb27SDimitry Andric     }
41306c3fb27SDimitry Andric     if (A)
41406c3fb27SDimitry Andric       dumpSectionedAddress(AddrOS, DumpOpts, *A);
41506c3fb27SDimitry Andric     else
416fe6060f1SDimitry Andric       OS << "<unresolved>";
417fe6060f1SDimitry Andric     break;
418fe6060f1SDimitry Andric   }
4190b57cec5SDimitry Andric   case DW_FORM_flag_present:
4200b57cec5SDimitry Andric     OS << "true";
4210b57cec5SDimitry Andric     break;
4220b57cec5SDimitry Andric   case DW_FORM_flag:
4230b57cec5SDimitry Andric   case DW_FORM_data1:
4240b57cec5SDimitry Andric     OS << format("0x%02x", (uint8_t)UValue);
4250b57cec5SDimitry Andric     break;
4260b57cec5SDimitry Andric   case DW_FORM_data2:
4270b57cec5SDimitry Andric     OS << format("0x%04x", (uint16_t)UValue);
4280b57cec5SDimitry Andric     break;
4290b57cec5SDimitry Andric   case DW_FORM_data4:
4300b57cec5SDimitry Andric     OS << format("0x%08x", (uint32_t)UValue);
4310b57cec5SDimitry Andric     break;
4320b57cec5SDimitry Andric   case DW_FORM_ref_sig8:
4330b57cec5SDimitry Andric     AddrOS << format("0x%016" PRIx64, UValue);
4340b57cec5SDimitry Andric     break;
4350b57cec5SDimitry Andric   case DW_FORM_data8:
4360b57cec5SDimitry Andric     OS << format("0x%016" PRIx64, UValue);
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric   case DW_FORM_data16:
439bdd1243dSDimitry Andric     OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16);
4400b57cec5SDimitry Andric     break;
4410b57cec5SDimitry Andric   case DW_FORM_string:
4420b57cec5SDimitry Andric     OS << '"';
4430b57cec5SDimitry Andric     OS.write_escaped(Value.cstr);
4440b57cec5SDimitry Andric     OS << '"';
4450b57cec5SDimitry Andric     break;
4460b57cec5SDimitry Andric   case DW_FORM_exprloc:
4470b57cec5SDimitry Andric   case DW_FORM_block:
4480b57cec5SDimitry Andric   case DW_FORM_block1:
4490b57cec5SDimitry Andric   case DW_FORM_block2:
4500b57cec5SDimitry Andric   case DW_FORM_block4:
4510b57cec5SDimitry Andric     if (UValue > 0) {
4520b57cec5SDimitry Andric       switch (Form) {
4530b57cec5SDimitry Andric       case DW_FORM_exprloc:
4540b57cec5SDimitry Andric       case DW_FORM_block:
4550b57cec5SDimitry Andric         AddrOS << format("<0x%" PRIx64 "> ", UValue);
4560b57cec5SDimitry Andric         break;
4570b57cec5SDimitry Andric       case DW_FORM_block1:
4580b57cec5SDimitry Andric         AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);
4590b57cec5SDimitry Andric         break;
4600b57cec5SDimitry Andric       case DW_FORM_block2:
4610b57cec5SDimitry Andric         AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);
4620b57cec5SDimitry Andric         break;
4630b57cec5SDimitry Andric       case DW_FORM_block4:
4640b57cec5SDimitry Andric         AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);
4650b57cec5SDimitry Andric         break;
4660b57cec5SDimitry Andric       default:
4670b57cec5SDimitry Andric         break;
4680b57cec5SDimitry Andric       }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric       const uint8_t *DataPtr = Value.data;
4710b57cec5SDimitry Andric       if (DataPtr) {
4720b57cec5SDimitry Andric         // UValue contains size of block
4730b57cec5SDimitry Andric         const uint8_t *EndDataPtr = DataPtr + UValue;
4740b57cec5SDimitry Andric         while (DataPtr < EndDataPtr) {
4750b57cec5SDimitry Andric           AddrOS << format("%2.2x ", *DataPtr);
4760b57cec5SDimitry Andric           ++DataPtr;
4770b57cec5SDimitry Andric         }
4780b57cec5SDimitry Andric       } else
4790b57cec5SDimitry Andric         OS << "NULL";
4800b57cec5SDimitry Andric     }
4810b57cec5SDimitry Andric     break;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   case DW_FORM_sdata:
4844652422eSDimitry Andric   case DW_FORM_implicit_const:
4850b57cec5SDimitry Andric     OS << Value.sval;
4860b57cec5SDimitry Andric     break;
4870b57cec5SDimitry Andric   case DW_FORM_udata:
4880b57cec5SDimitry Andric     OS << Value.uval;
4890b57cec5SDimitry Andric     break;
4900b57cec5SDimitry Andric   case DW_FORM_strp:
4910b57cec5SDimitry Andric     if (DumpOpts.Verbose)
4925ffd83dbSDimitry Andric       OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue);
4930b57cec5SDimitry Andric     dumpString(OS);
4940b57cec5SDimitry Andric     break;
4950b57cec5SDimitry Andric   case DW_FORM_line_strp:
4960b57cec5SDimitry Andric     if (DumpOpts.Verbose)
4975ffd83dbSDimitry Andric       OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth,
4985ffd83dbSDimitry Andric                    UValue);
4990b57cec5SDimitry Andric     dumpString(OS);
5000b57cec5SDimitry Andric     break;
5010b57cec5SDimitry Andric   case DW_FORM_strx:
5020b57cec5SDimitry Andric   case DW_FORM_strx1:
5030b57cec5SDimitry Andric   case DW_FORM_strx2:
5040b57cec5SDimitry Andric   case DW_FORM_strx3:
5050b57cec5SDimitry Andric   case DW_FORM_strx4:
5060b57cec5SDimitry Andric   case DW_FORM_GNU_str_index:
5070b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5080b57cec5SDimitry Andric       OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);
5090b57cec5SDimitry Andric     dumpString(OS);
5100b57cec5SDimitry Andric     break;
5110b57cec5SDimitry Andric   case DW_FORM_GNU_strp_alt:
5120b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5130b57cec5SDimitry Andric       OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);
5140b57cec5SDimitry Andric     dumpString(OS);
5150b57cec5SDimitry Andric     break;
5160b57cec5SDimitry Andric   case DW_FORM_ref_addr:
5170b57cec5SDimitry Andric     AddrOS << format("0x%016" PRIx64, UValue);
5180b57cec5SDimitry Andric     break;
5190b57cec5SDimitry Andric   case DW_FORM_ref1:
5200b57cec5SDimitry Andric     CURelativeOffset = true;
5210b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5220b57cec5SDimitry Andric       AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);
5230b57cec5SDimitry Andric     break;
5240b57cec5SDimitry Andric   case DW_FORM_ref2:
5250b57cec5SDimitry Andric     CURelativeOffset = true;
5260b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5270b57cec5SDimitry Andric       AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);
5280b57cec5SDimitry Andric     break;
5290b57cec5SDimitry Andric   case DW_FORM_ref4:
5300b57cec5SDimitry Andric     CURelativeOffset = true;
5310b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5320b57cec5SDimitry Andric       AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);
5330b57cec5SDimitry Andric     break;
5340b57cec5SDimitry Andric   case DW_FORM_ref8:
5350b57cec5SDimitry Andric     CURelativeOffset = true;
5360b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5370b57cec5SDimitry Andric       AddrOS << format("cu + 0x%8.8" PRIx64, UValue);
5380b57cec5SDimitry Andric     break;
5390b57cec5SDimitry Andric   case DW_FORM_ref_udata:
5400b57cec5SDimitry Andric     CURelativeOffset = true;
5410b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5420b57cec5SDimitry Andric       AddrOS << format("cu + 0x%" PRIx64, UValue);
5430b57cec5SDimitry Andric     break;
5440b57cec5SDimitry Andric   case DW_FORM_GNU_ref_alt:
5450b57cec5SDimitry Andric     AddrOS << format("<alt 0x%" PRIx64 ">", UValue);
5460b57cec5SDimitry Andric     break;
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   // All DW_FORM_indirect attributes should be resolved prior to calling
5490b57cec5SDimitry Andric   // this function
5500b57cec5SDimitry Andric   case DW_FORM_indirect:
5510b57cec5SDimitry Andric     OS << "DW_FORM_indirect";
5520b57cec5SDimitry Andric     break;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   case DW_FORM_rnglistx:
5550b57cec5SDimitry Andric     OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);
5560b57cec5SDimitry Andric     break;
5570b57cec5SDimitry Andric 
558480093f4SDimitry Andric   case DW_FORM_loclistx:
559480093f4SDimitry Andric     OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue);
560480093f4SDimitry Andric     break;
561480093f4SDimitry Andric 
5620b57cec5SDimitry Andric   case DW_FORM_sec_offset:
5635ffd83dbSDimitry Andric     AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue);
5640b57cec5SDimitry Andric     break;
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   default:
5670b57cec5SDimitry Andric     OS << format("DW_FORM(0x%4.4x)", Form);
5680b57cec5SDimitry Andric     break;
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   if (CURelativeOffset) {
5720b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5730b57cec5SDimitry Andric       OS << " => {";
5740b57cec5SDimitry Andric     if (DumpOpts.ShowAddresses)
5750b57cec5SDimitry Andric       WithColor(OS, HighlightColor::Address).get()
5760b57cec5SDimitry Andric           << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));
5770b57cec5SDimitry Andric     if (DumpOpts.Verbose)
5780b57cec5SDimitry Andric       OS << "}";
5790b57cec5SDimitry Andric   }
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric void DWARFFormValue::dumpString(raw_ostream &OS) const {
5830eae32dcSDimitry Andric   if (auto DbgStr = dwarf::toString(*this)) {
5840b57cec5SDimitry Andric     auto COS = WithColor(OS, HighlightColor::String);
5850b57cec5SDimitry Andric     COS.get() << '"';
5860eae32dcSDimitry Andric     COS.get().write_escaped(*DbgStr);
5870b57cec5SDimitry Andric     COS.get() << '"';
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910eae32dcSDimitry Andric Expected<const char *> DWARFFormValue::getAsCString() const {
5920b57cec5SDimitry Andric   if (!isFormClass(FC_String))
5930eae32dcSDimitry Andric     return make_error<StringError>("Invalid form for string attribute",
5940eae32dcSDimitry Andric                                    inconvertibleErrorCode());
5950b57cec5SDimitry Andric   if (Form == DW_FORM_string)
5960b57cec5SDimitry Andric     return Value.cstr;
5970b57cec5SDimitry Andric   // FIXME: Add support for DW_FORM_GNU_strp_alt
5980b57cec5SDimitry Andric   if (Form == DW_FORM_GNU_strp_alt || C == nullptr)
5990eae32dcSDimitry Andric     return make_error<StringError>("Unsupported form for string attribute",
6000eae32dcSDimitry Andric                                    inconvertibleErrorCode());
6018bcb0991SDimitry Andric   uint64_t Offset = Value.uval;
602bdd1243dSDimitry Andric   std::optional<uint32_t> Index;
6030b57cec5SDimitry Andric   if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||
6040b57cec5SDimitry Andric       Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||
6050b57cec5SDimitry Andric       Form == DW_FORM_strx4) {
6060b57cec5SDimitry Andric     if (!U)
6070eae32dcSDimitry Andric       return make_error<StringError>("API limitation - string extraction not "
6080eae32dcSDimitry Andric                                      "available without a DWARFUnit",
6090eae32dcSDimitry Andric                                      inconvertibleErrorCode());
6100eae32dcSDimitry Andric     Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);
6110eae32dcSDimitry Andric     Index = Offset;
6120b57cec5SDimitry Andric     if (!StrOffset)
6130eae32dcSDimitry Andric       return StrOffset.takeError();
6140b57cec5SDimitry Andric     Offset = *StrOffset;
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric   // Prefer the Unit's string extractor, because for .dwo it will point to
6170b57cec5SDimitry Andric   // .debug_str.dwo, while the Context's extractor always uses .debug_str.
61806c3fb27SDimitry Andric   bool IsDebugLineString = Form == DW_FORM_line_strp;
61906c3fb27SDimitry Andric   DataExtractor StrData =
62006c3fb27SDimitry Andric       IsDebugLineString ? C->getLineStringExtractor()
62106c3fb27SDimitry Andric                         : U ? U->getStringExtractor() : C->getStringExtractor();
6220eae32dcSDimitry Andric   if (const char *Str = StrData.getCStr(&Offset))
6230b57cec5SDimitry Andric     return Str;
6240eae32dcSDimitry Andric   std::string Msg = FormEncodingString(Form).str();
6250eae32dcSDimitry Andric   if (Index)
6260eae32dcSDimitry Andric     Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str();
62706c3fb27SDimitry Andric   Msg += (" offset " + Twine(Offset) + " is beyond " +
62806c3fb27SDimitry Andric           (IsDebugLineString ? ".debug_line_str" : ".debug_str") + " bounds")
62906c3fb27SDimitry Andric              .str();
6300eae32dcSDimitry Andric   return make_error<StringError>(Msg,
6310eae32dcSDimitry Andric       inconvertibleErrorCode());
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
634bdd1243dSDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsAddress() const {
6350b57cec5SDimitry Andric   if (auto SA = getAsSectionedAddress())
6360b57cec5SDimitry Andric     return SA->Address;
637bdd1243dSDimitry Andric   return std::nullopt;
6380b57cec5SDimitry Andric }
6398bcb0991SDimitry Andric 
64006c3fb27SDimitry Andric std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(
64106c3fb27SDimitry Andric     const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {
64206c3fb27SDimitry Andric   if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))
643bdd1243dSDimitry Andric     return std::nullopt;
644fe6060f1SDimitry Andric   bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
64506c3fb27SDimitry Andric   if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||
64606c3fb27SDimitry Andric       Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||
64706c3fb27SDimitry Andric       Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {
648fe6060f1SDimitry Andric 
649fe6060f1SDimitry Andric     uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;
6500b57cec5SDimitry Andric     if (!U)
651bdd1243dSDimitry Andric       return std::nullopt;
652bdd1243dSDimitry Andric     std::optional<object::SectionedAddress> SA =
653bdd1243dSDimitry Andric         U->getAddrOffsetSectionItem(Index);
6540b57cec5SDimitry Andric     if (!SA)
655bdd1243dSDimitry Andric       return std::nullopt;
656fe6060f1SDimitry Andric     if (AddrOffset)
657fe6060f1SDimitry Andric       SA->Address += (Value.uval & 0xffffffff);
6580b57cec5SDimitry Andric     return SA;
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric   return {{Value.uval, Value.SectionIndex}};
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric 
66306c3fb27SDimitry Andric std::optional<object::SectionedAddress>
66406c3fb27SDimitry Andric DWARFFormValue::getAsSectionedAddress() const {
66506c3fb27SDimitry Andric   return getAsSectionedAddress(Value, Form, U);
66606c3fb27SDimitry Andric }
66706c3fb27SDimitry Andric 
668*0fca6ea1SDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsRelativeReference() const {
6690b57cec5SDimitry Andric   switch (Form) {
6700b57cec5SDimitry Andric   case DW_FORM_ref1:
6710b57cec5SDimitry Andric   case DW_FORM_ref2:
6720b57cec5SDimitry Andric   case DW_FORM_ref4:
6730b57cec5SDimitry Andric   case DW_FORM_ref8:
6740b57cec5SDimitry Andric   case DW_FORM_ref_udata:
6750b57cec5SDimitry Andric     if (!U)
676bdd1243dSDimitry Andric       return std::nullopt;
677*0fca6ea1SDimitry Andric     return Value.uval;
678*0fca6ea1SDimitry Andric   default:
679*0fca6ea1SDimitry Andric     return std::nullopt;
680*0fca6ea1SDimitry Andric   }
681*0fca6ea1SDimitry Andric }
682*0fca6ea1SDimitry Andric 
683*0fca6ea1SDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsDebugInfoReference() const {
684*0fca6ea1SDimitry Andric   if (Form == DW_FORM_ref_addr)
685*0fca6ea1SDimitry Andric     return Value.uval;
686*0fca6ea1SDimitry Andric   return std::nullopt;
687*0fca6ea1SDimitry Andric }
688*0fca6ea1SDimitry Andric 
689*0fca6ea1SDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsSignatureReference() const {
690*0fca6ea1SDimitry Andric   if (Form == DW_FORM_ref_sig8)
691*0fca6ea1SDimitry Andric     return Value.uval;
692*0fca6ea1SDimitry Andric   return std::nullopt;
693*0fca6ea1SDimitry Andric }
694*0fca6ea1SDimitry Andric 
695*0fca6ea1SDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsSupplementaryReference() const {
696*0fca6ea1SDimitry Andric   switch (Form) {
6970b57cec5SDimitry Andric   case DW_FORM_GNU_ref_alt:
698*0fca6ea1SDimitry Andric   case DW_FORM_ref_sup4:
699*0fca6ea1SDimitry Andric   case DW_FORM_ref_sup8:
700*0fca6ea1SDimitry Andric     return Value.uval;
7010b57cec5SDimitry Andric   default:
702bdd1243dSDimitry Andric     return std::nullopt;
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
706bdd1243dSDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
7070b57cec5SDimitry Andric   if (!isFormClass(FC_SectionOffset))
708bdd1243dSDimitry Andric     return std::nullopt;
7090b57cec5SDimitry Andric   return Value.uval;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
712bdd1243dSDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
7130b57cec5SDimitry Andric   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
7140b57cec5SDimitry Andric       Form == DW_FORM_sdata)
715bdd1243dSDimitry Andric     return std::nullopt;
7160b57cec5SDimitry Andric   return Value.uval;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
719bdd1243dSDimitry Andric std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
7200b57cec5SDimitry Andric   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
7210b57cec5SDimitry Andric       (Form == DW_FORM_udata &&
7220b57cec5SDimitry Andric        uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))
723bdd1243dSDimitry Andric     return std::nullopt;
7240b57cec5SDimitry Andric   switch (Form) {
7250b57cec5SDimitry Andric   case DW_FORM_data4:
7260b57cec5SDimitry Andric     return int32_t(Value.uval);
7270b57cec5SDimitry Andric   case DW_FORM_data2:
7280b57cec5SDimitry Andric     return int16_t(Value.uval);
7290b57cec5SDimitry Andric   case DW_FORM_data1:
7300b57cec5SDimitry Andric     return int8_t(Value.uval);
7310b57cec5SDimitry Andric   case DW_FORM_sdata:
7320b57cec5SDimitry Andric   case DW_FORM_data8:
7330b57cec5SDimitry Andric   default:
7340b57cec5SDimitry Andric     return Value.sval;
7350b57cec5SDimitry Andric   }
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
738bdd1243dSDimitry Andric std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
7390b57cec5SDimitry Andric   if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&
7400b57cec5SDimitry Andric       Form != DW_FORM_data16)
741bdd1243dSDimitry Andric     return std::nullopt;
742bdd1243dSDimitry Andric   return ArrayRef(Value.data, Value.uval);
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
745bdd1243dSDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {
7460b57cec5SDimitry Andric   if (!isFormClass(FC_String) && Form == DW_FORM_string)
747bdd1243dSDimitry Andric     return std::nullopt;
7480b57cec5SDimitry Andric   return Value.uval;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric 
751bdd1243dSDimitry Andric std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
7520b57cec5SDimitry Andric   if (!isFormClass(FC_Reference))
753bdd1243dSDimitry Andric     return std::nullopt;
7540b57cec5SDimitry Andric   return Value.uval;
7550b57cec5SDimitry Andric }
756349cc55cSDimitry Andric 
757bdd1243dSDimitry Andric std::optional<std::string>
758349cc55cSDimitry Andric DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
759349cc55cSDimitry Andric   if (U == nullptr || !isFormClass(FC_Constant))
760bdd1243dSDimitry Andric     return std::nullopt;
761349cc55cSDimitry Andric   DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit();
762349cc55cSDimitry Andric   if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) {
763349cc55cSDimitry Andric     std::string FileName;
764349cc55cSDimitry Andric     if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind,
765349cc55cSDimitry Andric                                FileName))
766349cc55cSDimitry Andric       return FileName;
767349cc55cSDimitry Andric   }
768bdd1243dSDimitry Andric   return std::nullopt;
769349cc55cSDimitry Andric }
77006c3fb27SDimitry Andric 
77106c3fb27SDimitry Andric bool llvm::dwarf::doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC,
77206c3fb27SDimitry Andric                            uint16_t DwarfVersion) {
77306c3fb27SDimitry Andric   // First, check DWARF5 form classes.
774*0fca6ea1SDimitry Andric   if (Form < std::size(DWARF5FormClasses) && DWARF5FormClasses[Form] == FC)
77506c3fb27SDimitry Andric     return true;
77606c3fb27SDimitry Andric   // Check more forms from extensions and proposals.
77706c3fb27SDimitry Andric   switch (Form) {
77806c3fb27SDimitry Andric   case DW_FORM_GNU_ref_alt:
77906c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_Reference);
78006c3fb27SDimitry Andric   case DW_FORM_GNU_addr_index:
78106c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_Address);
78206c3fb27SDimitry Andric   case DW_FORM_GNU_str_index:
78306c3fb27SDimitry Andric   case DW_FORM_GNU_strp_alt:
78406c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_String);
78506c3fb27SDimitry Andric   case DW_FORM_LLVM_addrx_offset:
78606c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_Address);
78706c3fb27SDimitry Andric   case DW_FORM_strp:
78806c3fb27SDimitry Andric   case DW_FORM_line_strp:
78906c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_SectionOffset);
79006c3fb27SDimitry Andric   case DW_FORM_data4:
79106c3fb27SDimitry Andric   case DW_FORM_data8:
79206c3fb27SDimitry Andric     // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section
79306c3fb27SDimitry Andric     // offset.
79406c3fb27SDimitry Andric     return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3);
79506c3fb27SDimitry Andric   default:
79606c3fb27SDimitry Andric     return false;
79706c3fb27SDimitry Andric   }
79806c3fb27SDimitry Andric }
799