1 //===-- DWARFFormValue.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/dwarf.h"
14 #include "lldb/Symbol/ObjectFile.h"
15 #include "lldb/Utility/Stream.h"
17 #include "DWARFDebugInfo.h"
18 #include "DWARFFormValue.h"
19 #include "DWARFUnit.h"
21 using namespace lldb_private
;
22 using namespace lldb_private::dwarf
;
23 using namespace lldb_private::plugin::dwarf
;
25 void DWARFFormValue::Clear() {
27 m_form
= dw_form_t(0);
28 m_value
= ValueType();
31 bool DWARFFormValue::ExtractValue(const DWARFDataExtractor
&data
,
32 lldb::offset_t
*offset_ptr
) {
33 if (m_form
== DW_FORM_implicit_const
)
36 bool indirect
= false;
37 bool is_block
= false;
38 m_value
.data
= nullptr;
39 uint8_t ref_addr_size
;
40 // Read the value for the form into value and follow and DW_FORM_indirect
41 // instances we run into
48 data
.GetMaxU64(offset_ptr
, DWARFUnit::GetAddressByteSize(m_unit
));
51 m_value
.uval
= data
.GetU8(offset_ptr
);
55 m_value
.uval
= data
.GetU16(offset_ptr
);
59 m_value
.uval
= data
.GetU32(offset_ptr
);
68 m_value
.uval
= data
.GetULEB128(offset_ptr
);
72 m_value
.cstr
= data
.GetCStr(offset_ptr
);
75 m_value
.sval
= data
.GetSLEB128(offset_ptr
);
78 case DW_FORM_line_strp
:
79 case DW_FORM_sec_offset
:
80 m_value
.uval
= data
.GetMaxU64(offset_ptr
, 4);
87 m_value
.uval
= data
.GetU8(offset_ptr
);
93 m_value
.uval
= data
.GetU16(offset_ptr
);
97 m_value
.uval
= data
.GetMaxU64(offset_ptr
, 3);
103 m_value
.uval
= data
.GetU32(offset_ptr
);
107 case DW_FORM_ref_sig8
:
108 m_value
.uval
= data
.GetU64(offset_ptr
);
111 case DW_FORM_loclistx
:
112 case DW_FORM_rnglistx
:
115 case DW_FORM_ref_udata
:
116 case DW_FORM_GNU_str_index
:
117 case DW_FORM_GNU_addr_index
:
118 m_value
.uval
= data
.GetULEB128(offset_ptr
);
120 case DW_FORM_ref_addr
:
122 if (m_unit
->GetVersion() <= 2)
123 ref_addr_size
= m_unit
->GetAddressByteSize();
126 m_value
.uval
= data
.GetMaxU64(offset_ptr
, ref_addr_size
);
128 case DW_FORM_indirect
:
129 m_form
= static_cast<dw_form_t
>(data
.GetULEB128(offset_ptr
));
132 case DW_FORM_flag_present
:
141 m_value
.data
= data
.PeekData(*offset_ptr
, m_value
.uval
);
142 if (m_value
.data
!= nullptr) {
143 *offset_ptr
+= m_value
.uval
;
151 uint8_t valid
:1, size
:7;
153 static FormSize g_form_sizes
[] = {
154 {0, 0}, // 0x00 unused
155 {0, 0}, // 0x01 DW_FORM_addr
156 {0, 0}, // 0x02 unused
157 {0, 0}, // 0x03 DW_FORM_block2
158 {0, 0}, // 0x04 DW_FORM_block4
159 {1, 2}, // 0x05 DW_FORM_data2
160 {1, 4}, // 0x06 DW_FORM_data4
161 {1, 8}, // 0x07 DW_FORM_data8
162 {0, 0}, // 0x08 DW_FORM_string
163 {0, 0}, // 0x09 DW_FORM_block
164 {0, 0}, // 0x0a DW_FORM_block1
165 {1, 1}, // 0x0b DW_FORM_data1
166 {1, 1}, // 0x0c DW_FORM_flag
167 {0, 0}, // 0x0d DW_FORM_sdata
168 {1, 4}, // 0x0e DW_FORM_strp
169 {0, 0}, // 0x0f DW_FORM_udata
170 {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
171 // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
172 {1, 1}, // 0x11 DW_FORM_ref1
173 {1, 2}, // 0x12 DW_FORM_ref2
174 {1, 4}, // 0x13 DW_FORM_ref4
175 {1, 8}, // 0x14 DW_FORM_ref8
176 {0, 0}, // 0x15 DW_FORM_ref_udata
177 {0, 0}, // 0x16 DW_FORM_indirect
178 {1, 4}, // 0x17 DW_FORM_sec_offset
179 {0, 0}, // 0x18 DW_FORM_exprloc
180 {1, 0}, // 0x19 DW_FORM_flag_present
181 {0, 0}, // 0x1a DW_FORM_strx (ULEB128)
182 {0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
183 {1, 4}, // 0x1c DW_FORM_ref_sup4
184 {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
185 {1, 16}, // 0x1e DW_FORM_data16
186 {1, 4}, // 0x1f DW_FORM_line_strp
187 {1, 8}, // 0x20 DW_FORM_ref_sig8
190 std::optional
<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form
,
191 const DWARFUnit
*u
) {
192 if (form
<= DW_FORM_ref_sig8
&& g_form_sizes
[form
].valid
)
193 return static_cast<uint8_t>(g_form_sizes
[form
].size
);
194 if (form
== DW_FORM_addr
&& u
)
195 return u
->GetAddressByteSize();
199 std::optional
<uint8_t> DWARFFormValue::GetFixedSize() const {
200 return GetFixedSize(m_form
, m_unit
);
203 bool DWARFFormValue::SkipValue(const DWARFDataExtractor
&debug_info_data
,
204 lldb::offset_t
*offset_ptr
) const {
205 return DWARFFormValue::SkipValue(m_form
, debug_info_data
, offset_ptr
, m_unit
);
208 bool DWARFFormValue::SkipValue(dw_form_t form
,
209 const DWARFDataExtractor
&debug_info_data
,
210 lldb::offset_t
*offset_ptr
,
211 const DWARFUnit
*unit
) {
212 uint8_t ref_addr_size
;
214 // Blocks if inlined data that have a length field and the data bytes inlined
215 // in the .debug_info
216 case DW_FORM_exprloc
:
217 case DW_FORM_block
: {
218 uint64_t size
= debug_info_data
.GetULEB128(offset_ptr
);
222 case DW_FORM_block1
: {
223 uint8_t size
= debug_info_data
.GetU8(offset_ptr
);
227 case DW_FORM_block2
: {
228 uint16_t size
= debug_info_data
.GetU16(offset_ptr
);
232 case DW_FORM_block4
: {
233 uint32_t size
= debug_info_data
.GetU32(offset_ptr
);
238 // Inlined NULL terminated C-strings
240 debug_info_data
.GetCStr(offset_ptr
);
243 // Compile unit address sized values
245 *offset_ptr
+= DWARFUnit::GetAddressByteSize(unit
);
248 case DW_FORM_ref_addr
:
250 assert(unit
); // Unit must be valid for DW_FORM_ref_addr objects or we will
252 if (unit
->GetVersion() <= 2)
253 ref_addr_size
= unit
->GetAddressByteSize();
256 *offset_ptr
+= ref_addr_size
;
259 // 0 bytes values (implied from DW_FORM)
260 case DW_FORM_flag_present
:
261 case DW_FORM_implicit_const
:
287 // 32 bit for DWARF 32, 64 for DWARF 64
288 case DW_FORM_sec_offset
:
290 case DW_FORM_line_strp
:
305 case DW_FORM_ref_sig8
:
314 // signed or unsigned LEB 128 values
316 case DW_FORM_loclistx
:
317 case DW_FORM_rnglistx
:
320 case DW_FORM_ref_udata
:
321 case DW_FORM_GNU_addr_index
:
322 case DW_FORM_GNU_str_index
:
324 debug_info_data
.Skip_LEB128(offset_ptr
);
327 case DW_FORM_indirect
: {
329 static_cast<dw_form_t
>(debug_info_data
.GetULEB128(offset_ptr
));
330 return DWARFFormValue::SkipValue(indirect_form
, debug_info_data
,
340 void DWARFFormValue::Dump(Stream
&s
) const {
341 uint64_t uvalue
= Unsigned();
342 bool unit_relative_offset
= false;
346 DumpAddress(s
.AsRawOstream(), uvalue
, sizeof(uint64_t));
355 case DW_FORM_sec_offset
:
359 case DW_FORM_ref_sig8
:
364 s
.QuotedCString(AsCString());
366 case DW_FORM_exprloc
:
373 case DW_FORM_exprloc
:
375 s
.Printf("<0x%" PRIx64
"> ", uvalue
);
378 s
.Printf("<0x%2.2x> ", (uint8_t)uvalue
);
381 s
.Printf("<0x%4.4x> ", (uint16_t)uvalue
);
384 s
.Printf("<0x%8.8x> ", (uint32_t)uvalue
);
390 const uint8_t *data_ptr
= m_value
.data
;
392 const uint8_t *end_data_ptr
=
393 data_ptr
+ uvalue
; // uvalue contains size of block
394 while (data_ptr
< end_data_ptr
) {
395 s
.Printf("%2.2x ", *data_ptr
);
399 s
.PutCString("NULL");
404 s
.PutSLEB128(uvalue
);
407 s
.PutULEB128(uvalue
);
410 case DW_FORM_line_strp
: {
411 const char *dbg_str
= AsCString();
413 s
.QuotedCString(dbg_str
);
419 case DW_FORM_ref_addr
: {
420 assert(m_unit
); // Unit must be valid for DW_FORM_ref_addr objects or we
421 // will get this wrong
422 if (m_unit
->GetVersion() <= 2)
423 DumpAddress(s
.AsRawOstream(), uvalue
, sizeof(uint64_t) * 2);
425 DumpAddress(s
.AsRawOstream(), uvalue
,
426 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
427 // support DWARF64 yet
431 unit_relative_offset
= true;
434 unit_relative_offset
= true;
437 unit_relative_offset
= true;
440 unit_relative_offset
= true;
442 case DW_FORM_ref_udata
:
443 unit_relative_offset
= true;
446 // All DW_FORM_indirect attributes should be resolved prior to calling this
448 case DW_FORM_indirect
:
449 s
.PutCString("DW_FORM_indirect");
451 case DW_FORM_flag_present
:
454 s
.Printf("DW_FORM(0x%4.4x)", m_form
);
458 if (unit_relative_offset
) {
459 assert(m_unit
); // Unit must be valid for DW_FORM_ref forms that are compile
460 // unit relative or we will get this wrong
461 s
.Printf("{0x%8.8" PRIx64
"}", uvalue
+ m_unit
->GetOffset());
465 const char *DWARFFormValue::AsCString() const {
466 DWARFContext
&context
= m_unit
->GetSymbolFileDWARF().GetDWARFContext();
468 if (m_form
== DW_FORM_string
)
470 if (m_form
== DW_FORM_strp
)
471 return context
.getOrLoadStrData().PeekCStr(m_value
.uval
);
473 if (m_form
== DW_FORM_GNU_str_index
|| m_form
== DW_FORM_strx
||
474 m_form
== DW_FORM_strx1
|| m_form
== DW_FORM_strx2
||
475 m_form
== DW_FORM_strx3
|| m_form
== DW_FORM_strx4
) {
477 std::optional
<uint64_t> offset
=
478 m_unit
->GetStringOffsetSectionItem(m_value
.uval
);
481 return context
.getOrLoadStrData().PeekCStr(*offset
);
484 if (m_form
== DW_FORM_line_strp
)
485 return context
.getOrLoadLineStrData().PeekCStr(m_value
.uval
);
490 dw_addr_t
DWARFFormValue::Address() const {
491 SymbolFileDWARF
&symbol_file
= m_unit
->GetSymbolFileDWARF();
493 if (m_form
== DW_FORM_addr
)
497 assert(m_form
== DW_FORM_GNU_addr_index
|| m_form
== DW_FORM_addrx
||
498 m_form
== DW_FORM_addrx1
|| m_form
== DW_FORM_addrx2
||
499 m_form
== DW_FORM_addrx3
|| m_form
== DW_FORM_addrx4
);
501 uint32_t index_size
= m_unit
->GetAddressByteSize();
502 dw_offset_t addr_base
= m_unit
->GetAddrBase();
503 lldb::offset_t offset
= addr_base
+ m_value
.uval
* index_size
;
504 return symbol_file
.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
505 &offset
, index_size
);
508 std::pair
<DWARFUnit
*, uint64_t>
509 DWARFFormValue::ReferencedUnitAndOffset() const {
510 uint64_t value
= m_value
.uval
;
516 case DW_FORM_ref_udata
:
517 assert(m_unit
); // Unit must be valid for DW_FORM_ref forms that are compile
518 // unit relative or we will get this wrong
519 value
+= m_unit
->GetOffset();
520 if (!m_unit
->ContainsDIEOffset(value
)) {
521 m_unit
->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
522 "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value
);
525 return {const_cast<DWARFUnit
*>(m_unit
), value
};
527 case DW_FORM_ref_addr
: {
529 m_unit
->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
530 DIERef::Section::DebugInfo
, value
);
532 m_unit
->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
533 "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value
);
536 return {ref_cu
, value
};
539 case DW_FORM_ref_sig8
: {
541 m_unit
->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value
);
544 return {tu
, tu
->GetTypeOffset()};
552 DWARFDIE
DWARFFormValue::Reference() const {
553 auto [unit
, offset
] = ReferencedUnitAndOffset();
554 return unit
? unit
->GetDIE(offset
) : DWARFDIE();
557 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset
) const {
558 uint64_t value
= m_value
.uval
;
564 case DW_FORM_ref_udata
:
565 return value
+ base_offset
;
567 case DW_FORM_ref_addr
:
568 case DW_FORM_ref_sig8
:
569 case DW_FORM_GNU_ref_alt
:
573 return DW_INVALID_OFFSET
;
577 std::optional
<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
578 if ((!IsDataForm(m_form
)) || m_form
== lldb_private::dwarf::DW_FORM_sdata
)
583 std::optional
<int64_t> DWARFFormValue::getAsSignedConstant() const {
584 if ((!IsDataForm(m_form
)) ||
585 (m_form
== lldb_private::dwarf::DW_FORM_udata
&&
586 uint64_t(std::numeric_limits
<int64_t>::max()) < m_value
.uval
))
589 case lldb_private::dwarf::DW_FORM_data4
:
590 return int32_t(m_value
.uval
);
591 case lldb_private::dwarf::DW_FORM_data2
:
592 return int16_t(m_value
.uval
);
593 case lldb_private::dwarf::DW_FORM_data1
:
594 return int8_t(m_value
.uval
);
595 case lldb_private::dwarf::DW_FORM_sdata
:
596 case lldb_private::dwarf::DW_FORM_data8
:
602 const uint8_t *DWARFFormValue::BlockData() const { return m_value
.data
; }
604 bool DWARFFormValue::IsBlockForm(const dw_form_t form
) {
606 case DW_FORM_exprloc
:
616 llvm_unreachable("All cases handled above!");
619 bool DWARFFormValue::IsDataForm(const dw_form_t form
) {
631 llvm_unreachable("All cases handled above!");
634 bool DWARFFormValue::FormIsSupported(dw_form_t form
) {
638 case DW_FORM_loclistx
:
639 case DW_FORM_rnglistx
:
653 case DW_FORM_line_strp
:
660 case DW_FORM_ref_addr
:
665 case DW_FORM_ref_udata
:
666 case DW_FORM_indirect
:
667 case DW_FORM_sec_offset
:
668 case DW_FORM_exprloc
:
669 case DW_FORM_flag_present
:
670 case DW_FORM_ref_sig8
:
671 case DW_FORM_GNU_str_index
:
672 case DW_FORM_GNU_addr_index
:
673 case DW_FORM_implicit_const
: