1 //===-- DWARFFormValue.cpp ------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "SyntaxHighlighting.h" 11 #include "llvm/ADT/ArrayRef.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 14 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/Dwarf.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <cassert> 21 #include <limits> 22 using namespace llvm; 23 using namespace dwarf; 24 using namespace syntax; 25 26 namespace { 27 uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { 28 // FIXME: Support DWARF64. 29 return (Version == 2) ? AddrSize : 4; 30 } 31 32 template <uint8_t AddrSize, uint8_t RefAddrSize> 33 ArrayRef<uint8_t> makeFixedFormSizesArrayRef() { 34 static const uint8_t sizes[] = { 35 0, // 0x00 unused 36 AddrSize, // 0x01 DW_FORM_addr 37 0, // 0x02 unused 38 0, // 0x03 DW_FORM_block2 39 0, // 0x04 DW_FORM_block4 40 2, // 0x05 DW_FORM_data2 41 4, // 0x06 DW_FORM_data4 42 8, // 0x07 DW_FORM_data8 43 0, // 0x08 DW_FORM_string 44 0, // 0x09 DW_FORM_block 45 0, // 0x0a DW_FORM_block1 46 1, // 0x0b DW_FORM_data1 47 1, // 0x0c DW_FORM_flag 48 0, // 0x0d DW_FORM_sdata 49 4, // 0x0e DW_FORM_strp 50 0, // 0x0f DW_FORM_udata 51 RefAddrSize, // 0x10 DW_FORM_ref_addr 52 1, // 0x11 DW_FORM_ref1 53 2, // 0x12 DW_FORM_ref2 54 4, // 0x13 DW_FORM_ref4 55 8, // 0x14 DW_FORM_ref8 56 0, // 0x15 DW_FORM_ref_udata 57 0, // 0x16 DW_FORM_indirect 58 4, // 0x17 DW_FORM_sec_offset 59 0, // 0x18 DW_FORM_exprloc 60 0, // 0x19 DW_FORM_flag_present 61 }; 62 return makeArrayRef(sizes); 63 } 64 } 65 66 ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, 67 uint16_t Version) { 68 uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version); 69 if (AddrSize == 4 && RefAddrSize == 4) 70 return makeFixedFormSizesArrayRef<4, 4>(); 71 if (AddrSize == 4 && RefAddrSize == 8) 72 return makeFixedFormSizesArrayRef<4, 8>(); 73 if (AddrSize == 8 && RefAddrSize == 4) 74 return makeFixedFormSizesArrayRef<8, 4>(); 75 if (AddrSize == 8 && RefAddrSize == 8) 76 return makeFixedFormSizesArrayRef<8, 8>(); 77 return None; 78 } 79 80 static const DWARFFormValue::FormClass DWARF4FormClasses[] = { 81 DWARFFormValue::FC_Unknown, // 0x0 82 DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr 83 DWARFFormValue::FC_Unknown, // 0x02 unused 84 DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2 85 DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4 86 DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2 87 // --- These can be FC_SectionOffset in DWARF3 and below: 88 DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4 89 DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8 90 // --- 91 DWARFFormValue::FC_String, // 0x08 DW_FORM_string 92 DWARFFormValue::FC_Block, // 0x09 DW_FORM_block 93 DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1 94 DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1 95 DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag 96 DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata 97 DWARFFormValue::FC_String, // 0x0e DW_FORM_strp 98 DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata 99 DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr 100 DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1 101 DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2 102 DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4 103 DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8 104 DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata 105 DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect 106 DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset 107 DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc 108 DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present 109 }; 110 111 bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { 112 // First, check DWARF4 form classes. 113 if (Form < makeArrayRef(DWARF4FormClasses).size() && 114 DWARF4FormClasses[Form] == FC) 115 return true; 116 // Check more forms from DWARF4 and DWARF5 proposals. 117 switch (Form) { 118 case DW_FORM_ref_sig8: 119 case DW_FORM_GNU_ref_alt: 120 return (FC == FC_Reference); 121 case DW_FORM_GNU_addr_index: 122 return (FC == FC_Address); 123 case DW_FORM_GNU_str_index: 124 case DW_FORM_GNU_strp_alt: 125 return (FC == FC_String); 126 } 127 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. 128 // Don't check for DWARF version here, as some producers may still do this 129 // by mistake. 130 return (Form == DW_FORM_data4 || Form == DW_FORM_data8) && 131 FC == FC_SectionOffset; 132 } 133 134 bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, 135 const DWARFUnit *cu) { 136 bool indirect = false; 137 bool is_block = false; 138 Value.data = nullptr; 139 // Read the value for the form into value and follow and DW_FORM_indirect 140 // instances we run into 141 do { 142 indirect = false; 143 switch (Form) { 144 case DW_FORM_addr: 145 case DW_FORM_ref_addr: { 146 if (!cu) 147 return false; 148 uint16_t AddrSize = 149 (Form == DW_FORM_addr) 150 ? cu->getAddressByteSize() 151 : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 152 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); 153 if (AI != cu->getRelocMap()->end()) { 154 const std::pair<uint8_t, int64_t> &R = AI->second; 155 Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second; 156 } else 157 Value.uval = data.getUnsigned(offset_ptr, AddrSize); 158 break; 159 } 160 case DW_FORM_exprloc: 161 case DW_FORM_block: 162 Value.uval = data.getULEB128(offset_ptr); 163 is_block = true; 164 break; 165 case DW_FORM_block1: 166 Value.uval = data.getU8(offset_ptr); 167 is_block = true; 168 break; 169 case DW_FORM_block2: 170 Value.uval = data.getU16(offset_ptr); 171 is_block = true; 172 break; 173 case DW_FORM_block4: 174 Value.uval = data.getU32(offset_ptr); 175 is_block = true; 176 break; 177 case DW_FORM_data1: 178 case DW_FORM_ref1: 179 case DW_FORM_flag: 180 Value.uval = data.getU8(offset_ptr); 181 break; 182 case DW_FORM_data2: 183 case DW_FORM_ref2: 184 Value.uval = data.getU16(offset_ptr); 185 break; 186 case DW_FORM_data4: 187 case DW_FORM_ref4: { 188 Value.uval = data.getU32(offset_ptr); 189 if (!cu) 190 break; 191 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); 192 if (AI != cu->getRelocMap()->end()) 193 Value.uval += AI->second.second; 194 break; 195 } 196 case DW_FORM_data8: 197 case DW_FORM_ref8: 198 Value.uval = data.getU64(offset_ptr); 199 break; 200 case DW_FORM_sdata: 201 Value.sval = data.getSLEB128(offset_ptr); 202 break; 203 case DW_FORM_udata: 204 case DW_FORM_ref_udata: 205 Value.uval = data.getULEB128(offset_ptr); 206 break; 207 case DW_FORM_string: 208 Value.cstr = data.getCStr(offset_ptr); 209 break; 210 case DW_FORM_indirect: 211 Form = data.getULEB128(offset_ptr); 212 indirect = true; 213 break; 214 case DW_FORM_sec_offset: 215 case DW_FORM_strp: 216 case DW_FORM_GNU_ref_alt: 217 case DW_FORM_GNU_strp_alt: { 218 // FIXME: This is 64-bit for DWARF64. 219 Value.uval = data.getU32(offset_ptr); 220 if (!cu) 221 break; 222 RelocAddrMap::const_iterator AI = 223 cu->getRelocMap()->find(*offset_ptr - 4); 224 if (AI != cu->getRelocMap()->end()) 225 Value.uval += AI->second.second; 226 break; 227 } 228 case DW_FORM_flag_present: 229 Value.uval = 1; 230 break; 231 case DW_FORM_ref_sig8: 232 Value.uval = data.getU64(offset_ptr); 233 break; 234 case DW_FORM_GNU_addr_index: 235 case DW_FORM_GNU_str_index: 236 Value.uval = data.getULEB128(offset_ptr); 237 break; 238 default: 239 return false; 240 } 241 } while (indirect); 242 243 if (is_block) { 244 StringRef str = data.getData().substr(*offset_ptr, Value.uval); 245 Value.data = nullptr; 246 if (!str.empty()) { 247 Value.data = reinterpret_cast<const uint8_t *>(str.data()); 248 *offset_ptr += Value.uval; 249 } 250 } 251 252 return true; 253 } 254 255 bool 256 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, 257 const DWARFUnit *cu) const { 258 return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); 259 } 260 261 bool 262 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 263 uint32_t *offset_ptr, const DWARFUnit *cu) { 264 return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(), 265 cu->getAddressByteSize()); 266 } 267 bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 268 uint32_t *offset_ptr, uint16_t Version, 269 uint8_t AddrSize) { 270 bool indirect = false; 271 do { 272 switch (form) { 273 // Blocks if inlined data that have a length field and the data bytes 274 // inlined in the .debug_info 275 case DW_FORM_exprloc: 276 case DW_FORM_block: { 277 uint64_t size = debug_info_data.getULEB128(offset_ptr); 278 *offset_ptr += size; 279 return true; 280 } 281 case DW_FORM_block1: { 282 uint8_t size = debug_info_data.getU8(offset_ptr); 283 *offset_ptr += size; 284 return true; 285 } 286 case DW_FORM_block2: { 287 uint16_t size = debug_info_data.getU16(offset_ptr); 288 *offset_ptr += size; 289 return true; 290 } 291 case DW_FORM_block4: { 292 uint32_t size = debug_info_data.getU32(offset_ptr); 293 *offset_ptr += size; 294 return true; 295 } 296 297 // Inlined NULL terminated C-strings 298 case DW_FORM_string: 299 debug_info_data.getCStr(offset_ptr); 300 return true; 301 302 // Compile unit address sized values 303 case DW_FORM_addr: 304 *offset_ptr += AddrSize; 305 return true; 306 case DW_FORM_ref_addr: 307 *offset_ptr += getRefAddrSize(AddrSize, Version); 308 return true; 309 310 // 0 byte values - implied from the form. 311 case DW_FORM_flag_present: 312 return true; 313 314 // 1 byte values 315 case DW_FORM_data1: 316 case DW_FORM_flag: 317 case DW_FORM_ref1: 318 *offset_ptr += 1; 319 return true; 320 321 // 2 byte values 322 case DW_FORM_data2: 323 case DW_FORM_ref2: 324 *offset_ptr += 2; 325 return true; 326 327 // 4 byte values 328 case DW_FORM_data4: 329 case DW_FORM_ref4: 330 *offset_ptr += 4; 331 return true; 332 333 // 8 byte values 334 case DW_FORM_data8: 335 case DW_FORM_ref8: 336 case DW_FORM_ref_sig8: 337 *offset_ptr += 8; 338 return true; 339 340 // signed or unsigned LEB 128 values 341 // case DW_FORM_APPLE_db_str: 342 case DW_FORM_sdata: 343 case DW_FORM_udata: 344 case DW_FORM_ref_udata: 345 case DW_FORM_GNU_str_index: 346 case DW_FORM_GNU_addr_index: 347 debug_info_data.getULEB128(offset_ptr); 348 return true; 349 350 case DW_FORM_indirect: 351 indirect = true; 352 form = debug_info_data.getULEB128(offset_ptr); 353 break; 354 355 // FIXME: 4 for DWARF32, 8 for DWARF64. 356 case DW_FORM_sec_offset: 357 case DW_FORM_strp: 358 case DW_FORM_GNU_ref_alt: 359 case DW_FORM_GNU_strp_alt: 360 *offset_ptr += 4; 361 return true; 362 363 default: 364 return false; 365 } 366 } while (indirect); 367 return true; 368 } 369 370 void 371 DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { 372 uint64_t uvalue = Value.uval; 373 bool cu_relative_offset = false; 374 375 switch (Form) { 376 case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; 377 case DW_FORM_GNU_addr_index: { 378 OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); 379 uint64_t Address; 380 if (cu->getAddrOffsetSectionItem(uvalue, Address)) 381 OS << format("0x%016" PRIx64, Address); 382 else 383 OS << "<no .debug_addr section>"; 384 break; 385 } 386 case DW_FORM_flag_present: OS << "true"; break; 387 case DW_FORM_flag: 388 case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; 389 case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break; 390 case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break; 391 case DW_FORM_ref_sig8: 392 case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break; 393 case DW_FORM_string: 394 OS << '"'; 395 OS.write_escaped(Value.cstr); 396 OS << '"'; 397 break; 398 case DW_FORM_exprloc: 399 case DW_FORM_block: 400 case DW_FORM_block1: 401 case DW_FORM_block2: 402 case DW_FORM_block4: 403 if (uvalue > 0) { 404 switch (Form) { 405 case DW_FORM_exprloc: 406 case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break; 407 case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; 408 case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; 409 case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; 410 default: break; 411 } 412 413 const uint8_t* data_ptr = Value.data; 414 if (data_ptr) { 415 // uvalue contains size of block 416 const uint8_t* end_data_ptr = data_ptr + uvalue; 417 while (data_ptr < end_data_ptr) { 418 OS << format("%2.2x ", *data_ptr); 419 ++data_ptr; 420 } 421 } 422 else 423 OS << "NULL"; 424 } 425 break; 426 427 case DW_FORM_sdata: OS << Value.sval; break; 428 case DW_FORM_udata: OS << Value.uval; break; 429 case DW_FORM_strp: { 430 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 431 dumpString(OS, cu); 432 break; 433 } 434 case DW_FORM_GNU_str_index: { 435 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); 436 dumpString(OS, cu); 437 break; 438 } 439 case DW_FORM_GNU_strp_alt: { 440 OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue); 441 dumpString(OS, cu); 442 break; 443 } 444 case DW_FORM_ref_addr: 445 OS << format("0x%016" PRIx64, uvalue); 446 break; 447 case DW_FORM_ref1: 448 cu_relative_offset = true; 449 OS << format("cu + 0x%2.2x", (uint8_t)uvalue); 450 break; 451 case DW_FORM_ref2: 452 cu_relative_offset = true; 453 OS << format("cu + 0x%4.4x", (uint16_t)uvalue); 454 break; 455 case DW_FORM_ref4: 456 cu_relative_offset = true; 457 OS << format("cu + 0x%4.4x", (uint32_t)uvalue); 458 break; 459 case DW_FORM_ref8: 460 cu_relative_offset = true; 461 OS << format("cu + 0x%8.8" PRIx64, uvalue); 462 break; 463 case DW_FORM_ref_udata: 464 cu_relative_offset = true; 465 OS << format("cu + 0x%" PRIx64, uvalue); 466 break; 467 case DW_FORM_GNU_ref_alt: 468 OS << format("<alt 0x%" PRIx64 ">", uvalue); 469 break; 470 471 // All DW_FORM_indirect attributes should be resolved prior to calling 472 // this function 473 case DW_FORM_indirect: 474 OS << "DW_FORM_indirect"; 475 break; 476 477 // Should be formatted to 64-bit for DWARF64. 478 case DW_FORM_sec_offset: 479 OS << format("0x%08x", (uint32_t)uvalue); 480 break; 481 482 default: 483 OS << format("DW_FORM(0x%4.4x)", Form); 484 break; 485 } 486 487 if (cu_relative_offset) { 488 OS << " => {"; 489 WithColor(OS, syntax::Address).get() 490 << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0)); 491 OS << "}"; 492 } 493 } 494 495 void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const { 496 Optional<const char *> DbgStr = getAsCString(U); 497 if (DbgStr.hasValue()) { 498 raw_ostream &COS = WithColor(OS, syntax::String); 499 COS << '"'; 500 COS.write_escaped(DbgStr.getValue()); 501 COS << '"'; 502 } 503 } 504 505 Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { 506 if (!isFormClass(FC_String)) 507 return None; 508 if (Form == DW_FORM_string) 509 return Value.cstr; 510 // FIXME: Add support for DW_FORM_GNU_strp_alt 511 if (Form == DW_FORM_GNU_strp_alt || U == nullptr) 512 return None; 513 uint32_t Offset = Value.uval; 514 if (Form == DW_FORM_GNU_str_index) { 515 uint32_t StrOffset; 516 if (!U->getStringOffsetSectionItem(Offset, StrOffset)) 517 return None; 518 Offset = StrOffset; 519 } 520 if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { 521 return Str; 522 } 523 return None; 524 } 525 526 Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { 527 if (!isFormClass(FC_Address)) 528 return None; 529 if (Form == DW_FORM_GNU_addr_index) { 530 uint32_t Index = Value.uval; 531 uint64_t Result; 532 if (!U || !U->getAddrOffsetSectionItem(Index, Result)) 533 return None; 534 return Result; 535 } 536 return Value.uval; 537 } 538 539 Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { 540 if (!isFormClass(FC_Reference)) 541 return None; 542 switch (Form) { 543 case DW_FORM_ref1: 544 case DW_FORM_ref2: 545 case DW_FORM_ref4: 546 case DW_FORM_ref8: 547 case DW_FORM_ref_udata: 548 if (!U) 549 return None; 550 return Value.uval + U->getOffset(); 551 case DW_FORM_ref_addr: 552 return Value.uval; 553 // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt. 554 default: 555 return None; 556 } 557 } 558 559 Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { 560 if (!isFormClass(FC_SectionOffset)) 561 return None; 562 return Value.uval; 563 } 564 565 Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { 566 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) 567 || Form == DW_FORM_sdata) 568 return None; 569 return Value.uval; 570 } 571 572 Optional<int64_t> DWARFFormValue::getAsSignedConstant() const { 573 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || 574 (Form == DW_FORM_udata && uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval)) 575 return None; 576 switch (Form) { 577 case DW_FORM_data4: 578 return int32_t(Value.uval); 579 case DW_FORM_data2: 580 return int16_t(Value.uval); 581 case DW_FORM_data1: 582 return int8_t(Value.uval); 583 case DW_FORM_sdata: 584 case DW_FORM_data8: 585 default: 586 return Value.sval; 587 } 588 } 589 590 Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { 591 if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) 592 return None; 593 return makeArrayRef(Value.data, Value.uval); 594 } 595 596