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