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