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 "llvm/DebugInfo/DWARF/DWARFFormValue.h" 10 #include "llvm/ADT/ArrayRef.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/BinaryFormat/Dwarf.h" 13 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 14 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 15 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 16 #include "llvm/DebugInfo/DWARF/DWARFObject.h" 17 #include "llvm/DebugInfo/DWARF/DWARFSection.h" 18 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/Format.h" 21 #include "llvm/Support/WithColor.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cinttypes> 24 #include <cstdint> 25 #include <limits> 26 #include <optional> 27 28 using namespace llvm; 29 using namespace dwarf; 30 31 static const DWARFFormValue::FormClass DWARF5FormClasses[] = { 32 DWARFFormValue::FC_Unknown, // 0x0 33 DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr 34 DWARFFormValue::FC_Unknown, // 0x02 unused 35 DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2 36 DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4 37 DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2 38 // --- These can be FC_SectionOffset in DWARF3 and below: 39 DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4 40 DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8 41 // --- 42 DWARFFormValue::FC_String, // 0x08 DW_FORM_string 43 DWARFFormValue::FC_Block, // 0x09 DW_FORM_block 44 DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1 45 DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1 46 DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag 47 DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata 48 DWARFFormValue::FC_String, // 0x0e DW_FORM_strp 49 DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata 50 DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr 51 DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1 52 DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2 53 DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4 54 DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8 55 DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata 56 DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect 57 DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset 58 DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc 59 DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present 60 DWARFFormValue::FC_String, // 0x1a DW_FORM_strx 61 DWARFFormValue::FC_Address, // 0x1b DW_FORM_addrx 62 DWARFFormValue::FC_Reference, // 0x1c DW_FORM_ref_sup4 63 DWARFFormValue::FC_String, // 0x1d DW_FORM_strp_sup 64 DWARFFormValue::FC_Constant, // 0x1e DW_FORM_data16 65 DWARFFormValue::FC_String, // 0x1f DW_FORM_line_strp 66 DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig8 67 DWARFFormValue::FC_Constant, // 0x21 DW_FORM_implicit_const 68 DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx 69 DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx 70 DWARFFormValue::FC_Reference, // 0x24 DW_FORM_ref_sup8 71 DWARFFormValue::FC_String, // 0x25 DW_FORM_strx1 72 DWARFFormValue::FC_String, // 0x26 DW_FORM_strx2 73 DWARFFormValue::FC_String, // 0x27 DW_FORM_strx3 74 DWARFFormValue::FC_String, // 0x28 DW_FORM_strx4 75 DWARFFormValue::FC_Address, // 0x29 DW_FORM_addrx1 76 DWARFFormValue::FC_Address, // 0x2a DW_FORM_addrx2 77 DWARFFormValue::FC_Address, // 0x2b DW_FORM_addrx3 78 DWARFFormValue::FC_Address, // 0x2c DW_FORM_addrx4 79 DWARFFormValue::FC_Address, // 0x2001 DW_FORM_addrx_offset 80 }; 81 82 DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { 83 return DWARFFormValue(F, ValueType(V)); 84 } 85 86 DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) { 87 return DWARFFormValue(F, ValueType(V)); 88 } 89 90 DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) { 91 return DWARFFormValue(F, ValueType(V)); 92 } 93 94 DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, 95 ArrayRef<uint8_t> D) { 96 ValueType V; 97 V.uval = D.size(); 98 V.data = D.data(); 99 return DWARFFormValue(F, V); 100 } 101 102 DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, 103 uint64_t *OffsetPtr) { 104 DWARFFormValue FormValue(F); 105 FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, 106 U->getFormParams(), U); 107 return FormValue; 108 } 109 110 bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, 111 uint64_t *OffsetPtr, 112 const dwarf::FormParams Params) { 113 bool Indirect = false; 114 do { 115 switch (Form) { 116 // Blocks of inlined data that have a length field and the data bytes 117 // inlined in the .debug_info. 118 case DW_FORM_exprloc: 119 case DW_FORM_block: { 120 uint64_t size = DebugInfoData.getULEB128(OffsetPtr); 121 *OffsetPtr += size; 122 return true; 123 } 124 case DW_FORM_block1: { 125 uint8_t size = DebugInfoData.getU8(OffsetPtr); 126 *OffsetPtr += size; 127 return true; 128 } 129 case DW_FORM_block2: { 130 uint16_t size = DebugInfoData.getU16(OffsetPtr); 131 *OffsetPtr += size; 132 return true; 133 } 134 case DW_FORM_block4: { 135 uint32_t size = DebugInfoData.getU32(OffsetPtr); 136 *OffsetPtr += size; 137 return true; 138 } 139 140 // Inlined NULL terminated C-strings. 141 case DW_FORM_string: 142 DebugInfoData.getCStr(OffsetPtr); 143 return true; 144 145 case DW_FORM_addr: 146 case DW_FORM_ref_addr: 147 case DW_FORM_flag_present: 148 case DW_FORM_data1: 149 case DW_FORM_data2: 150 case DW_FORM_data4: 151 case DW_FORM_data8: 152 case DW_FORM_data16: 153 case DW_FORM_flag: 154 case DW_FORM_ref1: 155 case DW_FORM_ref2: 156 case DW_FORM_ref4: 157 case DW_FORM_ref8: 158 case DW_FORM_ref_sig8: 159 case DW_FORM_ref_sup4: 160 case DW_FORM_ref_sup8: 161 case DW_FORM_strx1: 162 case DW_FORM_strx2: 163 case DW_FORM_strx4: 164 case DW_FORM_addrx1: 165 case DW_FORM_addrx2: 166 case DW_FORM_addrx4: 167 case DW_FORM_sec_offset: 168 case DW_FORM_strp: 169 case DW_FORM_strp_sup: 170 case DW_FORM_line_strp: 171 case DW_FORM_GNU_ref_alt: 172 case DW_FORM_GNU_strp_alt: 173 case DW_FORM_implicit_const: 174 if (std::optional<uint8_t> FixedSize = 175 dwarf::getFixedFormByteSize(Form, Params)) { 176 *OffsetPtr += *FixedSize; 177 return true; 178 } 179 return false; 180 181 // signed or unsigned LEB 128 values. 182 case DW_FORM_sdata: 183 DebugInfoData.getSLEB128(OffsetPtr); 184 return true; 185 186 case DW_FORM_udata: 187 case DW_FORM_ref_udata: 188 case DW_FORM_strx: 189 case DW_FORM_addrx: 190 case DW_FORM_loclistx: 191 case DW_FORM_rnglistx: 192 case DW_FORM_GNU_addr_index: 193 case DW_FORM_GNU_str_index: 194 DebugInfoData.getULEB128(OffsetPtr); 195 return true; 196 197 case DW_FORM_LLVM_addrx_offset: 198 DebugInfoData.getULEB128(OffsetPtr); 199 *OffsetPtr += 4; 200 return true; 201 202 case DW_FORM_indirect: 203 Indirect = true; 204 Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr)); 205 break; 206 207 default: 208 return false; 209 } 210 } while (Indirect); 211 return true; 212 } 213 214 bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { 215 // First, check DWARF5 form classes. 216 if (Form < ArrayRef(DWARF5FormClasses).size() && 217 DWARF5FormClasses[Form] == FC) 218 return true; 219 // Check more forms from extensions and proposals. 220 switch (Form) { 221 case DW_FORM_GNU_ref_alt: 222 return (FC == FC_Reference); 223 case DW_FORM_GNU_addr_index: 224 return (FC == FC_Address); 225 case DW_FORM_GNU_str_index: 226 case DW_FORM_GNU_strp_alt: 227 return (FC == FC_String); 228 case DW_FORM_LLVM_addrx_offset: 229 return (FC == FC_Address); 230 default: 231 break; 232 } 233 234 if (FC == FC_SectionOffset) { 235 if (Form == DW_FORM_strp || Form == DW_FORM_line_strp) 236 return true; 237 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section 238 // offset. If we don't have a DWARFUnit, default to the old behavior. 239 if (Form == DW_FORM_data4 || Form == DW_FORM_data8) 240 return !U || U->getVersion() <= 3; 241 } 242 243 return false; 244 } 245 246 bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, 247 uint64_t *OffsetPtr, dwarf::FormParams FP, 248 const DWARFContext *Ctx, 249 const DWARFUnit *CU) { 250 if (!Ctx && CU) 251 Ctx = &CU->getContext(); 252 C = Ctx; 253 U = CU; 254 Format = FP.Format; 255 bool Indirect = false; 256 bool IsBlock = false; 257 Value.data = nullptr; 258 // Read the value for the form into value and follow and DW_FORM_indirect 259 // instances we run into 260 Error Err = Error::success(); 261 do { 262 Indirect = false; 263 switch (Form) { 264 case DW_FORM_addr: 265 case DW_FORM_ref_addr: { 266 uint16_t Size = 267 (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize(); 268 Value.uval = 269 Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err); 270 break; 271 } 272 case DW_FORM_exprloc: 273 case DW_FORM_block: 274 Value.uval = Data.getULEB128(OffsetPtr, &Err); 275 IsBlock = true; 276 break; 277 case DW_FORM_block1: 278 Value.uval = Data.getU8(OffsetPtr, &Err); 279 IsBlock = true; 280 break; 281 case DW_FORM_block2: 282 Value.uval = Data.getU16(OffsetPtr, &Err); 283 IsBlock = true; 284 break; 285 case DW_FORM_block4: 286 Value.uval = Data.getU32(OffsetPtr, &Err); 287 IsBlock = true; 288 break; 289 case DW_FORM_data1: 290 case DW_FORM_ref1: 291 case DW_FORM_flag: 292 case DW_FORM_strx1: 293 case DW_FORM_addrx1: 294 Value.uval = Data.getU8(OffsetPtr, &Err); 295 break; 296 case DW_FORM_data2: 297 case DW_FORM_ref2: 298 case DW_FORM_strx2: 299 case DW_FORM_addrx2: 300 Value.uval = Data.getU16(OffsetPtr, &Err); 301 break; 302 case DW_FORM_strx3: 303 Value.uval = Data.getU24(OffsetPtr, &Err); 304 break; 305 case DW_FORM_data4: 306 case DW_FORM_ref4: 307 case DW_FORM_ref_sup4: 308 case DW_FORM_strx4: 309 case DW_FORM_addrx4: 310 Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err); 311 break; 312 case DW_FORM_data8: 313 case DW_FORM_ref8: 314 case DW_FORM_ref_sup8: 315 Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err); 316 break; 317 case DW_FORM_data16: 318 // Treat this like a 16-byte block. 319 Value.uval = 16; 320 IsBlock = true; 321 break; 322 case DW_FORM_sdata: 323 Value.sval = Data.getSLEB128(OffsetPtr, &Err); 324 break; 325 case DW_FORM_udata: 326 case DW_FORM_ref_udata: 327 case DW_FORM_rnglistx: 328 case DW_FORM_loclistx: 329 case DW_FORM_GNU_addr_index: 330 case DW_FORM_GNU_str_index: 331 case DW_FORM_addrx: 332 case DW_FORM_strx: 333 Value.uval = Data.getULEB128(OffsetPtr, &Err); 334 break; 335 case DW_FORM_LLVM_addrx_offset: 336 Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32; 337 Value.uval |= Data.getU32(OffsetPtr, &Err); 338 break; 339 case DW_FORM_string: 340 Value.cstr = Data.getCStr(OffsetPtr, &Err); 341 break; 342 case DW_FORM_indirect: 343 Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err)); 344 Indirect = true; 345 break; 346 case DW_FORM_strp: 347 case DW_FORM_sec_offset: 348 case DW_FORM_GNU_ref_alt: 349 case DW_FORM_GNU_strp_alt: 350 case DW_FORM_line_strp: 351 case DW_FORM_strp_sup: { 352 Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), 353 OffsetPtr, nullptr, &Err); 354 break; 355 } 356 case DW_FORM_flag_present: 357 Value.uval = 1; 358 break; 359 case DW_FORM_ref_sig8: 360 Value.uval = Data.getU64(OffsetPtr, &Err); 361 break; 362 case DW_FORM_implicit_const: 363 // Value has been already set by DWARFFormValue::createFromSValue. 364 break; 365 default: 366 // DWARFFormValue::skipValue() will have caught this and caused all 367 // DWARF DIEs to fail to be parsed, so this code is not be reachable. 368 llvm_unreachable("unsupported form"); 369 } 370 } while (Indirect && !Err); 371 372 if (IsBlock) 373 Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin(); 374 375 return !errorToBool(std::move(Err)); 376 } 377 378 void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize, 379 uint64_t Address) { 380 uint8_t HexDigits = AddressSize * 2; 381 OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address); 382 } 383 384 void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, 385 DIDumpOptions DumpOpts, 386 object::SectionedAddress SA) const { 387 dumpAddress(OS, U->getAddressByteSize(), SA.Address); 388 dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, 389 SA.SectionIndex); 390 } 391 392 void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, 393 DIDumpOptions DumpOpts, 394 uint64_t SectionIndex) { 395 if (!DumpOpts.Verbose || SectionIndex == -1ULL) 396 return; 397 ArrayRef<SectionName> SectionNames = Obj.getSectionNames(); 398 const auto &SecRef = SectionNames[SectionIndex]; 399 400 OS << " \"" << SecRef.Name << '\"'; 401 402 // Print section index if name is not unique. 403 if (!SecRef.IsNameUnique) 404 OS << format(" [%" PRIu64 "]", SectionIndex); 405 } 406 407 void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { 408 uint64_t UValue = Value.uval; 409 bool CURelativeOffset = false; 410 raw_ostream &AddrOS = DumpOpts.ShowAddresses 411 ? WithColor(OS, HighlightColor::Address).get() 412 : nulls(); 413 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format); 414 switch (Form) { 415 case DW_FORM_addr: 416 dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex}); 417 break; 418 case DW_FORM_addrx: 419 case DW_FORM_addrx1: 420 case DW_FORM_addrx2: 421 case DW_FORM_addrx3: 422 case DW_FORM_addrx4: 423 case DW_FORM_GNU_addr_index: { 424 if (U == nullptr) { 425 OS << "<invalid dwarf unit>"; 426 break; 427 } 428 std::optional<object::SectionedAddress> A = 429 U->getAddrOffsetSectionItem(UValue); 430 if (!A || DumpOpts.Verbose) 431 AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); 432 if (A) 433 dumpSectionedAddress(AddrOS, DumpOpts, *A); 434 else 435 OS << "<unresolved>"; 436 break; 437 } 438 case DW_FORM_LLVM_addrx_offset: { 439 if (U == nullptr) { 440 OS << "<invalid dwarf unit>"; 441 break; 442 } 443 uint32_t Index = UValue >> 32; 444 uint32_t Offset = UValue & 0xffffffff; 445 std::optional<object::SectionedAddress> A = 446 U->getAddrOffsetSectionItem(Index); 447 if (!A || DumpOpts.Verbose) 448 AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset); 449 if (A) { 450 A->Address += Offset; 451 dumpSectionedAddress(AddrOS, DumpOpts, *A); 452 } else 453 OS << "<unresolved>"; 454 break; 455 } 456 case DW_FORM_flag_present: 457 OS << "true"; 458 break; 459 case DW_FORM_flag: 460 case DW_FORM_data1: 461 OS << format("0x%02x", (uint8_t)UValue); 462 break; 463 case DW_FORM_data2: 464 OS << format("0x%04x", (uint16_t)UValue); 465 break; 466 case DW_FORM_data4: 467 OS << format("0x%08x", (uint32_t)UValue); 468 break; 469 case DW_FORM_ref_sig8: 470 AddrOS << format("0x%016" PRIx64, UValue); 471 break; 472 case DW_FORM_data8: 473 OS << format("0x%016" PRIx64, UValue); 474 break; 475 case DW_FORM_data16: 476 OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16); 477 break; 478 case DW_FORM_string: 479 OS << '"'; 480 OS.write_escaped(Value.cstr); 481 OS << '"'; 482 break; 483 case DW_FORM_exprloc: 484 case DW_FORM_block: 485 case DW_FORM_block1: 486 case DW_FORM_block2: 487 case DW_FORM_block4: 488 if (UValue > 0) { 489 switch (Form) { 490 case DW_FORM_exprloc: 491 case DW_FORM_block: 492 AddrOS << format("<0x%" PRIx64 "> ", UValue); 493 break; 494 case DW_FORM_block1: 495 AddrOS << format("<0x%2.2x> ", (uint8_t)UValue); 496 break; 497 case DW_FORM_block2: 498 AddrOS << format("<0x%4.4x> ", (uint16_t)UValue); 499 break; 500 case DW_FORM_block4: 501 AddrOS << format("<0x%8.8x> ", (uint32_t)UValue); 502 break; 503 default: 504 break; 505 } 506 507 const uint8_t *DataPtr = Value.data; 508 if (DataPtr) { 509 // UValue contains size of block 510 const uint8_t *EndDataPtr = DataPtr + UValue; 511 while (DataPtr < EndDataPtr) { 512 AddrOS << format("%2.2x ", *DataPtr); 513 ++DataPtr; 514 } 515 } else 516 OS << "NULL"; 517 } 518 break; 519 520 case DW_FORM_sdata: 521 case DW_FORM_implicit_const: 522 OS << Value.sval; 523 break; 524 case DW_FORM_udata: 525 OS << Value.uval; 526 break; 527 case DW_FORM_strp: 528 if (DumpOpts.Verbose) 529 OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue); 530 dumpString(OS); 531 break; 532 case DW_FORM_line_strp: 533 if (DumpOpts.Verbose) 534 OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, 535 UValue); 536 dumpString(OS); 537 break; 538 case DW_FORM_strx: 539 case DW_FORM_strx1: 540 case DW_FORM_strx2: 541 case DW_FORM_strx3: 542 case DW_FORM_strx4: 543 case DW_FORM_GNU_str_index: 544 if (DumpOpts.Verbose) 545 OS << format("indexed (%8.8x) string = ", (uint32_t)UValue); 546 dumpString(OS); 547 break; 548 case DW_FORM_GNU_strp_alt: 549 if (DumpOpts.Verbose) 550 OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue); 551 dumpString(OS); 552 break; 553 case DW_FORM_ref_addr: 554 AddrOS << format("0x%016" PRIx64, UValue); 555 break; 556 case DW_FORM_ref1: 557 CURelativeOffset = true; 558 if (DumpOpts.Verbose) 559 AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue); 560 break; 561 case DW_FORM_ref2: 562 CURelativeOffset = true; 563 if (DumpOpts.Verbose) 564 AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue); 565 break; 566 case DW_FORM_ref4: 567 CURelativeOffset = true; 568 if (DumpOpts.Verbose) 569 AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue); 570 break; 571 case DW_FORM_ref8: 572 CURelativeOffset = true; 573 if (DumpOpts.Verbose) 574 AddrOS << format("cu + 0x%8.8" PRIx64, UValue); 575 break; 576 case DW_FORM_ref_udata: 577 CURelativeOffset = true; 578 if (DumpOpts.Verbose) 579 AddrOS << format("cu + 0x%" PRIx64, UValue); 580 break; 581 case DW_FORM_GNU_ref_alt: 582 AddrOS << format("<alt 0x%" PRIx64 ">", UValue); 583 break; 584 585 // All DW_FORM_indirect attributes should be resolved prior to calling 586 // this function 587 case DW_FORM_indirect: 588 OS << "DW_FORM_indirect"; 589 break; 590 591 case DW_FORM_rnglistx: 592 OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue); 593 break; 594 595 case DW_FORM_loclistx: 596 OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue); 597 break; 598 599 case DW_FORM_sec_offset: 600 AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue); 601 break; 602 603 default: 604 OS << format("DW_FORM(0x%4.4x)", Form); 605 break; 606 } 607 608 if (CURelativeOffset) { 609 if (DumpOpts.Verbose) 610 OS << " => {"; 611 if (DumpOpts.ShowAddresses) 612 WithColor(OS, HighlightColor::Address).get() 613 << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0)); 614 if (DumpOpts.Verbose) 615 OS << "}"; 616 } 617 } 618 619 void DWARFFormValue::dumpString(raw_ostream &OS) const { 620 if (auto DbgStr = dwarf::toString(*this)) { 621 auto COS = WithColor(OS, HighlightColor::String); 622 COS.get() << '"'; 623 COS.get().write_escaped(*DbgStr); 624 COS.get() << '"'; 625 } 626 } 627 628 Expected<const char *> DWARFFormValue::getAsCString() const { 629 if (!isFormClass(FC_String)) 630 return make_error<StringError>("Invalid form for string attribute", 631 inconvertibleErrorCode()); 632 if (Form == DW_FORM_string) 633 return Value.cstr; 634 // FIXME: Add support for DW_FORM_GNU_strp_alt 635 if (Form == DW_FORM_GNU_strp_alt || C == nullptr) 636 return make_error<StringError>("Unsupported form for string attribute", 637 inconvertibleErrorCode()); 638 uint64_t Offset = Value.uval; 639 std::optional<uint32_t> Index; 640 if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx || 641 Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || 642 Form == DW_FORM_strx4) { 643 if (!U) 644 return make_error<StringError>("API limitation - string extraction not " 645 "available without a DWARFUnit", 646 inconvertibleErrorCode()); 647 Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset); 648 Index = Offset; 649 if (!StrOffset) 650 return StrOffset.takeError(); 651 Offset = *StrOffset; 652 } 653 // Prefer the Unit's string extractor, because for .dwo it will point to 654 // .debug_str.dwo, while the Context's extractor always uses .debug_str. 655 DataExtractor StrData = Form == DW_FORM_line_strp 656 ? C->getLineStringExtractor() 657 : U ? U->getStringExtractor() 658 : C->getStringExtractor(); 659 if (const char *Str = StrData.getCStr(&Offset)) 660 return Str; 661 std::string Msg = FormEncodingString(Form).str(); 662 if (Index) 663 Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str(); 664 Msg += (" offset " + Twine(Offset) + " is beyond .debug_str bounds").str(); 665 return make_error<StringError>(Msg, 666 inconvertibleErrorCode()); 667 } 668 669 std::optional<uint64_t> DWARFFormValue::getAsAddress() const { 670 if (auto SA = getAsSectionedAddress()) 671 return SA->Address; 672 return std::nullopt; 673 } 674 675 std::optional<object::SectionedAddress> 676 DWARFFormValue::getAsSectionedAddress() const { 677 if (!isFormClass(FC_Address)) 678 return std::nullopt; 679 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset; 680 if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx || AddrOffset) { 681 682 uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval; 683 if (!U) 684 return std::nullopt; 685 std::optional<object::SectionedAddress> SA = 686 U->getAddrOffsetSectionItem(Index); 687 if (!SA) 688 return std::nullopt; 689 if (AddrOffset) 690 SA->Address += (Value.uval & 0xffffffff); 691 return SA; 692 } 693 return {{Value.uval, Value.SectionIndex}}; 694 } 695 696 std::optional<uint64_t> DWARFFormValue::getAsReference() const { 697 if (auto R = getAsRelativeReference()) 698 return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset; 699 return std::nullopt; 700 } 701 702 std::optional<DWARFFormValue::UnitOffset> 703 DWARFFormValue::getAsRelativeReference() const { 704 if (!isFormClass(FC_Reference)) 705 return std::nullopt; 706 switch (Form) { 707 case DW_FORM_ref1: 708 case DW_FORM_ref2: 709 case DW_FORM_ref4: 710 case DW_FORM_ref8: 711 case DW_FORM_ref_udata: 712 if (!U) 713 return std::nullopt; 714 return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; 715 case DW_FORM_ref_addr: 716 case DW_FORM_ref_sig8: 717 case DW_FORM_GNU_ref_alt: 718 return UnitOffset{nullptr, Value.uval}; 719 default: 720 return std::nullopt; 721 } 722 } 723 724 std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { 725 if (!isFormClass(FC_SectionOffset)) 726 return std::nullopt; 727 return Value.uval; 728 } 729 730 std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { 731 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || 732 Form == DW_FORM_sdata) 733 return std::nullopt; 734 return Value.uval; 735 } 736 737 std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const { 738 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || 739 (Form == DW_FORM_udata && 740 uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval)) 741 return std::nullopt; 742 switch (Form) { 743 case DW_FORM_data4: 744 return int32_t(Value.uval); 745 case DW_FORM_data2: 746 return int16_t(Value.uval); 747 case DW_FORM_data1: 748 return int8_t(Value.uval); 749 case DW_FORM_sdata: 750 case DW_FORM_data8: 751 default: 752 return Value.sval; 753 } 754 } 755 756 std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { 757 if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) && 758 Form != DW_FORM_data16) 759 return std::nullopt; 760 return ArrayRef(Value.data, Value.uval); 761 } 762 763 std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const { 764 if (!isFormClass(FC_String) && Form == DW_FORM_string) 765 return std::nullopt; 766 return Value.uval; 767 } 768 769 std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const { 770 if (!isFormClass(FC_Reference)) 771 return std::nullopt; 772 return Value.uval; 773 } 774 775 std::optional<std::string> 776 DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { 777 if (U == nullptr || !isFormClass(FC_Constant)) 778 return std::nullopt; 779 DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit(); 780 if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) { 781 std::string FileName; 782 if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind, 783 FileName)) 784 return FileName; 785 } 786 return std::nullopt; 787 } 788