669 lines · cpp
1//===-- DWARFFormValue.cpp ------------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include <cassert>10#include <optional>11 12#include "lldb/Core/Module.h"13#include "lldb/Core/dwarf.h"14#include "lldb/Symbol/ObjectFile.h"15#include "lldb/Utility/Stream.h"16 17#include "DWARFDebugInfo.h"18#include "DWARFFormValue.h"19#include "DWARFUnit.h"20 21using namespace lldb_private;22using namespace lldb_private::plugin::dwarf;23using namespace llvm::dwarf;24 25void DWARFFormValue::Clear() {26 m_unit = nullptr;27 m_form = dw_form_t(0);28 m_value = ValueType();29}30 31bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,32 lldb::offset_t *offset_ptr) {33 if (m_form == DW_FORM_implicit_const)34 return true;35 36 bool indirect = false;37 bool is_block = false;38 m_value.data = nullptr;39 // Read the value for the form into value and follow and DW_FORM_indirect40 // instances we run into41 do {42 indirect = false;43 switch (m_form) {44 case DW_FORM_addr:45 assert(m_unit);46 m_value.uval =47 data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));48 break;49 case DW_FORM_block1:50 m_value.uval = data.GetU8(offset_ptr);51 is_block = true;52 break;53 case DW_FORM_block2:54 m_value.uval = data.GetU16(offset_ptr);55 is_block = true;56 break;57 case DW_FORM_block4:58 m_value.uval = data.GetU32(offset_ptr);59 is_block = true;60 break;61 case DW_FORM_data16:62 m_value.uval = 16;63 is_block = true;64 break;65 case DW_FORM_exprloc:66 case DW_FORM_block:67 m_value.uval = data.GetULEB128(offset_ptr);68 is_block = true;69 break;70 case DW_FORM_string:71 m_value.cstr = data.GetCStr(offset_ptr);72 break;73 case DW_FORM_sdata:74 m_value.sval = data.GetSLEB128(offset_ptr);75 break;76 case DW_FORM_strp:77 case DW_FORM_line_strp:78 case DW_FORM_sec_offset:79 assert(m_unit);80 m_value.uval = data.GetMaxU64(81 offset_ptr, m_unit->GetFormParams().getDwarfOffsetByteSize());82 break;83 case DW_FORM_addrx1:84 case DW_FORM_strx1:85 case DW_FORM_ref1:86 case DW_FORM_data1:87 case DW_FORM_flag:88 m_value.uval = data.GetU8(offset_ptr);89 break;90 case DW_FORM_addrx2:91 case DW_FORM_strx2:92 case DW_FORM_ref2:93 case DW_FORM_data2:94 m_value.uval = data.GetU16(offset_ptr);95 break;96 case DW_FORM_addrx3:97 case DW_FORM_strx3:98 m_value.uval = data.GetMaxU64(offset_ptr, 3);99 break;100 case DW_FORM_addrx4:101 case DW_FORM_strx4:102 case DW_FORM_ref4:103 case DW_FORM_data4:104 m_value.uval = data.GetU32(offset_ptr);105 break;106 case DW_FORM_data8:107 case DW_FORM_ref8:108 case DW_FORM_ref_sig8:109 m_value.uval = data.GetU64(offset_ptr);110 break;111 case DW_FORM_addrx:112 case DW_FORM_loclistx:113 case DW_FORM_rnglistx:114 case DW_FORM_strx:115 case DW_FORM_udata:116 case DW_FORM_ref_udata:117 case DW_FORM_GNU_str_index:118 case DW_FORM_GNU_addr_index:119 m_value.uval = data.GetULEB128(offset_ptr);120 break;121 case DW_FORM_ref_addr:122 assert(m_unit);123 m_value.uval = data.GetMaxU64(124 offset_ptr, m_unit->GetFormParams().getRefAddrByteSize());125 break;126 case DW_FORM_indirect:127 m_form = static_cast<dw_form_t>(data.GetULEB128(offset_ptr));128 indirect = true;129 break;130 case DW_FORM_flag_present:131 m_value.uval = 1;132 break;133 default:134 return false;135 }136 } while (indirect);137 138 if (is_block) {139 m_value.data = data.PeekData(*offset_ptr, m_value.uval);140 if (m_value.data != nullptr) {141 *offset_ptr += m_value.uval;142 }143 }144 145 return true;146}147 148struct FormSize {149 uint8_t valid:1, size:7;150};151static FormSize g_form_sizes[] = {152 {0, 0}, // 0x00 unused153 {0, 0}, // 0x01 DW_FORM_addr154 {0, 0}, // 0x02 unused155 {0, 0}, // 0x03 DW_FORM_block2156 {0, 0}, // 0x04 DW_FORM_block4157 {1, 2}, // 0x05 DW_FORM_data2158 {1, 4}, // 0x06 DW_FORM_data4159 {1, 8}, // 0x07 DW_FORM_data8160 {0, 0}, // 0x08 DW_FORM_string161 {0, 0}, // 0x09 DW_FORM_block162 {0, 0}, // 0x0a DW_FORM_block1163 {1, 1}, // 0x0b DW_FORM_data1164 {1, 1}, // 0x0c DW_FORM_flag165 {0, 0}, // 0x0d DW_FORM_sdata166 {0, 0}, // 0x0e DW_FORM_strp (4 bytes for DWARF32, 8 bytes for DWARF64)167 {0, 0}, // 0x0f DW_FORM_udata168 {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes169 // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later170 {1, 1}, // 0x11 DW_FORM_ref1171 {1, 2}, // 0x12 DW_FORM_ref2172 {1, 4}, // 0x13 DW_FORM_ref4173 {1, 8}, // 0x14 DW_FORM_ref8174 {0, 0}, // 0x15 DW_FORM_ref_udata175 {0, 0}, // 0x16 DW_FORM_indirect176 {0, 0}, // 0x17 DW_FORM_sec_offset (4 bytes for DWARF32,8 bytes for DWARF64)177 {0, 0}, // 0x18 DW_FORM_exprloc178 {1, 0}, // 0x19 DW_FORM_flag_present179 {0, 0}, // 0x1a DW_FORM_strx (ULEB128)180 {0, 0}, // 0x1b DW_FORM_addrx (ULEB128)181 {1, 4}, // 0x1c DW_FORM_ref_sup4182 {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)183 {1, 16}, // 0x1e DW_FORM_data16184 {0, 0}, // 0x1f DW_FORM_line_strp (4 bytes for DWARF32, 8 bytes for DWARF64)185 {1, 8}, // 0x20 DW_FORM_ref_sig8186};187 188std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form,189 const DWARFUnit *u) {190 if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)191 return static_cast<uint8_t>(g_form_sizes[form].size);192 if (form == DW_FORM_addr && u)193 return u->GetAddressByteSize();194 return std::nullopt;195}196 197std::optional<uint8_t> DWARFFormValue::GetFixedSize() const {198 return GetFixedSize(m_form, m_unit);199}200 201bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,202 lldb::offset_t *offset_ptr) const {203 return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);204}205 206bool DWARFFormValue::SkipValue(dw_form_t form,207 const DWARFDataExtractor &debug_info_data,208 lldb::offset_t *offset_ptr,209 const DWARFUnit *unit) {210 switch (form) {211 // Blocks if inlined data that have a length field and the data bytes inlined212 // in the .debug_info213 case DW_FORM_exprloc:214 case DW_FORM_block: {215 uint64_t size = debug_info_data.GetULEB128(offset_ptr);216 *offset_ptr += size;217 }218 return true;219 case DW_FORM_block1: {220 uint8_t size = debug_info_data.GetU8(offset_ptr);221 *offset_ptr += size;222 }223 return true;224 case DW_FORM_block2: {225 uint16_t size = debug_info_data.GetU16(offset_ptr);226 *offset_ptr += size;227 }228 return true;229 case DW_FORM_block4: {230 uint32_t size = debug_info_data.GetU32(offset_ptr);231 *offset_ptr += size;232 }233 return true;234 235 // Inlined NULL terminated C-strings236 case DW_FORM_string:237 debug_info_data.GetCStr(offset_ptr);238 return true;239 240 // Compile unit address sized values241 case DW_FORM_addr:242 *offset_ptr += DWARFUnit::GetAddressByteSize(unit);243 return true;244 245 case DW_FORM_ref_addr:246 assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will247 // get this wrong248 *offset_ptr += unit->GetFormParams().getRefAddrByteSize();249 return true;250 251 // 0 bytes values (implied from DW_FORM)252 case DW_FORM_flag_present:253 case DW_FORM_implicit_const:254 return true;255 256 // 1 byte values257 case DW_FORM_addrx1:258 case DW_FORM_data1:259 case DW_FORM_flag:260 case DW_FORM_ref1:261 case DW_FORM_strx1:262 *offset_ptr += 1;263 return true;264 265 // 2 byte values266 case DW_FORM_addrx2:267 case DW_FORM_data2:268 case DW_FORM_ref2:269 case DW_FORM_strx2:270 *offset_ptr += 2;271 return true;272 273 // 3 byte values274 case DW_FORM_addrx3:275 case DW_FORM_strx3:276 *offset_ptr += 3;277 return true;278 279 // 32 bit for DWARF 32, 64 for DWARF 64280 case DW_FORM_sec_offset:281 case DW_FORM_strp:282 case DW_FORM_line_strp:283 assert(unit);284 *offset_ptr += unit->GetFormParams().getDwarfOffsetByteSize();285 return true;286 287 // 4 byte values288 case DW_FORM_addrx4:289 case DW_FORM_data4:290 case DW_FORM_ref4:291 case DW_FORM_strx4:292 *offset_ptr += 4;293 return true;294 295 // 8 byte values296 case DW_FORM_data8:297 case DW_FORM_ref8:298 case DW_FORM_ref_sig8:299 *offset_ptr += 8;300 return true;301 302 // 16 byte values303 case DW_FORM_data16:304 *offset_ptr += 16;305 return true;306 307 // signed or unsigned LEB 128 values308 case DW_FORM_addrx:309 case DW_FORM_loclistx:310 case DW_FORM_rnglistx:311 case DW_FORM_sdata:312 case DW_FORM_udata:313 case DW_FORM_ref_udata:314 case DW_FORM_GNU_addr_index:315 case DW_FORM_GNU_str_index:316 case DW_FORM_strx:317 debug_info_data.Skip_LEB128(offset_ptr);318 return true;319 320 case DW_FORM_indirect: {321 auto indirect_form =322 static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr));323 return DWARFFormValue::SkipValue(indirect_form, debug_info_data,324 offset_ptr, unit);325 }326 327 default:328 break;329 }330 return false;331}332 333void DWARFFormValue::Dump(Stream &s) const {334 uint64_t uvalue = Unsigned();335 bool unit_relative_offset = false;336 337 switch (m_form) {338 case DW_FORM_addr:339 DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));340 break;341 case DW_FORM_flag:342 case DW_FORM_data1:343 s.PutHex8(uvalue);344 break;345 case DW_FORM_data2:346 s.PutHex16(uvalue);347 break;348 case DW_FORM_sec_offset:349 case DW_FORM_data4:350 s.PutHex32(uvalue);351 break;352 case DW_FORM_ref_sig8:353 case DW_FORM_data8:354 s.PutHex64(uvalue);355 break;356 case DW_FORM_string:357 s.QuotedCString(AsCString());358 break;359 case DW_FORM_exprloc:360 case DW_FORM_block:361 case DW_FORM_block1:362 case DW_FORM_block2:363 case DW_FORM_block4:364 if (uvalue > 0) {365 switch (m_form) {366 case DW_FORM_exprloc:367 case DW_FORM_block:368 s.Printf("<0x%" PRIx64 "> ", uvalue);369 break;370 case DW_FORM_block1:371 s.Printf("<0x%2.2x> ", (uint8_t)uvalue);372 break;373 case DW_FORM_block2:374 s.Printf("<0x%4.4x> ", (uint16_t)uvalue);375 break;376 case DW_FORM_block4:377 s.Printf("<0x%8.8x> ", (uint32_t)uvalue);378 break;379 default:380 break;381 }382 383 const uint8_t *data_ptr = m_value.data;384 if (data_ptr) {385 const uint8_t *end_data_ptr =386 data_ptr + uvalue; // uvalue contains size of block387 while (data_ptr < end_data_ptr) {388 s.Printf("%2.2x ", *data_ptr);389 ++data_ptr;390 }391 } else392 s.PutCString("NULL");393 }394 break;395 396 case DW_FORM_sdata:397 s.PutSLEB128(uvalue);398 break;399 case DW_FORM_udata:400 s.PutULEB128(uvalue);401 break;402 case DW_FORM_strp:403 case DW_FORM_line_strp: {404 const char *dbg_str = AsCString();405 if (dbg_str) {406 s.QuotedCString(dbg_str);407 } else {408 s.PutHex32(uvalue);409 }410 } break;411 412 case DW_FORM_ref_addr: {413 assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we414 // will get this wrong415 DumpAddress(s.AsRawOstream(), uvalue,416 m_unit->GetFormParams().getRefAddrByteSize());417 break;418 }419 case DW_FORM_ref1:420 unit_relative_offset = true;421 break;422 case DW_FORM_ref2:423 unit_relative_offset = true;424 break;425 case DW_FORM_ref4:426 unit_relative_offset = true;427 break;428 case DW_FORM_ref8:429 unit_relative_offset = true;430 break;431 case DW_FORM_ref_udata:432 unit_relative_offset = true;433 break;434 435 // All DW_FORM_indirect attributes should be resolved prior to calling this436 // function437 case DW_FORM_indirect:438 s.PutCString("DW_FORM_indirect");439 break;440 case DW_FORM_flag_present:441 break;442 default:443 s.Printf("DW_FORM(0x%4.4x)", m_form);444 break;445 }446 447 if (unit_relative_offset) {448 assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile449 // unit relative or we will get this wrong450 s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());451 }452}453 454const char *DWARFFormValue::AsCString() const {455 DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();456 457 if (m_form == DW_FORM_string)458 return m_value.cstr;459 if (m_form == DW_FORM_strp)460 return context.getOrLoadStrData().PeekCStr(m_value.uval);461 462 if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||463 m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||464 m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {465 466 std::optional<uint64_t> offset =467 m_unit->GetStringOffsetSectionItem(m_value.uval);468 if (!offset)469 return nullptr;470 return context.getOrLoadStrData().PeekCStr(*offset);471 }472 473 if (m_form == DW_FORM_line_strp)474 return context.getOrLoadLineStrData().PeekCStr(m_value.uval);475 476 return nullptr;477}478 479dw_addr_t DWARFFormValue::Address() const {480 SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();481 482 if (m_form == DW_FORM_addr)483 return Unsigned();484 485 assert(m_unit);486 assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||487 m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||488 m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);489 490 uint32_t index_size = m_unit->GetAddressByteSize();491 dw_offset_t addr_base = m_unit->GetAddrBase();492 lldb::offset_t offset = addr_base + m_value.uval * index_size;493 return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(494 &offset, index_size);495}496 497std::pair<DWARFUnit *, uint64_t>498DWARFFormValue::ReferencedUnitAndOffset() const {499 uint64_t value = m_value.uval;500 switch (m_form) {501 case DW_FORM_ref1:502 case DW_FORM_ref2:503 case DW_FORM_ref4:504 case DW_FORM_ref8:505 case DW_FORM_ref_udata:506 assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile507 // unit relative or we will get this wrong508 value += m_unit->GetOffset();509 if (!m_unit->ContainsDIEOffset(value)) {510 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(511 "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);512 return {nullptr, 0};513 }514 return {const_cast<DWARFUnit *>(m_unit), value};515 516 case DW_FORM_ref_addr: {517 DWARFUnit *ref_cu =518 m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(519 DIERef::Section::DebugInfo, value);520 if (!ref_cu) {521 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(522 "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);523 return {nullptr, 0};524 }525 return {ref_cu, value};526 }527 528 case DW_FORM_ref_sig8: {529 DWARFTypeUnit *tu =530 m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);531 if (!tu)532 return {nullptr, 0};533 return {tu, tu->GetTypeOffset()};534 }535 536 default:537 return {nullptr, 0};538 }539}540 541DWARFDIE DWARFFormValue::Reference() const {542 auto [unit, offset] = ReferencedUnitAndOffset();543 return unit ? unit->GetDIE(offset) : DWARFDIE();544}545 546uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {547 uint64_t value = m_value.uval;548 switch (m_form) {549 case DW_FORM_ref1:550 case DW_FORM_ref2:551 case DW_FORM_ref4:552 case DW_FORM_ref8:553 case DW_FORM_ref_udata:554 return value + base_offset;555 556 case DW_FORM_ref_addr:557 case DW_FORM_ref_sig8:558 case DW_FORM_GNU_ref_alt:559 return value;560 561 default:562 return DW_INVALID_OFFSET;563 }564}565 566std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {567 if ((!IsDataForm(m_form)) || m_form == llvm::dwarf::DW_FORM_sdata)568 return std::nullopt;569 return m_value.uval;570}571 572std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {573 if ((!IsDataForm(m_form)) ||574 (m_form == llvm::dwarf::DW_FORM_udata &&575 uint64_t(std::numeric_limits<int64_t>::max()) < m_value.uval))576 return std::nullopt;577 switch (m_form) {578 case llvm::dwarf::DW_FORM_data4:579 return int32_t(m_value.uval);580 case llvm::dwarf::DW_FORM_data2:581 return int16_t(m_value.uval);582 case llvm::dwarf::DW_FORM_data1:583 return int8_t(m_value.uval);584 case llvm::dwarf::DW_FORM_sdata:585 case llvm::dwarf::DW_FORM_data8:586 default:587 return m_value.sval;588 }589}590 591const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }592 593bool DWARFFormValue::IsBlockForm(const dw_form_t form) {594 switch (form) {595 case DW_FORM_exprloc:596 case DW_FORM_block:597 case DW_FORM_block1:598 case DW_FORM_block2:599 case DW_FORM_block4:600 case DW_FORM_data16:601 return true;602 default:603 return false;604 }605 llvm_unreachable("All cases handled above!");606}607 608bool DWARFFormValue::IsDataForm(const dw_form_t form) {609 switch (form) {610 case DW_FORM_sdata:611 case DW_FORM_udata:612 case DW_FORM_data1:613 case DW_FORM_data2:614 case DW_FORM_data4:615 case DW_FORM_data8:616 return true;617 default:618 return false;619 }620 llvm_unreachable("All cases handled above!");621}622 623bool DWARFFormValue::FormIsSupported(dw_form_t form) {624 switch (form) {625 case DW_FORM_addr:626 case DW_FORM_addrx:627 case DW_FORM_loclistx:628 case DW_FORM_rnglistx:629 case DW_FORM_block2:630 case DW_FORM_block4:631 case DW_FORM_data2:632 case DW_FORM_data4:633 case DW_FORM_data8:634 case DW_FORM_data16:635 case DW_FORM_string:636 case DW_FORM_block:637 case DW_FORM_block1:638 case DW_FORM_data1:639 case DW_FORM_flag:640 case DW_FORM_sdata:641 case DW_FORM_strp:642 case DW_FORM_line_strp:643 case DW_FORM_strx:644 case DW_FORM_strx1:645 case DW_FORM_strx2:646 case DW_FORM_strx3:647 case DW_FORM_strx4:648 case DW_FORM_udata:649 case DW_FORM_ref_addr:650 case DW_FORM_ref1:651 case DW_FORM_ref2:652 case DW_FORM_ref4:653 case DW_FORM_ref8:654 case DW_FORM_ref_udata:655 case DW_FORM_indirect:656 case DW_FORM_sec_offset:657 case DW_FORM_exprloc:658 case DW_FORM_flag_present:659 case DW_FORM_ref_sig8:660 case DW_FORM_GNU_str_index:661 case DW_FORM_GNU_addr_index:662 case DW_FORM_implicit_const:663 return true;664 default:665 break;666 }667 return false;668}669