1 //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===// 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 <assert.h> 11 12 #include "lldb/Core/dwarf.h" 13 #include "lldb/Core/Stream.h" 14 15 #include "DWARFFormValue.h" 16 #include "DWARFCompileUnit.h" 17 18 class DWARFCompileUnit; 19 20 using namespace lldb_private; 21 22 23 static uint8_t g_form_sizes_addr4[] = 24 { 25 0, // 0x00 unused 26 4, // 0x01 DW_FORM_addr 27 0, // 0x02 unused 28 0, // 0x03 DW_FORM_block2 29 0, // 0x04 DW_FORM_block4 30 2, // 0x05 DW_FORM_data2 31 4, // 0x06 DW_FORM_data4 32 8, // 0x07 DW_FORM_data8 33 0, // 0x08 DW_FORM_string 34 0, // 0x09 DW_FORM_block 35 0, // 0x0a DW_FORM_block1 36 1, // 0x0b DW_FORM_data1 37 1, // 0x0c DW_FORM_flag 38 0, // 0x0d DW_FORM_sdata 39 4, // 0x0e DW_FORM_strp 40 0, // 0x0f DW_FORM_udata 41 4, // 0x10 DW_FORM_ref_addr 42 1, // 0x11 DW_FORM_ref1 43 2, // 0x12 DW_FORM_ref2 44 4, // 0x13 DW_FORM_ref4 45 8, // 0x14 DW_FORM_ref8 46 0, // 0x15 DW_FORM_ref_udata 47 0, // 0x16 DW_FORM_indirect 48 4, // 0x17 DW_FORM_sec_offset 49 0, // 0x18 DW_FORM_exprloc 50 0, // 0x19 DW_FORM_flag_present 51 0, // 0x1a 52 0, // 0x1b 53 0, // 0x1c 54 0, // 0x1d 55 0, // 0x1e 56 0, // 0x1f 57 8, // 0x20 DW_FORM_ref_sig8 58 59 }; 60 61 static uint8_t 62 g_form_sizes_addr8[] = 63 { 64 0, // 0x00 unused 65 8, // 0x01 DW_FORM_addr 66 0, // 0x02 unused 67 0, // 0x03 DW_FORM_block2 68 0, // 0x04 DW_FORM_block4 69 2, // 0x05 DW_FORM_data2 70 4, // 0x06 DW_FORM_data4 71 8, // 0x07 DW_FORM_data8 72 0, // 0x08 DW_FORM_string 73 0, // 0x09 DW_FORM_block 74 0, // 0x0a DW_FORM_block1 75 1, // 0x0b DW_FORM_data1 76 1, // 0x0c DW_FORM_flag 77 0, // 0x0d DW_FORM_sdata 78 4, // 0x0e DW_FORM_strp 79 0, // 0x0f DW_FORM_udata 80 8, // 0x10 DW_FORM_ref_addr 81 1, // 0x11 DW_FORM_ref1 82 2, // 0x12 DW_FORM_ref2 83 4, // 0x13 DW_FORM_ref4 84 8, // 0x14 DW_FORM_ref8 85 0, // 0x15 DW_FORM_ref_udata 86 0, // 0x16 DW_FORM_indirect 87 4, // 0x17 DW_FORM_sec_offset 88 0, // 0x18 DW_FORM_exprloc 89 0, // 0x19 DW_FORM_flag_present 90 0, // 0x1a 91 0, // 0x1b 92 0, // 0x1c 93 0, // 0x1d 94 0, // 0x1e 95 0, // 0x1f 96 8, // 0x20 DW_FORM_ref_sig8 97 }; 98 99 const uint8_t * 100 DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size) 101 { 102 switch (addr_size) 103 { 104 case 4: return g_form_sizes_addr4; 105 case 8: return g_form_sizes_addr8; 106 } 107 return NULL; 108 } 109 110 DWARFFormValue::DWARFFormValue(dw_form_t form) : 111 m_form(form), 112 m_value() 113 { 114 } 115 116 bool 117 DWARFFormValue::ExtractValue(const DataExtractor& data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) 118 { 119 bool indirect = false; 120 bool is_block = false; 121 m_value.data = NULL; 122 // Read the value for the form into value and follow and DW_FORM_indirect instances we run into 123 do 124 { 125 indirect = false; 126 switch (m_form) 127 { 128 case DW_FORM_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; 129 case DW_FORM_block2: m_value.value.uval = data.GetU16(offset_ptr); is_block = true; break; 130 case DW_FORM_block4: m_value.value.uval = data.GetU32(offset_ptr); is_block = true; break; 131 case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break; 132 case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break; 133 case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break; 134 case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); 135 // Set the string value to also be the data for inlined cstr form values only 136 // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form 137 // values; 138 m_value.data = (uint8_t*)m_value.value.cstr; break; 139 case DW_FORM_exprloc: 140 case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break; 141 case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break; 142 case DW_FORM_data1: m_value.value.uval = data.GetU8(offset_ptr); break; 143 case DW_FORM_flag: m_value.value.uval = data.GetU8(offset_ptr); break; 144 case DW_FORM_sdata: m_value.value.sval = data.GetSLEB128(offset_ptr); break; 145 case DW_FORM_strp: m_value.value.uval = data.GetU32(offset_ptr); break; 146 // case DW_FORM_APPLE_db_str: 147 case DW_FORM_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; 148 case DW_FORM_ref_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; 149 case DW_FORM_ref1: m_value.value.uval = data.GetU8(offset_ptr); break; 150 case DW_FORM_ref2: m_value.value.uval = data.GetU16(offset_ptr); break; 151 case DW_FORM_ref4: m_value.value.uval = data.GetU32(offset_ptr); break; 152 case DW_FORM_ref8: m_value.value.uval = data.GetU64(offset_ptr); break; 153 case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; 154 case DW_FORM_indirect: 155 m_form = data.GetULEB128(offset_ptr); 156 indirect = true; 157 break; 158 159 case DW_FORM_sec_offset: m_value.value.uval = data.GetU32(offset_ptr); break; 160 case DW_FORM_flag_present: m_value.value.uval = 1; break; 161 case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break; 162 default: 163 return false; 164 break; 165 } 166 } while (indirect); 167 168 if (is_block) 169 { 170 m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); 171 if (m_value.data != NULL) 172 { 173 *offset_ptr += m_value.value.uval; 174 } 175 } 176 177 return true; 178 } 179 180 bool 181 DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) const 182 { 183 return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu); 184 } 185 186 bool 187 DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, uint32_t* offset_ptr, const DWARFCompileUnit* cu) 188 { 189 switch (form) 190 { 191 // Blocks if inlined data that have a length field and the data bytes 192 // inlined in the .debug_info 193 case DW_FORM_exprloc: 194 case DW_FORM_block: { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true; 195 case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr); *offset_ptr += size; } return true; 196 case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr); *offset_ptr += size; } return true; 197 case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr); *offset_ptr += size; } return true; 198 199 // Inlined NULL terminated C-strings 200 case DW_FORM_string: 201 debug_info_data.GetCStr(offset_ptr); 202 return true; 203 204 // Compile unit address sized values 205 case DW_FORM_addr: 206 case DW_FORM_ref_addr: 207 *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu); 208 return true; 209 210 // 0 bytes values (implied from DW_FORM) 211 case DW_FORM_flag_present: 212 return true; 213 214 // 1 byte values 215 case DW_FORM_data1: 216 case DW_FORM_flag: 217 case DW_FORM_ref1: 218 *offset_ptr += 1; 219 return true; 220 221 // 2 byte values 222 case DW_FORM_data2: 223 case DW_FORM_ref2: 224 *offset_ptr += 2; 225 return true; 226 227 // 32 bit for DWARF 32, 64 for DWARF 64 228 case DW_FORM_sec_offset: 229 *offset_ptr += 4; 230 return true; 231 232 // 4 byte values 233 case DW_FORM_strp: 234 case DW_FORM_data4: 235 case DW_FORM_ref4: 236 *offset_ptr += 4; 237 return true; 238 239 // 8 byte values 240 case DW_FORM_data8: 241 case DW_FORM_ref8: 242 case DW_FORM_ref_sig8: 243 *offset_ptr += 8; 244 return true; 245 246 // signed or unsigned LEB 128 values 247 case DW_FORM_sdata: 248 case DW_FORM_udata: 249 case DW_FORM_ref_udata: 250 debug_info_data.Skip_LEB128(offset_ptr); 251 return true; 252 253 case DW_FORM_indirect: 254 { 255 dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr); 256 return DWARFFormValue::SkipValue (indirect_form, 257 debug_info_data, 258 offset_ptr, 259 cu); 260 } 261 262 default: 263 break; 264 } 265 return false; 266 } 267 268 269 void 270 DWARFFormValue::Dump(Stream &s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const 271 { 272 uint64_t uvalue = Unsigned(); 273 bool cu_relative_offset = false; 274 275 bool verbose = s.GetVerbose(); 276 277 switch (m_form) 278 { 279 case DW_FORM_addr: s.Address(uvalue, sizeof (uint64_t)); break; 280 case DW_FORM_flag: 281 case DW_FORM_data1: s.PutHex8(uvalue); break; 282 case DW_FORM_data2: s.PutHex16(uvalue); break; 283 case DW_FORM_sec_offset: 284 case DW_FORM_data4: s.PutHex32(uvalue); break; 285 case DW_FORM_ref_sig8: 286 case DW_FORM_data8: s.PutHex64(uvalue); break; 287 case DW_FORM_string: s.QuotedCString(AsCString(NULL)); break; 288 case DW_FORM_exprloc: 289 case DW_FORM_block: 290 case DW_FORM_block1: 291 case DW_FORM_block2: 292 case DW_FORM_block4: 293 if (uvalue > 0) 294 { 295 switch (m_form) 296 { 297 case DW_FORM_exprloc: 298 case DW_FORM_block: s.Printf("<0x%" PRIx64 "> ", uvalue); break; 299 case DW_FORM_block1: s.Printf("<0x%2.2x> ", (uint8_t)uvalue); break; 300 case DW_FORM_block2: s.Printf("<0x%4.4x> ", (uint16_t)uvalue); break; 301 case DW_FORM_block4: s.Printf("<0x%8.8x> ", (uint32_t)uvalue); break; 302 default: break; 303 } 304 305 const uint8_t* data_ptr = m_value.data; 306 if (data_ptr) 307 { 308 const uint8_t* end_data_ptr = data_ptr + uvalue; // uvalue contains size of block 309 while (data_ptr < end_data_ptr) 310 { 311 s.Printf("%2.2x ", *data_ptr); 312 ++data_ptr; 313 } 314 } 315 else 316 s.PutCString("NULL"); 317 } 318 break; 319 320 case DW_FORM_sdata: s.PutSLEB128(uvalue); break; 321 case DW_FORM_udata: s.PutULEB128(uvalue); break; 322 case DW_FORM_strp: 323 if (debug_str_data) 324 { 325 if (verbose) 326 s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 327 328 const char* dbg_str = AsCString(debug_str_data); 329 if (dbg_str) 330 s.QuotedCString(dbg_str); 331 } 332 else 333 { 334 s.PutHex32(uvalue); 335 } 336 break; 337 338 case DW_FORM_ref_addr: 339 { 340 s.Address(uvalue, sizeof (uint64_t) * 2); 341 break; 342 } 343 case DW_FORM_ref1: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%2.2x", (uint8_t)uvalue); break; 344 case DW_FORM_ref2: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%4.4x", (uint16_t)uvalue); break; 345 case DW_FORM_ref4: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%4.4x", (uint32_t)uvalue); break; 346 case DW_FORM_ref8: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%8.8" PRIx64, uvalue); break; 347 case DW_FORM_ref_udata: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%" PRIx64, uvalue); break; 348 349 // All DW_FORM_indirect attributes should be resolved prior to calling this function 350 case DW_FORM_indirect: s.PutCString("DW_FORM_indirect"); break; 351 case DW_FORM_flag_present: break; 352 default: 353 s.Printf("DW_FORM(0x%4.4x)", m_form); 354 break; 355 } 356 357 if (cu_relative_offset) 358 { 359 if (verbose) 360 s.PutCString(" => "); 361 362 s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0))); 363 } 364 } 365 366 const char* 367 DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const 368 { 369 if (IsInlinedCStr()) 370 return m_value.value.cstr; 371 else if (debug_str_data_ptr) 372 return debug_str_data_ptr->PeekCStr(m_value.value.uval); 373 return NULL; 374 } 375 376 uint64_t 377 DWARFFormValue::Reference(const DWARFCompileUnit* cu) const 378 { 379 uint64_t die_offset = m_value.value.uval; 380 switch (m_form) 381 { 382 case DW_FORM_ref1: 383 case DW_FORM_ref2: 384 case DW_FORM_ref4: 385 case DW_FORM_ref8: 386 case DW_FORM_ref_udata: 387 die_offset += (cu ? cu->GetOffset() : 0); 388 break; 389 390 default: 391 break; 392 } 393 394 return die_offset; 395 } 396 397 uint64_t 398 DWARFFormValue::Reference (dw_offset_t base_offset) const 399 { 400 uint64_t die_offset = m_value.value.uval; 401 switch (m_form) 402 { 403 case DW_FORM_ref1: 404 case DW_FORM_ref2: 405 case DW_FORM_ref4: 406 case DW_FORM_ref8: 407 case DW_FORM_ref_udata: 408 die_offset += base_offset; 409 break; 410 411 default: 412 break; 413 } 414 415 return die_offset; 416 } 417 418 //---------------------------------------------------------------------- 419 // Resolve any compile unit specific references so that we don't need 420 // the compile unit at a later time in order to work with the form 421 // value. 422 //---------------------------------------------------------------------- 423 bool 424 DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu) 425 { 426 switch (m_form) 427 { 428 case DW_FORM_ref1: 429 case DW_FORM_ref2: 430 case DW_FORM_ref4: 431 case DW_FORM_ref8: 432 case DW_FORM_ref_udata: 433 m_value.value.uval += cu->GetOffset(); 434 m_form = DW_FORM_ref_addr; 435 return true; 436 break; 437 438 default: 439 break; 440 } 441 442 return false; 443 } 444 445 const uint8_t* 446 DWARFFormValue::BlockData() const 447 { 448 if (!IsInlinedCStr()) 449 return m_value.data; 450 return NULL; 451 } 452 453 454 bool 455 DWARFFormValue::IsBlockForm(const dw_form_t form) 456 { 457 switch (form) 458 { 459 case DW_FORM_block: 460 case DW_FORM_block1: 461 case DW_FORM_block2: 462 case DW_FORM_block4: 463 return true; 464 } 465 return false; 466 } 467 468 bool 469 DWARFFormValue::IsDataForm(const dw_form_t form) 470 { 471 switch (form) 472 { 473 case DW_FORM_sdata: 474 case DW_FORM_udata: 475 case DW_FORM_data1: 476 case DW_FORM_data2: 477 case DW_FORM_data4: 478 case DW_FORM_data8: 479 return true; 480 } 481 return false; 482 } 483 484 int 485 DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr) 486 { 487 dw_form_t a_form = a_value.Form(); 488 dw_form_t b_form = b_value.Form(); 489 if (a_form < b_form) 490 return -1; 491 if (a_form > b_form) 492 return 1; 493 switch (a_form) 494 { 495 case DW_FORM_addr: 496 case DW_FORM_flag: 497 case DW_FORM_data1: 498 case DW_FORM_data2: 499 case DW_FORM_data4: 500 case DW_FORM_data8: 501 case DW_FORM_udata: 502 case DW_FORM_ref_addr: 503 case DW_FORM_sec_offset: 504 case DW_FORM_flag_present: 505 case DW_FORM_ref_sig8: 506 { 507 uint64_t a = a_value.Unsigned(); 508 uint64_t b = b_value.Unsigned(); 509 if (a < b) 510 return -1; 511 if (a > b) 512 return 1; 513 return 0; 514 } 515 516 case DW_FORM_sdata: 517 { 518 int64_t a = a_value.Signed(); 519 int64_t b = b_value.Signed(); 520 if (a < b) 521 return -1; 522 if (a > b) 523 return 1; 524 return 0; 525 } 526 527 case DW_FORM_string: 528 case DW_FORM_strp: 529 { 530 const char *a_string = a_value.AsCString(debug_str_data_ptr); 531 const char *b_string = b_value.AsCString(debug_str_data_ptr); 532 if (a_string == b_string) 533 return 0; 534 else if (a_string && b_string) 535 return strcmp(a_string, b_string); 536 else if (a_string == NULL) 537 return -1; // A string is NULL, and B is valid 538 else 539 return 1; // A string valid, and B is NULL 540 } 541 542 543 case DW_FORM_block: 544 case DW_FORM_block1: 545 case DW_FORM_block2: 546 case DW_FORM_block4: 547 case DW_FORM_exprloc: 548 { 549 uint64_t a_len = a_value.Unsigned(); 550 uint64_t b_len = b_value.Unsigned(); 551 if (a_len < b_len) 552 return -1; 553 if (a_len > b_len) 554 return 1; 555 // The block lengths are the same 556 return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned()); 557 } 558 break; 559 560 case DW_FORM_ref1: 561 case DW_FORM_ref2: 562 case DW_FORM_ref4: 563 case DW_FORM_ref8: 564 case DW_FORM_ref_udata: 565 { 566 uint64_t a = a_value.Reference(a_cu); 567 uint64_t b = b_value.Reference(b_cu); 568 if (a < b) 569 return -1; 570 if (a > b) 571 return 1; 572 return 0; 573 } 574 575 case DW_FORM_indirect: 576 assert(!"This shouldn't happen after the form has been extracted..."); 577 break; 578 579 default: 580 assert(!"Unhandled DW_FORM"); 581 break; 582 } 583 return -1; 584 } 585 586