Index: source/Plugins/SymbolFile/DWARF/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -23,6 +23,7 @@ DWARFDIE.cpp DWARFDIECollection.cpp DWARFFormValue.cpp + DWARFIndex.cpp DWARFUnit.cpp HashedNameToDIE.cpp LogChannelDWARF.cpp Index: source/Plugins/SymbolFile/DWARF/DWARFIndex.h =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -0,0 +1,181 @@ +//===-- DWARFIndex.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_DWARFINDEX_H +#define LLDB_DWARFINDEX_H + +#include "Plugins/SymbolFile/DWARF/DIERef.h" +#include "Plugins/SymbolFile/DWARF/DWARFDIE.h" +#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" +#include "Plugins/SymbolFile/DWARF/HashedNameToDIE.h" + +class DWARFUnit; +class DWARFDebugInfo; + +namespace lldb_private { +class DWARFIndex { +public: + DWARFIndex(Module &module) : m_module(module) {} + virtual ~DWARFIndex(); + + virtual void Preload() = 0; + + virtual void GetGlobalVariables(ConstString name, DIEArray &offsets) = 0; + virtual void GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) = 0; + virtual void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) = 0; + virtual void GetObjCMethods(ConstString class_name, DIEArray &offsets) = 0; + virtual void GetCompleteObjCClass(ConstString class_name, + bool must_be_implementation, + DIEArray &offsets) = 0; + virtual void GetTypes(ConstString name, DIEArray &offsets) = 0; + virtual void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) = 0; + virtual void GetNamespaces(ConstString name, DIEArray &offsets) = 0; + virtual void GetFunctions( + ConstString name, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + llvm::function_ref + get_decl_context_containing_uid, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, + bool include_inlines, SymbolContextList &sc_list) = 0; + virtual void GetFunctions( + const RegularExpression ®ex, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) = 0; + + virtual void ReportInvalidDIEOffset(dw_offset_t offset, + llvm::StringRef name) = 0; + virtual void Dump(Stream &s) = 0; + +protected: + Module &m_module; + + void ParseFunctions( + const DIEArray &offsets, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list); +}; + +class AppleIndex : public DWARFIndex { +public: + static std::unique_ptr + Create(Module &module, DWARFDataExtractor apple_names, + DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, + DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str); + + AppleIndex(Module &module, + std::unique_ptr apple_names, + std::unique_ptr apple_namespaces, + std::unique_ptr apple_types, + std::unique_ptr apple_objc) + : DWARFIndex(module), m_apple_names_up(std::move(apple_names)), + m_apple_namespaces_up(std::move(apple_namespaces)), + m_apple_types_up(std::move(apple_types)), + m_apple_objc_up(std::move(apple_objc)) {} + + void Preload() override {} + + void GetGlobalVariables(ConstString name, DIEArray &offsets) override; + void GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) override; + void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; + void GetObjCMethods(ConstString class_name, DIEArray &offsets) override; + void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, + DIEArray &offsets) override; + void GetTypes(ConstString name, DIEArray &offsets) override; + void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; + void GetNamespaces(ConstString name, DIEArray &offsets) override; + void GetFunctions( + ConstString name, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + llvm::function_ref + get_decl_context_containing_uid, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; + void GetFunctions( + const RegularExpression ®ex, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) override; + + void ReportInvalidDIEOffset(dw_offset_t offset, + llvm::StringRef name) override; + void Dump(Stream &s) override; + +private: + std::unique_ptr m_apple_names_up; + std::unique_ptr m_apple_namespaces_up; + std::unique_ptr m_apple_types_up; + std::unique_ptr m_apple_objc_up; +}; + +class ManualIndex : public DWARFIndex { +public: + ManualIndex(Module &module, DWARFDebugInfo *debug_info) + : DWARFIndex(module), m_debug_info(debug_info) {} + + void Preload() override { Index(); } + + void GetGlobalVariables(ConstString name, DIEArray &offsets) override; + void GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) override; + void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; + void GetObjCMethods(ConstString class_name, DIEArray &offsets) override; + void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, + DIEArray &offsets) override; + void GetTypes(ConstString name, DIEArray &offsets) override; + void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; + void GetNamespaces(ConstString name, DIEArray &offsets) override; + void GetFunctions( + ConstString name, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + llvm::function_ref + get_decl_context_containing_uid, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; + void GetFunctions( + const RegularExpression ®ex, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) override; + + void ReportInvalidDIEOffset(dw_offset_t offset, + llvm::StringRef name) override {} + void Dump(Stream &s) override; + +private: + void Index(); + + /// Non-null value means we haven't built the index yet. + DWARFDebugInfo *m_debug_info; + + NameToDIE m_function_basenames; + NameToDIE m_function_fullnames; + NameToDIE m_function_methods; + NameToDIE m_function_selectors; + NameToDIE m_objc_class_selectors; + NameToDIE m_globals; + NameToDIE m_types; + NameToDIE m_namespaces; +}; +} // namespace lldb_private + +#endif // LLDB_DWARFINDEX_H Index: source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -0,0 +1,574 @@ +//===-- DWARFIndex.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/SymbolFile/DWARF/DWARFIndex.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h" +#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" +#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" +#include "lldb/Core/Module.h" +#include "lldb/Host/TaskPool.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Utility/Timer.h" + +using namespace lldb_private; +using namespace lldb; + +DWARFIndex::~DWARFIndex() = default; + +void DWARFIndex::ParseFunctions( + const DIEArray &offsets, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) { + const size_t num_matches = offsets.size(); + for (size_t i = 0; i < num_matches; ++i) { + DWARFDIE die = info.GetDIE(offsets[i]); + if (die) + resolve_function(die, include_inlines, sc_list); + } +} + +std::unique_ptr AppleIndex::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( + 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( + 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( + 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( + 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( + 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 AppleIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) { + if (!m_apple_names_up) + return; + + const char *name_cstr = name.GetCString(); + llvm::StringRef basename; + llvm::StringRef context; + + if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename)) + basename = name_cstr; + + m_apple_names_up->FindByName(basename, offsets); +} + +void AppleIndex::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 AppleIndex::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.GetNextCompileUnitOffset(), hash_data)) + DWARFMappedHash::ExtractDIEArray(hash_data, offsets); +} + +void AppleIndex::GetObjCMethods(ConstString class_name, DIEArray &offsets) { + if (m_apple_objc_up) + m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets); +} + +void AppleIndex::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 AppleIndex::GetTypes(ConstString name, DIEArray &offsets) { + if (m_apple_types_up) + m_apple_types_up->FindByName(name.GetStringRef(), offsets); +} + +void AppleIndex::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 AppleIndex::GetNamespaces(ConstString name, DIEArray &offsets) { + if (m_apple_namespaces_up) + m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); +} + +void AppleIndex::GetFunctions( + ConstString name, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + llvm::function_ref + get_decl_context_containing_uid, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, + bool include_inlines, SymbolContextList &sc_list) { + if (!m_apple_names_up) + return; + + std::set resolved_dies; + DIEArray offsets; + + uint32_t num_matches = 0; + + if (name_type_mask & eFunctionNameTypeFull) { + // If they asked for the full name, match what they typed. At some + // point we may want to canonicalize this (strip double spaces, etc. + // For now, we just add all the dies that we find by exact match. + num_matches = m_apple_names_up->FindByName(name.GetStringRef(), offsets); + for (uint32_t i = 0; i < num_matches; i++) { + const DIERef &die_ref = offsets[i]; + DWARFDIE die = info.GetDIE(die_ref); + if (die) { + if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } else + ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef()); + } + } + + if (name_type_mask & eFunctionNameTypeSelector) { + if (parent_decl_ctx && parent_decl_ctx->IsValid()) + return; // no selectors in namespaces + + num_matches = m_apple_names_up->FindByName(name.GetStringRef(), offsets); + // Now make sure these are actually ObjC methods. In this case we can + // simply look up the name, and if it is an ObjC method name, we're + // good. + + for (uint32_t i = 0; i < num_matches; i++) { + const DIERef &die_ref = offsets[i]; + DWARFDIE die = info.GetDIE(die_ref); + if (die) { + const char *die_name = die.GetName(); + if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) { + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } + } else + ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef()); + } + offsets.clear(); + } + + if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || + name_type_mask & eFunctionNameTypeBase) { + // The apple_names table stores just the "base name" of C++ methods in + // the table. So we have to extract the base name, look that up, and + // if there is any other information in the name we were passed in we + // have to post-filter based on that. + + // FIXME: Arrange the logic above so that we don't calculate the base + // name twice: + num_matches = m_apple_names_up->FindByName(name.GetStringRef(), offsets); + + for (uint32_t i = 0; i < num_matches; i++) { + const DIERef &die_ref = offsets[i]; + DWARFDIE die = info.GetDIE(die_ref); + if (die) { + if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + // If we get to here, the die is good, and we should add it: + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && + resolve_function(die, include_inlines, sc_list)) { + bool keep_die = true; + if ((name_type_mask & + (eFunctionNameTypeBase | eFunctionNameTypeMethod)) != + (eFunctionNameTypeBase | eFunctionNameTypeMethod)) { + // We are looking for either basenames or methods, so we need + // to trim out the ones we won't want by looking at the type + SymbolContext sc; + if (sc_list.GetLastContext(sc)) { + if (sc.block) { + // We have an inlined function + } else if (sc.function) { + Type *type = sc.function->GetType(); + + if (type) { + CompilerDeclContext decl_ctx = + get_decl_context_containing_uid(type->GetID()); + if (decl_ctx.IsStructUnionOrClass()) { + if (name_type_mask & eFunctionNameTypeBase) { + sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); + keep_die = false; + } + } else { + if (name_type_mask & eFunctionNameTypeMethod) { + sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); + keep_die = false; + } + } + } else { + m_module.ReportWarning( + "function at die offset 0x%8.8x had no function type", + die_ref.die_offset); + } + } + } + } + if (keep_die) + resolved_dies.insert(die.GetDIE()); + } + } else + ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef()); + } + offsets.clear(); + } +} + +void AppleIndex::GetFunctions( + const RegularExpression ®ex, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) { + if (!m_apple_names_up) + return; + + DIEArray offsets; + DWARFMappedHash::DIEInfoArray hash_data; + if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) { + DWARFMappedHash::ExtractDIEArray(hash_data, offsets); + ParseFunctions(offsets, info, resolve_function, include_inlines, sc_list); + } +} + +void AppleIndex::ReportInvalidDIEOffset(dw_offset_t offset, + llvm::StringRef name) { + m_module.ReportErrorIfModifyDetected( + "the DWARF debug information has been modified (accelerator table had " + "bad die 0x%8.8x for '%s')\n", + offset, name.str().c_str()); +} + +void AppleIndex::Dump(Stream &s) { + // TODO: Implement dumping. +} + +void ManualIndex::Index() { + if (!m_debug_info) + return; + + DWARFDebugInfo &debug_info = *m_debug_info; + m_debug_info = nullptr; + + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, "%p", static_cast(&debug_info)); + + const uint32_t num_compile_units = debug_info.GetNumCompileUnits(); + if (num_compile_units == 0) + return; + + std::vector function_basenames(num_compile_units); + std::vector function_fullnames(num_compile_units); + std::vector function_methods(num_compile_units); + std::vector function_selectors(num_compile_units); + std::vector objc_class_selectors(num_compile_units); + std::vector globals(num_compile_units); + std::vector types(num_compile_units); + std::vector namespaces(num_compile_units); + + // std::vector might be implemented using bit test-and-set, so use + // uint8_t instead. + std::vector clear_cu_dies(num_compile_units, false); + auto parser_fn = [&](size_t cu_idx) { + DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx); + if (dwarf_cu) { + dwarf_cu->Index(function_basenames[cu_idx], function_fullnames[cu_idx], + function_methods[cu_idx], function_selectors[cu_idx], + objc_class_selectors[cu_idx], globals[cu_idx], + types[cu_idx], namespaces[cu_idx]); + } + }; + + auto extract_fn = [&debug_info, &clear_cu_dies](size_t cu_idx) { + DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx); + if (dwarf_cu) { + // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the DIEs + // for a compile unit have already been parsed. + if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1) + clear_cu_dies[cu_idx] = true; + } + }; + + // Create a task runner that extracts dies for each DWARF compile unit in a + // separate thread + //---------------------------------------------------------------------- + // First figure out which compile units didn't have their DIEs already + // parsed and remember this. If no DIEs were parsed prior to this index + // function call, we are going to want to clear the CU dies after we are + // done indexing to make sure we don't pull in all DWARF dies, but we need + // to wait until all compile units have been indexed in case a DIE in one + // compile unit refers to another and the indexes accesses those DIEs. + //---------------------------------------------------------------------- + TaskMapOverInt(0, num_compile_units, extract_fn); + + // Now create a task runner that can index each DWARF compile unit in a + // separate thread so we can index quickly. + + TaskMapOverInt(0, num_compile_units, parser_fn); + + auto finalize_fn = [](NameToDIE &index, std::vector &srcs) { + for (auto &src : srcs) + index.Append(src); + index.Finalize(); + }; + + TaskPool::RunTasks( + [&]() { finalize_fn(m_function_basenames, function_basenames); }, + [&]() { finalize_fn(m_function_fullnames, function_fullnames); }, + [&]() { finalize_fn(m_function_methods, function_methods); }, + [&]() { finalize_fn(m_function_selectors, function_selectors); }, + [&]() { finalize_fn(m_objc_class_selectors, objc_class_selectors); }, + [&]() { finalize_fn(m_globals, globals); }, + [&]() { finalize_fn(m_types, types); }, + [&]() { finalize_fn(m_namespaces, namespaces); }); + + //---------------------------------------------------------------------- + // Keep memory down by clearing DIEs for any compile units if indexing + // caused us to load the compile unit's DIEs. + //---------------------------------------------------------------------- + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { + if (clear_cu_dies[cu_idx]) + debug_info.GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true); + } +} + +void ManualIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) { + Index(); + m_globals.Find(name, offsets); +} + +void ManualIndex::GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) { + Index(); + m_globals.Find(regex, offsets); +} + +void ManualIndex::GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) { + Index(); + m_globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets); +} + +void ManualIndex::GetObjCMethods(ConstString class_name, DIEArray &offsets) { + Index(); + m_objc_class_selectors.Find(class_name, offsets); +} + +void ManualIndex::GetCompleteObjCClass(ConstString class_name, + bool must_be_implementation, + DIEArray &offsets) { + Index(); + m_types.Find(class_name, offsets); +} + +void ManualIndex::GetTypes(ConstString name, DIEArray &offsets) { + Index(); + m_types.Find(name, offsets); +} + +void ManualIndex::GetTypes(const DWARFDeclContext &context, DIEArray &offsets) { + Index(); + m_types.Find(ConstString(context[0].name), offsets); +} + +void ManualIndex::GetNamespaces(ConstString name, DIEArray &offsets) { + Index(); + m_namespaces.Find(name, offsets); +} + +void ManualIndex::GetFunctions( + ConstString name, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + llvm::function_ref + get_decl_context_containing_uid, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, + bool include_inlines, SymbolContextList &sc_list) { + + Index(); + + std::set resolved_dies; + DIEArray offsets; + if (name_type_mask & eFunctionNameTypeFull) { + uint32_t num_matches = m_function_basenames.Find(name, offsets); + num_matches += m_function_methods.Find(name, offsets); + num_matches += m_function_fullnames.Find(name, offsets); + for (uint32_t i = 0; i < num_matches; i++) { + const DIERef &die_ref = offsets[i]; + DWARFDIE die = info.GetDIE(die_ref); + if (die) { + if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } + } + offsets.clear(); + } + if (name_type_mask & eFunctionNameTypeBase) { + uint32_t num_base = m_function_basenames.Find(name, offsets); + for (uint32_t i = 0; i < num_base; i++) { + DWARFDIE die = info.GetDIE(offsets[i]); + if (die) { + if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + // If we get to here, the die is good, and we should add it: + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } + } + offsets.clear(); + } + + if (name_type_mask & eFunctionNameTypeMethod) { + if (parent_decl_ctx && parent_decl_ctx->IsValid()) + return; // no methods in namespaces + + uint32_t num_base = m_function_methods.Find(name, offsets); + { + for (uint32_t i = 0; i < num_base; i++) { + DWARFDIE die = info.GetDIE(offsets[i]); + if (die) { + // If we get to here, the die is good, and we should add it: + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } + } + } + offsets.clear(); + } + + if ((name_type_mask & eFunctionNameTypeSelector) && + (!parent_decl_ctx || !parent_decl_ctx->IsValid())) { + uint32_t num_selectors = m_function_selectors.Find(name, offsets); + for (uint32_t i = 0; i < num_selectors; i++) { + DWARFDIE die = info.GetDIE(offsets[i]); + if (die) { + // If we get to here, the die is good, and we should add it: + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); + } + } + } + } +} + +void ManualIndex::GetFunctions( + const RegularExpression ®ex, DWARFDebugInfo &info, + llvm::function_ref + resolve_function, + bool include_inlines, SymbolContextList &sc_list) { + Index(); + + DIEArray offsets; + m_function_basenames.Find(regex, offsets); + m_function_fullnames.Find(regex, offsets); + ParseFunctions(offsets, info, resolve_function, include_inlines, sc_list); +} + +void ManualIndex::Dump(Stream &s) { + s.Format("DWARF index for ({0}) '{1:F}':", + m_module.GetArchitecture().GetArchitectureName(), + m_module.GetObjectFile()->GetFileSpec()); + s.Printf("\nFunction basenames:\n"); + m_function_basenames.Dump(&s); + s.Printf("\nFunction fullnames:\n"); + m_function_fullnames.Dump(&s); + s.Printf("\nFunction methods:\n"); + m_function_methods.Dump(&s); + s.Printf("\nFunction selectors:\n"); + m_function_selectors.Dump(&s); + s.Printf("\nObjective C class selectors:\n"); + m_objc_class_selectors.Dump(&s); + s.Printf("\nGlobals and statics:\n"); + m_globals.Dump(&s); + s.Printf("\nTypes:\n"); + m_types.Dump(&s); + s.Printf("\nNamespaces:\n"); + m_namespaces.Dump(&s); +} Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -38,8 +38,7 @@ // Project includes #include "DWARFDataExtractor.h" #include "DWARFDefines.h" -#include "HashedNameToDIE.h" -#include "NameToDIE.h" +#include "DWARFIndex.h" #include "UniqueDWARFASTType.h" //---------------------------------------------------------------------- @@ -313,6 +312,10 @@ // the method returns a pointer to the base compile unit. virtual DWARFUnit *GetBaseCompileUnit(); + static bool + DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx, + const DWARFDIE &die); + protected: typedef llvm::DenseMap DIEToTypePtr; @@ -340,10 +343,6 @@ bool DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx); - bool - DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx, - const DWARFDIE &die); - virtual DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); @@ -390,19 +389,6 @@ bool ResolveFunction(const DWARFDIE &die, bool include_inlines, lldb_private::SymbolContextList &sc_list); - void FindFunctions(const lldb_private::ConstString &name, - const NameToDIE &name_to_die, bool include_inlines, - lldb_private::SymbolContextList &sc_list); - - void FindFunctions(const lldb_private::RegularExpression ®ex, - const NameToDIE &name_to_die, bool include_inlines, - lldb_private::SymbolContextList &sc_list); - - void FindFunctions(const lldb_private::RegularExpression ®ex, - const DWARFMappedHash::MemoryTable &memory_table, - bool include_inlines, - lldb_private::SymbolContextList &sc_list); - virtual lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); @@ -413,14 +399,9 @@ lldb_private::Symbol * GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name); - void ParseFunctions(const DIEArray &die_offsets, bool include_inlines, - lldb_private::SymbolContextList &sc_list); - lldb::TypeSP GetTypeForDIE(const DWARFDIE &die, bool resolve_function_context = false); - void Index(); - void DumpIndexes(); void SetDebugMapModule(const lldb::ModuleSP &module_sp) { @@ -506,10 +487,6 @@ std::unique_ptr m_abbr; std::unique_ptr m_info; std::unique_ptr m_line; - std::unique_ptr m_apple_names_ap; - std::unique_ptr m_apple_types_ap; - std::unique_ptr m_apple_namespaces_ap; - std::unique_ptr m_apple_objc_ap; std::unique_ptr m_global_aranges_ap; typedef std::unordered_map @@ -517,17 +494,8 @@ DebugMacrosMap m_debug_macros_map; ExternalTypeModuleMap m_external_type_modules; - NameToDIE m_function_basename_index; // All concrete functions - NameToDIE m_function_fullname_index; // All concrete functions - NameToDIE m_function_method_index; // All inlined functions - NameToDIE - m_function_selector_index; // All method names for functions of classes - NameToDIE m_objc_class_selectors_index; // Given a class name, find all - // selectors for the class - NameToDIE m_global_index; // Global and static variables - NameToDIE m_type_index; // All type DIE offsets - NameToDIE m_namespace_index; // All type DIE offsets - bool m_indexed : 1, m_using_apple_tables : 1, m_fetched_external_modules : 1; + std::unique_ptr m_index; + bool m_fetched_external_modules : 1; lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; typedef std::shared_ptr> DIERefSetSP; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -49,13 +49,8 @@ #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" - #include "lldb/Target/Language.h" -#include "lldb/Host/TaskPool.h" - #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" #include "DWARFUnit.h" @@ -393,21 +388,16 @@ } SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile) - : SymbolFile(objfile), - UserID(uint64_t(DW_INVALID_OFFSET) << 32), // Used by SymbolFileDWARFDebugMap to when - // this class parses .o files to contain - // the .o file index/ID + : SymbolFile(objfile), UserID(uint64_t(DW_INVALID_OFFSET) + << 32), // Used by SymbolFileDWARFDebugMap to + // when this class parses .o files to + // contain the .o file index/ID m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(), m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(), m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(), m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(), - m_line(), m_apple_names_ap(), m_apple_types_ap(), m_apple_namespaces_ap(), - m_apple_objc_ap(), m_function_basename_index(), - m_function_fullname_index(), m_function_method_index(), - m_function_selector_index(), m_objc_class_selectors_index(), - m_global_index(), m_type_index(), m_namespace_index(), m_indexed(false), - m_using_apple_tables(false), m_fetched_external_modules(false), + m_line(), m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(), m_unique_ast_type_map() {} @@ -450,45 +440,19 @@ m_obj_file->ReadSectionData(section, m_dwarf_data); } - get_apple_names_data(); - if (m_data_apple_names.m_data.GetByteSize() > 0) { - m_apple_names_ap.reset(new DWARFMappedHash::MemoryTable( - m_data_apple_names.m_data, get_debug_str_data(), ".apple_names")); - if (m_apple_names_ap->IsValid()) - m_using_apple_tables = true; - else - m_apple_names_ap.reset(); - } - get_apple_types_data(); - if (m_data_apple_types.m_data.GetByteSize() > 0) { - m_apple_types_ap.reset(new DWARFMappedHash::MemoryTable( - m_data_apple_types.m_data, get_debug_str_data(), ".apple_types")); - if (m_apple_types_ap->IsValid()) - m_using_apple_tables = true; - else - m_apple_types_ap.reset(); - } + DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc; + LoadSectionData(eSectionTypeDWARFAppleNames, apple_names); + LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces); + LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types); + LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc); - get_apple_namespaces_data(); - if (m_data_apple_namespaces.m_data.GetByteSize() > 0) { - m_apple_namespaces_ap.reset(new DWARFMappedHash::MemoryTable( - m_data_apple_namespaces.m_data, get_debug_str_data(), - ".apple_namespaces")); - if (m_apple_namespaces_ap->IsValid()) - m_using_apple_tables = true; - else - m_apple_namespaces_ap.reset(); - } + m_index = AppleIndex::Create(*GetObjectFile()->GetModule(), apple_names, + apple_namespaces, apple_types, apple_objc, + get_debug_str_data()); - get_apple_objc_data(); - if (m_data_apple_objc.m_data.GetByteSize() > 0) { - m_apple_objc_ap.reset(new DWARFMappedHash::MemoryTable( - m_data_apple_objc.m_data, get_debug_str_data(), ".apple_objc")); - if (m_apple_objc_ap->IsValid()) - m_using_apple_tables = true; - else - m_apple_objc_ap.reset(); - } + if (!m_index) + m_index = llvm::make_unique(*GetObjectFile()->GetModule(), + DebugInfo()); } bool SymbolFileDWARF::SupportedVersion(uint16_t version) { @@ -1509,16 +1473,7 @@ size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name, DIEArray &method_die_offsets) { method_die_offsets.clear(); - if (m_using_apple_tables) { - if (m_apple_objc_ap.get()) - m_apple_objc_ap->FindByName(class_name.GetStringRef(), - method_die_offsets); - } else { - if (!m_indexed) - Index(); - - m_objc_class_selectors_index.Find(class_name, method_die_offsets); - } + m_index->GetObjCMethods(class_name, method_die_offsets); return method_die_offsets.size(); } @@ -1981,133 +1936,7 @@ void SymbolFileDWARF::PreloadSymbols() { std::lock_guard guard( GetObjectFile()->GetModule()->GetMutex()); - Index(); -} - -void SymbolFileDWARF::Index() { - if (m_indexed) - return; - m_indexed = true; - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "SymbolFileDWARF::Index (%s)", - GetObjectFile()->GetFileSpec().GetFilename().AsCString("")); - - DWARFDebugInfo *debug_info = DebugInfo(); - if (debug_info) { - const uint32_t num_compile_units = GetNumCompileUnits(); - if (num_compile_units == 0) - return; - - std::vector function_basename_index(num_compile_units); - std::vector function_fullname_index(num_compile_units); - std::vector function_method_index(num_compile_units); - std::vector function_selector_index(num_compile_units); - std::vector objc_class_selectors_index(num_compile_units); - std::vector global_index(num_compile_units); - std::vector type_index(num_compile_units); - std::vector namespace_index(num_compile_units); - - // std::vector might be implemented using bit test-and-set, so use - // uint8_t instead. - std::vector clear_cu_dies(num_compile_units, false); - auto parser_fn = [debug_info, &function_basename_index, - &function_fullname_index, &function_method_index, - &function_selector_index, &objc_class_selectors_index, - &global_index, &type_index, - &namespace_index](size_t cu_idx) { - DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); - if (dwarf_cu) { - dwarf_cu->Index( - function_basename_index[cu_idx], function_fullname_index[cu_idx], - function_method_index[cu_idx], function_selector_index[cu_idx], - objc_class_selectors_index[cu_idx], global_index[cu_idx], - type_index[cu_idx], namespace_index[cu_idx]); - } - }; - - auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) { - DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); - if (dwarf_cu) { - // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the DIEs - // for a compile unit have already been parsed. - if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1) - clear_cu_dies[cu_idx] = true; - } - }; - - // Create a task runner that extracts dies for each DWARF compile unit in a - // separate thread - //---------------------------------------------------------------------- - // First figure out which compile units didn't have their DIEs already - // parsed and remember this. If no DIEs were parsed prior to this index - // function call, we are going to want to clear the CU dies after we are - // done indexing to make sure we don't pull in all DWARF dies, but we need - // to wait until all compile units have been indexed in case a DIE in one - // compile unit refers to another and the indexes accesses those DIEs. - //---------------------------------------------------------------------- - TaskMapOverInt(0, num_compile_units, extract_fn); - - // Now create a task runner that can index each DWARF compile unit in a - // separate thread so we can index quickly. - - TaskMapOverInt(0, num_compile_units, parser_fn); - - auto finalize_fn = [](NameToDIE &index, std::vector &srcs) { - for (auto &src : srcs) - index.Append(src); - index.Finalize(); - }; - - TaskPool::RunTasks( - [&]() { - finalize_fn(m_function_basename_index, function_basename_index); - }, - [&]() { - finalize_fn(m_function_fullname_index, function_fullname_index); - }, - [&]() { finalize_fn(m_function_method_index, function_method_index); }, - [&]() { - finalize_fn(m_function_selector_index, function_selector_index); - }, - [&]() { - finalize_fn(m_objc_class_selectors_index, objc_class_selectors_index); - }, - [&]() { finalize_fn(m_global_index, global_index); }, - [&]() { finalize_fn(m_type_index, type_index); }, - [&]() { finalize_fn(m_namespace_index, namespace_index); }); - - //---------------------------------------------------------------------- - // Keep memory down by clearing DIEs for any compile units if indexing - // caused us to load the compile unit's DIEs. - //---------------------------------------------------------------------- - for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - if (clear_cu_dies[cu_idx]) - debug_info->GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true); - } - -#if defined(ENABLE_DEBUG_PRINTF) - StreamFile s(stdout, false); - s.Printf("DWARF index for '%s':", - GetObjectFile()->GetFileSpec().GetPath().c_str()); - s.Printf("\nFunction basenames:\n"); - m_function_basename_index.Dump(&s); - s.Printf("\nFunction fullnames:\n"); - m_function_fullname_index.Dump(&s); - s.Printf("\nFunction methods:\n"); - m_function_method_index.Dump(&s); - s.Printf("\nFunction selectors:\n"); - m_function_selector_index.Dump(&s); - s.Printf("\nObjective C class selectors:\n"); - m_objc_class_selectors_index.Dump(&s); - s.Printf("\nGlobals and statics:\n"); - m_global_index.Dump(&s); - s.Printf("\nTypes:\n"); - m_type_index.Dump(&s); - s.Printf("\nNamespaces:\n"); - m_namespace_index.Dump(&s); -#endif - } + m_index->Preload(); } bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( @@ -2163,27 +1992,7 @@ const uint32_t original_size = variables.GetSize(); DIEArray die_offsets; - - if (m_using_apple_tables) { - if (m_apple_names_ap.get()) { - const char *name_cstr = name.GetCString(); - llvm::StringRef basename; - llvm::StringRef context; - - if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, - basename)) - basename = name_cstr; - - m_apple_names_ap->FindByName(basename, die_offsets); - } - } else { - // Index the DWARF if we haven't already - if (!m_indexed) - Index(); - - m_global_index.Find(name, die_offsets); - } - + m_index->GetGlobalVariables(name, die_offsets); const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { SymbolContext sc; @@ -2226,12 +2035,8 @@ } break; } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_names " - "accelerator table had bad die 0x%8.8x for '%s')\n", - die_ref.die_offset, name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + name.GetStringRef()); } } } @@ -2273,21 +2078,7 @@ const uint32_t original_size = variables.GetSize(); DIEArray die_offsets; - - if (m_using_apple_tables) { - if (m_apple_names_ap.get()) { - DWARFMappedHash::DIEInfoArray hash_data_array; - if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex(regex, - hash_data_array)) - DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets); - } - } else { - // Index the DWARF if we haven't already - if (!m_indexed) - Index(); - - m_global_index.Find(regex, die_offsets); - } + m_index->GetGlobalVariables(regex, die_offsets); SymbolContext sc; sc.module_sp = m_obj_file->GetModule(); @@ -2306,14 +2097,8 @@ if (variables.GetSize() - original_size >= max_matches) break; - } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_names " - "accelerator table had bad die 0x%8.8x for regex '%s')\n", - die_ref.die_offset, regex.GetText().str().c_str()); - } - } + } else + m_index->ReportInvalidDIEOffset(die_ref.die_offset, regex.GetText()); } } @@ -2381,48 +2166,6 @@ return false; } -void SymbolFileDWARF::FindFunctions(const ConstString &name, - const NameToDIE &name_to_die, - bool include_inlines, - SymbolContextList &sc_list) { - DIEArray die_offsets; - if (name_to_die.Find(name, die_offsets)) { - ParseFunctions(die_offsets, include_inlines, sc_list); - } -} - -void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, - const NameToDIE &name_to_die, - bool include_inlines, - SymbolContextList &sc_list) { - DIEArray die_offsets; - if (name_to_die.Find(regex, die_offsets)) { - ParseFunctions(die_offsets, include_inlines, sc_list); - } -} - -void SymbolFileDWARF::FindFunctions( - const RegularExpression ®ex, - const DWARFMappedHash::MemoryTable &memory_table, bool include_inlines, - SymbolContextList &sc_list) { - DIEArray die_offsets; - DWARFMappedHash::DIEInfoArray hash_data_array; - if (memory_table.AppendAllDIEsThatMatchingRegex(regex, hash_data_array)) { - DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets); - ParseFunctions(die_offsets, include_inlines, sc_list); - } -} - -void SymbolFileDWARF::ParseFunctions(const DIEArray &die_offsets, - bool include_inlines, - SymbolContextList &sc_list) { - const size_t num_matches = die_offsets.size(); - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) - ResolveFunction(die_offsets[i], include_inlines, sc_list); - } -} - bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, const DWARFDIE &die) { // If we have no parent decl context to match this DIE matches, and if the @@ -2485,210 +2228,16 @@ if (info == NULL) return 0; - std::set resolved_dies; - if (m_using_apple_tables) { - if (m_apple_names_ap.get()) { - - DIEArray die_offsets; - - uint32_t num_matches = 0; - - if (name_type_mask & eFunctionNameTypeFull) { - // If they asked for the full name, match what they typed. At some - // point we may want to canonicalize this (strip double spaces, etc. - // For now, we just add all the dies that we find by exact match. - num_matches = - m_apple_names_ap->FindByName(name.GetStringRef(), die_offsets); - for (uint32_t i = 0; i < num_matches; i++) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = info->GetDIE(die_ref); - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction(die, include_inlines, sc_list)) - resolved_dies.insert(die.GetDIE()); - } - } else { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_names " - "accelerator table had bad die 0x%8.8x for '%s')", - die_ref.die_offset, name.GetCString()); - } - } - } - - if (name_type_mask & eFunctionNameTypeSelector) { - if (parent_decl_ctx && parent_decl_ctx->IsValid()) - return 0; // no selectors in namespaces - - num_matches = - m_apple_names_ap->FindByName(name.GetStringRef(), die_offsets); - // Now make sure these are actually ObjC methods. In this case we can - // simply look up the name, and if it is an ObjC method name, we're - // good. - - for (uint32_t i = 0; i < num_matches; i++) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = info->GetDIE(die_ref); - if (die) { - const char *die_name = die.GetName(); - if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) { - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction(die, include_inlines, sc_list)) - resolved_dies.insert(die.GetDIE()); - } - } - } else { - GetObjectFile()->GetModule()->ReportError( - "the DWARF debug information has been modified (.apple_names " - "accelerator table had bad die 0x%8.8x for '%s')", - die_ref.die_offset, name.GetCString()); - } - } - die_offsets.clear(); - } - - if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || - name_type_mask & eFunctionNameTypeBase) { - // The apple_names table stores just the "base name" of C++ methods in - // the table. So we have to extract the base name, look that up, and - // if there is any other information in the name we were passed in we - // have to post-filter based on that. - - // FIXME: Arrange the logic above so that we don't calculate the base - // name twice: - num_matches = - m_apple_names_ap->FindByName(name.GetStringRef(), die_offsets); - - for (uint32_t i = 0; i < num_matches; i++) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = info->GetDIE(die_ref); - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && - ResolveFunction(die, include_inlines, sc_list)) { - bool keep_die = true; - if ((name_type_mask & - (eFunctionNameTypeBase | eFunctionNameTypeMethod)) != - (eFunctionNameTypeBase | eFunctionNameTypeMethod)) { - // We are looking for either basenames or methods, so we need - // to trim out the ones we won't want by looking at the type - SymbolContext sc; - if (sc_list.GetLastContext(sc)) { - if (sc.block) { - // We have an inlined function - } else if (sc.function) { - Type *type = sc.function->GetType(); - - if (type) { - CompilerDeclContext decl_ctx = - GetDeclContextContainingUID(type->GetID()); - if (decl_ctx.IsStructUnionOrClass()) { - if (name_type_mask & eFunctionNameTypeBase) { - sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); - keep_die = false; - } - } else { - if (name_type_mask & eFunctionNameTypeMethod) { - sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); - keep_die = false; - } - } - } else { - GetObjectFile()->GetModule()->ReportWarning( - "function at die offset 0x%8.8x had no function type", - die_ref.die_offset); - } - } - } - } - if (keep_die) - resolved_dies.insert(die.GetDIE()); - } - } else { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_names " - "accelerator table had bad die 0x%8.8x for '%s')", - die_ref.die_offset, name.GetCString()); - } - } - die_offsets.clear(); - } - } - } else { - - // Index the DWARF if we haven't already - if (!m_indexed) - Index(); - - DIEArray die_offsets; - if (name_type_mask & eFunctionNameTypeFull) { - uint32_t num_matches = m_function_basename_index.Find(name, die_offsets); - num_matches += m_function_method_index.Find(name, die_offsets); - num_matches += m_function_fullname_index.Find(name, die_offsets); - for (uint32_t i = 0; i < num_matches; i++) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = info->GetDIE(die_ref); - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction(die, include_inlines, sc_list)) - resolved_dies.insert(die.GetDIE()); - } - } - } - die_offsets.clear(); - } - if (name_type_mask & eFunctionNameTypeBase) { - uint32_t num_base = m_function_basename_index.Find(name, die_offsets); - for (uint32_t i = 0; i < num_base; i++) { - DWARFDIE die = info->GetDIE(die_offsets[i]); - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction(die, include_inlines, sc_list)) - resolved_dies.insert(die.GetDIE()); - } - } - } - die_offsets.clear(); - } - - if (name_type_mask & eFunctionNameTypeMethod) { - if (parent_decl_ctx && parent_decl_ctx->IsValid()) - return 0; // no methods in namespaces - - uint32_t num_base = m_function_method_index.Find(name, die_offsets); - { - for (uint32_t i = 0; i < num_base; i++) { - DWARFDIE die = info->GetDIE(die_offsets[i]); - if (die) { - // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction(die, include_inlines, sc_list)) - resolved_dies.insert(die.GetDIE()); - } - } - } - } - die_offsets.clear(); - } - - if ((name_type_mask & eFunctionNameTypeSelector) && - (!parent_decl_ctx || !parent_decl_ctx->IsValid())) { - FindFunctions(name, m_function_selector_index, include_inlines, sc_list); - } - } + m_index->GetFunctions(name, *info, + [this](const DWARFDIE &die, bool include_inlines, + lldb_private::SymbolContextList &sc_list) { + return ResolveFunction(die, include_inlines, sc_list); + }, + [this](lldb::user_id_t type_uid) { + return GetDeclContextContainingUID(type_uid); + }, + parent_decl_ctx, name_type_mask, include_inlines, + sc_list); // Return the number of variable that were appended to the list const uint32_t num_matches = sc_list.GetSize() - original_size; @@ -2724,22 +2273,20 @@ if (!append) sc_list.Clear(); + DWARFDebugInfo *info = DebugInfo(); + if (!info) + return 0; + // Remember how many sc_list are in the list before we search in case we are // appending the results to a variable list. uint32_t original_size = sc_list.GetSize(); - if (m_using_apple_tables) { - if (m_apple_names_ap.get()) - FindFunctions(regex, *m_apple_names_ap, include_inlines, sc_list); - } else { - // Index the DWARF if we haven't already - if (!m_indexed) - Index(); - - FindFunctions(regex, m_function_basename_index, include_inlines, sc_list); - - FindFunctions(regex, m_function_fullname_index, include_inlines, sc_list); - } + m_index->GetFunctions(regex, *info, + [this](const DWARFDIE &die, bool include_inlines, + lldb_private::SymbolContextList &sc_list) { + return ResolveFunction(die, include_inlines, sc_list); + }, + include_inlines, sc_list); // Return the number of variable that were appended to the list return sc_list.GetSize() - original_size; @@ -2816,18 +2363,7 @@ return 0; DIEArray die_offsets; - - if (m_using_apple_tables) { - if (m_apple_types_ap.get()) { - m_apple_types_ap->FindByName(name.GetStringRef(), die_offsets); - } - } else { - if (!m_indexed) - Index(); - - m_type_index.Find(name, die_offsets); - } - + m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { @@ -2849,12 +2385,8 @@ break; } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_types " - "accelerator table had bad die 0x%8.8x for '%s')\n", - die_ref.die_offset, name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + name.GetStringRef()); } } const uint32_t num_matches = types.GetSize() - initial_types_size; @@ -2903,24 +2435,13 @@ if (context.empty()) return 0; - DIEArray die_offsets; - ConstString name = context.back().name; if (!name) return 0; - if (m_using_apple_tables) { - if (m_apple_types_ap.get()) { - m_apple_types_ap->FindByName(name.GetStringRef(), die_offsets); - } - } else { - if (!m_indexed) - Index(); - - m_type_index.Find(name, die_offsets); - } - + DIEArray die_offsets; + m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { @@ -2943,12 +2464,8 @@ ++num_matches; } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_types " - "accelerator table had bad die 0x%8.8x for '%s')\n", - die_ref.die_offset, name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + name.GetStringRef()); } } return num_matches; @@ -2975,20 +2492,7 @@ DWARFDebugInfo *info = DebugInfo(); if (info) { DIEArray die_offsets; - - // Index if we already haven't to make sure the compile units get indexed - // and make their global DIE index list - if (m_using_apple_tables) { - if (m_apple_namespaces_ap.get()) { - m_apple_namespaces_ap->FindByName(name.GetStringRef(), die_offsets); - } - } else { - if (!m_indexed) - Index(); - - m_namespace_index.Find(name, die_offsets); - } - + m_index->GetNamespaces(name, die_offsets); const size_t num_matches = die_offsets.size(); if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { @@ -3006,13 +2510,8 @@ break; } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified " - "(.apple_namespaces accelerator table had bad die 0x%8.8x for " - "'%s')\n", - die_ref.die_offset, name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + name.GetStringRef()); } } } @@ -3169,18 +2668,7 @@ return type_sp; DIEArray die_offsets; - - if (m_using_apple_tables) { - if (m_apple_types_ap.get()) { - m_apple_types_ap->FindCompleteObjCClassByName( - type_name.GetStringRef(), die_offsets, must_be_implementation); - } - } else { - if (!m_indexed) - Index(); - - m_type_index.Find(type_name, die_offsets); - } + m_index->GetCompleteObjCClass(type_name, must_be_implementation, die_offsets); const size_t num_matches = die_offsets.size(); @@ -3229,12 +2717,8 @@ } } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_types " - "accelerator table had bad die 0x%8.8x for '%s')\n", - die_ref.die_offset, type_name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + type_name.GetStringRef()); } } } @@ -3353,41 +2837,7 @@ } DIEArray die_offsets; - - if (m_using_apple_tables) { - if (m_apple_types_ap.get()) { - const bool has_tag = - m_apple_types_ap->GetHeader().header_data.ContainsAtom( - DWARFMappedHash::eAtomTypeTag); - const bool has_qualified_name_hash = - m_apple_types_ap->GetHeader().header_data.ContainsAtom( - DWARFMappedHash::eAtomTypeQualNameHash); - if (has_tag && has_qualified_name_hash) { - const char *qualified_name = dwarf_decl_ctx.GetQualifiedName(); - const uint32_t qualified_name_hash = llvm::djbHash(qualified_name); - if (log) - GetObjectFile()->GetModule()->LogMessage( - log, "FindByNameAndTagAndQualifiedNameHash()"); - m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash( - type_name.GetStringRef(), tag, qualified_name_hash, - die_offsets); - } else if (has_tag) { - if (log) - GetObjectFile()->GetModule()->LogMessage(log, - "FindByNameAndTag()"); - m_apple_types_ap->FindByNameAndTag(type_name.GetStringRef(), tag, - die_offsets); - } else { - m_apple_types_ap->FindByName(type_name.GetStringRef(), die_offsets); - } - } - } else { - if (!m_indexed) - Index(); - - m_type_index.Find(type_name, die_offsets); - } - + m_index->GetTypes(dwarf_decl_ctx, die_offsets); const size_t num_matches = die_offsets.size(); // Get the type system that we are looking to find a type for. We will @@ -3477,12 +2927,8 @@ } } } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified (.apple_types " - "accelerator table had bad die 0x%8.8x for '%s')\n", - die_ref.die_offset, type_name.GetCString()); - } + m_index->ReportInvalidDIEOffset(die_ref.die_offset, + type_name.GetStringRef()); } } } @@ -3637,25 +3083,7 @@ sc.comp_unit->SetVariableList(variables); DIEArray die_offsets; - if (m_using_apple_tables) { - if (m_apple_names_ap.get()) { - DWARFMappedHash::DIEInfoArray hash_data_array; - if (m_apple_names_ap->AppendAllDIEsInRange( - dwarf_cu->GetOffset(), dwarf_cu->GetNextCompileUnitOffset(), - hash_data_array)) { - DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets); - } - } - } else { - // Index if we already haven't to make sure the compile units get - // indexed and make their global DIE index list - if (!m_indexed) - Index(); - - m_global_index.FindAllEntriesForCompileUnit(dwarf_cu->GetOffset(), - die_offsets); - } - + m_index->GetGlobalVariables(*dwarf_cu, die_offsets); const size_t num_matches = die_offsets.size(); if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { @@ -3668,14 +3096,8 @@ variables->AddVariableIfUnique(var_sp); ++vars_added; } - } else { - if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "the DWARF debug information has been modified " - "(.apple_names accelerator table had bad die 0x%8.8x)\n", - die_ref.die_offset); - } - } + } else + m_index->ReportInvalidDIEOffset(die_ref.die_offset, ""); } } } @@ -4269,27 +3691,7 @@ void SymbolFileDWARF::DumpIndexes() { StreamFile s(stdout, false); - - s.Printf( - "DWARF index for (%s) '%s':", - GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(), - GetObjectFile()->GetFileSpec().GetPath().c_str()); - s.Printf("\nFunction basenames:\n"); - m_function_basename_index.Dump(&s); - s.Printf("\nFunction fullnames:\n"); - m_function_fullname_index.Dump(&s); - s.Printf("\nFunction methods:\n"); - m_function_method_index.Dump(&s); - s.Printf("\nFunction selectors:\n"); - m_function_selector_index.Dump(&s); - s.Printf("\nObjective C class selectors:\n"); - m_objc_class_selectors_index.Dump(&s); - s.Printf("\nGlobals and statics:\n"); - m_global_index.Dump(&s); - s.Printf("\nTypes:\n"); - m_type_index.Dump(&s); - s.Printf("\nNamespaces:\n"); - m_namespace_index.Dump(&s); + m_index->Dump(s); } SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {