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 <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 DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext(); 458 459 if (m_form == DW_FORM_string) 460 return m_value.value.cstr; 461 if (m_form == DW_FORM_strp) 462 return context.getOrLoadStrData().PeekCStr(m_value.value.uval); 463 464 if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx || 465 m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 || 466 m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) { 467 468 llvm::Optional<uint64_t> offset = 469 m_unit->GetStringOffsetSectionItem(m_value.value.uval); 470 if (!offset) 471 return nullptr; 472 return context.getOrLoadStrData().PeekCStr(*offset); 473 } 474 475 if (m_form == DW_FORM_line_strp) 476 return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval); 477 478 return nullptr; 479 } 480 481 dw_addr_t DWARFFormValue::Address() const { 482 SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); 483 484 if (m_form == DW_FORM_addr) 485 return Unsigned(); 486 487 assert(m_unit); 488 assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || 489 m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || 490 m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); 491 492 uint32_t index_size = m_unit->GetAddressByteSize(); 493 dw_offset_t addr_base = m_unit->GetAddrBase(); 494 lldb::offset_t offset = addr_base + m_value.value.uval * index_size; 495 return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( 496 &offset, index_size); 497 } 498 499 DWARFDIE DWARFFormValue::Reference() const { 500 uint64_t value = m_value.value.uval; 501 switch (m_form) { 502 case DW_FORM_ref1: 503 case DW_FORM_ref2: 504 case DW_FORM_ref4: 505 case DW_FORM_ref8: 506 case DW_FORM_ref_udata: 507 assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile 508 // unit relative or we will get this wrong 509 value += m_unit->GetOffset(); 510 if (!m_unit->ContainsDIEOffset(value)) { 511 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 512 "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU", 513 value); 514 return {}; 515 } 516 return const_cast<DWARFUnit *>(m_unit)->GetDIE(value); 517 518 case DW_FORM_ref_addr: { 519 DWARFUnit *ref_cu = 520 m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset( 521 DIERef::Section::DebugInfo, value); 522 if (!ref_cu) { 523 m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 524 "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU", 525 value); 526 return {}; 527 } 528 return ref_cu->GetDIE(value); 529 } 530 531 case DW_FORM_ref_sig8: { 532 DWARFTypeUnit *tu = 533 m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value); 534 if (!tu) 535 return {}; 536 return tu->GetDIE(tu->GetTypeOffset()); 537 } 538 539 default: 540 return {}; 541 } 542 } 543 544 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const { 545 uint64_t value = m_value.value.uval; 546 switch (m_form) { 547 case DW_FORM_ref1: 548 case DW_FORM_ref2: 549 case DW_FORM_ref4: 550 case DW_FORM_ref8: 551 case DW_FORM_ref_udata: 552 return value + base_offset; 553 554 case DW_FORM_ref_addr: 555 case DW_FORM_ref_sig8: 556 case DW_FORM_GNU_ref_alt: 557 return value; 558 559 default: 560 return DW_INVALID_OFFSET; 561 } 562 } 563 564 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; } 565 566 bool DWARFFormValue::IsBlockForm(const dw_form_t form) { 567 switch (form) { 568 case DW_FORM_exprloc: 569 case DW_FORM_block: 570 case DW_FORM_block1: 571 case DW_FORM_block2: 572 case DW_FORM_block4: 573 return true; 574 } 575 return false; 576 } 577 578 bool DWARFFormValue::IsDataForm(const dw_form_t form) { 579 switch (form) { 580 case DW_FORM_sdata: 581 case DW_FORM_udata: 582 case DW_FORM_data1: 583 case DW_FORM_data2: 584 case DW_FORM_data4: 585 case DW_FORM_data8: 586 return true; 587 } 588 return false; 589 } 590 591 bool DWARFFormValue::FormIsSupported(dw_form_t form) { 592 switch (form) { 593 case DW_FORM_addr: 594 case DW_FORM_addrx: 595 case DW_FORM_loclistx: 596 case DW_FORM_rnglistx: 597 case DW_FORM_block2: 598 case DW_FORM_block4: 599 case DW_FORM_data2: 600 case DW_FORM_data4: 601 case DW_FORM_data8: 602 case DW_FORM_string: 603 case DW_FORM_block: 604 case DW_FORM_block1: 605 case DW_FORM_data1: 606 case DW_FORM_flag: 607 case DW_FORM_sdata: 608 case DW_FORM_strp: 609 case DW_FORM_strx: 610 case DW_FORM_strx1: 611 case DW_FORM_strx2: 612 case DW_FORM_strx3: 613 case DW_FORM_strx4: 614 case DW_FORM_udata: 615 case DW_FORM_ref_addr: 616 case DW_FORM_ref1: 617 case DW_FORM_ref2: 618 case DW_FORM_ref4: 619 case DW_FORM_ref8: 620 case DW_FORM_ref_udata: 621 case DW_FORM_indirect: 622 case DW_FORM_sec_offset: 623 case DW_FORM_exprloc: 624 case DW_FORM_flag_present: 625 case DW_FORM_ref_sig8: 626 case DW_FORM_GNU_str_index: 627 case DW_FORM_GNU_addr_index: 628 case DW_FORM_implicit_const: 629 return true; 630 default: 631 break; 632 } 633 return false; 634 } 635