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