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> 22using namespace llvm; 23using namespace dwarf; 24using namespace syntax; 25 26namespace { 27uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { 28 // FIXME: Support DWARF64. 29 return (Version == 2) ? AddrSize : 4; 30} 31 32template <uint8_t AddrSize, uint8_t RefAddrSize> 33ArrayRef<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 66ArrayRef<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 80static 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 111bool 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 DW_FORM_ref_sig8 from DWARF4. 117 if (Form == DW_FORM_ref_sig8) 118 return (FC == FC_Reference); 119 // Check for some DWARF5 forms. 120 if (Form == DW_FORM_GNU_addr_index) 121 return (FC == FC_Address); 122 if (Form == DW_FORM_GNU_str_index) 123 return (FC == FC_String); 124 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. 125 // Don't check for DWARF version here, as some producers may still do this 126 // by mistake. 127 if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) && 128 FC == FC_SectionOffset) 129 return true; 130 return false; 131} 132 133bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, 134 const DWARFUnit *cu) { 135 bool indirect = false; 136 bool is_block = false; 137 Value.data = nullptr; 138 // Read the value for the form into value and follow and DW_FORM_indirect 139 // instances we run into 140 do { 141 indirect = false; 142 switch (Form) { 143 case DW_FORM_addr: 144 case DW_FORM_ref_addr: { 145 if (!cu) 146 return false; 147 uint16_t AddrSize = 148 (Form == DW_FORM_addr) 149 ? cu->getAddressByteSize() 150 : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 151 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); 152 if (AI != cu->getRelocMap()->end()) { 153 const std::pair<uint8_t, int64_t> &R = AI->second; 154 Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second; 155 } else 156 Value.uval = data.getUnsigned(offset_ptr, AddrSize); 157 break; 158 } 159 case DW_FORM_exprloc: 160 case DW_FORM_block: 161 Value.uval = data.getULEB128(offset_ptr); 162 is_block = true; 163 break; 164 case DW_FORM_block1: 165 Value.uval = data.getU8(offset_ptr); 166 is_block = true; 167 break; 168 case DW_FORM_block2: 169 Value.uval = data.getU16(offset_ptr); 170 is_block = true; 171 break; 172 case DW_FORM_block4: 173 Value.uval = data.getU32(offset_ptr); 174 is_block = true; 175 break; 176 case DW_FORM_data1: 177 case DW_FORM_ref1: 178 case DW_FORM_flag: 179 Value.uval = data.getU8(offset_ptr); 180 break; 181 case DW_FORM_data2: 182 case DW_FORM_ref2: 183 Value.uval = data.getU16(offset_ptr); 184 break; 185 case DW_FORM_data4: 186 case DW_FORM_ref4: { 187 Value.uval = data.getU32(offset_ptr); 188 if (!cu) 189 break; 190 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); 191 if (AI != cu->getRelocMap()->end()) 192 Value.uval += AI->second.second; 193 break; 194 } 195 case DW_FORM_data8: 196 case DW_FORM_ref8: 197 Value.uval = data.getU64(offset_ptr); 198 break; 199 case DW_FORM_sdata: 200 Value.sval = data.getSLEB128(offset_ptr); 201 break; 202 case DW_FORM_strp: { 203 Value.uval = data.getU32(offset_ptr); 204 if (!cu) 205 break; 206 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); 207 if (AI != cu->getRelocMap()->end()) 208 Value.uval += AI->second.second; 209 break; 210 } 211 case DW_FORM_udata: 212 case DW_FORM_ref_udata: 213 Value.uval = data.getULEB128(offset_ptr); 214 break; 215 case DW_FORM_string: 216 Value.cstr = data.getCStr(offset_ptr); 217 break; 218 case DW_FORM_indirect: 219 Form = data.getULEB128(offset_ptr); 220 indirect = true; 221 break; 222 case DW_FORM_sec_offset: { 223 // FIXME: This is 64-bit for DWARF64. 224 Value.uval = data.getU32(offset_ptr); 225 if (!cu) 226 break; 227 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); 228 if (AI != cu->getRelocMap()->end()) 229 Value.uval += AI->second.second; 230 break; 231 } 232 case DW_FORM_flag_present: 233 Value.uval = 1; 234 break; 235 case DW_FORM_ref_sig8: 236 Value.uval = data.getU64(offset_ptr); 237 break; 238 case DW_FORM_GNU_addr_index: 239 case DW_FORM_GNU_str_index: 240 Value.uval = data.getULEB128(offset_ptr); 241 break; 242 default: 243 return false; 244 } 245 } while (indirect); 246 247 if (is_block) { 248 StringRef str = data.getData().substr(*offset_ptr, Value.uval); 249 Value.data = nullptr; 250 if (!str.empty()) { 251 Value.data = reinterpret_cast<const uint8_t *>(str.data()); 252 *offset_ptr += Value.uval; 253 } 254 } 255 256 return true; 257} 258 259bool 260DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, 261 const DWARFUnit *cu) const { 262 return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); 263} 264 265bool 266DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 267 uint32_t *offset_ptr, const DWARFUnit *cu) { 268 bool indirect = false; 269 do { 270 switch (form) { 271 // Blocks if inlined data that have a length field and the data bytes 272 // inlined in the .debug_info 273 case DW_FORM_exprloc: 274 case DW_FORM_block: { 275 uint64_t size = debug_info_data.getULEB128(offset_ptr); 276 *offset_ptr += size; 277 return true; 278 } 279 case DW_FORM_block1: { 280 uint8_t size = debug_info_data.getU8(offset_ptr); 281 *offset_ptr += size; 282 return true; 283 } 284 case DW_FORM_block2: { 285 uint16_t size = debug_info_data.getU16(offset_ptr); 286 *offset_ptr += size; 287 return true; 288 } 289 case DW_FORM_block4: { 290 uint32_t size = debug_info_data.getU32(offset_ptr); 291 *offset_ptr += size; 292 return true; 293 } 294 295 // Inlined NULL terminated C-strings 296 case DW_FORM_string: 297 debug_info_data.getCStr(offset_ptr); 298 return true; 299 300 // Compile unit address sized values 301 case DW_FORM_addr: 302 *offset_ptr += cu->getAddressByteSize(); 303 return true; 304 case DW_FORM_ref_addr: 305 *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 306 return true; 307 308 // 0 byte values - implied from the form. 309 case DW_FORM_flag_present: 310 return true; 311 312 // 1 byte values 313 case DW_FORM_data1: 314 case DW_FORM_flag: 315 case DW_FORM_ref1: 316 *offset_ptr += 1; 317 return true; 318 319 // 2 byte values 320 case DW_FORM_data2: 321 case DW_FORM_ref2: 322 *offset_ptr += 2; 323 return true; 324 325 // 4 byte values 326 case DW_FORM_strp: 327 case DW_FORM_data4: 328 case DW_FORM_ref4: 329 *offset_ptr += 4; 330 return true; 331 332 // 8 byte values 333 case DW_FORM_data8: 334 case DW_FORM_ref8: 335 case DW_FORM_ref_sig8: 336 *offset_ptr += 8; 337 return true; 338 339 // signed or unsigned LEB 128 values 340 // case DW_FORM_APPLE_db_str: 341 case DW_FORM_sdata: 342 case DW_FORM_udata: 343 case DW_FORM_ref_udata: 344 case DW_FORM_GNU_str_index: 345 case DW_FORM_GNU_addr_index: 346 debug_info_data.getULEB128(offset_ptr); 347 return true; 348 349 case DW_FORM_indirect: 350 indirect = true; 351 form = debug_info_data.getULEB128(offset_ptr); 352 break; 353 354 // FIXME: 4 for DWARF32, 8 for DWARF64. 355 case DW_FORM_sec_offset: 356 *offset_ptr += 4; 357 return true; 358 359 default: 360 return false; 361 } 362 } while (indirect); 363 return true; 364} 365 366void 367DWARFFormValue::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 Optional<const char *> DbgStr = getAsCString(cu); 428 if (DbgStr.hasValue()) { 429 raw_ostream &COS = WithColor(OS, syntax::String); 430 COS << '"'; 431 COS.write_escaped(DbgStr.getValue()); 432 COS << '"'; 433 } 434 break; 435 } 436 case DW_FORM_GNU_str_index: { 437 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); 438 Optional<const char *> DbgStr = getAsCString(cu); 439 if (DbgStr.hasValue()) { 440 raw_ostream &COS = WithColor(OS, syntax::String); 441 COS << '"'; 442 COS.write_escaped(DbgStr.getValue()); 443 COS << '"'; 444 } 445 break; 446 } 447 case DW_FORM_ref_addr: 448 OS << format("0x%016" PRIx64, uvalue); 449 break; 450 case DW_FORM_ref1: 451 cu_relative_offset = true; 452 OS << format("cu + 0x%2.2x", (uint8_t)uvalue); 453 break; 454 case DW_FORM_ref2: 455 cu_relative_offset = true; 456 OS << format("cu + 0x%4.4x", (uint16_t)uvalue); 457 break; 458 case DW_FORM_ref4: 459 cu_relative_offset = true; 460 OS << format("cu + 0x%4.4x", (uint32_t)uvalue); 461 break; 462 case DW_FORM_ref8: 463 cu_relative_offset = true; 464 OS << format("cu + 0x%8.8" PRIx64, uvalue); 465 break; 466 case DW_FORM_ref_udata: 467 cu_relative_offset = true; 468 OS << format("cu + 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 495Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { 496 if (!isFormClass(FC_String)) 497 return None; 498 if (Form == DW_FORM_string) 499 return Value.cstr; 500 if (!U) 501 return None; 502 uint32_t Offset = Value.uval; 503 if (Form == DW_FORM_GNU_str_index) { 504 uint32_t StrOffset; 505 if (!U->getStringOffsetSectionItem(Offset, StrOffset)) 506 return None; 507 Offset = StrOffset; 508 } 509 if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { 510 return Str; 511 } 512 return None; 513} 514 515Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { 516 if (!isFormClass(FC_Address)) 517 return None; 518 if (Form == DW_FORM_GNU_addr_index) { 519 uint32_t Index = Value.uval; 520 uint64_t Result; 521 if (!U || !U->getAddrOffsetSectionItem(Index, Result)) 522 return None; 523 return Result; 524 } 525 return Value.uval; 526} 527 528Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { 529 if (!isFormClass(FC_Reference)) 530 return None; 531 switch (Form) { 532 case DW_FORM_ref1: 533 case DW_FORM_ref2: 534 case DW_FORM_ref4: 535 case DW_FORM_ref8: 536 case DW_FORM_ref_udata: 537 if (!U) 538 return None; 539 return Value.uval + U->getOffset(); 540 case DW_FORM_ref_addr: 541 return Value.uval; 542 // FIXME: Add proper support for DW_FORM_ref_sig8 543 default: 544 return Value.uval; 545 } 546} 547 548Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const { 549 if (!isFormClass(FC_SectionOffset)) 550 return None; 551 return Value.uval; 552} 553 554Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { 555 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) 556 || Form == DW_FORM_sdata) 557 return None; 558 return Value.uval; 559} 560 561Optional<int64_t> DWARFFormValue::getAsSignedConstant() const { 562 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) || 563 (Form == DW_FORM_udata && uint64_t(LLONG_MAX) < Value.uval)) 564 return None; 565 switch (Form) { 566 case DW_FORM_data4: 567 return int32_t(Value.uval); 568 case DW_FORM_data2: 569 return int16_t(Value.uval); 570 case DW_FORM_data1: 571 return int8_t(Value.uval); 572 case DW_FORM_sdata: 573 case DW_FORM_data8: 574 default: 575 return Value.sval; 576 } 577} 578 579Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { 580 if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) 581 return None; 582 return ArrayRef<uint8_t>(Value.data, Value.uval); 583} 584 585