1 //===-- DWARFUnit.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 "DWARFUnit.h" 11 12 #include "Plugins/Language/ObjC/ObjCLanguage.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Symbol/ObjectFile.h" 15 16 #include "DWARFCompileUnit.h" 17 #include "DWARFDebugInfo.h" 18 #include "LogChannelDWARF.h" 19 #include "SymbolFileDWARFDwo.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace std; 24 25 extern int g_verbose; 26 27 DWARFUnit::DWARFUnit() {} 28 29 DWARFUnit::~DWARFUnit() {} 30 31 size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { 32 return Data().ExtractDIEsIfNeeded(cu_die_only); 33 } 34 35 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 36 return Data().LookupAddress(address); 37 } 38 39 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 40 DWARFDIECollection &dies, 41 uint32_t depth) const { 42 return Data().AppendDIEsWithTag(tag, dies, depth); 43 } 44 45 bool DWARFUnit::Verify(Stream *s) const { 46 return Data().Verify(s); 47 } 48 49 void DWARFUnit::Dump(Stream *s) const { 50 Data().Dump(s); 51 } 52 53 lldb::user_id_t DWARFUnit::GetID() const { 54 return Data().GetID(); 55 } 56 57 uint32_t DWARFUnit::Size() const { return IsDWARF64() ? 23 : 11; } 58 59 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 60 return m_offset + (IsDWARF64() ? 12 : 4) + GetLength(); 61 } 62 63 size_t DWARFUnit::GetDebugInfoSize() const { 64 return (IsDWARF64() ? 12 : 4) + GetLength() - Size(); 65 } 66 67 uint32_t DWARFUnit::GetLength() const { return Data().m_length; } 68 uint16_t DWARFUnit::GetVersion() const { return Data().m_version; } 69 70 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 71 return Data().m_abbrevs; 72 } 73 74 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 75 return Data().GetAbbrevOffset(); 76 } 77 78 uint8_t DWARFUnit::GetAddressByteSize() const { return Data().m_addr_size; } 79 80 dw_addr_t DWARFUnit::GetBaseAddress() const { return Data().m_base_addr; } 81 82 dw_addr_t DWARFUnit::GetAddrBase() const { return Data().m_addr_base; } 83 84 dw_addr_t DWARFUnit::GetRangesBase() const { return Data().m_ranges_base; } 85 86 void DWARFUnit::SetAddrBase(dw_addr_t addr_base, 87 dw_addr_t ranges_base, 88 dw_offset_t base_obj_offset) { 89 Data().SetAddrBase(addr_base, ranges_base, base_obj_offset); 90 } 91 92 void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) { 93 Data().ClearDIEs(keep_compile_unit_die); 94 } 95 96 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, 97 DWARFDebugAranges *debug_aranges) { 98 Data().BuildAddressRangeTable(dwarf2Data, debug_aranges); 99 } 100 101 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 102 return Data().m_dwarf2Data->GetObjectFile()->GetByteOrder(); 103 } 104 105 TypeSystem *DWARFUnit::GetTypeSystem() { 106 return Data().GetTypeSystem(); 107 } 108 109 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 110 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 111 IsDWARF64()); 112 } 113 114 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { 115 Data().m_base_addr = base_addr; 116 } 117 118 DWARFDIE DWARFUnit::GetCompileUnitDIEOnly() { 119 return Data().GetCompileUnitDIEOnly(); 120 } 121 122 DWARFDIE DWARFUnit::DIE() { 123 return Data().DIE(); 124 } 125 126 bool DWARFUnit::HasDIEsParsed() const { return Data().m_die_array.size() > 1; } 127 128 //---------------------------------------------------------------------- 129 // Compare function DWARFDebugAranges::Range structures 130 //---------------------------------------------------------------------- 131 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 132 const dw_offset_t die_offset) { 133 return die.GetOffset() < die_offset; 134 } 135 136 //---------------------------------------------------------------------- 137 // GetDIE() 138 // 139 // Get the DIE (Debug Information Entry) with the specified offset by 140 // first checking if the DIE is contained within this compile unit and 141 // grabbing the DIE from this compile unit. Otherwise we grab the DIE 142 // from the DWARF file. 143 //---------------------------------------------------------------------- 144 DWARFDIE 145 DWARFUnit::GetDIE(dw_offset_t die_offset) { 146 if (die_offset != DW_INVALID_OFFSET) { 147 if (GetDwoSymbolFile()) 148 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 149 150 if (ContainsDIEOffset(die_offset)) { 151 ExtractDIEsIfNeeded(false); 152 DWARFDebugInfoEntry::iterator end = Data().m_die_array.end(); 153 DWARFDebugInfoEntry::iterator pos = lower_bound( 154 Data().m_die_array.begin(), end, die_offset, CompareDIEOffset); 155 if (pos != end) { 156 if (die_offset == (*pos).GetOffset()) 157 return DWARFDIE(this, &(*pos)); 158 } 159 } else { 160 // Don't specify the compile unit offset as we don't know it because the 161 // DIE belongs to 162 // a different compile unit in the same symbol file. 163 return Data().m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset); 164 } 165 } 166 return DWARFDIE(); // Not found 167 } 168 169 static uint8_t g_default_addr_size = 4; 170 171 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 172 if (cu) 173 return cu->GetAddressByteSize(); 174 return DWARFCompileUnit::GetDefaultAddressSize(); 175 } 176 177 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 178 if (cu) 179 return cu->IsDWARF64(); 180 return false; 181 } 182 183 uint8_t DWARFUnit::GetDefaultAddressSize() { 184 return g_default_addr_size; 185 } 186 187 void DWARFUnit::SetDefaultAddressSize(uint8_t addr_size) { 188 g_default_addr_size = addr_size; 189 } 190 191 void *DWARFUnit::GetUserData() const { return Data().m_user_data; } 192 193 void DWARFUnit::SetUserData(void *d) { 194 Data().SetUserData(d); 195 } 196 197 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 198 if (GetProducer() == eProducerLLVMGCC) 199 return false; 200 return true; 201 } 202 203 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 204 // llvm-gcc makes completely invalid decl file attributes and won't ever 205 // be fixed, so we need to know to ignore these. 206 return GetProducer() == eProducerLLVMGCC; 207 } 208 209 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 210 if (GetProducer() == eProducerClang) { 211 const uint32_t major_version = GetProducerVersionMajor(); 212 if (major_version > 425 || 213 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 214 return true; 215 else 216 return false; 217 } 218 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 219 // info 220 } 221 222 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { 223 return Data().m_dwarf2Data; 224 } 225 226 DWARFProducer DWARFUnit::GetProducer() { 227 return Data().GetProducer(); 228 } 229 230 uint32_t DWARFUnit::GetProducerVersionMajor() { 231 return Data().GetProducerVersionMajor(); 232 } 233 234 uint32_t DWARFUnit::GetProducerVersionMinor() { 235 return Data().GetProducerVersionMinor(); 236 } 237 238 uint32_t DWARFUnit::GetProducerVersionUpdate() { 239 return Data().GetProducerVersionUpdate(); 240 } 241 242 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 243 // Note: user languages between lo_user and hi_user 244 // must be handled explicitly here. 245 switch (val) { 246 case DW_LANG_Mips_Assembler: 247 return eLanguageTypeMipsAssembler; 248 case DW_LANG_GOOGLE_RenderScript: 249 return eLanguageTypeExtRenderScript; 250 default: 251 return static_cast<LanguageType>(val); 252 } 253 } 254 255 LanguageType DWARFUnit::GetLanguageType() { 256 return Data().GetLanguageType(); 257 } 258 259 bool DWARFUnit::IsDWARF64() const { return Data().m_is_dwarf64; } 260 261 bool DWARFUnit::GetIsOptimized() { 262 return Data().GetIsOptimized(); 263 } 264 265 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 266 return Data().m_dwo_symbol_file.get(); 267 } 268 269 dw_offset_t DWARFUnit::GetBaseObjOffset() const { 270 return Data().m_base_obj_offset; 271 } 272 273 const DWARFDebugInfoEntry *DWARFUnit::GetCompileUnitDIEPtrOnly() { 274 return Data().GetCompileUnitDIEPtrOnly(); 275 } 276 277 const DWARFDebugInfoEntry *DWARFUnit::DIEPtr() { 278 return Data().DIEPtr(); 279 } 280 281 void DWARFUnit::Index(NameToDIE &func_basenames, 282 NameToDIE &func_fullnames, NameToDIE &func_methods, 283 NameToDIE &func_selectors, 284 NameToDIE &objc_class_selectors, 285 NameToDIE &globals, NameToDIE &types, 286 NameToDIE &namespaces) { 287 assert(!Data().m_dwarf2Data->GetBaseCompileUnit() && 288 "DWARFUnit associated with .dwo or .dwp " 289 "should not be indexed directly"); 290 291 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); 292 293 if (log) { 294 Data().m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage( 295 log, 296 "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]", 297 GetOffset()); 298 } 299 300 const LanguageType cu_language = GetLanguageType(); 301 DWARFFormValue::FixedFormSizes fixed_form_sizes = 302 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 303 IsDWARF64()); 304 305 IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames, 306 func_fullnames, func_methods, func_selectors, 307 objc_class_selectors, globals, types, namespaces); 308 309 SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile(); 310 if (dwo_symbol_file) { 311 IndexPrivate( 312 dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes, 313 GetOffset(), func_basenames, func_fullnames, func_methods, 314 func_selectors, objc_class_selectors, globals, types, namespaces); 315 } 316 } 317 318 void DWARFUnit::IndexPrivate( 319 DWARFUnit *dwarf_cu, const LanguageType cu_language, 320 const DWARFFormValue::FixedFormSizes &fixed_form_sizes, 321 const dw_offset_t cu_offset, NameToDIE &func_basenames, 322 NameToDIE &func_fullnames, NameToDIE &func_methods, 323 NameToDIE &func_selectors, NameToDIE &objc_class_selectors, 324 NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { 325 DWARFDebugInfoEntry::const_iterator pos; 326 DWARFDebugInfoEntry::const_iterator begin = 327 dwarf_cu->Data().m_die_array.begin(); 328 DWARFDebugInfoEntry::const_iterator end = dwarf_cu->Data().m_die_array.end(); 329 for (pos = begin; pos != end; ++pos) { 330 const DWARFDebugInfoEntry &die = *pos; 331 332 const dw_tag_t tag = die.Tag(); 333 334 switch (tag) { 335 case DW_TAG_array_type: 336 case DW_TAG_base_type: 337 case DW_TAG_class_type: 338 case DW_TAG_constant: 339 case DW_TAG_enumeration_type: 340 case DW_TAG_inlined_subroutine: 341 case DW_TAG_namespace: 342 case DW_TAG_string_type: 343 case DW_TAG_structure_type: 344 case DW_TAG_subprogram: 345 case DW_TAG_subroutine_type: 346 case DW_TAG_typedef: 347 case DW_TAG_union_type: 348 case DW_TAG_unspecified_type: 349 case DW_TAG_variable: 350 break; 351 352 default: 353 continue; 354 } 355 356 DWARFAttributes attributes; 357 const char *name = NULL; 358 const char *mangled_cstr = NULL; 359 bool is_declaration = false; 360 // bool is_artificial = false; 361 bool has_address = false; 362 bool has_location_or_const_value = false; 363 bool is_global_or_static_variable = false; 364 365 DWARFFormValue specification_die_form; 366 const size_t num_attributes = 367 die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes); 368 if (num_attributes > 0) { 369 for (uint32_t i = 0; i < num_attributes; ++i) { 370 dw_attr_t attr = attributes.AttributeAtIndex(i); 371 DWARFFormValue form_value; 372 switch (attr) { 373 case DW_AT_name: 374 if (attributes.ExtractFormValueAtIndex(i, form_value)) 375 name = form_value.AsCString(); 376 break; 377 378 case DW_AT_declaration: 379 if (attributes.ExtractFormValueAtIndex(i, form_value)) 380 is_declaration = form_value.Unsigned() != 0; 381 break; 382 383 // case DW_AT_artificial: 384 // if (attributes.ExtractFormValueAtIndex(i, 385 // form_value)) 386 // is_artificial = form_value.Unsigned() != 0; 387 // break; 388 389 case DW_AT_MIPS_linkage_name: 390 case DW_AT_linkage_name: 391 if (attributes.ExtractFormValueAtIndex(i, form_value)) 392 mangled_cstr = form_value.AsCString(); 393 break; 394 395 case DW_AT_low_pc: 396 case DW_AT_high_pc: 397 case DW_AT_ranges: 398 has_address = true; 399 break; 400 401 case DW_AT_entry_pc: 402 has_address = true; 403 break; 404 405 case DW_AT_location: 406 case DW_AT_const_value: 407 has_location_or_const_value = true; 408 if (tag == DW_TAG_variable) { 409 const DWARFDebugInfoEntry *parent_die = die.GetParent(); 410 while (parent_die != NULL) { 411 switch (parent_die->Tag()) { 412 case DW_TAG_subprogram: 413 case DW_TAG_lexical_block: 414 case DW_TAG_inlined_subroutine: 415 // Even if this is a function level static, we don't add it. We 416 // could theoretically 417 // add these if we wanted to by introspecting into the 418 // DW_AT_location and seeing 419 // if the location describes a hard coded address, but we dont 420 // want the performance 421 // penalty of that right now. 422 is_global_or_static_variable = false; 423 // if 424 // (attributes.ExtractFormValueAtIndex(dwarf2Data, 425 // i, form_value)) 426 // { 427 // // If we have valid block 428 // data, then we have location 429 // expression bytes 430 // // that are fixed (not a 431 // location list). 432 // const uint8_t *block_data = 433 // form_value.BlockData(); 434 // if (block_data) 435 // { 436 // uint32_t block_length = 437 // form_value.Unsigned(); 438 // if (block_length == 1 + 439 // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) 440 // { 441 // if (block_data[0] == 442 // DW_OP_addr) 443 // add_die = true; 444 // } 445 // } 446 // } 447 parent_die = NULL; // Terminate the while loop. 448 break; 449 450 case DW_TAG_compile_unit: 451 is_global_or_static_variable = true; 452 parent_die = NULL; // Terminate the while loop. 453 break; 454 455 default: 456 parent_die = 457 parent_die->GetParent(); // Keep going in the while loop. 458 break; 459 } 460 } 461 } 462 break; 463 464 case DW_AT_specification: 465 if (attributes.ExtractFormValueAtIndex(i, form_value)) 466 specification_die_form = form_value; 467 break; 468 } 469 } 470 } 471 472 switch (tag) { 473 case DW_TAG_subprogram: 474 if (has_address) { 475 if (name) { 476 ObjCLanguage::MethodName objc_method(name, true); 477 if (objc_method.IsValid(true)) { 478 ConstString objc_class_name_with_category( 479 objc_method.GetClassNameWithCategory()); 480 ConstString objc_selector_name(objc_method.GetSelector()); 481 ConstString objc_fullname_no_category_name( 482 objc_method.GetFullNameWithoutCategory(true)); 483 ConstString objc_class_name_no_category(objc_method.GetClassName()); 484 func_fullnames.Insert(ConstString(name), 485 DIERef(cu_offset, die.GetOffset())); 486 if (objc_class_name_with_category) 487 objc_class_selectors.Insert(objc_class_name_with_category, 488 DIERef(cu_offset, die.GetOffset())); 489 if (objc_class_name_no_category && 490 objc_class_name_no_category != objc_class_name_with_category) 491 objc_class_selectors.Insert(objc_class_name_no_category, 492 DIERef(cu_offset, die.GetOffset())); 493 if (objc_selector_name) 494 func_selectors.Insert(objc_selector_name, 495 DIERef(cu_offset, die.GetOffset())); 496 if (objc_fullname_no_category_name) 497 func_fullnames.Insert(objc_fullname_no_category_name, 498 DIERef(cu_offset, die.GetOffset())); 499 } 500 // If we have a mangled name, then the DW_AT_name attribute 501 // is usually the method name without the class or any parameters 502 const DWARFDebugInfoEntry *parent = die.GetParent(); 503 bool is_method = false; 504 if (parent) { 505 dw_tag_t parent_tag = parent->Tag(); 506 if (parent_tag == DW_TAG_class_type || 507 parent_tag == DW_TAG_structure_type) { 508 is_method = true; 509 } else { 510 if (specification_die_form.IsValid()) { 511 DWARFDIE specification_die = 512 dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE( 513 DIERef(specification_die_form)); 514 if (specification_die.GetParent().IsStructOrClass()) 515 is_method = true; 516 } 517 } 518 } 519 520 if (is_method) 521 func_methods.Insert(ConstString(name), 522 DIERef(cu_offset, die.GetOffset())); 523 else 524 func_basenames.Insert(ConstString(name), 525 DIERef(cu_offset, die.GetOffset())); 526 527 if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) 528 func_fullnames.Insert(ConstString(name), 529 DIERef(cu_offset, die.GetOffset())); 530 } 531 if (mangled_cstr) { 532 // Make sure our mangled name isn't the same string table entry 533 // as our name. If it starts with '_', then it is ok, else compare 534 // the string to make sure it isn't the same and we don't end up 535 // with duplicate entries 536 if (name && name != mangled_cstr && 537 ((mangled_cstr[0] == '_') || 538 (::strcmp(name, mangled_cstr) != 0))) { 539 Mangled mangled(ConstString(mangled_cstr), true); 540 func_fullnames.Insert(mangled.GetMangledName(), 541 DIERef(cu_offset, die.GetOffset())); 542 ConstString demangled = mangled.GetDemangledName(cu_language); 543 if (demangled) 544 func_fullnames.Insert(demangled, 545 DIERef(cu_offset, die.GetOffset())); 546 } 547 } 548 } 549 break; 550 551 case DW_TAG_inlined_subroutine: 552 if (has_address) { 553 if (name) 554 func_basenames.Insert(ConstString(name), 555 DIERef(cu_offset, die.GetOffset())); 556 if (mangled_cstr) { 557 // Make sure our mangled name isn't the same string table entry 558 // as our name. If it starts with '_', then it is ok, else compare 559 // the string to make sure it isn't the same and we don't end up 560 // with duplicate entries 561 if (name && name != mangled_cstr && 562 ((mangled_cstr[0] == '_') || 563 (::strcmp(name, mangled_cstr) != 0))) { 564 Mangled mangled(ConstString(mangled_cstr), true); 565 func_fullnames.Insert(mangled.GetMangledName(), 566 DIERef(cu_offset, die.GetOffset())); 567 ConstString demangled = mangled.GetDemangledName(cu_language); 568 if (demangled) 569 func_fullnames.Insert(demangled, 570 DIERef(cu_offset, die.GetOffset())); 571 } 572 } else 573 func_fullnames.Insert(ConstString(name), 574 DIERef(cu_offset, die.GetOffset())); 575 } 576 break; 577 578 case DW_TAG_array_type: 579 case DW_TAG_base_type: 580 case DW_TAG_class_type: 581 case DW_TAG_constant: 582 case DW_TAG_enumeration_type: 583 case DW_TAG_string_type: 584 case DW_TAG_structure_type: 585 case DW_TAG_subroutine_type: 586 case DW_TAG_typedef: 587 case DW_TAG_union_type: 588 case DW_TAG_unspecified_type: 589 if (name && !is_declaration) 590 types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); 591 if (mangled_cstr && !is_declaration) 592 types.Insert(ConstString(mangled_cstr), 593 DIERef(cu_offset, die.GetOffset())); 594 break; 595 596 case DW_TAG_namespace: 597 if (name) 598 namespaces.Insert(ConstString(name), 599 DIERef(cu_offset, die.GetOffset())); 600 break; 601 602 case DW_TAG_variable: 603 if (name && has_location_or_const_value && is_global_or_static_variable) { 604 globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); 605 // Be sure to include variables by their mangled and demangled 606 // names if they have any since a variable can have a basename 607 // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled 608 // mangled name "(anonymous namespace)::i"... 609 610 // Make sure our mangled name isn't the same string table entry 611 // as our name. If it starts with '_', then it is ok, else compare 612 // the string to make sure it isn't the same and we don't end up 613 // with duplicate entries 614 if (mangled_cstr && name != mangled_cstr && 615 ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { 616 Mangled mangled(ConstString(mangled_cstr), true); 617 globals.Insert(mangled.GetMangledName(), 618 DIERef(cu_offset, die.GetOffset())); 619 ConstString demangled = mangled.GetDemangledName(cu_language); 620 if (demangled) 621 globals.Insert(demangled, DIERef(cu_offset, die.GetOffset())); 622 } 623 } 624 break; 625 626 default: 627 continue; 628 } 629 } 630 } 631