1dda28197Spatrick //===-- DWARFFormValue.cpp ------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9be691f3bSpatrick #include <cassert>
10*f6aab3d8Srobert #include <optional>
11061da546Spatrick
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/dwarf.h"
14061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
15061da546Spatrick #include "lldb/Utility/Stream.h"
16061da546Spatrick
17061da546Spatrick #include "DWARFDebugInfo.h"
18061da546Spatrick #include "DWARFFormValue.h"
19061da546Spatrick #include "DWARFUnit.h"
20061da546Spatrick
21061da546Spatrick class DWARFUnit;
22061da546Spatrick
23061da546Spatrick using namespace lldb_private;
24*f6aab3d8Srobert using namespace lldb_private::dwarf;
25061da546Spatrick
Clear()26061da546Spatrick void DWARFFormValue::Clear() {
27061da546Spatrick m_unit = nullptr;
28061da546Spatrick m_form = 0;
29061da546Spatrick m_value = ValueTypeTag();
30061da546Spatrick }
31061da546Spatrick
ExtractValue(const DWARFDataExtractor & data,lldb::offset_t * offset_ptr)32061da546Spatrick bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
33061da546Spatrick lldb::offset_t *offset_ptr) {
34061da546Spatrick if (m_form == DW_FORM_implicit_const)
35061da546Spatrick return true;
36061da546Spatrick
37061da546Spatrick bool indirect = false;
38061da546Spatrick bool is_block = false;
39061da546Spatrick m_value.data = nullptr;
40061da546Spatrick uint8_t ref_addr_size;
41061da546Spatrick // Read the value for the form into value and follow and DW_FORM_indirect
42061da546Spatrick // instances we run into
43061da546Spatrick do {
44061da546Spatrick indirect = false;
45061da546Spatrick switch (m_form) {
46061da546Spatrick case DW_FORM_addr:
47061da546Spatrick assert(m_unit);
48061da546Spatrick m_value.value.uval =
49061da546Spatrick data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
50061da546Spatrick break;
51061da546Spatrick case DW_FORM_block1:
52061da546Spatrick m_value.value.uval = data.GetU8(offset_ptr);
53061da546Spatrick is_block = true;
54061da546Spatrick break;
55061da546Spatrick case DW_FORM_block2:
56061da546Spatrick m_value.value.uval = data.GetU16(offset_ptr);
57061da546Spatrick is_block = true;
58061da546Spatrick break;
59061da546Spatrick case DW_FORM_block4:
60061da546Spatrick m_value.value.uval = data.GetU32(offset_ptr);
61061da546Spatrick is_block = true;
62061da546Spatrick break;
63061da546Spatrick case DW_FORM_data16:
64061da546Spatrick m_value.value.uval = 16;
65061da546Spatrick is_block = true;
66061da546Spatrick break;
67061da546Spatrick case DW_FORM_exprloc:
68061da546Spatrick case DW_FORM_block:
69061da546Spatrick m_value.value.uval = data.GetULEB128(offset_ptr);
70061da546Spatrick is_block = true;
71061da546Spatrick break;
72061da546Spatrick case DW_FORM_string:
73061da546Spatrick m_value.value.cstr = data.GetCStr(offset_ptr);
74061da546Spatrick break;
75061da546Spatrick case DW_FORM_sdata:
76061da546Spatrick m_value.value.sval = data.GetSLEB128(offset_ptr);
77061da546Spatrick break;
78061da546Spatrick case DW_FORM_strp:
79061da546Spatrick case DW_FORM_line_strp:
80061da546Spatrick case DW_FORM_sec_offset:
81061da546Spatrick m_value.value.uval = data.GetMaxU64(offset_ptr, 4);
82061da546Spatrick break;
83061da546Spatrick case DW_FORM_addrx1:
84061da546Spatrick case DW_FORM_strx1:
85061da546Spatrick case DW_FORM_ref1:
86061da546Spatrick case DW_FORM_data1:
87061da546Spatrick case DW_FORM_flag:
88061da546Spatrick m_value.value.uval = data.GetU8(offset_ptr);
89061da546Spatrick break;
90061da546Spatrick case DW_FORM_addrx2:
91061da546Spatrick case DW_FORM_strx2:
92061da546Spatrick case DW_FORM_ref2:
93061da546Spatrick case DW_FORM_data2:
94061da546Spatrick m_value.value.uval = data.GetU16(offset_ptr);
95061da546Spatrick break;
96061da546Spatrick case DW_FORM_addrx3:
97061da546Spatrick case DW_FORM_strx3:
98061da546Spatrick m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
99061da546Spatrick break;
100061da546Spatrick case DW_FORM_addrx4:
101061da546Spatrick case DW_FORM_strx4:
102061da546Spatrick case DW_FORM_ref4:
103061da546Spatrick case DW_FORM_data4:
104061da546Spatrick m_value.value.uval = data.GetU32(offset_ptr);
105061da546Spatrick break;
106061da546Spatrick case DW_FORM_data8:
107061da546Spatrick case DW_FORM_ref8:
108061da546Spatrick case DW_FORM_ref_sig8:
109061da546Spatrick m_value.value.uval = data.GetU64(offset_ptr);
110061da546Spatrick break;
111061da546Spatrick case DW_FORM_addrx:
112061da546Spatrick case DW_FORM_loclistx:
113061da546Spatrick case DW_FORM_rnglistx:
114061da546Spatrick case DW_FORM_strx:
115061da546Spatrick case DW_FORM_udata:
116061da546Spatrick case DW_FORM_ref_udata:
117061da546Spatrick case DW_FORM_GNU_str_index:
118061da546Spatrick case DW_FORM_GNU_addr_index:
119061da546Spatrick m_value.value.uval = data.GetULEB128(offset_ptr);
120061da546Spatrick break;
121061da546Spatrick case DW_FORM_ref_addr:
122061da546Spatrick assert(m_unit);
123061da546Spatrick if (m_unit->GetVersion() <= 2)
124061da546Spatrick ref_addr_size = m_unit->GetAddressByteSize();
125061da546Spatrick else
126061da546Spatrick ref_addr_size = 4;
127061da546Spatrick m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
128061da546Spatrick break;
129061da546Spatrick case DW_FORM_indirect:
130061da546Spatrick m_form = data.GetULEB128(offset_ptr);
131061da546Spatrick indirect = true;
132061da546Spatrick break;
133061da546Spatrick case DW_FORM_flag_present:
134061da546Spatrick m_value.value.uval = 1;
135061da546Spatrick break;
136061da546Spatrick default:
137061da546Spatrick return false;
138061da546Spatrick }
139061da546Spatrick } while (indirect);
140061da546Spatrick
141061da546Spatrick if (is_block) {
142061da546Spatrick m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
143061da546Spatrick if (m_value.data != nullptr) {
144061da546Spatrick *offset_ptr += m_value.value.uval;
145061da546Spatrick }
146061da546Spatrick }
147061da546Spatrick
148061da546Spatrick return true;
149061da546Spatrick }
150061da546Spatrick
151061da546Spatrick struct FormSize {
152061da546Spatrick uint8_t valid:1, size:7;
153061da546Spatrick };
154061da546Spatrick static FormSize g_form_sizes[] = {
155061da546Spatrick {0, 0}, // 0x00 unused
156061da546Spatrick {0, 0}, // 0x01 DW_FORM_addr
157061da546Spatrick {0, 0}, // 0x02 unused
158061da546Spatrick {0, 0}, // 0x03 DW_FORM_block2
159061da546Spatrick {0, 0}, // 0x04 DW_FORM_block4
160061da546Spatrick {1, 2}, // 0x05 DW_FORM_data2
161061da546Spatrick {1, 4}, // 0x06 DW_FORM_data4
162061da546Spatrick {1, 8}, // 0x07 DW_FORM_data8
163061da546Spatrick {0, 0}, // 0x08 DW_FORM_string
164061da546Spatrick {0, 0}, // 0x09 DW_FORM_block
165061da546Spatrick {0, 0}, // 0x0a DW_FORM_block1
166061da546Spatrick {1, 1}, // 0x0b DW_FORM_data1
167061da546Spatrick {1, 1}, // 0x0c DW_FORM_flag
168061da546Spatrick {0, 0}, // 0x0d DW_FORM_sdata
169061da546Spatrick {1, 4}, // 0x0e DW_FORM_strp
170061da546Spatrick {0, 0}, // 0x0f DW_FORM_udata
171be691f3bSpatrick {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
172be691f3bSpatrick // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
173061da546Spatrick {1, 1}, // 0x11 DW_FORM_ref1
174061da546Spatrick {1, 2}, // 0x12 DW_FORM_ref2
175061da546Spatrick {1, 4}, // 0x13 DW_FORM_ref4
176061da546Spatrick {1, 8}, // 0x14 DW_FORM_ref8
177061da546Spatrick {0, 0}, // 0x15 DW_FORM_ref_udata
178061da546Spatrick {0, 0}, // 0x16 DW_FORM_indirect
179061da546Spatrick {1, 4}, // 0x17 DW_FORM_sec_offset
180061da546Spatrick {0, 0}, // 0x18 DW_FORM_exprloc
181061da546Spatrick {1, 0}, // 0x19 DW_FORM_flag_present
182be691f3bSpatrick {0, 0}, // 0x1a DW_FORM_strx (ULEB128)
183be691f3bSpatrick {0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
184be691f3bSpatrick {1, 4}, // 0x1c DW_FORM_ref_sup4
185be691f3bSpatrick {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
186be691f3bSpatrick {1, 16}, // 0x1e DW_FORM_data16
187be691f3bSpatrick {1, 4}, // 0x1f DW_FORM_line_strp
188061da546Spatrick {1, 8}, // 0x20 DW_FORM_ref_sig8
189061da546Spatrick };
190061da546Spatrick
GetFixedSize(dw_form_t form,const DWARFUnit * u)191*f6aab3d8Srobert std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form,
192*f6aab3d8Srobert const DWARFUnit *u) {
193061da546Spatrick if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)
194*f6aab3d8Srobert return static_cast<uint8_t>(g_form_sizes[form].size);
195061da546Spatrick if (form == DW_FORM_addr && u)
196061da546Spatrick return u->GetAddressByteSize();
197*f6aab3d8Srobert return std::nullopt;
198061da546Spatrick }
199061da546Spatrick
GetFixedSize() const200*f6aab3d8Srobert std::optional<uint8_t> DWARFFormValue::GetFixedSize() const {
201061da546Spatrick return GetFixedSize(m_form, m_unit);
202061da546Spatrick }
203061da546Spatrick
SkipValue(const DWARFDataExtractor & debug_info_data,lldb::offset_t * offset_ptr) const204061da546Spatrick bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
205061da546Spatrick lldb::offset_t *offset_ptr) const {
206061da546Spatrick return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);
207061da546Spatrick }
208061da546Spatrick
SkipValue(dw_form_t form,const DWARFDataExtractor & debug_info_data,lldb::offset_t * offset_ptr,const DWARFUnit * unit)209061da546Spatrick bool DWARFFormValue::SkipValue(dw_form_t form,
210061da546Spatrick const DWARFDataExtractor &debug_info_data,
211061da546Spatrick lldb::offset_t *offset_ptr,
212061da546Spatrick const DWARFUnit *unit) {
213061da546Spatrick uint8_t ref_addr_size;
214061da546Spatrick switch (form) {
215061da546Spatrick // Blocks if inlined data that have a length field and the data bytes inlined
216061da546Spatrick // in the .debug_info
217061da546Spatrick case DW_FORM_exprloc:
218061da546Spatrick case DW_FORM_block: {
219061da546Spatrick dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
220061da546Spatrick *offset_ptr += size;
221061da546Spatrick }
222061da546Spatrick return true;
223061da546Spatrick case DW_FORM_block1: {
224061da546Spatrick dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);
225061da546Spatrick *offset_ptr += size;
226061da546Spatrick }
227061da546Spatrick return true;
228061da546Spatrick case DW_FORM_block2: {
229061da546Spatrick dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);
230061da546Spatrick *offset_ptr += size;
231061da546Spatrick }
232061da546Spatrick return true;
233061da546Spatrick case DW_FORM_block4: {
234061da546Spatrick dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);
235061da546Spatrick *offset_ptr += size;
236061da546Spatrick }
237061da546Spatrick return true;
238061da546Spatrick
239061da546Spatrick // Inlined NULL terminated C-strings
240061da546Spatrick case DW_FORM_string:
241061da546Spatrick debug_info_data.GetCStr(offset_ptr);
242061da546Spatrick return true;
243061da546Spatrick
244061da546Spatrick // Compile unit address sized values
245061da546Spatrick case DW_FORM_addr:
246061da546Spatrick *offset_ptr += DWARFUnit::GetAddressByteSize(unit);
247061da546Spatrick return true;
248061da546Spatrick
249061da546Spatrick case DW_FORM_ref_addr:
250061da546Spatrick ref_addr_size = 4;
251061da546Spatrick assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
252061da546Spatrick // get this wrong
253061da546Spatrick if (unit->GetVersion() <= 2)
254061da546Spatrick ref_addr_size = unit->GetAddressByteSize();
255061da546Spatrick else
256061da546Spatrick ref_addr_size = 4;
257061da546Spatrick *offset_ptr += ref_addr_size;
258061da546Spatrick return true;
259061da546Spatrick
260061da546Spatrick // 0 bytes values (implied from DW_FORM)
261061da546Spatrick case DW_FORM_flag_present:
262061da546Spatrick case DW_FORM_implicit_const:
263061da546Spatrick return true;
264061da546Spatrick
265061da546Spatrick // 1 byte values
266061da546Spatrick case DW_FORM_addrx1:
267061da546Spatrick case DW_FORM_data1:
268061da546Spatrick case DW_FORM_flag:
269061da546Spatrick case DW_FORM_ref1:
270061da546Spatrick case DW_FORM_strx1:
271061da546Spatrick *offset_ptr += 1;
272061da546Spatrick return true;
273061da546Spatrick
274061da546Spatrick // 2 byte values
275061da546Spatrick case DW_FORM_addrx2:
276061da546Spatrick case DW_FORM_data2:
277061da546Spatrick case DW_FORM_ref2:
278061da546Spatrick case DW_FORM_strx2:
279061da546Spatrick *offset_ptr += 2;
280061da546Spatrick return true;
281061da546Spatrick
282061da546Spatrick // 3 byte values
283061da546Spatrick case DW_FORM_addrx3:
284061da546Spatrick case DW_FORM_strx3:
285061da546Spatrick *offset_ptr += 3;
286061da546Spatrick return true;
287061da546Spatrick
288061da546Spatrick // 32 bit for DWARF 32, 64 for DWARF 64
289061da546Spatrick case DW_FORM_sec_offset:
290061da546Spatrick case DW_FORM_strp:
291be691f3bSpatrick case DW_FORM_line_strp:
292061da546Spatrick *offset_ptr += 4;
293061da546Spatrick return true;
294061da546Spatrick
295061da546Spatrick // 4 byte values
296061da546Spatrick case DW_FORM_addrx4:
297061da546Spatrick case DW_FORM_data4:
298061da546Spatrick case DW_FORM_ref4:
299061da546Spatrick case DW_FORM_strx4:
300061da546Spatrick *offset_ptr += 4;
301061da546Spatrick return true;
302061da546Spatrick
303061da546Spatrick // 8 byte values
304061da546Spatrick case DW_FORM_data8:
305061da546Spatrick case DW_FORM_ref8:
306061da546Spatrick case DW_FORM_ref_sig8:
307061da546Spatrick *offset_ptr += 8;
308061da546Spatrick return true;
309061da546Spatrick
310061da546Spatrick // signed or unsigned LEB 128 values
311061da546Spatrick case DW_FORM_addrx:
312061da546Spatrick case DW_FORM_loclistx:
313061da546Spatrick case DW_FORM_rnglistx:
314061da546Spatrick case DW_FORM_sdata:
315061da546Spatrick case DW_FORM_udata:
316061da546Spatrick case DW_FORM_ref_udata:
317061da546Spatrick case DW_FORM_GNU_addr_index:
318061da546Spatrick case DW_FORM_GNU_str_index:
319061da546Spatrick case DW_FORM_strx:
320061da546Spatrick debug_info_data.Skip_LEB128(offset_ptr);
321061da546Spatrick return true;
322061da546Spatrick
323061da546Spatrick case DW_FORM_indirect: {
324061da546Spatrick dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
325061da546Spatrick return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr,
326061da546Spatrick unit);
327061da546Spatrick }
328061da546Spatrick
329061da546Spatrick default:
330061da546Spatrick break;
331061da546Spatrick }
332061da546Spatrick return false;
333061da546Spatrick }
334061da546Spatrick
Dump(Stream & s) const335061da546Spatrick void DWARFFormValue::Dump(Stream &s) const {
336061da546Spatrick uint64_t uvalue = Unsigned();
337061da546Spatrick bool unit_relative_offset = false;
338061da546Spatrick
339061da546Spatrick switch (m_form) {
340061da546Spatrick case DW_FORM_addr:
341061da546Spatrick DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));
342061da546Spatrick break;
343061da546Spatrick case DW_FORM_flag:
344061da546Spatrick case DW_FORM_data1:
345061da546Spatrick s.PutHex8(uvalue);
346061da546Spatrick break;
347061da546Spatrick case DW_FORM_data2:
348061da546Spatrick s.PutHex16(uvalue);
349061da546Spatrick break;
350061da546Spatrick case DW_FORM_sec_offset:
351061da546Spatrick case DW_FORM_data4:
352061da546Spatrick s.PutHex32(uvalue);
353061da546Spatrick break;
354061da546Spatrick case DW_FORM_ref_sig8:
355061da546Spatrick case DW_FORM_data8:
356061da546Spatrick s.PutHex64(uvalue);
357061da546Spatrick break;
358061da546Spatrick case DW_FORM_string:
359061da546Spatrick s.QuotedCString(AsCString());
360061da546Spatrick break;
361061da546Spatrick case DW_FORM_exprloc:
362061da546Spatrick case DW_FORM_block:
363061da546Spatrick case DW_FORM_block1:
364061da546Spatrick case DW_FORM_block2:
365061da546Spatrick case DW_FORM_block4:
366061da546Spatrick if (uvalue > 0) {
367061da546Spatrick switch (m_form) {
368061da546Spatrick case DW_FORM_exprloc:
369061da546Spatrick case DW_FORM_block:
370061da546Spatrick s.Printf("<0x%" PRIx64 "> ", uvalue);
371061da546Spatrick break;
372061da546Spatrick case DW_FORM_block1:
373061da546Spatrick s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
374061da546Spatrick break;
375061da546Spatrick case DW_FORM_block2:
376061da546Spatrick s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
377061da546Spatrick break;
378061da546Spatrick case DW_FORM_block4:
379061da546Spatrick s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
380061da546Spatrick break;
381061da546Spatrick default:
382061da546Spatrick break;
383061da546Spatrick }
384061da546Spatrick
385061da546Spatrick const uint8_t *data_ptr = m_value.data;
386061da546Spatrick if (data_ptr) {
387061da546Spatrick const uint8_t *end_data_ptr =
388061da546Spatrick data_ptr + uvalue; // uvalue contains size of block
389061da546Spatrick while (data_ptr < end_data_ptr) {
390061da546Spatrick s.Printf("%2.2x ", *data_ptr);
391061da546Spatrick ++data_ptr;
392061da546Spatrick }
393061da546Spatrick } else
394061da546Spatrick s.PutCString("NULL");
395061da546Spatrick }
396061da546Spatrick break;
397061da546Spatrick
398061da546Spatrick case DW_FORM_sdata:
399061da546Spatrick s.PutSLEB128(uvalue);
400061da546Spatrick break;
401061da546Spatrick case DW_FORM_udata:
402061da546Spatrick s.PutULEB128(uvalue);
403061da546Spatrick break;
404be691f3bSpatrick case DW_FORM_strp:
405be691f3bSpatrick case DW_FORM_line_strp: {
406061da546Spatrick const char *dbg_str = AsCString();
407061da546Spatrick if (dbg_str) {
408061da546Spatrick s.QuotedCString(dbg_str);
409061da546Spatrick } else {
410061da546Spatrick s.PutHex32(uvalue);
411061da546Spatrick }
412061da546Spatrick } break;
413061da546Spatrick
414061da546Spatrick case DW_FORM_ref_addr: {
415061da546Spatrick assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
416061da546Spatrick // will get this wrong
417061da546Spatrick if (m_unit->GetVersion() <= 2)
418061da546Spatrick DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2);
419061da546Spatrick else
420061da546Spatrick DumpAddress(s.AsRawOstream(), uvalue,
421061da546Spatrick 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
422061da546Spatrick // support DWARF64 yet
423061da546Spatrick break;
424061da546Spatrick }
425061da546Spatrick case DW_FORM_ref1:
426061da546Spatrick unit_relative_offset = true;
427061da546Spatrick break;
428061da546Spatrick case DW_FORM_ref2:
429061da546Spatrick unit_relative_offset = true;
430061da546Spatrick break;
431061da546Spatrick case DW_FORM_ref4:
432061da546Spatrick unit_relative_offset = true;
433061da546Spatrick break;
434061da546Spatrick case DW_FORM_ref8:
435061da546Spatrick unit_relative_offset = true;
436061da546Spatrick break;
437061da546Spatrick case DW_FORM_ref_udata:
438061da546Spatrick unit_relative_offset = true;
439061da546Spatrick break;
440061da546Spatrick
441061da546Spatrick // All DW_FORM_indirect attributes should be resolved prior to calling this
442061da546Spatrick // function
443061da546Spatrick case DW_FORM_indirect:
444061da546Spatrick s.PutCString("DW_FORM_indirect");
445061da546Spatrick break;
446061da546Spatrick case DW_FORM_flag_present:
447061da546Spatrick break;
448061da546Spatrick default:
449061da546Spatrick s.Printf("DW_FORM(0x%4.4x)", m_form);
450061da546Spatrick break;
451061da546Spatrick }
452061da546Spatrick
453061da546Spatrick if (unit_relative_offset) {
454061da546Spatrick assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
455061da546Spatrick // unit relative or we will get this wrong
456061da546Spatrick s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());
457061da546Spatrick }
458061da546Spatrick }
459061da546Spatrick
AsCString() const460061da546Spatrick const char *DWARFFormValue::AsCString() const {
461dda28197Spatrick DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();
462061da546Spatrick
463dda28197Spatrick if (m_form == DW_FORM_string)
464061da546Spatrick return m_value.value.cstr;
465dda28197Spatrick if (m_form == DW_FORM_strp)
466dda28197Spatrick return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
467061da546Spatrick
468dda28197Spatrick if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||
469dda28197Spatrick m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||
470dda28197Spatrick m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {
471061da546Spatrick
472*f6aab3d8Srobert std::optional<uint64_t> offset =
473dda28197Spatrick m_unit->GetStringOffsetSectionItem(m_value.value.uval);
474dda28197Spatrick if (!offset)
475dda28197Spatrick return nullptr;
476dda28197Spatrick return context.getOrLoadStrData().PeekCStr(*offset);
477061da546Spatrick }
478061da546Spatrick
479061da546Spatrick if (m_form == DW_FORM_line_strp)
480dda28197Spatrick return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
481061da546Spatrick
482061da546Spatrick return nullptr;
483061da546Spatrick }
484061da546Spatrick
Address() const485061da546Spatrick dw_addr_t DWARFFormValue::Address() const {
486061da546Spatrick SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
487061da546Spatrick
488061da546Spatrick if (m_form == DW_FORM_addr)
489061da546Spatrick return Unsigned();
490061da546Spatrick
491061da546Spatrick assert(m_unit);
492061da546Spatrick assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
493061da546Spatrick m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
494061da546Spatrick m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
495061da546Spatrick
496061da546Spatrick uint32_t index_size = m_unit->GetAddressByteSize();
497061da546Spatrick dw_offset_t addr_base = m_unit->GetAddrBase();
498061da546Spatrick lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
499061da546Spatrick return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
500061da546Spatrick &offset, index_size);
501061da546Spatrick }
502061da546Spatrick
Reference() const503061da546Spatrick DWARFDIE DWARFFormValue::Reference() const {
504061da546Spatrick uint64_t value = m_value.value.uval;
505061da546Spatrick switch (m_form) {
506061da546Spatrick case DW_FORM_ref1:
507061da546Spatrick case DW_FORM_ref2:
508061da546Spatrick case DW_FORM_ref4:
509061da546Spatrick case DW_FORM_ref8:
510061da546Spatrick case DW_FORM_ref_udata:
511061da546Spatrick assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
512061da546Spatrick // unit relative or we will get this wrong
513061da546Spatrick value += m_unit->GetOffset();
514061da546Spatrick if (!m_unit->ContainsDIEOffset(value)) {
515061da546Spatrick m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
516*f6aab3d8Srobert "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);
517061da546Spatrick return {};
518061da546Spatrick }
519061da546Spatrick return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
520061da546Spatrick
521061da546Spatrick case DW_FORM_ref_addr: {
522061da546Spatrick DWARFUnit *ref_cu =
523dda28197Spatrick m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
524061da546Spatrick DIERef::Section::DebugInfo, value);
525061da546Spatrick if (!ref_cu) {
526061da546Spatrick m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
527*f6aab3d8Srobert "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);
528061da546Spatrick return {};
529061da546Spatrick }
530061da546Spatrick return ref_cu->GetDIE(value);
531061da546Spatrick }
532061da546Spatrick
533061da546Spatrick case DW_FORM_ref_sig8: {
534061da546Spatrick DWARFTypeUnit *tu =
535dda28197Spatrick m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);
536061da546Spatrick if (!tu)
537061da546Spatrick return {};
538061da546Spatrick return tu->GetDIE(tu->GetTypeOffset());
539061da546Spatrick }
540061da546Spatrick
541061da546Spatrick default:
542061da546Spatrick return {};
543061da546Spatrick }
544061da546Spatrick }
545061da546Spatrick
Reference(dw_offset_t base_offset) const546061da546Spatrick uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
547061da546Spatrick uint64_t value = m_value.value.uval;
548061da546Spatrick switch (m_form) {
549061da546Spatrick case DW_FORM_ref1:
550061da546Spatrick case DW_FORM_ref2:
551061da546Spatrick case DW_FORM_ref4:
552061da546Spatrick case DW_FORM_ref8:
553061da546Spatrick case DW_FORM_ref_udata:
554061da546Spatrick return value + base_offset;
555061da546Spatrick
556061da546Spatrick case DW_FORM_ref_addr:
557061da546Spatrick case DW_FORM_ref_sig8:
558061da546Spatrick case DW_FORM_GNU_ref_alt:
559061da546Spatrick return value;
560061da546Spatrick
561061da546Spatrick default:
562061da546Spatrick return DW_INVALID_OFFSET;
563061da546Spatrick }
564061da546Spatrick }
565061da546Spatrick
BlockData() const566061da546Spatrick const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
567061da546Spatrick
IsBlockForm(const dw_form_t form)568061da546Spatrick bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
569061da546Spatrick switch (form) {
570061da546Spatrick case DW_FORM_exprloc:
571061da546Spatrick case DW_FORM_block:
572061da546Spatrick case DW_FORM_block1:
573061da546Spatrick case DW_FORM_block2:
574061da546Spatrick case DW_FORM_block4:
575061da546Spatrick return true;
576061da546Spatrick }
577061da546Spatrick return false;
578061da546Spatrick }
579061da546Spatrick
IsDataForm(const dw_form_t form)580061da546Spatrick bool DWARFFormValue::IsDataForm(const dw_form_t form) {
581061da546Spatrick switch (form) {
582061da546Spatrick case DW_FORM_sdata:
583061da546Spatrick case DW_FORM_udata:
584061da546Spatrick case DW_FORM_data1:
585061da546Spatrick case DW_FORM_data2:
586061da546Spatrick case DW_FORM_data4:
587061da546Spatrick case DW_FORM_data8:
588061da546Spatrick return true;
589061da546Spatrick }
590061da546Spatrick return false;
591061da546Spatrick }
592061da546Spatrick
FormIsSupported(dw_form_t form)593061da546Spatrick bool DWARFFormValue::FormIsSupported(dw_form_t form) {
594061da546Spatrick switch (form) {
595061da546Spatrick case DW_FORM_addr:
596061da546Spatrick case DW_FORM_addrx:
597061da546Spatrick case DW_FORM_loclistx:
598061da546Spatrick case DW_FORM_rnglistx:
599061da546Spatrick case DW_FORM_block2:
600061da546Spatrick case DW_FORM_block4:
601061da546Spatrick case DW_FORM_data2:
602061da546Spatrick case DW_FORM_data4:
603061da546Spatrick case DW_FORM_data8:
604061da546Spatrick case DW_FORM_string:
605061da546Spatrick case DW_FORM_block:
606061da546Spatrick case DW_FORM_block1:
607061da546Spatrick case DW_FORM_data1:
608061da546Spatrick case DW_FORM_flag:
609061da546Spatrick case DW_FORM_sdata:
610061da546Spatrick case DW_FORM_strp:
611be691f3bSpatrick case DW_FORM_line_strp:
612061da546Spatrick case DW_FORM_strx:
613061da546Spatrick case DW_FORM_strx1:
614061da546Spatrick case DW_FORM_strx2:
615061da546Spatrick case DW_FORM_strx3:
616061da546Spatrick case DW_FORM_strx4:
617061da546Spatrick case DW_FORM_udata:
618061da546Spatrick case DW_FORM_ref_addr:
619061da546Spatrick case DW_FORM_ref1:
620061da546Spatrick case DW_FORM_ref2:
621061da546Spatrick case DW_FORM_ref4:
622061da546Spatrick case DW_FORM_ref8:
623061da546Spatrick case DW_FORM_ref_udata:
624061da546Spatrick case DW_FORM_indirect:
625061da546Spatrick case DW_FORM_sec_offset:
626061da546Spatrick case DW_FORM_exprloc:
627061da546Spatrick case DW_FORM_flag_present:
628061da546Spatrick case DW_FORM_ref_sig8:
629061da546Spatrick case DW_FORM_GNU_str_index:
630061da546Spatrick case DW_FORM_GNU_addr_index:
631061da546Spatrick case DW_FORM_implicit_const:
632061da546Spatrick return true;
633061da546Spatrick default:
634061da546Spatrick break;
635061da546Spatrick }
636061da546Spatrick return false;
637061da546Spatrick }
638