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