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
Clear()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
ExtractValue(const DWARFDataExtractor & data,lldb::offset_t * offset_ptr)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
GetFixedSize(dw_form_t form,const DWARFUnit * u)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
GetFixedSize() const199bdd1243dSDimitry Andric std::optional<uint8_t> DWARFFormValue::GetFixedSize() const {
2000b57cec5SDimitry Andric return GetFixedSize(m_form, m_unit);
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric
SkipValue(const DWARFDataExtractor & debug_info_data,lldb::offset_t * offset_ptr) const2030b57cec5SDimitry 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
SkipValue(dw_form_t form,const DWARFDataExtractor & debug_info_data,lldb::offset_t * offset_ptr,const DWARFUnit * unit)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
Dump(Stream & s) const3350b57cec5SDimitry 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
AsCString() const4600b57cec5SDimitry 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
Address() const4850b57cec5SDimitry 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
5037a6dacacSDimitry Andric std::pair<DWARFUnit *, uint64_t>
ReferencedUnitAndOffset() const5047a6dacacSDimitry 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);
5187a6dacacSDimitry Andric return {nullptr, 0};
5190b57cec5SDimitry Andric }
5207a6dacacSDimitry 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);
5297a6dacacSDimitry Andric return {nullptr, 0};
5300b57cec5SDimitry Andric }
5317a6dacacSDimitry 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)
5387a6dacacSDimitry Andric return {nullptr, 0};
5397a6dacacSDimitry Andric return {tu, tu->GetTypeOffset()};
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric default:
5437a6dacacSDimitry Andric return {nullptr, 0};
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric
Reference() const5477a6dacacSDimitry Andric DWARFDIE DWARFFormValue::Reference() const {
5487a6dacacSDimitry Andric auto [unit, offset] = ReferencedUnitAndOffset();
5497a6dacacSDimitry Andric return unit ? unit->GetDIE(offset) : DWARFDIE();
5507a6dacacSDimitry Andric }
5517a6dacacSDimitry Andric
Reference(dw_offset_t base_offset) const5520b57cec5SDimitry 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
BlockData() const5720b57cec5SDimitry Andric const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
5730b57cec5SDimitry Andric
IsBlockForm(const dw_form_t form)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
IsDataForm(const dw_form_t form)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
FormIsSupported(dw_form_t form)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