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