| //===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h" |
| #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" |
| #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" |
| #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" |
| |
| #include "lldb/Core/Module.h" |
| #include "lldb/Symbol/Function.h" |
| |
| using namespace lldb_private; |
| using namespace lldb; |
| |
| std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( |
| Module &module, DWARFDataExtractor apple_names, |
| DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, |
| DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) { |
| auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( |
| apple_names, debug_str, ".apple_names"); |
| if (!apple_names_table_up->IsValid()) |
| apple_names_table_up.reset(); |
| |
| auto apple_namespaces_table_up = |
| llvm::make_unique<DWARFMappedHash::MemoryTable>( |
| apple_namespaces, debug_str, ".apple_namespaces"); |
| if (!apple_namespaces_table_up->IsValid()) |
| apple_namespaces_table_up.reset(); |
| |
| auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( |
| apple_types, debug_str, ".apple_types"); |
| if (!apple_types_table_up->IsValid()) |
| apple_types_table_up.reset(); |
| |
| auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( |
| apple_objc, debug_str, ".apple_objc"); |
| if (!apple_objc_table_up->IsValid()) |
| apple_objc_table_up.reset(); |
| |
| if (apple_names_table_up || apple_names_table_up || apple_types_table_up || |
| apple_objc_table_up) |
| return llvm::make_unique<AppleDWARFIndex>( |
| module, std::move(apple_names_table_up), |
| std::move(apple_namespaces_table_up), std::move(apple_types_table_up), |
| std::move(apple_objc_table_up)); |
| |
| return nullptr; |
| } |
| |
| void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) { |
| if (m_apple_names_up) |
| m_apple_names_up->FindByName(basename.GetStringRef(), offsets); |
| } |
| |
| void AppleDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, |
| DIEArray &offsets) { |
| if (!m_apple_names_up) |
| return; |
| |
| DWARFMappedHash::DIEInfoArray hash_data; |
| if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) |
| DWARFMappedHash::ExtractDIEArray(hash_data, offsets); |
| } |
| |
| void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, |
| DIEArray &offsets) { |
| if (!m_apple_names_up) |
| return; |
| |
| DWARFMappedHash::DIEInfoArray hash_data; |
| if (m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), |
| cu.GetNextUnitOffset(), hash_data)) |
| DWARFMappedHash::ExtractDIEArray(hash_data, offsets); |
| } |
| |
| void AppleDWARFIndex::GetObjCMethods(ConstString class_name, |
| DIEArray &offsets) { |
| if (m_apple_objc_up) |
| m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets); |
| } |
| |
| void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name, |
| bool must_be_implementation, |
| DIEArray &offsets) { |
| if (m_apple_types_up) { |
| m_apple_types_up->FindCompleteObjCClassByName( |
| class_name.GetStringRef(), offsets, must_be_implementation); |
| } |
| } |
| |
| void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { |
| if (m_apple_types_up) |
| m_apple_types_up->FindByName(name.GetStringRef(), offsets); |
| } |
| |
| void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, |
| DIEArray &offsets) { |
| if (!m_apple_types_up) |
| return; |
| |
| Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | |
| DWARF_LOG_LOOKUPS); |
| const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom( |
| DWARFMappedHash::eAtomTypeTag); |
| const bool has_qualified_name_hash = |
| m_apple_types_up->GetHeader().header_data.ContainsAtom( |
| DWARFMappedHash::eAtomTypeQualNameHash); |
| const ConstString type_name(context[0].name); |
| const dw_tag_t tag = context[0].tag; |
| if (has_tag && has_qualified_name_hash) { |
| const char *qualified_name = context.GetQualifiedName(); |
| const uint32_t qualified_name_hash = llvm::djbHash(qualified_name); |
| if (log) |
| m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); |
| m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( |
| type_name.GetStringRef(), tag, qualified_name_hash, offsets); |
| } else if (has_tag) { |
| if (log) |
| m_module.LogMessage(log, "FindByNameAndTag()"); |
| m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); |
| } else |
| m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); |
| } |
| |
| void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { |
| if (m_apple_namespaces_up) |
| m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); |
| } |
| |
| void AppleDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf, |
| const CompilerDeclContext &parent_decl_ctx, |
| uint32_t name_type_mask, |
| std::vector<DWARFDIE> &dies) { |
| DIEArray offsets; |
| m_apple_names_up->FindByName(name.GetStringRef(), offsets); |
| for (const DIERef &die_ref : offsets) { |
| ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, parent_decl_ctx, |
| name_type_mask, dies); |
| } |
| } |
| |
| void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex, |
| DIEArray &offsets) { |
| if (!m_apple_names_up) |
| return; |
| |
| DWARFMappedHash::DIEInfoArray hash_data; |
| if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) |
| DWARFMappedHash::ExtractDIEArray(hash_data, offsets); |
| } |
| |
| void AppleDWARFIndex::ReportInvalidDIERef(const DIERef &ref, |
| llvm::StringRef name) { |
| m_module.ReportErrorIfModifyDetected( |
| "the DWARF debug information has been modified (accelerator table had " |
| "bad die 0x%8.8x for '%s')\n", |
| ref.die_offset(), name.str().c_str()); |
| } |
| |
| void AppleDWARFIndex::Dump(Stream &s) { |
| if (m_apple_names_up) |
| s.PutCString(".apple_names index present\n"); |
| if (m_apple_namespaces_up) |
| s.PutCString(".apple_namespaces index present\n"); |
| if (m_apple_types_up) |
| s.PutCString(".apple_types index present\n"); |
| if (m_apple_objc_up) |
| s.PutCString(".apple_objc index present\n"); |
| // TODO: Dump index contents |
| } |