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