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