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