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