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 <climits> 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 < ArrayRef<FormClass>(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 if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) && 131 FC == FC_SectionOffset) 132 return true; 133 return false; 134 } 135 136 bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, 137 const DWARFUnit *cu) { 138 bool indirect = false; 139 bool is_block = false; 140 Value.data = nullptr; 141 // Read the value for the form into value and follow and DW_FORM_indirect 142 // instances we run into 143 do { 144 indirect = false; 145 switch (Form) { 146 case DW_FORM_addr: 147 case DW_FORM_ref_addr: { 148 if (!cu) 149 return false; 150 uint16_t AddrSize = 151 (Form == DW_FORM_addr) 152 ? cu->getAddressByteSize() 153 : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 154 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); 155 if (AI != cu->getRelocMap()->end()) { 156 const std::pair<uint8_t, int64_t> &R = AI->second; 157 Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second; 158 } else 159 Value.uval = data.getUnsigned(offset_ptr, AddrSize); 160 break; 161 } 162 case DW_FORM_exprloc: 163 case DW_FORM_block: 164 Value.uval = data.getULEB128(offset_ptr); 165 is_block = true; 166 break; 167 case DW_FORM_block1: 168 Value.uval = data.getU8(offset_ptr); 169 is_block = true; 170 break; 171 case DW_FORM_block2: 172 Value.uval = data.getU16(offset_ptr); 173 is_block = true; 174 break; 175 case DW_FORM_block4: 176 Value.uval = data.getU32(offset_ptr); 177 is_block = true; 178 break; 179 case DW_FORM_data1: 180 case DW_FORM_ref1: 181 case DW_FORM_flag: 182 Value.uval = data.getU8(offset_ptr); 183 break; 184 case DW_FORM_data2: 185 case DW_FORM_ref2: 186 Value.uval = data.getU16(offset_ptr); 187 break; 188 case DW_FORM_data4: 189 case DW_FORM_ref4: { 190 Value.uval = data.getU32(offset_ptr); 191 if (!cu) 192 break; 193 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); 194 if (AI != cu->getRelocMap()->end()) 195 Value.uval += AI->second.second; 196 break; 197 } 198 case DW_FORM_data8: 199 case DW_FORM_ref8: 200 Value.uval = data.getU64(offset_ptr); 201 break; 202 case DW_FORM_sdata: 203 Value.sval = data.getSLEB128(offset_ptr); 204 break; 205 case DW_FORM_udata: 206 case DW_FORM_ref_udata: 207 Value.uval = data.getULEB128(offset_ptr); 208 break; 209 case DW_FORM_string: 210 Value.cstr = data.getCStr(offset_ptr); 211 break; 212 case DW_FORM_indirect: 213 Form = data.getULEB128(offset_ptr); 214 indirect = true; 215 break; 216 case DW_FORM_sec_offset: 217 case DW_FORM_strp: 218 case DW_FORM_GNU_ref_alt: 219 case DW_FORM_GNU_strp_alt: { 220 // FIXME: This is 64-bit for DWARF64. 221 Value.uval = data.getU32(offset_ptr); 222 if (!cu) 223 break; 224 RelocAddrMap::const_iterator AI = 225 cu->getRelocMap()->find(*offset_ptr - 4); 226 if (AI != cu->getRelocMap()->end()) 227 Value.uval += AI->second.second; 228 break; 229 } 230 case DW_FORM_flag_present: 231 Value.uval = 1; 232 break; 233 case DW_FORM_ref_sig8: 234 Value.uval = data.getU64(offset_ptr); 235 break; 236 case DW_FORM_GNU_addr_index: 237 case DW_FORM_GNU_str_index: 238 Value.uval = data.getULEB128(offset_ptr); 239 break; 240 default: 241 return false; 242 } 243 } while (indirect); 244 245 if (is_block) { 246 StringRef str = data.getData().substr(*offset_ptr, Value.uval); 247 Value.data = nullptr; 248 if (!str.empty()) { 249 Value.data = reinterpret_cast<const uint8_t *>(str.data()); 250 *offset_ptr += Value.uval; 251 } 252 } 253 254 return true; 255 } 256 257 bool 258 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, 259 const DWARFUnit *cu) const { 260 return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); 261 } 262 263 bool 264 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 265 uint32_t *offset_ptr, const DWARFUnit *cu) { 266 bool indirect = false; 267 do { 268 switch (form) { 269 // Blocks if inlined data that have a length field and the data bytes 270 // inlined in the .debug_info 271 case DW_FORM_exprloc: 272 case DW_FORM_block: { 273 uint64_t size = debug_info_data.getULEB128(offset_ptr); 274 *offset_ptr += size; 275 return true; 276 } 277 case DW_FORM_block1: { 278 uint8_t size = debug_info_data.getU8(offset_ptr); 279 *offset_ptr += size; 280 return true; 281 } 282 case DW_FORM_block2: { 283 uint16_t size = debug_info_data.getU16(offset_ptr); 284 *offset_ptr += size; 285 return true; 286 } 287 case DW_FORM_block4: { 288 uint32_t size = debug_info_data.getU32(offset_ptr); 289 *offset_ptr += size; 290 return true; 291 } 292 293 // Inlined NULL terminated C-strings 294 case DW_FORM_string: 295 debug_info_data.getCStr(offset_ptr); 296 return true; 297 298 // Compile unit address sized values 299 case DW_FORM_addr: 300 *offset_ptr += cu->getAddressByteSize(); 301 return true; 302 case DW_FORM_ref_addr: 303 *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 304 return true; 305 306 // 0 byte values - implied from the form. 307 case DW_FORM_flag_present: 308 return true; 309 310 // 1 byte values 311 case DW_FORM_data1: 312 case DW_FORM_flag: 313 case DW_FORM_ref1: 314 *offset_ptr += 1; 315 return true; 316 317 // 2 byte values 318 case DW_FORM_data2: 319 case DW_FORM_ref2: 320 *offset_ptr += 2; 321 return true; 322 323 // 4 byte values 324 case DW_FORM_data4: 325 case DW_FORM_ref4: 326 *offset_ptr += 4; 327 return true; 328 329 // 8 byte values 330 case DW_FORM_data8: 331 case DW_FORM_ref8: 332 case DW_FORM_ref_sig8: 333 *offset_ptr += 8; 334 return true; 335 336 // signed or unsigned LEB 128 values 337 // case DW_FORM_APPLE_db_str: 338 case DW_FORM_sdata: 339 case DW_FORM_udata: 340 case DW_FORM_ref_udata: 341 case DW_FORM_GNU_str_index: 342 case DW_FORM_GNU_addr_index: 343 debug_info_data.getULEB128(offset_ptr); 344 return true; 345 346 case DW_FORM_indirect: 347 indirect = true; 348 form = debug_info_data.getULEB128(offset_ptr); 349 break; 350 351 // FIXME: 4 for DWARF32, 8 for DWARF64. 352 case DW_FORM_sec_offset: 353 case DW_FORM_strp: 354 case DW_FORM_GNU_ref_alt: 355 case DW_FORM_GNU_strp_alt: 356 *offset_ptr += 4; 357 return true; 358 359 default: 360 return false; 361 } 362 } while (indirect); 363 return true; 364 } 365 366 void 367 DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { 368 uint64_t uvalue = Value.uval; 369 bool cu_relative_offset = false; 370 371 switch (Form) { 372 case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; 373 case DW_FORM_GNU_addr_index: { 374 OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); 375 uint64_t Address; 376 if (cu->getAddrOffsetSectionItem(uvalue, Address)) 377 OS << format("0x%016" PRIx64, Address); 378 else 379 OS << "<no .debug_addr section>"; 380 break; 381 } 382 case DW_FORM_flag_present: OS << "true"; break; 383 case DW_FORM_flag: 384 case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; 385 case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break; 386 case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break; 387 case DW_FORM_ref_sig8: 388 case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break; 389 case DW_FORM_string: 390 OS << '"'; 391 OS.write_escaped(Value.cstr); 392 OS << '"'; 393 break; 394 case DW_FORM_exprloc: 395 case DW_FORM_block: 396 case DW_FORM_block1: 397 case DW_FORM_block2: 398 case DW_FORM_block4: 399 if (uvalue > 0) { 400 switch (Form) { 401 case DW_FORM_exprloc: 402 case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break; 403 case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; 404 case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; 405 case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; 406 default: break; 407 } 408 409 const uint8_t* data_ptr = Value.data; 410 if (data_ptr) { 411 // uvalue contains size of block 412 const uint8_t* end_data_ptr = data_ptr + uvalue; 413 while (data_ptr < end_data_ptr) { 414 OS << format("%2.2x ", *data_ptr); 415 ++data_ptr; 416 } 417 } 418 else 419 OS << "NULL"; 420 } 421 break; 422 423 case DW_FORM_sdata: OS << Value.sval; break; 424 case DW_FORM_udata: OS << Value.uval; break; 425 case DW_FORM_strp: { 426 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 427 dumpString(OS, cu); 428 break; 429 } 430 case DW_FORM_GNU_str_index: { 431 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); 432 dumpString(OS, cu); 433 break; 434 } 435 case DW_FORM_GNU_strp_alt: { 436 OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue); 437 dumpString(OS, cu); 438 break; 439 } 440 case DW_FORM_ref_addr: 441 OS << format("0x%016" PRIx64, uvalue); 442 break; 443 case DW_FORM_ref1: 444 cu_relative_offset = true; 445 OS << format("cu + 0x%2.2x", (uint8_t)uvalue); 446 break; 447 case DW_FORM_ref2: 448 cu_relative_offset = true; 449 OS << format("cu + 0x%4.4x", (uint16_t)uvalue); 450 break; 451 case DW_FORM_ref4: 452 cu_relative_offset = true; 453 OS << format("cu + 0x%4.4x", (uint32_t)uvalue); 454 break; 455 case DW_FORM_ref8: 456 cu_relative_offset = true; 457 OS << format("cu + 0x%8.8" PRIx64, uvalue); 458 break; 459 case DW_FORM_ref_udata: 460 cu_relative_offset = true; 461 OS << format("cu + 0x%" PRIx64, uvalue); 462 break; 463 case DW_FORM_GNU_ref_alt: 464 OS << format("<alt 0x%" PRIx64 ">", uvalue); 465 break; 466 467 // All DW_FORM_indirect attributes should be resolved prior to calling 468 // this function 469 case DW_FORM_indirect: 470 OS << "DW_FORM_indirect"; 471 break; 472 473 // Should be formatted to 64-bit for DWARF64. 474 case DW_FORM_sec_offset: 475 OS << format("0x%08x", (uint32_t)uvalue); 476 break; 477 478 default: 479 OS << format("DW_FORM(0x%4.4x)", Form); 480 break; 481 } 482 483 if (cu_relative_offset) { 484 OS << " => {"; 485 WithColor(OS, syntax::Address).get() 486 << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0)); 487 OS << "}"; 488 } 489 } 490 491 void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const { 492 Optional<const char *> DbgStr = getAsCString(U); 493 if (DbgStr.hasValue()) { 494 raw_ostream &COS = WithColor(OS, syntax::String); 495 COS << '"'; 496 COS.write_escaped(DbgStr.getValue()); 497 COS << '"'; 498 } 499 } 500 501 Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { 502 if (!isFormClass(FC_String)) 503 return None; 504 if (Form == DW_FORM_string) 505 return Value.cstr; 506 // FIXME: Add support for DW_FORM_GNU_strp_alt 507 if (Form == DW_FORM_GNU_strp_alt || U == nullptr) 508 return None; 509 uint32_t Offset = Value.uval; 510 if (Form == DW_FORM_GNU_str_index) { 511 uint32_t StrOffset; 512 if (!U->getStringOffsetSectionItem(Offset, StrOffset)) 513 return None; 514 Offset = StrOffset; 515 } 516 if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { 517 return Str; 518 } 519 return None; 520 } 521 522 Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { 523 if (!isFormClass(FC_Address)) 524 return None; 525 if (Form == DW_FORM_GNU_addr_index) { 526 uint32_t Index = Value.uval; 527 uint64_t Result; 528 if (!U || !U->getAddrOffsetSectionItem(Index, Result)) 529 return None; 530 return Result; 531 } 532 return Value.uval; 533 } 534 535 Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { 536 if (!isFormClass(FC_Reference)) 537 return None; 538 switch (Form) { 539 case DW_FORM_ref1: 540 case DW_FORM_ref2: 541 case DW_FORM_ref4: 542 case DW_FORM_ref8: 543 case DW_FORM_ref_udata: 544 if (!U) 545 return None; 546 return Value.uval + U->getOffset(); 547 case DW_FORM_ref_addr: 548 return Value.uval; 549 // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt. 550 default: 551 return None; 552 } 553 } 554 555 Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { 556 if (!isFormClass(FC_SectionOffset)) 557 return None; 558 return Value.uval; 559 } 560 561 Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { 562 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) 563 || Form == DW_FORM_sdata) 564 return None; 565 return Value.uval; 566 } 567 568 Optional<int64_t> DWARFFormValue::getAsSignedConstant() const { 569 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || 570 (Form == DW_FORM_udata && uint64_t(LLONG_MAX) < Value.uval)) 571 return None; 572 switch (Form) { 573 case DW_FORM_data4: 574 return int32_t(Value.uval); 575 case DW_FORM_data2: 576 return int16_t(Value.uval); 577 case DW_FORM_data1: 578 return int8_t(Value.uval); 579 case DW_FORM_sdata: 580 case DW_FORM_data8: 581 default: 582 return Value.sval; 583 } 584 } 585 586 Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { 587 if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) 588 return None; 589 return ArrayRef<uint8_t>(Value.data, Value.uval); 590 } 591 592