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