1 //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===// 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 <assert.h> 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 for 170 // 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 181 {0,0}, // 0x1b 182 {0,0}, // 0x1c 183 {0,0}, // 0x1d 184 {0,0}, // 0x1e 185 {0,0}, // 0x1f 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 *offset_ptr += 4; 290 return true; 291 292 // 4 byte values 293 case DW_FORM_addrx4: 294 case DW_FORM_data4: 295 case DW_FORM_ref4: 296 case DW_FORM_strx4: 297 *offset_ptr += 4; 298 return true; 299 300 // 8 byte values 301 case DW_FORM_data8: 302 case DW_FORM_ref8: 303 case DW_FORM_ref_sig8: 304 *offset_ptr += 8; 305 return true; 306 307 // signed or unsigned LEB 128 values 308 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 dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr); 322 return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr, 323 unit); 324 } 325 326 default: 327 break; 328 } 329 return false; 330 } 331 332 void DWARFFormValue::Dump(Stream &s) const { 333 uint64_t uvalue = Unsigned(); 334 bool unit_relative_offset = false; 335 336 switch (m_form) { 337 case DW_FORM_addr: 338 DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t)); 339 break; 340 case DW_FORM_flag: 341 case DW_FORM_data1: 342 s.PutHex8(uvalue); 343 break; 344 case DW_FORM_data2: 345 s.PutHex16(uvalue); 346 break; 347 case DW_FORM_sec_offset: 348 case DW_FORM_data4: 349 s.PutHex32(uvalue); 350 break; 351 case DW_FORM_ref_sig8: 352 case DW_FORM_data8: 353 s.PutHex64(uvalue); 354 break; 355 case DW_FORM_string: 356 s.QuotedCString(AsCString()); 357 break; 358 case DW_FORM_exprloc: 359 case DW_FORM_block: 360 case DW_FORM_block1: 361 case DW_FORM_block2: 362 case DW_FORM_block4: 363 if (uvalue > 0) { 364 switch (m_form) { 365 case DW_FORM_exprloc: 366 case DW_FORM_block: 367 s.Printf("<0x%" PRIx64 "> ", uvalue); 368 break; 369 case DW_FORM_block1: 370 s.Printf("<0x%2.2x> ", (uint8_t)uvalue); 371 break; 372 case DW_FORM_block2: 373 s.Printf("<0x%4.4x> ", (uint16_t)uvalue); 374 break; 375 case DW_FORM_block4: 376 s.Printf("<0x%8.8x> ", (uint32_t)uvalue); 377 break; 378 default: 379 break; 380 } 381 382 const uint8_t *data_ptr = m_value.data; 383 if (data_ptr) { 384 const uint8_t *end_data_ptr = 385 data_ptr + uvalue; // uvalue contains size of block 386 while (data_ptr < end_data_ptr) { 387 s.Printf("%2.2x ", *data_ptr); 388 ++data_ptr; 389 } 390 } else 391 s.PutCString("NULL"); 392 } 393 break; 394 395 case DW_FORM_sdata: 396 s.PutSLEB128(uvalue); 397 break; 398 case DW_FORM_udata: 399 s.PutULEB128(uvalue); 400 break; 401 case DW_FORM_strp: { 402 const char *dbg_str = AsCString(); 403 if (dbg_str) { 404 s.QuotedCString(dbg_str); 405 } else { 406 s.PutHex32(uvalue); 407 } 408 } break; 409 410 case DW_FORM_ref_addr: { 411 assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we 412 // will get this wrong 413 if (m_unit->GetVersion() <= 2) 414 DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2); 415 else 416 DumpAddress(s.AsRawOstream(), uvalue, 417 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't 418 // support DWARF64 yet 419 break; 420 } 421 case DW_FORM_ref1: 422 unit_relative_offset = true; 423 break; 424 case DW_FORM_ref2: 425 unit_relative_offset = true; 426 break; 427 case DW_FORM_ref4: 428 unit_relative_offset = true; 429 break; 430 case DW_FORM_ref8: 431 unit_relative_offset = true; 432 break; 433 case DW_FORM_ref_udata: 434 unit_relative_offset = true; 435 break; 436 437 // All DW_FORM_indirect attributes should be resolved prior to calling this 438 // function 439 case DW_FORM_indirect: 440 s.PutCString("DW_FORM_indirect"); 441 break; 442 case DW_FORM_flag_present: 443 break; 444 default: 445 s.Printf("DW_FORM(0x%4.4x)", m_form); 446 break; 447 } 448 449 if (unit_relative_offset) { 450 assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile 451 // unit relative or we will get this wrong 452 s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset()); 453 } 454 } 455 456 const char *DWARFFormValue::AsCString() const { 457 SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); 458 459 if (m_form == DW_FORM_string) { 460 return m_value.value.cstr; 461 } else if (m_form == DW_FORM_strp) { 462 return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( 463 m_value.value.uval); 464 } else if (m_form == DW_FORM_GNU_str_index) { 465 uint32_t index_size = 4; 466 lldb::offset_t offset = m_value.value.uval * index_size; 467 dw_offset_t str_offset = 468 symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( 469 &offset, index_size); 470 return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( 471 str_offset); 472 } 473 474 if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 || 475 m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 || 476 m_form == DW_FORM_strx4) { 477 478 // The same code as above. 479 uint32_t indexSize = 4; 480 lldb::offset_t offset = 481 m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize; 482 dw_offset_t strOffset = 483 symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( 484 &offset, indexSize); 485 return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset); 486 } 487 488 if (m_form == DW_FORM_line_strp) 489 return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr( 490 m_value.value.uval); 491 492 return nullptr; 493 } 494 495 dw_addr_t DWARFFormValue::Address() const { 496 SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); 497 498 if (m_form == DW_FORM_addr) 499 return Unsigned(); 500 501 assert(m_unit); 502 assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || 503 m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || 504 m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); 505 506 uint32_t index_size = m_unit->GetAddressByteSize(); 507 dw_offset_t addr_base = m_unit->GetAddrBase(); 508 lldb::offset_t offset = addr_base + m_value.value.uval * index_size; 509 return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( 510 &offset, index_size); 511 } 512 513 DWARFDIE DWARFFormValue::Reference() const { 514 uint64_t value = m_value.value.uval; 515 switch (m_form) { 516 case DW_FORM_ref1: 517 case DW_FORM_ref2: 518 case DW_FORM_ref4: 519 case DW_FORM_ref8: 520 case DW_FORM_ref_udata: 521 assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile 522 // unit relative or we will get this wrong 523 value += m_unit->GetOffset(); 524 if (!m_unit->ContainsDIEOffset(value)) { 525 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 526 "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU", 527 value); 528 return {}; 529 } 530 return const_cast<DWARFUnit *>(m_unit)->GetDIE(value); 531 532 case DW_FORM_ref_addr: { 533 DWARFUnit *ref_cu = 534 m_unit->GetSymbolFileDWARF().DebugInfo()->GetUnitContainingDIEOffset( 535 DIERef::Section::DebugInfo, value); 536 if (!ref_cu) { 537 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 538 "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU", 539 value); 540 return {}; 541 } 542 return ref_cu->GetDIE(value); 543 } 544 545 case DW_FORM_ref_sig8: { 546 DWARFTypeUnit *tu = 547 m_unit->GetSymbolFileDWARF().DebugInfo()->GetTypeUnitForHash(value); 548 if (!tu) 549 return {}; 550 return tu->GetDIE(tu->GetTypeOffset()); 551 } 552 553 default: 554 return {}; 555 } 556 } 557 558 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const { 559 uint64_t value = m_value.value.uval; 560 switch (m_form) { 561 case DW_FORM_ref1: 562 case DW_FORM_ref2: 563 case DW_FORM_ref4: 564 case DW_FORM_ref8: 565 case DW_FORM_ref_udata: 566 return value + base_offset; 567 568 case DW_FORM_ref_addr: 569 case DW_FORM_ref_sig8: 570 case DW_FORM_GNU_ref_alt: 571 return value; 572 573 default: 574 return DW_INVALID_OFFSET; 575 } 576 } 577 578 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; } 579 580 bool DWARFFormValue::IsBlockForm(const dw_form_t form) { 581 switch (form) { 582 case DW_FORM_exprloc: 583 case DW_FORM_block: 584 case DW_FORM_block1: 585 case DW_FORM_block2: 586 case DW_FORM_block4: 587 return true; 588 } 589 return false; 590 } 591 592 bool DWARFFormValue::IsDataForm(const dw_form_t form) { 593 switch (form) { 594 case DW_FORM_sdata: 595 case DW_FORM_udata: 596 case DW_FORM_data1: 597 case DW_FORM_data2: 598 case DW_FORM_data4: 599 case DW_FORM_data8: 600 return true; 601 } 602 return false; 603 } 604 605 bool DWARFFormValue::FormIsSupported(dw_form_t form) { 606 switch (form) { 607 case DW_FORM_addr: 608 case DW_FORM_addrx: 609 case DW_FORM_loclistx: 610 case DW_FORM_rnglistx: 611 case DW_FORM_block2: 612 case DW_FORM_block4: 613 case DW_FORM_data2: 614 case DW_FORM_data4: 615 case DW_FORM_data8: 616 case DW_FORM_string: 617 case DW_FORM_block: 618 case DW_FORM_block1: 619 case DW_FORM_data1: 620 case DW_FORM_flag: 621 case DW_FORM_sdata: 622 case DW_FORM_strp: 623 case DW_FORM_strx: 624 case DW_FORM_strx1: 625 case DW_FORM_strx2: 626 case DW_FORM_strx3: 627 case DW_FORM_strx4: 628 case DW_FORM_udata: 629 case DW_FORM_ref_addr: 630 case DW_FORM_ref1: 631 case DW_FORM_ref2: 632 case DW_FORM_ref4: 633 case DW_FORM_ref8: 634 case DW_FORM_ref_udata: 635 case DW_FORM_indirect: 636 case DW_FORM_sec_offset: 637 case DW_FORM_exprloc: 638 case DW_FORM_flag_present: 639 case DW_FORM_ref_sig8: 640 case DW_FORM_GNU_str_index: 641 case DW_FORM_GNU_addr_index: 642 case DW_FORM_implicit_const: 643 return true; 644 default: 645 break; 646 } 647 return false; 648 } 649