DWARFFormValue.cpp revision e7285c72793b69f005b5656be9f7aed101cdee4a
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 8, // 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 if (cu->getAddressByteSize() == 4) 177 Value.uval = data.getU32(offset_ptr); 178 else 179 Value.uval = data.getU64(offset_ptr); 180 break; 181 case DW_FORM_flag_present: 182 Value.uval = 1; 183 break; 184 case DW_FORM_ref_sig8: 185 Value.uval = data.getU64(offset_ptr); 186 break; 187 case DW_FORM_GNU_addr_index: 188 Value.uval = data.getULEB128(offset_ptr); 189 break; 190 case DW_FORM_GNU_str_index: 191 Value.uval = data.getULEB128(offset_ptr); 192 break; 193 default: 194 return false; 195 } 196 } while (indirect); 197 198 if (is_block) { 199 StringRef str = data.getData().substr(*offset_ptr, Value.uval); 200 Value.data = NULL; 201 if (!str.empty()) { 202 Value.data = reinterpret_cast<const uint8_t *>(str.data()); 203 *offset_ptr += Value.uval; 204 } 205 } 206 207 return true; 208} 209 210bool 211DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, 212 const DWARFCompileUnit *cu) const { 213 return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); 214} 215 216bool 217DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 218 uint32_t *offset_ptr, const DWARFCompileUnit *cu) { 219 bool indirect = false; 220 do { 221 indirect = false; 222 switch (form) { 223 // Blocks if inlined data that have a length field and the data bytes 224 // inlined in the .debug_info 225 case DW_FORM_exprloc: 226 case DW_FORM_block: { 227 uint64_t size = debug_info_data.getULEB128(offset_ptr); 228 *offset_ptr += size; 229 return true; 230 } 231 case DW_FORM_block1: { 232 uint8_t size = debug_info_data.getU8(offset_ptr); 233 *offset_ptr += size; 234 return true; 235 } 236 case DW_FORM_block2: { 237 uint16_t size = debug_info_data.getU16(offset_ptr); 238 *offset_ptr += size; 239 return true; 240 } 241 case DW_FORM_block4: { 242 uint32_t size = debug_info_data.getU32(offset_ptr); 243 *offset_ptr += size; 244 return true; 245 } 246 247 // Inlined NULL terminated C-strings 248 case DW_FORM_string: 249 debug_info_data.getCStr(offset_ptr); 250 return true; 251 252 // Compile unit address sized values 253 case DW_FORM_addr: 254 case DW_FORM_ref_addr: 255 *offset_ptr += cu->getAddressByteSize(); 256 return true; 257 258 // 0 byte values - implied from the form. 259 case DW_FORM_flag_present: 260 return true; 261 262 // 1 byte values 263 case DW_FORM_data1: 264 case DW_FORM_flag: 265 case DW_FORM_ref1: 266 *offset_ptr += 1; 267 return true; 268 269 // 2 byte values 270 case DW_FORM_data2: 271 case DW_FORM_ref2: 272 *offset_ptr += 2; 273 return true; 274 275 // 4 byte values 276 case DW_FORM_strp: 277 case DW_FORM_data4: 278 case DW_FORM_ref4: 279 *offset_ptr += 4; 280 return true; 281 282 // 8 byte values 283 case DW_FORM_data8: 284 case DW_FORM_ref8: 285 case DW_FORM_ref_sig8: 286 *offset_ptr += 8; 287 return true; 288 289 // signed or unsigned LEB 128 values 290 // case DW_FORM_APPLE_db_str: 291 case DW_FORM_sdata: 292 case DW_FORM_udata: 293 case DW_FORM_ref_udata: 294 case DW_FORM_GNU_str_index: 295 case DW_FORM_GNU_addr_index: 296 debug_info_data.getULEB128(offset_ptr); 297 return true; 298 299 case DW_FORM_indirect: 300 indirect = true; 301 form = debug_info_data.getULEB128(offset_ptr); 302 break; 303 304 // 4 for DWARF32, 8 for DWARF64. 305 case DW_FORM_sec_offset: 306 if (cu->getAddressByteSize() == 4) 307 *offset_ptr += 4; 308 else 309 *offset_ptr += 8; 310 return true; 311 312 default: 313 return false; 314 } 315 } while (indirect); 316 return true; 317} 318 319void 320DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { 321 DataExtractor debug_str_data(cu->getStringSection(), true, 0); 322 DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0); 323 uint64_t uvalue = getUnsigned(); 324 bool cu_relative_offset = false; 325 326 switch (Form) { 327 case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; 328 case DW_FORM_flag_present: OS << "true"; break; 329 case DW_FORM_flag: 330 case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; 331 case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break; 332 case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break; 333 case DW_FORM_ref_sig8: 334 case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break; 335 case DW_FORM_string: 336 OS << '"'; 337 OS.write_escaped(getAsCString(NULL)); 338 OS << '"'; 339 break; 340 case DW_FORM_exprloc: 341 case DW_FORM_block: 342 case DW_FORM_block1: 343 case DW_FORM_block2: 344 case DW_FORM_block4: 345 if (uvalue > 0) { 346 switch (Form) { 347 case DW_FORM_exprloc: 348 case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break; 349 case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; 350 case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; 351 case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; 352 default: break; 353 } 354 355 const uint8_t* data_ptr = Value.data; 356 if (data_ptr) { 357 // uvalue contains size of block 358 const uint8_t* end_data_ptr = data_ptr + uvalue; 359 while (data_ptr < end_data_ptr) { 360 OS << format("%2.2x ", *data_ptr); 361 ++data_ptr; 362 } 363 } 364 else 365 OS << "NULL"; 366 } 367 break; 368 369 case DW_FORM_sdata: OS << getSigned(); break; 370 case DW_FORM_udata: OS << getUnsigned(); break; 371 case DW_FORM_strp: { 372 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 373 const char* dbg_str = getAsCString(&debug_str_data); 374 if (dbg_str) { 375 OS << '"'; 376 OS.write_escaped(dbg_str); 377 OS << '"'; 378 } 379 break; 380 } 381 case DW_FORM_GNU_str_index: { 382 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); 383 const char *dbg_str = getIndirectCString(&debug_str_data, 384 &debug_str_offset_data); 385 if (dbg_str) { 386 OS << '"'; 387 OS.write_escaped(dbg_str); 388 OS << '"'; 389 } 390 break; 391 } 392 case DW_FORM_ref_addr: 393 OS << format("0x%016" PRIx64, uvalue); 394 break; 395 case DW_FORM_ref1: 396 cu_relative_offset = true; 397 OS << format("cu + 0x%2.2x", (uint8_t)uvalue); 398 break; 399 case DW_FORM_ref2: 400 cu_relative_offset = true; 401 OS << format("cu + 0x%4.4x", (uint16_t)uvalue); 402 break; 403 case DW_FORM_ref4: 404 cu_relative_offset = true; 405 OS << format("cu + 0x%4.4x", (uint32_t)uvalue); 406 break; 407 case DW_FORM_ref8: 408 cu_relative_offset = true; 409 OS << format("cu + 0x%8.8" PRIx64, uvalue); 410 break; 411 case DW_FORM_ref_udata: 412 cu_relative_offset = true; 413 OS << format("cu + 0x%" PRIx64, uvalue); 414 break; 415 416 // All DW_FORM_indirect attributes should be resolved prior to calling 417 // this function 418 case DW_FORM_indirect: 419 OS << "DW_FORM_indirect"; 420 break; 421 422 case DW_FORM_sec_offset: 423 if (cu->getAddressByteSize() == 4) 424 OS << format("0x%08x", (uint32_t)uvalue); 425 else 426 OS << format("0x%016" PRIx64, uvalue); 427 break; 428 429 default: 430 OS << format("DW_FORM(0x%4.4x)", Form); 431 break; 432 } 433 434 if (cu_relative_offset) 435 OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0)); 436} 437 438const char* 439DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const { 440 if (isInlinedCStr()) { 441 return Value.cstr; 442 } else if (debug_str_data_ptr) { 443 uint32_t offset = Value.uval; 444 return debug_str_data_ptr->getCStr(&offset); 445 } 446 return NULL; 447} 448 449const char* 450DWARFFormValue::getIndirectCString(const DataExtractor *DS, 451 const DataExtractor *DSO) const { 452 if (!DS || !DSO) return NULL; 453 454 uint32_t offset = Value.uval * 4; 455 uint32_t soffset = DSO->getULEB128(&offset); 456 return DS->getCStr(&soffset); 457} 458 459uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const { 460 uint64_t die_offset = Value.uval; 461 switch (Form) { 462 case DW_FORM_ref1: 463 case DW_FORM_ref2: 464 case DW_FORM_ref4: 465 case DW_FORM_ref8: 466 case DW_FORM_ref_udata: 467 die_offset += (cu ? cu->getOffset() : 0); 468 break; 469 default: 470 break; 471 } 472 473 return die_offset; 474} 475 476bool 477DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) { 478 switch (Form) { 479 case DW_FORM_ref1: 480 case DW_FORM_ref2: 481 case DW_FORM_ref4: 482 case DW_FORM_ref8: 483 case DW_FORM_ref_udata: 484 Value.uval += cu->getOffset(); 485 Form = DW_FORM_ref_addr; 486 return true; 487 default: 488 break; 489 } 490 return false; 491} 492 493const uint8_t *DWARFFormValue::BlockData() const { 494 if (!isInlinedCStr()) 495 return Value.data; 496 return NULL; 497} 498 499bool DWARFFormValue::isBlockForm(uint16_t form) { 500 switch (form) { 501 case DW_FORM_exprloc: 502 case DW_FORM_block: 503 case DW_FORM_block1: 504 case DW_FORM_block2: 505 case DW_FORM_block4: 506 return true; 507 } 508 return false; 509} 510 511bool DWARFFormValue::isDataForm(uint16_t form) { 512 switch (form) { 513 case DW_FORM_sdata: 514 case DW_FORM_udata: 515 case DW_FORM_data1: 516 case DW_FORM_data2: 517 case DW_FORM_data4: 518 case DW_FORM_data8: 519 return true; 520 } 521 return false; 522} 523