1 //===-- DWARFDIE.cpp ------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DWARFDIE.h" 10 11 #include "DWARFASTParser.h" 12 #include "DWARFDebugInfo.h" 13 #include "DWARFDebugInfoEntry.h" 14 #include "DWARFDeclContext.h" 15 #include "DWARFUnit.h" 16 #include "lldb/Symbol/Type.h" 17 18 #include "llvm/ADT/iterator.h" 19 #include "llvm/BinaryFormat/Dwarf.h" 20 21 using namespace lldb_private; 22 using namespace lldb_private::dwarf; 23 using namespace lldb_private::plugin::dwarf; 24 25 namespace { 26 27 /// Iterate through all DIEs elaborating (i.e. reachable by a chain of 28 /// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For 29 /// convenience, the starting die is included in the sequence as the first 30 /// item. 31 class ElaboratingDIEIterator 32 : public llvm::iterator_facade_base< 33 ElaboratingDIEIterator, std::input_iterator_tag, DWARFDIE, 34 std::ptrdiff_t, DWARFDIE *, DWARFDIE *> { 35 36 // The operating invariant is: top of m_worklist contains the "current" item 37 // and the rest of the list are items yet to be visited. An empty worklist 38 // means we've reached the end. 39 // Infinite recursion is prevented by maintaining a list of seen DIEs. 40 // Container sizes are optimized for the case of following DW_AT_specification 41 // and DW_AT_abstract_origin just once. 42 llvm::SmallVector<DWARFDIE, 2> m_worklist; 43 llvm::SmallSet<DWARFDebugInfoEntry *, 3> m_seen; 44 45 void Next() { 46 assert(!m_worklist.empty() && "Incrementing end iterator?"); 47 48 // Pop the current item from the list. 49 DWARFDIE die = m_worklist.back(); 50 m_worklist.pop_back(); 51 52 // And add back any items that elaborate it. 53 for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) { 54 if (DWARFDIE d = die.GetReferencedDIE(attr)) 55 if (m_seen.insert(die.GetDIE()).second) 56 m_worklist.push_back(d); 57 } 58 } 59 60 public: 61 /// An iterator starting at die d. 62 explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {} 63 64 /// End marker 65 ElaboratingDIEIterator() = default; 66 67 const DWARFDIE &operator*() const { return m_worklist.back(); } 68 ElaboratingDIEIterator &operator++() { 69 Next(); 70 return *this; 71 } 72 73 friend bool operator==(const ElaboratingDIEIterator &a, 74 const ElaboratingDIEIterator &b) { 75 if (a.m_worklist.empty() || b.m_worklist.empty()) 76 return a.m_worklist.empty() == b.m_worklist.empty(); 77 return a.m_worklist.back() == b.m_worklist.back(); 78 } 79 }; 80 81 llvm::iterator_range<ElaboratingDIEIterator> 82 elaborating_dies(const DWARFDIE &die) { 83 return llvm::make_range(ElaboratingDIEIterator(die), 84 ElaboratingDIEIterator()); 85 } 86 } // namespace 87 88 DWARFDIE 89 DWARFDIE::GetParent() const { 90 if (IsValid()) 91 return DWARFDIE(m_cu, m_die->GetParent()); 92 else 93 return DWARFDIE(); 94 } 95 96 DWARFDIE 97 DWARFDIE::GetFirstChild() const { 98 if (IsValid()) 99 return DWARFDIE(m_cu, m_die->GetFirstChild()); 100 else 101 return DWARFDIE(); 102 } 103 104 DWARFDIE 105 DWARFDIE::GetSibling() const { 106 if (IsValid()) 107 return DWARFDIE(m_cu, m_die->GetSibling()); 108 else 109 return DWARFDIE(); 110 } 111 112 DWARFDIE 113 DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const { 114 if (IsValid()) 115 return m_die->GetAttributeValueAsReference(GetCU(), attr); 116 else 117 return {}; 118 } 119 120 DWARFDIE 121 DWARFDIE::GetDIE(dw_offset_t die_offset) const { 122 if (IsValid()) 123 return m_cu->GetDIE(die_offset); 124 else 125 return DWARFDIE(); 126 } 127 128 DWARFDIE 129 DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const { 130 if (IsValid()) { 131 DWARFUnit *cu = GetCU(); 132 const bool check_specification_or_abstract_origin = true; 133 DWARFFormValue form_value; 134 if (m_die->GetAttributeValue(cu, attr, form_value, nullptr, 135 check_specification_or_abstract_origin)) 136 return form_value.Reference(); 137 } 138 return DWARFDIE(); 139 } 140 141 DWARFDIE 142 DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const { 143 if (!IsValid()) 144 return DWARFDIE(); 145 146 DWARFDIE result; 147 bool check_children = false; 148 bool match_addr_range = false; 149 switch (Tag()) { 150 case DW_TAG_class_type: 151 case DW_TAG_namespace: 152 case DW_TAG_structure_type: 153 case DW_TAG_common_block: 154 check_children = true; 155 break; 156 case DW_TAG_compile_unit: 157 case DW_TAG_module: 158 case DW_TAG_catch_block: 159 case DW_TAG_subprogram: 160 case DW_TAG_try_block: 161 case DW_TAG_partial_unit: 162 match_addr_range = true; 163 break; 164 case DW_TAG_lexical_block: 165 case DW_TAG_inlined_subroutine: 166 check_children = true; 167 match_addr_range = true; 168 break; 169 default: 170 break; 171 } 172 173 if (match_addr_range) { 174 DWARFRangeList ranges = 175 m_die->GetAttributeAddressRanges(m_cu, /*check_hi_lo_pc=*/true); 176 if (ranges.FindEntryThatContains(address)) { 177 check_children = true; 178 switch (Tag()) { 179 default: 180 break; 181 182 case DW_TAG_inlined_subroutine: // Inlined Function 183 case DW_TAG_lexical_block: // Block { } in code 184 result = *this; 185 break; 186 } 187 } else { 188 check_children = false; 189 } 190 } 191 192 if (check_children) { 193 for (DWARFDIE child : children()) { 194 if (DWARFDIE child_result = child.LookupDeepestBlock(address)) 195 return child_result; 196 } 197 } 198 return result; 199 } 200 201 const char *DWARFDIE::GetMangledName() const { 202 if (IsValid()) 203 return m_die->GetMangledName(m_cu); 204 else 205 return nullptr; 206 } 207 208 const char *DWARFDIE::GetPubname() const { 209 if (IsValid()) 210 return m_die->GetPubname(m_cu); 211 else 212 return nullptr; 213 } 214 215 // GetName 216 // 217 // Get value of the DW_AT_name attribute and place that value into the supplied 218 // stream object. If the DIE is a NULL object "NULL" is placed into the stream, 219 // and if no DW_AT_name attribute exists for the DIE then nothing is printed. 220 void DWARFDIE::GetName(Stream &s) const { 221 if (!IsValid()) 222 return; 223 if (GetDIE()->IsNULL()) { 224 s.PutCString("NULL"); 225 return; 226 } 227 const char *name = GetDIE()->GetAttributeValueAsString(GetCU(), DW_AT_name, nullptr, true); 228 if (!name) 229 return; 230 s.PutCString(name); 231 } 232 233 // AppendTypeName 234 // 235 // Follows the type name definition down through all needed tags to end up with 236 // a fully qualified type name and dump the results to the supplied stream. 237 // This is used to show the name of types given a type identifier. 238 void DWARFDIE::AppendTypeName(Stream &s) const { 239 if (!IsValid()) 240 return; 241 if (GetDIE()->IsNULL()) { 242 s.PutCString("NULL"); 243 return; 244 } 245 if (const char *name = GetPubname()) { 246 s.PutCString(name); 247 return; 248 } 249 switch (Tag()) { 250 case DW_TAG_array_type: 251 break; // print out a "[]" after printing the full type of the element 252 // below 253 case DW_TAG_base_type: 254 s.PutCString("base "); 255 break; 256 case DW_TAG_class_type: 257 s.PutCString("class "); 258 break; 259 case DW_TAG_const_type: 260 s.PutCString("const "); 261 break; 262 case DW_TAG_enumeration_type: 263 s.PutCString("enum "); 264 break; 265 case DW_TAG_file_type: 266 s.PutCString("file "); 267 break; 268 case DW_TAG_interface_type: 269 s.PutCString("interface "); 270 break; 271 case DW_TAG_packed_type: 272 s.PutCString("packed "); 273 break; 274 case DW_TAG_pointer_type: 275 break; // print out a '*' after printing the full type below 276 case DW_TAG_ptr_to_member_type: 277 break; // print out a '*' after printing the full type below 278 case DW_TAG_reference_type: 279 break; // print out a '&' after printing the full type below 280 case DW_TAG_restrict_type: 281 s.PutCString("restrict "); 282 break; 283 case DW_TAG_set_type: 284 s.PutCString("set "); 285 break; 286 case DW_TAG_shared_type: 287 s.PutCString("shared "); 288 break; 289 case DW_TAG_string_type: 290 s.PutCString("string "); 291 break; 292 case DW_TAG_structure_type: 293 s.PutCString("struct "); 294 break; 295 case DW_TAG_subrange_type: 296 s.PutCString("subrange "); 297 break; 298 case DW_TAG_subroutine_type: 299 s.PutCString("function "); 300 break; 301 case DW_TAG_thrown_type: 302 s.PutCString("thrown "); 303 break; 304 case DW_TAG_union_type: 305 s.PutCString("union "); 306 break; 307 case DW_TAG_unspecified_type: 308 s.PutCString("unspecified "); 309 break; 310 case DW_TAG_volatile_type: 311 s.PutCString("volatile "); 312 break; 313 case DW_TAG_LLVM_ptrauth_type: { 314 unsigned key = GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_key, 0); 315 bool isAddressDiscriminated = GetAttributeValueAsUnsigned( 316 DW_AT_LLVM_ptrauth_address_discriminated, 0); 317 unsigned extraDiscriminator = 318 GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_extra_discriminator, 0); 319 bool isaPointer = 320 GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_isa_pointer, 0); 321 bool authenticatesNullValues = GetAttributeValueAsUnsigned( 322 DW_AT_LLVM_ptrauth_authenticates_null_values, 0); 323 unsigned authenticationMode = 324 GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_authentication_mode, 3); 325 326 s.Printf("__ptrauth(%d, %d, 0x0%x, %d, %d, %d)", key, 327 isAddressDiscriminated, extraDiscriminator, isaPointer, 328 authenticatesNullValues, authenticationMode); 329 break; 330 } 331 default: 332 return; 333 } 334 335 // Follow the DW_AT_type if possible 336 if (DWARFDIE next_die = GetAttributeValueAsReferenceDIE(DW_AT_type)) 337 next_die.AppendTypeName(s); 338 339 switch (Tag()) { 340 case DW_TAG_array_type: 341 s.PutCString("[]"); 342 break; 343 case DW_TAG_pointer_type: 344 s.PutChar('*'); 345 break; 346 case DW_TAG_ptr_to_member_type: 347 s.PutChar('*'); 348 break; 349 case DW_TAG_reference_type: 350 s.PutChar('&'); 351 break; 352 default: 353 break; 354 } 355 } 356 357 lldb_private::Type *DWARFDIE::ResolveType() const { 358 if (IsValid()) 359 return GetDWARF()->ResolveType(*this, true); 360 else 361 return nullptr; 362 } 363 364 lldb_private::Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const { 365 if (SymbolFileDWARF *dwarf = GetDWARF()) 366 return dwarf->ResolveTypeUID(die, true); 367 return nullptr; 368 } 369 370 static void GetDeclContextImpl(DWARFDIE die, 371 llvm::SmallSet<lldb::user_id_t, 4> &seen, 372 std::vector<CompilerContext> &context) { 373 // Stop if we hit a cycle. 374 while (die && seen.insert(die.GetID()).second) { 375 // Handle outline member function DIEs by following the specification. 376 if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_specification)) { 377 die = spec; 378 continue; 379 } 380 // To find the name of a type in a type unit, we must follow the signature. 381 if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_signature)) { 382 die = spec; 383 continue; 384 } 385 386 // Add this DIE's contribution at the end of the chain. 387 auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { 388 context.push_back({kind, ConstString(name)}); 389 }; 390 switch (die.Tag()) { 391 case DW_TAG_module: 392 push_ctx(CompilerContextKind::Module, die.GetName()); 393 break; 394 case DW_TAG_namespace: 395 push_ctx(CompilerContextKind::Namespace, die.GetName()); 396 break; 397 case DW_TAG_class_type: 398 case DW_TAG_structure_type: 399 push_ctx(CompilerContextKind::ClassOrStruct, die.GetName()); 400 break; 401 case DW_TAG_union_type: 402 push_ctx(CompilerContextKind::Union, die.GetName()); 403 break; 404 case DW_TAG_enumeration_type: 405 push_ctx(CompilerContextKind::Enum, die.GetName()); 406 break; 407 case DW_TAG_subprogram: 408 push_ctx(CompilerContextKind::Function, die.GetName()); 409 break; 410 case DW_TAG_variable: 411 push_ctx(CompilerContextKind::Variable, die.GetPubname()); 412 break; 413 case DW_TAG_typedef: 414 push_ctx(CompilerContextKind::Typedef, die.GetName()); 415 break; 416 default: 417 break; 418 } 419 // Now process the parent. 420 die = die.GetParent(); 421 } 422 } 423 424 std::vector<CompilerContext> DWARFDIE::GetDeclContext() const { 425 llvm::SmallSet<lldb::user_id_t, 4> seen; 426 std::vector<CompilerContext> context; 427 GetDeclContextImpl(*this, seen, context); 428 std::reverse(context.begin(), context.end()); 429 return context; 430 } 431 432 static void GetTypeLookupContextImpl(DWARFDIE die, 433 llvm::SmallSet<lldb::user_id_t, 4> &seen, 434 std::vector<CompilerContext> &context) { 435 // Stop if we hit a cycle. 436 while (die && seen.insert(die.GetID()).second) { 437 // To find the name of a type in a type unit, we must follow the signature. 438 if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_signature)) { 439 die = spec; 440 continue; 441 } 442 443 // If there is no name, then there is no need to look anything up for this 444 // DIE. 445 const char *name = die.GetName(); 446 if (!name || !name[0]) 447 return; 448 449 // Add this DIE's contribution at the end of the chain. 450 auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { 451 context.push_back({kind, ConstString(name)}); 452 }; 453 switch (die.Tag()) { 454 case DW_TAG_namespace: 455 push_ctx(CompilerContextKind::Namespace, die.GetName()); 456 break; 457 case DW_TAG_class_type: 458 case DW_TAG_structure_type: 459 push_ctx(CompilerContextKind::ClassOrStruct, die.GetName()); 460 break; 461 case DW_TAG_union_type: 462 push_ctx(CompilerContextKind::Union, die.GetName()); 463 break; 464 case DW_TAG_enumeration_type: 465 push_ctx(CompilerContextKind::Enum, die.GetName()); 466 break; 467 case DW_TAG_variable: 468 push_ctx(CompilerContextKind::Variable, die.GetPubname()); 469 break; 470 case DW_TAG_typedef: 471 push_ctx(CompilerContextKind::Typedef, die.GetName()); 472 break; 473 case DW_TAG_base_type: 474 push_ctx(CompilerContextKind::Builtin, name); 475 break; 476 // If any of the tags below appear in the parent chain, stop the decl 477 // context and return. Prior to these being in here, if a type existed in a 478 // namespace "a" like "a::my_struct", but we also have a function in that 479 // same namespace "a" which contained a type named "my_struct", both would 480 // return "a::my_struct" as the declaration context since the 481 // DW_TAG_subprogram would be skipped and its parent would be found. 482 case DW_TAG_compile_unit: 483 case DW_TAG_type_unit: 484 case DW_TAG_subprogram: 485 case DW_TAG_lexical_block: 486 case DW_TAG_inlined_subroutine: 487 return; 488 default: 489 break; 490 } 491 // Now process the parent. 492 die = die.GetParent(); 493 } 494 } 495 496 std::vector<CompilerContext> DWARFDIE::GetTypeLookupContext() const { 497 llvm::SmallSet<lldb::user_id_t, 4> seen; 498 std::vector<CompilerContext> context; 499 GetTypeLookupContextImpl(*this, seen, context); 500 std::reverse(context.begin(), context.end()); 501 return context; 502 } 503 504 static DWARFDeclContext GetDWARFDeclContextImpl(DWARFDIE die) { 505 DWARFDeclContext dwarf_decl_ctx; 506 while (die) { 507 const dw_tag_t tag = die.Tag(); 508 if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) 509 break; 510 dwarf_decl_ctx.AppendDeclContext(tag, die.GetName()); 511 DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE(); 512 if (parent_decl_ctx_die == die) 513 break; 514 die = parent_decl_ctx_die; 515 } 516 return dwarf_decl_ctx; 517 } 518 519 DWARFDeclContext DWARFDIE::GetDWARFDeclContext() const { 520 return GetDWARFDeclContextImpl(*this); 521 } 522 523 static DWARFDIE GetParentDeclContextDIEImpl(DWARFDIE die) { 524 DWARFDIE orig_die = die; 525 while (die) { 526 // If this is the original DIE that we are searching for a declaration for, 527 // then don't look in the cache as we don't want our own decl context to be 528 // our decl context... 529 if (die != orig_die) { 530 switch (die.Tag()) { 531 case DW_TAG_compile_unit: 532 case DW_TAG_partial_unit: 533 case DW_TAG_namespace: 534 case DW_TAG_structure_type: 535 case DW_TAG_union_type: 536 case DW_TAG_class_type: 537 return die; 538 539 default: 540 break; 541 } 542 } 543 544 if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) { 545 if (DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE()) 546 return decl_ctx_die; 547 } 548 549 if (DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin)) { 550 if (DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE()) 551 return decl_ctx_die; 552 } 553 554 die = die.GetParent(); 555 } 556 return DWARFDIE(); 557 } 558 559 DWARFDIE 560 DWARFDIE::GetParentDeclContextDIE() const { 561 return GetParentDeclContextDIEImpl(*this); 562 } 563 564 bool DWARFDIE::IsStructUnionOrClass() const { 565 const dw_tag_t tag = Tag(); 566 return tag == DW_TAG_class_type || tag == DW_TAG_structure_type || 567 tag == DW_TAG_union_type; 568 } 569 570 bool DWARFDIE::IsMethod() const { 571 for (DWARFDIE d : elaborating_dies(*this)) 572 if (d.GetParent().IsStructUnionOrClass()) 573 return true; 574 return false; 575 } 576 577 bool DWARFDIE::GetDIENamesAndRanges( 578 const char *&name, const char *&mangled, DWARFRangeList &ranges, 579 std::optional<int> &decl_file, std::optional<int> &decl_line, 580 std::optional<int> &decl_column, std::optional<int> &call_file, 581 std::optional<int> &call_line, std::optional<int> &call_column, 582 lldb_private::DWARFExpressionList *frame_base) const { 583 if (IsValid()) { 584 return m_die->GetDIENamesAndRanges( 585 GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, 586 call_file, call_line, call_column, frame_base); 587 } else 588 return false; 589 } 590 591 llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const { 592 return llvm::make_range(child_iterator(*this), child_iterator()); 593 } 594