1 //===-- DebugNamesDWARFIndex.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 "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h" 10 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 12 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" 13 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Utility/RegularExpression.h" 16 #include "lldb/Utility/Stream.h" 17 #include "llvm/ADT/Sequence.h" 18 #include <optional> 19 20 using namespace lldb_private; 21 using namespace lldb; 22 using namespace lldb_private::dwarf; 23 using namespace lldb_private::plugin::dwarf; 24 25 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> 26 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, 27 DWARFDataExtractor debug_str, 28 SymbolFileDWARF &dwarf) { 29 auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVMDWARF(), 30 debug_str.GetAsLLVM()); 31 if (llvm::Error E = index_up->extract()) 32 return std::move(E); 33 34 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex( 35 module, std::move(index_up), debug_names, debug_str, dwarf)); 36 } 37 38 llvm::DenseSet<uint64_t> 39 DebugNamesDWARFIndex::GetTypeUnitSignatures(const DebugNames &debug_names) { 40 llvm::DenseSet<uint64_t> result; 41 for (const DebugNames::NameIndex &ni : debug_names) { 42 const uint32_t num_tus = ni.getForeignTUCount(); 43 for (uint32_t tu = 0; tu < num_tus; ++tu) 44 result.insert(ni.getForeignTUSignature(tu)); 45 } 46 return result; 47 } 48 49 llvm::DenseSet<dw_offset_t> 50 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { 51 llvm::DenseSet<dw_offset_t> result; 52 for (const DebugNames::NameIndex &ni : debug_names) { 53 const uint32_t num_cus = ni.getCUCount(); 54 for (uint32_t cu = 0; cu < num_cus; ++cu) 55 result.insert(ni.getCUOffset(cu)); 56 const uint32_t num_tus = ni.getLocalTUCount(); 57 for (uint32_t tu = 0; tu < num_tus; ++tu) 58 result.insert(ni.getLocalTUOffset(tu)); 59 } 60 return result; 61 } 62 63 std::optional<DWARFTypeUnit *> 64 DebugNamesDWARFIndex::GetForeignTypeUnit(const DebugNames::Entry &entry) const { 65 std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature(); 66 if (!type_sig.has_value()) 67 return std::nullopt; 68 69 // Ask the entry for the skeleton compile unit offset and fetch the .dwo 70 // file from it and get the type unit by signature from there. If we find 71 // the type unit in the .dwo file, we don't need to check that the 72 // DW_AT_dwo_name matches because each .dwo file can have its own type unit. 73 std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset(); 74 if (!cu_offset) 75 return nullptr; // Return NULL, this is a type unit, but couldn't find it. 76 77 DWARFUnit *cu = 78 m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); 79 if (!cu) 80 return nullptr; // Return NULL, this is a type unit, but couldn't find it. 81 82 auto dwp_sp = m_debug_info.GetDwpSymbolFile(); 83 if (!dwp_sp) { 84 // No .dwp file, we need to load the .dwo file. 85 DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit(); 86 // We don't need the check if the type unit matches the .dwo file if we have 87 // a .dwo file (not a .dwp), so we can just return the value here. 88 if (!dwo_cu.IsDWOUnit()) 89 return nullptr; // We weren't able to load the .dwo file. 90 return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash( 91 *type_sig); 92 } 93 // We have a .dwp file, just get the type unit from there. We need to verify 94 // that the type unit that ended up in the final .dwp file is the right type 95 // unit. Type units have signatures which are the same across multiple .dwo 96 // files, but only one of those type units will end up in the .dwp file. The 97 // contents of type units for the same type can be different in different .dwo 98 // files, which means the DIE offsets might not be the same between two 99 // different type units. So we need to determine if this accelerator table 100 // matches the type unit that ended up in the .dwp file. If it doesn't match, 101 // then we need to ignore this accelerator table entry as the type unit that 102 // is in the .dwp file will have its own index. In order to determine if the 103 // type unit that ended up in a .dwp file matches this DebugNames::Entry, we 104 // need to find the skeleton compile unit for this entry. 105 DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig); 106 if (!foreign_tu) 107 return nullptr; // Return NULL, this is a type unit, but couldn't find it. 108 109 DWARFBaseDIE cu_die = cu->GetUnitDIEOnly(); 110 DWARFBaseDIE tu_die = foreign_tu->GetUnitDIEOnly(); 111 llvm::StringRef cu_dwo_name = 112 cu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr); 113 llvm::StringRef tu_dwo_name = 114 tu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr); 115 if (cu_dwo_name == tu_dwo_name) 116 return foreign_tu; // We found a match! 117 return nullptr; // Return NULL, this is a type unit, but couldn't find it. 118 } 119 120 DWARFUnit * 121 DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const { 122 123 if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry)) 124 return foreign_tu.value(); 125 126 // Look for a DWARF unit offset (CU offset or local TU offset) as they are 127 // both offsets into the .debug_info section. 128 std::optional<uint64_t> unit_offset = entry.getCUOffset(); 129 if (!unit_offset) 130 unit_offset = entry.getLocalTUOffset(); 131 if (unit_offset) { 132 if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, 133 *unit_offset)) 134 return &cu->GetNonSkeletonUnit(); 135 } 136 return nullptr; 137 } 138 139 DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const { 140 DWARFUnit *unit = GetNonSkeletonUnit(entry); 141 std::optional<uint64_t> die_offset = entry.getDIEUnitOffset(); 142 if (!unit || !die_offset) 143 return DWARFDIE(); 144 if (DWARFDIE die = unit->GetDIE(unit->GetOffset() + *die_offset)) 145 return die; 146 147 m_module.ReportErrorIfModifyDetected( 148 "the DWARF debug information has been modified (bad offset {0:x} in " 149 "debug_names section)\n", 150 *die_offset); 151 return DWARFDIE(); 152 } 153 154 bool DebugNamesDWARFIndex::ProcessEntry( 155 const DebugNames::Entry &entry, 156 llvm::function_ref<bool(DWARFDIE die)> callback) { 157 DWARFDIE die = GetDIE(entry); 158 if (!die) 159 return true; 160 // Clang used to erroneously emit index entries for declaration DIEs in case 161 // when the definition is in a type unit (llvm.org/pr77696). 162 if (die.IsStructUnionOrClass() && 163 die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0)) 164 return true; 165 return callback(die); 166 } 167 168 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, 169 const DebugNames::NameIndex &ni, 170 llvm::StringRef name) { 171 // Ignore SentinelErrors, log everything else. 172 LLDB_LOG_ERROR( 173 GetLog(DWARFLog::Lookups), 174 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}), 175 "Failed to parse index entries for index at {1:x}, name {2}: {0}", 176 ni.getUnitOffset(), name); 177 } 178 179 void DebugNamesDWARFIndex::GetGlobalVariables( 180 ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) { 181 for (const DebugNames::Entry &entry : 182 m_debug_names_up->equal_range(basename.GetStringRef())) { 183 if (entry.tag() != DW_TAG_variable) 184 continue; 185 186 if (!ProcessEntry(entry, callback)) 187 return; 188 } 189 190 m_fallback.GetGlobalVariables(basename, callback); 191 } 192 193 void DebugNamesDWARFIndex::GetGlobalVariables( 194 const RegularExpression ®ex, 195 llvm::function_ref<bool(DWARFDIE die)> callback) { 196 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 197 for (DebugNames::NameTableEntry nte: ni) { 198 Mangled mangled_name(nte.getString()); 199 if (!mangled_name.NameMatches(regex)) 200 continue; 201 202 uint64_t entry_offset = nte.getEntryOffset(); 203 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 204 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 205 if (entry_or->tag() != DW_TAG_variable) 206 continue; 207 208 if (!ProcessEntry(*entry_or, callback)) 209 return; 210 } 211 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 212 } 213 } 214 215 m_fallback.GetGlobalVariables(regex, callback); 216 } 217 218 void DebugNamesDWARFIndex::GetGlobalVariables( 219 DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) { 220 uint64_t cu_offset = cu.GetOffset(); 221 bool found_entry_for_cu = false; 222 for (const DebugNames::NameIndex &ni : *m_debug_names_up) { 223 // Check if this name index contains an entry for the given CU. 224 bool cu_matches = false; 225 for (uint32_t i = 0; i < ni.getCUCount(); ++i) { 226 if (ni.getCUOffset(i) == cu_offset) { 227 cu_matches = true; 228 break; 229 } 230 } 231 if (!cu_matches) 232 continue; 233 234 for (DebugNames::NameTableEntry nte : ni) { 235 uint64_t entry_offset = nte.getEntryOffset(); 236 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 237 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 238 if (entry_or->tag() != DW_TAG_variable) 239 continue; 240 if (entry_or->getCUOffset() != cu_offset) 241 continue; 242 243 found_entry_for_cu = true; 244 if (!ProcessEntry(*entry_or, callback)) 245 return; 246 } 247 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 248 } 249 } 250 // If no name index for that particular CU was found, fallback to 251 // creating the manual index. 252 if (!found_entry_for_cu) 253 m_fallback.GetGlobalVariables(cu, callback); 254 } 255 256 void DebugNamesDWARFIndex::GetCompleteObjCClass( 257 ConstString class_name, bool must_be_implementation, 258 llvm::function_ref<bool(DWARFDIE die)> callback) { 259 // Keep a list of incomplete types as fallback for when we don't find the 260 // complete type. 261 std::vector<DWARFDIE> incomplete_types; 262 263 for (const DebugNames::Entry &entry : 264 m_debug_names_up->equal_range(class_name.GetStringRef())) { 265 if (entry.tag() != DW_TAG_structure_type && 266 entry.tag() != DW_TAG_class_type) 267 continue; 268 269 DWARFDIE die = GetDIE(entry); 270 if (!die) { 271 // Report invalid 272 continue; 273 } 274 DWARFUnit *cu = die.GetCU(); 275 if (!cu->Supports_DW_AT_APPLE_objc_complete_type()) { 276 incomplete_types.push_back(die); 277 continue; 278 } 279 280 if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { 281 // If we find the complete version we're done. 282 callback(die); 283 return; 284 } 285 incomplete_types.push_back(die); 286 } 287 288 for (DWARFDIE die : incomplete_types) 289 if (!callback(die)) 290 return; 291 292 m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback); 293 } 294 295 namespace { 296 using Entry = llvm::DWARFDebugNames::Entry; 297 298 /// If `entry` and all of its parents have an `IDX_parent`, use that information 299 /// to build and return a list of at most `max_parents` parent Entries. 300 /// `entry` itself is not included in the list. 301 /// If any parent does not have an `IDX_parent`, or the Entry data is corrupted, 302 /// nullopt is returned. 303 std::optional<llvm::SmallVector<Entry, 4>> 304 getParentChain(Entry entry, uint32_t max_parents) { 305 llvm::SmallVector<Entry, 4> parent_entries; 306 307 do { 308 if (!entry.hasParentInformation()) 309 return std::nullopt; 310 311 llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry(); 312 if (!parent) { 313 // Bad data. 314 LLDB_LOG_ERROR( 315 GetLog(DWARFLog::Lookups), parent.takeError(), 316 "Failed to extract parent entry from a non-empty IDX_parent"); 317 return std::nullopt; 318 } 319 320 // Last parent in the chain. 321 if (!parent->has_value()) 322 break; 323 324 parent_entries.push_back(**parent); 325 entry = **parent; 326 } while (parent_entries.size() < max_parents); 327 328 return parent_entries; 329 } 330 } // namespace 331 332 void DebugNamesDWARFIndex::GetFullyQualifiedType( 333 const DWARFDeclContext &context, 334 llvm::function_ref<bool(DWARFDIE die)> callback) { 335 if (context.GetSize() == 0) 336 return; 337 338 llvm::StringRef leaf_name = context[0].name; 339 llvm::SmallVector<llvm::StringRef> parent_names; 340 for (auto idx : llvm::seq<int>(1, context.GetSize())) 341 parent_names.emplace_back(context[idx].name); 342 343 // For each entry, grab its parent chain and check if we have a match. 344 for (const DebugNames::Entry &entry : 345 m_debug_names_up->equal_range(leaf_name)) { 346 if (!isType(entry.tag())) 347 continue; 348 349 // If we get a NULL foreign_tu back, the entry doesn't match the type unit 350 // in the .dwp file, or we were not able to load the .dwo file or the DWO ID 351 // didn't match. 352 std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry); 353 if (foreign_tu && foreign_tu.value() == nullptr) 354 continue; 355 356 // Grab at most one extra parent, subsequent parents are not necessary to 357 // test equality. 358 std::optional<llvm::SmallVector<Entry, 4>> parent_chain = 359 getParentChain(entry, parent_names.size() + 1); 360 361 if (!parent_chain) { 362 // Fallback: use the base class implementation. 363 if (!ProcessEntry(entry, [&](DWARFDIE die) { 364 return GetFullyQualifiedTypeImpl(context, die, callback); 365 })) 366 return; 367 continue; 368 } 369 370 if (SameParentChain(parent_names, *parent_chain) && 371 !ProcessEntry(entry, callback)) 372 return; 373 } 374 } 375 376 bool DebugNamesDWARFIndex::SameParentChain( 377 llvm::ArrayRef<llvm::StringRef> parent_names, 378 llvm::ArrayRef<DebugNames::Entry> parent_entries) const { 379 380 if (parent_entries.size() != parent_names.size()) 381 return false; 382 383 auto SameAsEntryATName = [this](llvm::StringRef name, 384 const DebugNames::Entry &entry) { 385 // Peek at the AT_name of `entry` and test equality to `name`. 386 auto maybe_dieoffset = entry.getDIEUnitOffset(); 387 if (!maybe_dieoffset) 388 return false; 389 DWARFUnit *unit = GetNonSkeletonUnit(entry); 390 if (!unit) 391 return false; 392 return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset); 393 }; 394 395 // If the AT_name of any parent fails to match the expected name, we don't 396 // have a match. 397 for (auto [parent_name, parent_entry] : 398 llvm::zip_equal(parent_names, parent_entries)) 399 if (!SameAsEntryATName(parent_name, parent_entry)) 400 return false; 401 return true; 402 } 403 404 void DebugNamesDWARFIndex::GetTypes( 405 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) { 406 for (const DebugNames::Entry &entry : 407 m_debug_names_up->equal_range(name.GetStringRef())) { 408 if (isType(entry.tag())) { 409 if (!ProcessEntry(entry, callback)) 410 return; 411 } 412 } 413 414 m_fallback.GetTypes(name, callback); 415 } 416 417 void DebugNamesDWARFIndex::GetTypes( 418 const DWARFDeclContext &context, 419 llvm::function_ref<bool(DWARFDIE die)> callback) { 420 auto name = context[0].name; 421 for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) { 422 if (entry.tag() == context[0].tag) { 423 if (!ProcessEntry(entry, callback)) 424 return; 425 } 426 } 427 428 m_fallback.GetTypes(context, callback); 429 } 430 431 void DebugNamesDWARFIndex::GetNamespaces( 432 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) { 433 for (const DebugNames::Entry &entry : 434 m_debug_names_up->equal_range(name.GetStringRef())) { 435 lldb_private::dwarf::Tag entry_tag = entry.tag(); 436 if (entry_tag == DW_TAG_namespace || 437 entry_tag == DW_TAG_imported_declaration) { 438 if (!ProcessEntry(entry, callback)) 439 return; 440 } 441 } 442 443 m_fallback.GetNamespaces(name, callback); 444 } 445 446 void DebugNamesDWARFIndex::GetFunctions( 447 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, 448 const CompilerDeclContext &parent_decl_ctx, 449 llvm::function_ref<bool(DWARFDIE die)> callback) { 450 ConstString name = lookup_info.GetLookupName(); 451 std::set<DWARFDebugInfoEntry *> seen; 452 for (const DebugNames::Entry &entry : 453 m_debug_names_up->equal_range(name.GetStringRef())) { 454 Tag tag = entry.tag(); 455 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) 456 continue; 457 458 if (DWARFDIE die = GetDIE(entry)) { 459 if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, 460 [&](DWARFDIE die) { 461 if (!seen.insert(die.GetDIE()).second) 462 return true; 463 return callback(die); 464 })) 465 return; 466 } 467 } 468 469 m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback); 470 } 471 472 void DebugNamesDWARFIndex::GetFunctions( 473 const RegularExpression ®ex, 474 llvm::function_ref<bool(DWARFDIE die)> callback) { 475 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 476 for (DebugNames::NameTableEntry nte: ni) { 477 if (!regex.Execute(nte.getString())) 478 continue; 479 480 uint64_t entry_offset = nte.getEntryOffset(); 481 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 482 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 483 Tag tag = entry_or->tag(); 484 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) 485 continue; 486 487 if (!ProcessEntry(*entry_or, callback)) 488 return; 489 } 490 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 491 } 492 } 493 494 m_fallback.GetFunctions(regex, callback); 495 } 496 497 void DebugNamesDWARFIndex::Dump(Stream &s) { 498 m_fallback.Dump(s); 499 500 std::string data; 501 llvm::raw_string_ostream os(data); 502 m_debug_names_up->dump(os); 503 s.PutCString(os.str()); 504 } 505