15ffd83dbSDimitry 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 9fe6060f1SDimitry Andric #include <cassert> 10bdd1243dSDimitry Andric #include <optional> 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Core/Module.h" 130b57cec5SDimitry Andric #include "lldb/Core/dwarf.h" 140b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 150b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "DWARFDebugInfo.h" 180b57cec5SDimitry Andric #include "DWARFFormValue.h" 190b57cec5SDimitry Andric #include "DWARFUnit.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace lldb_private; 2281ad6265SDimitry Andric using namespace lldb_private::dwarf; 235f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric void DWARFFormValue::Clear() { 260b57cec5SDimitry Andric m_unit = nullptr; 2706c3fb27SDimitry Andric m_form = dw_form_t(0); 280b57cec5SDimitry Andric m_value = ValueTypeTag(); 290b57cec5SDimitry Andric } 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, 320b57cec5SDimitry Andric lldb::offset_t *offset_ptr) { 330b57cec5SDimitry Andric if (m_form == DW_FORM_implicit_const) 340b57cec5SDimitry Andric return true; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric bool indirect = false; 370b57cec5SDimitry Andric bool is_block = false; 380b57cec5SDimitry Andric m_value.data = nullptr; 390b57cec5SDimitry Andric uint8_t ref_addr_size; 400b57cec5SDimitry Andric // Read the value for the form into value and follow and DW_FORM_indirect 410b57cec5SDimitry Andric // instances we run into 420b57cec5SDimitry Andric do { 430b57cec5SDimitry Andric indirect = false; 440b57cec5SDimitry Andric switch (m_form) { 450b57cec5SDimitry Andric case DW_FORM_addr: 460b57cec5SDimitry Andric assert(m_unit); 470b57cec5SDimitry Andric m_value.value.uval = 480b57cec5SDimitry Andric data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit)); 490b57cec5SDimitry Andric break; 500b57cec5SDimitry Andric case DW_FORM_block1: 510b57cec5SDimitry Andric m_value.value.uval = data.GetU8(offset_ptr); 520b57cec5SDimitry Andric is_block = true; 530b57cec5SDimitry Andric break; 540b57cec5SDimitry Andric case DW_FORM_block2: 550b57cec5SDimitry Andric m_value.value.uval = data.GetU16(offset_ptr); 560b57cec5SDimitry Andric is_block = true; 570b57cec5SDimitry Andric break; 580b57cec5SDimitry Andric case DW_FORM_block4: 590b57cec5SDimitry Andric m_value.value.uval = data.GetU32(offset_ptr); 600b57cec5SDimitry Andric is_block = true; 610b57cec5SDimitry Andric break; 620b57cec5SDimitry Andric case DW_FORM_data16: 630b57cec5SDimitry Andric m_value.value.uval = 16; 640b57cec5SDimitry Andric is_block = true; 650b57cec5SDimitry Andric break; 660b57cec5SDimitry Andric case DW_FORM_exprloc: 670b57cec5SDimitry Andric case DW_FORM_block: 680b57cec5SDimitry Andric m_value.value.uval = data.GetULEB128(offset_ptr); 690b57cec5SDimitry Andric is_block = true; 700b57cec5SDimitry Andric break; 710b57cec5SDimitry Andric case DW_FORM_string: 720b57cec5SDimitry Andric m_value.value.cstr = data.GetCStr(offset_ptr); 730b57cec5SDimitry Andric break; 740b57cec5SDimitry Andric case DW_FORM_sdata: 750b57cec5SDimitry Andric m_value.value.sval = data.GetSLEB128(offset_ptr); 760b57cec5SDimitry Andric break; 770b57cec5SDimitry Andric case DW_FORM_strp: 780b57cec5SDimitry Andric case DW_FORM_line_strp: 790b57cec5SDimitry Andric case DW_FORM_sec_offset: 800b57cec5SDimitry Andric m_value.value.uval = data.GetMaxU64(offset_ptr, 4); 810b57cec5SDimitry Andric break; 820b57cec5SDimitry Andric case DW_FORM_addrx1: 830b57cec5SDimitry Andric case DW_FORM_strx1: 840b57cec5SDimitry Andric case DW_FORM_ref1: 850b57cec5SDimitry Andric case DW_FORM_data1: 860b57cec5SDimitry Andric case DW_FORM_flag: 870b57cec5SDimitry Andric m_value.value.uval = data.GetU8(offset_ptr); 880b57cec5SDimitry Andric break; 890b57cec5SDimitry Andric case DW_FORM_addrx2: 900b57cec5SDimitry Andric case DW_FORM_strx2: 910b57cec5SDimitry Andric case DW_FORM_ref2: 920b57cec5SDimitry Andric case DW_FORM_data2: 930b57cec5SDimitry Andric m_value.value.uval = data.GetU16(offset_ptr); 940b57cec5SDimitry Andric break; 950b57cec5SDimitry Andric case DW_FORM_addrx3: 960b57cec5SDimitry Andric case DW_FORM_strx3: 970b57cec5SDimitry Andric m_value.value.uval = data.GetMaxU64(offset_ptr, 3); 980b57cec5SDimitry Andric break; 990b57cec5SDimitry Andric case DW_FORM_addrx4: 1000b57cec5SDimitry Andric case DW_FORM_strx4: 1010b57cec5SDimitry Andric case DW_FORM_ref4: 1020b57cec5SDimitry Andric case DW_FORM_data4: 1030b57cec5SDimitry Andric m_value.value.uval = data.GetU32(offset_ptr); 1040b57cec5SDimitry Andric break; 1050b57cec5SDimitry Andric case DW_FORM_data8: 1060b57cec5SDimitry Andric case DW_FORM_ref8: 1070b57cec5SDimitry Andric case DW_FORM_ref_sig8: 1080b57cec5SDimitry Andric m_value.value.uval = data.GetU64(offset_ptr); 1090b57cec5SDimitry Andric break; 1100b57cec5SDimitry Andric case DW_FORM_addrx: 111480093f4SDimitry Andric case DW_FORM_loclistx: 1120b57cec5SDimitry Andric case DW_FORM_rnglistx: 1130b57cec5SDimitry Andric case DW_FORM_strx: 1140b57cec5SDimitry Andric case DW_FORM_udata: 1150b57cec5SDimitry Andric case DW_FORM_ref_udata: 1160b57cec5SDimitry Andric case DW_FORM_GNU_str_index: 1170b57cec5SDimitry Andric case DW_FORM_GNU_addr_index: 1180b57cec5SDimitry Andric m_value.value.uval = data.GetULEB128(offset_ptr); 1190b57cec5SDimitry Andric break; 1200b57cec5SDimitry Andric case DW_FORM_ref_addr: 1210b57cec5SDimitry Andric assert(m_unit); 1220b57cec5SDimitry Andric if (m_unit->GetVersion() <= 2) 1230b57cec5SDimitry Andric ref_addr_size = m_unit->GetAddressByteSize(); 1240b57cec5SDimitry Andric else 1250b57cec5SDimitry Andric ref_addr_size = 4; 1260b57cec5SDimitry Andric m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size); 1270b57cec5SDimitry Andric break; 1280b57cec5SDimitry Andric case DW_FORM_indirect: 12906c3fb27SDimitry Andric m_form = static_cast<dw_form_t>(data.GetULEB128(offset_ptr)); 1300b57cec5SDimitry Andric indirect = true; 1310b57cec5SDimitry Andric break; 1320b57cec5SDimitry Andric case DW_FORM_flag_present: 1330b57cec5SDimitry Andric m_value.value.uval = 1; 1340b57cec5SDimitry Andric break; 1350b57cec5SDimitry Andric default: 1360b57cec5SDimitry Andric return false; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric } while (indirect); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric if (is_block) { 1410b57cec5SDimitry Andric m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); 1420b57cec5SDimitry Andric if (m_value.data != nullptr) { 1430b57cec5SDimitry Andric *offset_ptr += m_value.value.uval; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric struct FormSize { 1510b57cec5SDimitry Andric uint8_t valid:1, size:7; 1520b57cec5SDimitry Andric }; 1530b57cec5SDimitry Andric static FormSize g_form_sizes[] = { 1540b57cec5SDimitry Andric {0, 0}, // 0x00 unused 1550b57cec5SDimitry Andric {0, 0}, // 0x01 DW_FORM_addr 1560b57cec5SDimitry Andric {0, 0}, // 0x02 unused 1570b57cec5SDimitry Andric {0, 0}, // 0x03 DW_FORM_block2 1580b57cec5SDimitry Andric {0, 0}, // 0x04 DW_FORM_block4 1590b57cec5SDimitry Andric {1, 2}, // 0x05 DW_FORM_data2 1600b57cec5SDimitry Andric {1, 4}, // 0x06 DW_FORM_data4 1610b57cec5SDimitry Andric {1, 8}, // 0x07 DW_FORM_data8 1620b57cec5SDimitry Andric {0, 0}, // 0x08 DW_FORM_string 1630b57cec5SDimitry Andric {0, 0}, // 0x09 DW_FORM_block 1640b57cec5SDimitry Andric {0, 0}, // 0x0a DW_FORM_block1 1650b57cec5SDimitry Andric {1, 1}, // 0x0b DW_FORM_data1 1660b57cec5SDimitry Andric {1, 1}, // 0x0c DW_FORM_flag 1670b57cec5SDimitry Andric {0, 0}, // 0x0d DW_FORM_sdata 1680b57cec5SDimitry Andric {1, 4}, // 0x0e DW_FORM_strp 1690b57cec5SDimitry Andric {0, 0}, // 0x0f DW_FORM_udata 170fe6060f1SDimitry Andric {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes 171fe6060f1SDimitry Andric // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later 1720b57cec5SDimitry Andric {1, 1}, // 0x11 DW_FORM_ref1 1730b57cec5SDimitry Andric {1, 2}, // 0x12 DW_FORM_ref2 1740b57cec5SDimitry Andric {1, 4}, // 0x13 DW_FORM_ref4 1750b57cec5SDimitry Andric {1, 8}, // 0x14 DW_FORM_ref8 1760b57cec5SDimitry Andric {0, 0}, // 0x15 DW_FORM_ref_udata 1770b57cec5SDimitry Andric {0, 0}, // 0x16 DW_FORM_indirect 1780b57cec5SDimitry Andric {1, 4}, // 0x17 DW_FORM_sec_offset 1790b57cec5SDimitry Andric {0, 0}, // 0x18 DW_FORM_exprloc 1800b57cec5SDimitry Andric {1, 0}, // 0x19 DW_FORM_flag_present 181fe6060f1SDimitry Andric {0, 0}, // 0x1a DW_FORM_strx (ULEB128) 182fe6060f1SDimitry Andric {0, 0}, // 0x1b DW_FORM_addrx (ULEB128) 183fe6060f1SDimitry Andric {1, 4}, // 0x1c DW_FORM_ref_sup4 184fe6060f1SDimitry Andric {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64) 185fe6060f1SDimitry Andric {1, 16}, // 0x1e DW_FORM_data16 186fe6060f1SDimitry Andric {1, 4}, // 0x1f DW_FORM_line_strp 1870b57cec5SDimitry Andric {1, 8}, // 0x20 DW_FORM_ref_sig8 1880b57cec5SDimitry Andric }; 1890b57cec5SDimitry Andric 190bdd1243dSDimitry Andric std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form, 191bdd1243dSDimitry Andric const DWARFUnit *u) { 1920b57cec5SDimitry Andric if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid) 193bdd1243dSDimitry Andric return static_cast<uint8_t>(g_form_sizes[form].size); 1940b57cec5SDimitry Andric if (form == DW_FORM_addr && u) 1950b57cec5SDimitry Andric return u->GetAddressByteSize(); 196bdd1243dSDimitry Andric return std::nullopt; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 199bdd1243dSDimitry Andric std::optional<uint8_t> DWARFFormValue::GetFixedSize() const { 2000b57cec5SDimitry Andric return GetFixedSize(m_form, m_unit); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data, 2040b57cec5SDimitry Andric lldb::offset_t *offset_ptr) const { 2050b57cec5SDimitry Andric return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit); 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric bool DWARFFormValue::SkipValue(dw_form_t form, 2090b57cec5SDimitry Andric const DWARFDataExtractor &debug_info_data, 2100b57cec5SDimitry Andric lldb::offset_t *offset_ptr, 2110b57cec5SDimitry Andric const DWARFUnit *unit) { 2120b57cec5SDimitry Andric uint8_t ref_addr_size; 2130b57cec5SDimitry Andric switch (form) { 2140b57cec5SDimitry Andric // Blocks if inlined data that have a length field and the data bytes inlined 2150b57cec5SDimitry Andric // in the .debug_info 2160b57cec5SDimitry Andric case DW_FORM_exprloc: 2170b57cec5SDimitry Andric case DW_FORM_block: { 21806c3fb27SDimitry Andric uint64_t size = debug_info_data.GetULEB128(offset_ptr); 2190b57cec5SDimitry Andric *offset_ptr += size; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric return true; 2220b57cec5SDimitry Andric case DW_FORM_block1: { 22306c3fb27SDimitry Andric uint8_t size = debug_info_data.GetU8(offset_ptr); 2240b57cec5SDimitry Andric *offset_ptr += size; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric return true; 2270b57cec5SDimitry Andric case DW_FORM_block2: { 22806c3fb27SDimitry Andric uint16_t size = debug_info_data.GetU16(offset_ptr); 2290b57cec5SDimitry Andric *offset_ptr += size; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric return true; 2320b57cec5SDimitry Andric case DW_FORM_block4: { 23306c3fb27SDimitry Andric uint32_t size = debug_info_data.GetU32(offset_ptr); 2340b57cec5SDimitry Andric *offset_ptr += size; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric return true; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // Inlined NULL terminated C-strings 2390b57cec5SDimitry Andric case DW_FORM_string: 2400b57cec5SDimitry Andric debug_info_data.GetCStr(offset_ptr); 2410b57cec5SDimitry Andric return true; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Compile unit address sized values 2440b57cec5SDimitry Andric case DW_FORM_addr: 2450b57cec5SDimitry Andric *offset_ptr += DWARFUnit::GetAddressByteSize(unit); 2460b57cec5SDimitry Andric return true; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric case DW_FORM_ref_addr: 2490b57cec5SDimitry Andric ref_addr_size = 4; 2500b57cec5SDimitry Andric assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will 2510b57cec5SDimitry Andric // get this wrong 2520b57cec5SDimitry Andric if (unit->GetVersion() <= 2) 2530b57cec5SDimitry Andric ref_addr_size = unit->GetAddressByteSize(); 2540b57cec5SDimitry Andric else 2550b57cec5SDimitry Andric ref_addr_size = 4; 2560b57cec5SDimitry Andric *offset_ptr += ref_addr_size; 2570b57cec5SDimitry Andric return true; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // 0 bytes values (implied from DW_FORM) 2600b57cec5SDimitry Andric case DW_FORM_flag_present: 2610b57cec5SDimitry Andric case DW_FORM_implicit_const: 2620b57cec5SDimitry Andric return true; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // 1 byte values 2650b57cec5SDimitry Andric case DW_FORM_addrx1: 2660b57cec5SDimitry Andric case DW_FORM_data1: 2670b57cec5SDimitry Andric case DW_FORM_flag: 2680b57cec5SDimitry Andric case DW_FORM_ref1: 2690b57cec5SDimitry Andric case DW_FORM_strx1: 2700b57cec5SDimitry Andric *offset_ptr += 1; 2710b57cec5SDimitry Andric return true; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric // 2 byte values 2740b57cec5SDimitry Andric case DW_FORM_addrx2: 2750b57cec5SDimitry Andric case DW_FORM_data2: 2760b57cec5SDimitry Andric case DW_FORM_ref2: 2770b57cec5SDimitry Andric case DW_FORM_strx2: 2780b57cec5SDimitry Andric *offset_ptr += 2; 2790b57cec5SDimitry Andric return true; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // 3 byte values 2820b57cec5SDimitry Andric case DW_FORM_addrx3: 2830b57cec5SDimitry Andric case DW_FORM_strx3: 2840b57cec5SDimitry Andric *offset_ptr += 3; 2850b57cec5SDimitry Andric return true; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric // 32 bit for DWARF 32, 64 for DWARF 64 2880b57cec5SDimitry Andric case DW_FORM_sec_offset: 2890b57cec5SDimitry Andric case DW_FORM_strp: 290fe6060f1SDimitry Andric case DW_FORM_line_strp: 2910b57cec5SDimitry Andric *offset_ptr += 4; 2920b57cec5SDimitry Andric return true; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // 4 byte values 2950b57cec5SDimitry Andric case DW_FORM_addrx4: 2960b57cec5SDimitry Andric case DW_FORM_data4: 2970b57cec5SDimitry Andric case DW_FORM_ref4: 2980b57cec5SDimitry Andric case DW_FORM_strx4: 2990b57cec5SDimitry Andric *offset_ptr += 4; 3000b57cec5SDimitry Andric return true; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // 8 byte values 3030b57cec5SDimitry Andric case DW_FORM_data8: 3040b57cec5SDimitry Andric case DW_FORM_ref8: 3050b57cec5SDimitry Andric case DW_FORM_ref_sig8: 3060b57cec5SDimitry Andric *offset_ptr += 8; 3070b57cec5SDimitry Andric return true; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric // signed or unsigned LEB 128 values 3100b57cec5SDimitry Andric case DW_FORM_addrx: 311480093f4SDimitry Andric case DW_FORM_loclistx: 3120b57cec5SDimitry Andric case DW_FORM_rnglistx: 3130b57cec5SDimitry Andric case DW_FORM_sdata: 3140b57cec5SDimitry Andric case DW_FORM_udata: 3150b57cec5SDimitry Andric case DW_FORM_ref_udata: 3160b57cec5SDimitry Andric case DW_FORM_GNU_addr_index: 3170b57cec5SDimitry Andric case DW_FORM_GNU_str_index: 3180b57cec5SDimitry Andric case DW_FORM_strx: 3190b57cec5SDimitry Andric debug_info_data.Skip_LEB128(offset_ptr); 3200b57cec5SDimitry Andric return true; 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric case DW_FORM_indirect: { 32306c3fb27SDimitry Andric auto indirect_form = 32406c3fb27SDimitry Andric static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr)); 32506c3fb27SDimitry Andric return DWARFFormValue::SkipValue(indirect_form, debug_info_data, 32606c3fb27SDimitry Andric offset_ptr, unit); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric default: 3300b57cec5SDimitry Andric break; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric return false; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric void DWARFFormValue::Dump(Stream &s) const { 3360b57cec5SDimitry Andric uint64_t uvalue = Unsigned(); 3370b57cec5SDimitry Andric bool unit_relative_offset = false; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric switch (m_form) { 3400b57cec5SDimitry Andric case DW_FORM_addr: 341480093f4SDimitry Andric DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t)); 3420b57cec5SDimitry Andric break; 3430b57cec5SDimitry Andric case DW_FORM_flag: 3440b57cec5SDimitry Andric case DW_FORM_data1: 3450b57cec5SDimitry Andric s.PutHex8(uvalue); 3460b57cec5SDimitry Andric break; 3470b57cec5SDimitry Andric case DW_FORM_data2: 3480b57cec5SDimitry Andric s.PutHex16(uvalue); 3490b57cec5SDimitry Andric break; 3500b57cec5SDimitry Andric case DW_FORM_sec_offset: 3510b57cec5SDimitry Andric case DW_FORM_data4: 3520b57cec5SDimitry Andric s.PutHex32(uvalue); 3530b57cec5SDimitry Andric break; 3540b57cec5SDimitry Andric case DW_FORM_ref_sig8: 3550b57cec5SDimitry Andric case DW_FORM_data8: 3560b57cec5SDimitry Andric s.PutHex64(uvalue); 3570b57cec5SDimitry Andric break; 3580b57cec5SDimitry Andric case DW_FORM_string: 3590b57cec5SDimitry Andric s.QuotedCString(AsCString()); 3600b57cec5SDimitry Andric break; 3610b57cec5SDimitry Andric case DW_FORM_exprloc: 3620b57cec5SDimitry Andric case DW_FORM_block: 3630b57cec5SDimitry Andric case DW_FORM_block1: 3640b57cec5SDimitry Andric case DW_FORM_block2: 3650b57cec5SDimitry Andric case DW_FORM_block4: 3660b57cec5SDimitry Andric if (uvalue > 0) { 3670b57cec5SDimitry Andric switch (m_form) { 3680b57cec5SDimitry Andric case DW_FORM_exprloc: 3690b57cec5SDimitry Andric case DW_FORM_block: 3700b57cec5SDimitry Andric s.Printf("<0x%" PRIx64 "> ", uvalue); 3710b57cec5SDimitry Andric break; 3720b57cec5SDimitry Andric case DW_FORM_block1: 3730b57cec5SDimitry Andric s.Printf("<0x%2.2x> ", (uint8_t)uvalue); 3740b57cec5SDimitry Andric break; 3750b57cec5SDimitry Andric case DW_FORM_block2: 3760b57cec5SDimitry Andric s.Printf("<0x%4.4x> ", (uint16_t)uvalue); 3770b57cec5SDimitry Andric break; 3780b57cec5SDimitry Andric case DW_FORM_block4: 3790b57cec5SDimitry Andric s.Printf("<0x%8.8x> ", (uint32_t)uvalue); 3800b57cec5SDimitry Andric break; 3810b57cec5SDimitry Andric default: 3820b57cec5SDimitry Andric break; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric const uint8_t *data_ptr = m_value.data; 3860b57cec5SDimitry Andric if (data_ptr) { 3870b57cec5SDimitry Andric const uint8_t *end_data_ptr = 3880b57cec5SDimitry Andric data_ptr + uvalue; // uvalue contains size of block 3890b57cec5SDimitry Andric while (data_ptr < end_data_ptr) { 3900b57cec5SDimitry Andric s.Printf("%2.2x ", *data_ptr); 3910b57cec5SDimitry Andric ++data_ptr; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric } else 3940b57cec5SDimitry Andric s.PutCString("NULL"); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric break; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric case DW_FORM_sdata: 3990b57cec5SDimitry Andric s.PutSLEB128(uvalue); 4000b57cec5SDimitry Andric break; 4010b57cec5SDimitry Andric case DW_FORM_udata: 4020b57cec5SDimitry Andric s.PutULEB128(uvalue); 4030b57cec5SDimitry Andric break; 404fe6060f1SDimitry Andric case DW_FORM_strp: 405fe6060f1SDimitry Andric case DW_FORM_line_strp: { 4060b57cec5SDimitry Andric const char *dbg_str = AsCString(); 4070b57cec5SDimitry Andric if (dbg_str) { 4080b57cec5SDimitry Andric s.QuotedCString(dbg_str); 4090b57cec5SDimitry Andric } else { 4100b57cec5SDimitry Andric s.PutHex32(uvalue); 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric } break; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric case DW_FORM_ref_addr: { 4150b57cec5SDimitry Andric assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we 4160b57cec5SDimitry Andric // will get this wrong 4170b57cec5SDimitry Andric if (m_unit->GetVersion() <= 2) 418480093f4SDimitry Andric DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2); 4190b57cec5SDimitry Andric else 420480093f4SDimitry Andric DumpAddress(s.AsRawOstream(), uvalue, 421480093f4SDimitry Andric 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't 4220b57cec5SDimitry Andric // support DWARF64 yet 4230b57cec5SDimitry Andric break; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric case DW_FORM_ref1: 4260b57cec5SDimitry Andric unit_relative_offset = true; 4270b57cec5SDimitry Andric break; 4280b57cec5SDimitry Andric case DW_FORM_ref2: 4290b57cec5SDimitry Andric unit_relative_offset = true; 4300b57cec5SDimitry Andric break; 4310b57cec5SDimitry Andric case DW_FORM_ref4: 4320b57cec5SDimitry Andric unit_relative_offset = true; 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric case DW_FORM_ref8: 4350b57cec5SDimitry Andric unit_relative_offset = true; 4360b57cec5SDimitry Andric break; 4370b57cec5SDimitry Andric case DW_FORM_ref_udata: 4380b57cec5SDimitry Andric unit_relative_offset = true; 4390b57cec5SDimitry Andric break; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric // All DW_FORM_indirect attributes should be resolved prior to calling this 4420b57cec5SDimitry Andric // function 4430b57cec5SDimitry Andric case DW_FORM_indirect: 4440b57cec5SDimitry Andric s.PutCString("DW_FORM_indirect"); 4450b57cec5SDimitry Andric break; 4460b57cec5SDimitry Andric case DW_FORM_flag_present: 4470b57cec5SDimitry Andric break; 4480b57cec5SDimitry Andric default: 4490b57cec5SDimitry Andric s.Printf("DW_FORM(0x%4.4x)", m_form); 4500b57cec5SDimitry Andric break; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric if (unit_relative_offset) { 4540b57cec5SDimitry Andric assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile 4550b57cec5SDimitry Andric // unit relative or we will get this wrong 4560b57cec5SDimitry Andric s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset()); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric const char *DWARFFormValue::AsCString() const { 4615ffd83dbSDimitry Andric DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext(); 4620b57cec5SDimitry Andric 4635ffd83dbSDimitry Andric if (m_form == DW_FORM_string) 4640b57cec5SDimitry Andric return m_value.value.cstr; 4655ffd83dbSDimitry Andric if (m_form == DW_FORM_strp) 4665ffd83dbSDimitry Andric return context.getOrLoadStrData().PeekCStr(m_value.value.uval); 4670b57cec5SDimitry Andric 4685ffd83dbSDimitry Andric if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx || 4695ffd83dbSDimitry Andric m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 || 4705ffd83dbSDimitry Andric m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) { 4710b57cec5SDimitry Andric 472bdd1243dSDimitry Andric std::optional<uint64_t> offset = 4735ffd83dbSDimitry Andric m_unit->GetStringOffsetSectionItem(m_value.value.uval); 4745ffd83dbSDimitry Andric if (!offset) 4755ffd83dbSDimitry Andric return nullptr; 4765ffd83dbSDimitry Andric return context.getOrLoadStrData().PeekCStr(*offset); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (m_form == DW_FORM_line_strp) 4805ffd83dbSDimitry Andric return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval); 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric return nullptr; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric dw_addr_t DWARFFormValue::Address() const { 4860b57cec5SDimitry Andric SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric if (m_form == DW_FORM_addr) 4890b57cec5SDimitry Andric return Unsigned(); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric assert(m_unit); 4920b57cec5SDimitry Andric assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || 4930b57cec5SDimitry Andric m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || 4940b57cec5SDimitry Andric m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric uint32_t index_size = m_unit->GetAddressByteSize(); 4970b57cec5SDimitry Andric dw_offset_t addr_base = m_unit->GetAddrBase(); 4980b57cec5SDimitry Andric lldb::offset_t offset = addr_base + m_value.value.uval * index_size; 4990b57cec5SDimitry Andric return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( 5000b57cec5SDimitry Andric &offset, index_size); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 503*7a6dacacSDimitry Andric std::pair<DWARFUnit *, uint64_t> 504*7a6dacacSDimitry Andric DWARFFormValue::ReferencedUnitAndOffset() const { 5050b57cec5SDimitry Andric uint64_t value = m_value.value.uval; 5060b57cec5SDimitry Andric switch (m_form) { 5070b57cec5SDimitry Andric case DW_FORM_ref1: 5080b57cec5SDimitry Andric case DW_FORM_ref2: 5090b57cec5SDimitry Andric case DW_FORM_ref4: 5100b57cec5SDimitry Andric case DW_FORM_ref8: 5110b57cec5SDimitry Andric case DW_FORM_ref_udata: 5120b57cec5SDimitry Andric assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile 5130b57cec5SDimitry Andric // unit relative or we will get this wrong 5140b57cec5SDimitry Andric value += m_unit->GetOffset(); 5150b57cec5SDimitry Andric if (!m_unit->ContainsDIEOffset(value)) { 5160b57cec5SDimitry Andric m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 517bdd1243dSDimitry Andric "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value); 518*7a6dacacSDimitry Andric return {nullptr, 0}; 5190b57cec5SDimitry Andric } 520*7a6dacacSDimitry Andric return {const_cast<DWARFUnit *>(m_unit), value}; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric case DW_FORM_ref_addr: { 5230b57cec5SDimitry Andric DWARFUnit *ref_cu = 5245ffd83dbSDimitry Andric m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset( 5250b57cec5SDimitry Andric DIERef::Section::DebugInfo, value); 5260b57cec5SDimitry Andric if (!ref_cu) { 5270b57cec5SDimitry Andric m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 528bdd1243dSDimitry Andric "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value); 529*7a6dacacSDimitry Andric return {nullptr, 0}; 5300b57cec5SDimitry Andric } 531*7a6dacacSDimitry Andric return {ref_cu, value}; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric case DW_FORM_ref_sig8: { 5350b57cec5SDimitry Andric DWARFTypeUnit *tu = 5365ffd83dbSDimitry Andric m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value); 5370b57cec5SDimitry Andric if (!tu) 538*7a6dacacSDimitry Andric return {nullptr, 0}; 539*7a6dacacSDimitry Andric return {tu, tu->GetTypeOffset()}; 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric default: 543*7a6dacacSDimitry Andric return {nullptr, 0}; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 547*7a6dacacSDimitry Andric DWARFDIE DWARFFormValue::Reference() const { 548*7a6dacacSDimitry Andric auto [unit, offset] = ReferencedUnitAndOffset(); 549*7a6dacacSDimitry Andric return unit ? unit->GetDIE(offset) : DWARFDIE(); 550*7a6dacacSDimitry Andric } 551*7a6dacacSDimitry Andric 5520b57cec5SDimitry Andric uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const { 5530b57cec5SDimitry Andric uint64_t value = m_value.value.uval; 5540b57cec5SDimitry Andric switch (m_form) { 5550b57cec5SDimitry Andric case DW_FORM_ref1: 5560b57cec5SDimitry Andric case DW_FORM_ref2: 5570b57cec5SDimitry Andric case DW_FORM_ref4: 5580b57cec5SDimitry Andric case DW_FORM_ref8: 5590b57cec5SDimitry Andric case DW_FORM_ref_udata: 5600b57cec5SDimitry Andric return value + base_offset; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric case DW_FORM_ref_addr: 5630b57cec5SDimitry Andric case DW_FORM_ref_sig8: 5640b57cec5SDimitry Andric case DW_FORM_GNU_ref_alt: 5650b57cec5SDimitry Andric return value; 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric default: 5680b57cec5SDimitry Andric return DW_INVALID_OFFSET; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric bool DWARFFormValue::IsBlockForm(const dw_form_t form) { 5750b57cec5SDimitry Andric switch (form) { 5760b57cec5SDimitry Andric case DW_FORM_exprloc: 5770b57cec5SDimitry Andric case DW_FORM_block: 5780b57cec5SDimitry Andric case DW_FORM_block1: 5790b57cec5SDimitry Andric case DW_FORM_block2: 5800b57cec5SDimitry Andric case DW_FORM_block4: 5810b57cec5SDimitry Andric return true; 58206c3fb27SDimitry Andric default: 5830b57cec5SDimitry Andric return false; 5840b57cec5SDimitry Andric } 58506c3fb27SDimitry Andric llvm_unreachable("All cases handled above!"); 58606c3fb27SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric bool DWARFFormValue::IsDataForm(const dw_form_t form) { 5890b57cec5SDimitry Andric switch (form) { 5900b57cec5SDimitry Andric case DW_FORM_sdata: 5910b57cec5SDimitry Andric case DW_FORM_udata: 5920b57cec5SDimitry Andric case DW_FORM_data1: 5930b57cec5SDimitry Andric case DW_FORM_data2: 5940b57cec5SDimitry Andric case DW_FORM_data4: 5950b57cec5SDimitry Andric case DW_FORM_data8: 5960b57cec5SDimitry Andric return true; 59706c3fb27SDimitry Andric default: 5980b57cec5SDimitry Andric return false; 5990b57cec5SDimitry Andric } 60006c3fb27SDimitry Andric llvm_unreachable("All cases handled above!"); 60106c3fb27SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric bool DWARFFormValue::FormIsSupported(dw_form_t form) { 6040b57cec5SDimitry Andric switch (form) { 6050b57cec5SDimitry Andric case DW_FORM_addr: 6060b57cec5SDimitry Andric case DW_FORM_addrx: 607480093f4SDimitry Andric case DW_FORM_loclistx: 6080b57cec5SDimitry Andric case DW_FORM_rnglistx: 6090b57cec5SDimitry Andric case DW_FORM_block2: 6100b57cec5SDimitry Andric case DW_FORM_block4: 6110b57cec5SDimitry Andric case DW_FORM_data2: 6120b57cec5SDimitry Andric case DW_FORM_data4: 6130b57cec5SDimitry Andric case DW_FORM_data8: 6140b57cec5SDimitry Andric case DW_FORM_string: 6150b57cec5SDimitry Andric case DW_FORM_block: 6160b57cec5SDimitry Andric case DW_FORM_block1: 6170b57cec5SDimitry Andric case DW_FORM_data1: 6180b57cec5SDimitry Andric case DW_FORM_flag: 6190b57cec5SDimitry Andric case DW_FORM_sdata: 6200b57cec5SDimitry Andric case DW_FORM_strp: 621fe6060f1SDimitry Andric case DW_FORM_line_strp: 6220b57cec5SDimitry Andric case DW_FORM_strx: 6230b57cec5SDimitry Andric case DW_FORM_strx1: 6240b57cec5SDimitry Andric case DW_FORM_strx2: 6250b57cec5SDimitry Andric case DW_FORM_strx3: 6260b57cec5SDimitry Andric case DW_FORM_strx4: 6270b57cec5SDimitry Andric case DW_FORM_udata: 6280b57cec5SDimitry Andric case DW_FORM_ref_addr: 6290b57cec5SDimitry Andric case DW_FORM_ref1: 6300b57cec5SDimitry Andric case DW_FORM_ref2: 6310b57cec5SDimitry Andric case DW_FORM_ref4: 6320b57cec5SDimitry Andric case DW_FORM_ref8: 6330b57cec5SDimitry Andric case DW_FORM_ref_udata: 6340b57cec5SDimitry Andric case DW_FORM_indirect: 6350b57cec5SDimitry Andric case DW_FORM_sec_offset: 6360b57cec5SDimitry Andric case DW_FORM_exprloc: 6370b57cec5SDimitry Andric case DW_FORM_flag_present: 6380b57cec5SDimitry Andric case DW_FORM_ref_sig8: 6390b57cec5SDimitry Andric case DW_FORM_GNU_str_index: 6400b57cec5SDimitry Andric case DW_FORM_GNU_addr_index: 6410b57cec5SDimitry Andric case DW_FORM_implicit_const: 6420b57cec5SDimitry Andric return true; 6430b57cec5SDimitry Andric default: 6440b57cec5SDimitry Andric break; 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric return false; 6470b57cec5SDimitry Andric } 648