Revert "[DWARF] Extract indexing code into a separate class hierarchy"
This reverts commit r332719 due to breaking this green dragon build: http://green.lab.llvm.org/green/job/lldb-xcode/6644 llvm-svn: 332730
This commit is contained in:
parent
8d34dff1d5
commit
29b8df607e
|
|
@ -1,306 +0,0 @@
|
||||||
//===-- AppleDWARFIndex.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/AppleDWARFIndex.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
|
|
||||||
|
|
||||||
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
|
|
||||||
#include "Plugins/Language/ObjC/ObjCLanguage.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 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 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.GetNextCompileUnitOffset(), 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, DWARFDebugInfo &info,
|
|
||||||
llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
llvm::function_ref<CompilerDeclContext(lldb::user_id_t type_uid)>
|
|
||||||
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<const DWARFDebugInfoEntry *> 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 AppleDWARFIndex::GetFunctions(
|
|
||||||
const RegularExpression ®ex, DWARFDebugInfo &info,
|
|
||||||
llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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 AppleDWARFIndex::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 AppleDWARFIndex::Dump(Stream &s) {
|
|
||||||
// TODO: Implement dumping.
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
//===-- AppleDWARFIndex.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_APPLEDWARFINDEX_H
|
|
||||||
#define LLDB_APPLEDWARFINDEX_H
|
|
||||||
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/HashedNameToDIE.h"
|
|
||||||
|
|
||||||
namespace lldb_private {
|
|
||||||
class AppleDWARFIndex : public DWARFIndex {
|
|
||||||
public:
|
|
||||||
static std::unique_ptr<AppleDWARFIndex>
|
|
||||||
Create(Module &module, DWARFDataExtractor apple_names,
|
|
||||||
DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
|
|
||||||
DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str);
|
|
||||||
|
|
||||||
AppleDWARFIndex(
|
|
||||||
Module &module, std::unique_ptr<DWARFMappedHash::MemoryTable> apple_names,
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> apple_namespaces,
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> apple_types,
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> 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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
llvm::function_ref<CompilerDeclContext(lldb::user_id_t type_uid)>
|
|
||||||
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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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<DWARFMappedHash::MemoryTable> m_apple_names_up;
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_up;
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_up;
|
|
||||||
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_up;
|
|
||||||
};
|
|
||||||
} // namespace lldb_private
|
|
||||||
|
|
||||||
#endif // LLDB_APPLEDWARFINDEX_H
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
|
add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
|
||||||
AppleDWARFIndex.cpp
|
|
||||||
DIERef.cpp
|
DIERef.cpp
|
||||||
DWARFAbbreviationDeclaration.cpp
|
DWARFAbbreviationDeclaration.cpp
|
||||||
DWARFASTParserClang.cpp
|
DWARFASTParserClang.cpp
|
||||||
|
|
@ -24,11 +23,9 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
|
||||||
DWARFDIE.cpp
|
DWARFDIE.cpp
|
||||||
DWARFDIECollection.cpp
|
DWARFDIECollection.cpp
|
||||||
DWARFFormValue.cpp
|
DWARFFormValue.cpp
|
||||||
DWARFIndex.cpp
|
|
||||||
DWARFUnit.cpp
|
DWARFUnit.cpp
|
||||||
HashedNameToDIE.cpp
|
HashedNameToDIE.cpp
|
||||||
LogChannelDWARF.cpp
|
LogChannelDWARF.cpp
|
||||||
ManualDWARFIndex.cpp
|
|
||||||
NameToDIE.cpp
|
NameToDIE.cpp
|
||||||
SymbolFileDWARF.cpp
|
SymbolFileDWARF.cpp
|
||||||
SymbolFileDWARFDwo.cpp
|
SymbolFileDWARFDwo.cpp
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#include "DWARFAbbreviationDeclaration.h"
|
#include "DWARFAbbreviationDeclaration.h"
|
||||||
|
|
||||||
#include "lldb/Core/dwarf.h"
|
#include "lldb/Core/dwarf.h"
|
||||||
#include "lldb/Utility/Stream.h"
|
|
||||||
|
|
||||||
#include "DWARFFormValue.h"
|
#include "DWARFFormValue.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#include "DWARFCompileUnit.h"
|
#include "DWARFCompileUnit.h"
|
||||||
|
|
||||||
#include "SymbolFileDWARF.h"
|
#include "SymbolFileDWARF.h"
|
||||||
#include "lldb/Utility/Stream.h"
|
|
||||||
|
|
||||||
using namespace lldb;
|
using namespace lldb;
|
||||||
using namespace lldb_private;
|
using namespace lldb_private;
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
//===-- 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/SymbolFile/DWARF/DWARFDIE.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
|
|
||||||
|
|
||||||
using namespace lldb_private;
|
|
||||||
using namespace lldb;
|
|
||||||
|
|
||||||
DWARFIndex::~DWARFIndex() = default;
|
|
||||||
|
|
||||||
void DWARFIndex::ParseFunctions(
|
|
||||||
const DIEArray &offsets, DWARFDebugInfo &info,
|
|
||||||
llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
//===-- 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/DWARFFormValue.h"
|
|
||||||
|
|
||||||
class DWARFDebugInfo;
|
|
||||||
class DWARFDeclContext;
|
|
||||||
class DWARFDIE;
|
|
||||||
|
|
||||||
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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
llvm::function_ref<CompilerDeclContext(lldb::user_id_t type_uid)>
|
|
||||||
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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
bool include_inlines, SymbolContextList &sc_list);
|
|
||||||
};
|
|
||||||
} // namespace lldb_private
|
|
||||||
|
|
||||||
#endif // LLDB_DWARFINDEX_H
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#include "DWARFDebugAranges.h"
|
#include "DWARFDebugAranges.h"
|
||||||
#include "DWARFDebugInfo.h"
|
#include "DWARFDebugInfo.h"
|
||||||
#include "LogChannelDWARF.h"
|
#include "LogChannelDWARF.h"
|
||||||
#include "NameToDIE.h"
|
|
||||||
#include "SymbolFileDWARFDebugMap.h"
|
#include "SymbolFileDWARFDebugMap.h"
|
||||||
#include "SymbolFileDWARFDwo.h"
|
#include "SymbolFileDWARFDwo.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,278 +0,0 @@
|
||||||
//===-- ManualDWARFIndex.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/ManualDWARFIndex.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
|
|
||||||
#include "lldb/Core/Module.h"
|
|
||||||
#include "lldb/Host/TaskPool.h"
|
|
||||||
#include "lldb/Symbol/ObjectFile.h"
|
|
||||||
#include "lldb/Utility/Stream.h"
|
|
||||||
#include "lldb/Utility/Timer.h"
|
|
||||||
|
|
||||||
using namespace lldb_private;
|
|
||||||
using namespace lldb;
|
|
||||||
|
|
||||||
void ManualDWARFIndex::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<void *>(&debug_info));
|
|
||||||
|
|
||||||
const uint32_t num_compile_units = debug_info.GetNumCompileUnits();
|
|
||||||
if (num_compile_units == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<NameToDIE> function_basenames(num_compile_units);
|
|
||||||
std::vector<NameToDIE> function_fullnames(num_compile_units);
|
|
||||||
std::vector<NameToDIE> function_methods(num_compile_units);
|
|
||||||
std::vector<NameToDIE> function_selectors(num_compile_units);
|
|
||||||
std::vector<NameToDIE> objc_class_selectors(num_compile_units);
|
|
||||||
std::vector<NameToDIE> globals(num_compile_units);
|
|
||||||
std::vector<NameToDIE> types(num_compile_units);
|
|
||||||
std::vector<NameToDIE> namespaces(num_compile_units);
|
|
||||||
|
|
||||||
// std::vector<bool> might be implemented using bit test-and-set, so use
|
|
||||||
// uint8_t instead.
|
|
||||||
std::vector<uint8_t> 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<NameToDIE> &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 ManualDWARFIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_globals.Find(name, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetGlobalVariables(const RegularExpression ®ex,
|
|
||||||
DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_globals.Find(regex, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
|
|
||||||
DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetObjCMethods(ConstString class_name,
|
|
||||||
DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_objc_class_selectors.Find(class_name, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetCompleteObjCClass(ConstString class_name,
|
|
||||||
bool must_be_implementation,
|
|
||||||
DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_types.Find(class_name, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_types.Find(name, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetTypes(const DWARFDeclContext &context,
|
|
||||||
DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_types.Find(ConstString(context[0].name), offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
|
|
||||||
Index();
|
|
||||||
m_namespaces.Find(name, offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManualDWARFIndex::GetFunctions(
|
|
||||||
ConstString name, DWARFDebugInfo &info,
|
|
||||||
llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
llvm::function_ref<CompilerDeclContext(lldb::user_id_t type_uid)>
|
|
||||||
get_decl_context_containing_uid,
|
|
||||||
const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask,
|
|
||||||
bool include_inlines, SymbolContextList &sc_list) {
|
|
||||||
|
|
||||||
Index();
|
|
||||||
|
|
||||||
std::set<const DWARFDebugInfoEntry *> 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 ManualDWARFIndex::GetFunctions(
|
|
||||||
const RegularExpression ®ex, DWARFDebugInfo &info,
|
|
||||||
llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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 ManualDWARFIndex::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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
//===-- ManulaDWARFIndex.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_MANUALDWARFINDEX_H
|
|
||||||
#define LLDB_MANUALDWARFINDEX_H
|
|
||||||
|
|
||||||
#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
|
|
||||||
#include "Plugins/SymbolFile/DWARF/NameToDIE.h"
|
|
||||||
|
|
||||||
namespace lldb_private {
|
|
||||||
class ManualDWARFIndex : public DWARFIndex {
|
|
||||||
public:
|
|
||||||
ManualDWARFIndex(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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
resolve_function,
|
|
||||||
llvm::function_ref<CompilerDeclContext(lldb::user_id_t type_uid)>
|
|
||||||
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<bool(const DWARFDIE &die, bool include_inlines,
|
|
||||||
lldb_private::SymbolContextList &sc_list)>
|
|
||||||
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_MANUALDWARFINDEX_H
|
|
||||||
|
|
@ -49,11 +49,16 @@
|
||||||
#include "lldb/Symbol/TypeSystem.h"
|
#include "lldb/Symbol/TypeSystem.h"
|
||||||
#include "lldb/Symbol/VariableList.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/Target/Language.h"
|
||||||
|
|
||||||
#include "AppleDWARFIndex.h"
|
#include "lldb/Host/TaskPool.h"
|
||||||
|
|
||||||
#include "DWARFASTParser.h"
|
#include "DWARFASTParser.h"
|
||||||
#include "DWARFASTParserClang.h"
|
#include "DWARFASTParserClang.h"
|
||||||
|
#include "DWARFUnit.h"
|
||||||
#include "DWARFDIECollection.h"
|
#include "DWARFDIECollection.h"
|
||||||
#include "DWARFDebugAbbrev.h"
|
#include "DWARFDebugAbbrev.h"
|
||||||
#include "DWARFDebugAranges.h"
|
#include "DWARFDebugAranges.h"
|
||||||
|
|
@ -63,9 +68,7 @@
|
||||||
#include "DWARFDebugRanges.h"
|
#include "DWARFDebugRanges.h"
|
||||||
#include "DWARFDeclContext.h"
|
#include "DWARFDeclContext.h"
|
||||||
#include "DWARFFormValue.h"
|
#include "DWARFFormValue.h"
|
||||||
#include "DWARFUnit.h"
|
|
||||||
#include "LogChannelDWARF.h"
|
#include "LogChannelDWARF.h"
|
||||||
#include "ManualDWARFIndex.h"
|
|
||||||
#include "SymbolFileDWARFDebugMap.h"
|
#include "SymbolFileDWARFDebugMap.h"
|
||||||
#include "SymbolFileDWARFDwo.h"
|
#include "SymbolFileDWARFDwo.h"
|
||||||
#include "SymbolFileDWARFDwp.h"
|
#include "SymbolFileDWARFDwp.h"
|
||||||
|
|
@ -390,16 +393,21 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
|
SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
|
||||||
: SymbolFile(objfile), UserID(uint64_t(DW_INVALID_OFFSET)
|
: SymbolFile(objfile),
|
||||||
<< 32), // Used by SymbolFileDWARFDebugMap to
|
UserID(uint64_t(DW_INVALID_OFFSET) << 32), // Used by SymbolFileDWARFDebugMap to when
|
||||||
// when this class parses .o files to
|
// this class parses .o files to contain
|
||||||
// contain the .o file index/ID
|
// the .o file index/ID
|
||||||
m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
|
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_aranges(), m_data_debug_frame(), m_data_debug_info(),
|
||||||
m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
|
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_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
|
||||||
m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
|
m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
|
||||||
m_line(), m_fetched_external_modules(false),
|
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_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
|
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
|
||||||
m_unique_ast_type_map() {}
|
m_unique_ast_type_map() {}
|
||||||
|
|
||||||
|
|
@ -442,19 +450,45 @@ void SymbolFileDWARF::InitializeObject() {
|
||||||
m_obj_file->ReadSectionData(section, m_dwarf_data);
|
m_obj_file->ReadSectionData(section, m_dwarf_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
|
get_apple_names_data();
|
||||||
LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
|
if (m_data_apple_names.m_data.GetByteSize() > 0) {
|
||||||
LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
|
m_apple_names_ap.reset(new DWARFMappedHash::MemoryTable(
|
||||||
LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
|
m_data_apple_names.m_data, get_debug_str_data(), ".apple_names"));
|
||||||
LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
m_index = AppleDWARFIndex::Create(*GetObjectFile()->GetModule(), apple_names,
|
get_apple_namespaces_data();
|
||||||
apple_namespaces, apple_types, apple_objc,
|
if (m_data_apple_namespaces.m_data.GetByteSize() > 0) {
|
||||||
get_debug_str_data());
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_index)
|
get_apple_objc_data();
|
||||||
m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(),
|
if (m_data_apple_objc.m_data.GetByteSize() > 0) {
|
||||||
DebugInfo());
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
|
bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
|
||||||
|
|
@ -1475,7 +1509,16 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu,
|
||||||
size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
|
size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
|
||||||
DIEArray &method_die_offsets) {
|
DIEArray &method_die_offsets) {
|
||||||
method_die_offsets.clear();
|
method_die_offsets.clear();
|
||||||
m_index->GetObjCMethods(class_name, method_die_offsets);
|
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);
|
||||||
|
}
|
||||||
return method_die_offsets.size();
|
return method_die_offsets.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1938,7 +1981,133 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
|
||||||
void SymbolFileDWARF::PreloadSymbols() {
|
void SymbolFileDWARF::PreloadSymbols() {
|
||||||
std::lock_guard<std::recursive_mutex> guard(
|
std::lock_guard<std::recursive_mutex> guard(
|
||||||
GetObjectFile()->GetModule()->GetMutex());
|
GetObjectFile()->GetModule()->GetMutex());
|
||||||
m_index->Preload();
|
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("<Unknown>"));
|
||||||
|
|
||||||
|
DWARFDebugInfo *debug_info = DebugInfo();
|
||||||
|
if (debug_info) {
|
||||||
|
const uint32_t num_compile_units = GetNumCompileUnits();
|
||||||
|
if (num_compile_units == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<NameToDIE> function_basename_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> function_fullname_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> function_method_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> function_selector_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> global_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> type_index(num_compile_units);
|
||||||
|
std::vector<NameToDIE> namespace_index(num_compile_units);
|
||||||
|
|
||||||
|
// std::vector<bool> might be implemented using bit test-and-set, so use
|
||||||
|
// uint8_t instead.
|
||||||
|
std::vector<uint8_t> 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<NameToDIE> &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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
|
bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
|
||||||
|
|
@ -1994,7 +2163,27 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
|
||||||
const uint32_t original_size = variables.GetSize();
|
const uint32_t original_size = variables.GetSize();
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetGlobalVariables(name, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_die_matches = die_offsets.size();
|
const size_t num_die_matches = die_offsets.size();
|
||||||
if (num_die_matches) {
|
if (num_die_matches) {
|
||||||
SymbolContext sc;
|
SymbolContext sc;
|
||||||
|
|
@ -2037,8 +2226,12 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2080,7 +2273,21 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex,
|
||||||
const uint32_t original_size = variables.GetSize();
|
const uint32_t original_size = variables.GetSize();
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetGlobalVariables(regex, 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);
|
||||||
|
}
|
||||||
|
|
||||||
SymbolContext sc;
|
SymbolContext sc;
|
||||||
sc.module_sp = m_obj_file->GetModule();
|
sc.module_sp = m_obj_file->GetModule();
|
||||||
|
|
@ -2099,8 +2306,14 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex,
|
||||||
|
|
||||||
if (variables.GetSize() - original_size >= max_matches)
|
if (variables.GetSize() - original_size >= max_matches)
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset, regex.GetText());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2168,6 +2381,48 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
|
||||||
return false;
|
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,
|
bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx,
|
||||||
const DWARFDIE &die) {
|
const DWARFDIE &die) {
|
||||||
// If we have no parent decl context to match this DIE matches, and if the
|
// If we have no parent decl context to match this DIE matches, and if the
|
||||||
|
|
@ -2230,16 +2485,210 @@ SymbolFileDWARF::FindFunctions(const ConstString &name,
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
m_index->GetFunctions(name, *info,
|
std::set<const DWARFDebugInfoEntry *> resolved_dies;
|
||||||
[this](const DWARFDIE &die, bool include_inlines,
|
if (m_using_apple_tables) {
|
||||||
lldb_private::SymbolContextList &sc_list) {
|
if (m_apple_names_ap.get()) {
|
||||||
return ResolveFunction(die, include_inlines, sc_list);
|
|
||||||
},
|
DIEArray die_offsets;
|
||||||
[this](lldb::user_id_t type_uid) {
|
|
||||||
return GetDeclContextContainingUID(type_uid);
|
uint32_t num_matches = 0;
|
||||||
},
|
|
||||||
parent_decl_ctx, name_type_mask, include_inlines,
|
if (name_type_mask & eFunctionNameTypeFull) {
|
||||||
sc_list);
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return the number of variable that were appended to the list
|
// Return the number of variable that were appended to the list
|
||||||
const uint32_t num_matches = sc_list.GetSize() - original_size;
|
const uint32_t num_matches = sc_list.GetSize() - original_size;
|
||||||
|
|
@ -2275,20 +2724,22 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex,
|
||||||
if (!append)
|
if (!append)
|
||||||
sc_list.Clear();
|
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
|
// Remember how many sc_list are in the list before we search in case we are
|
||||||
// appending the results to a variable list.
|
// appending the results to a variable list.
|
||||||
uint32_t original_size = sc_list.GetSize();
|
uint32_t original_size = sc_list.GetSize();
|
||||||
|
|
||||||
m_index->GetFunctions(regex, *info,
|
if (m_using_apple_tables) {
|
||||||
[this](const DWARFDIE &die, bool include_inlines,
|
if (m_apple_names_ap.get())
|
||||||
lldb_private::SymbolContextList &sc_list) {
|
FindFunctions(regex, *m_apple_names_ap, include_inlines, sc_list);
|
||||||
return ResolveFunction(die, include_inlines, sc_list);
|
} else {
|
||||||
},
|
// Index the DWARF if we haven't already
|
||||||
include_inlines, sc_list);
|
if (!m_indexed)
|
||||||
|
Index();
|
||||||
|
|
||||||
|
FindFunctions(regex, m_function_basename_index, include_inlines, sc_list);
|
||||||
|
|
||||||
|
FindFunctions(regex, m_function_fullname_index, include_inlines, sc_list);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the number of variable that were appended to the list
|
// Return the number of variable that were appended to the list
|
||||||
return sc_list.GetSize() - original_size;
|
return sc_list.GetSize() - original_size;
|
||||||
|
|
@ -2365,7 +2816,18 @@ uint32_t SymbolFileDWARF::FindTypes(
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetTypes(name, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_die_matches = die_offsets.size();
|
const size_t num_die_matches = die_offsets.size();
|
||||||
|
|
||||||
if (num_die_matches) {
|
if (num_die_matches) {
|
||||||
|
|
@ -2387,8 +2849,12 @@ uint32_t SymbolFileDWARF::FindTypes(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uint32_t num_matches = types.GetSize() - initial_types_size;
|
const uint32_t num_matches = types.GetSize() - initial_types_size;
|
||||||
|
|
@ -2437,13 +2903,24 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
|
||||||
if (context.empty())
|
if (context.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
DIEArray die_offsets;
|
||||||
|
|
||||||
ConstString name = context.back().name;
|
ConstString name = context.back().name;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DIEArray die_offsets;
|
if (m_using_apple_tables) {
|
||||||
m_index->GetTypes(name, die_offsets);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_die_matches = die_offsets.size();
|
const size_t num_die_matches = die_offsets.size();
|
||||||
|
|
||||||
if (num_die_matches) {
|
if (num_die_matches) {
|
||||||
|
|
@ -2466,8 +2943,12 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
|
||||||
++num_matches;
|
++num_matches;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return num_matches;
|
return num_matches;
|
||||||
|
|
@ -2494,7 +2975,20 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
|
||||||
DWARFDebugInfo *info = DebugInfo();
|
DWARFDebugInfo *info = DebugInfo();
|
||||||
if (info) {
|
if (info) {
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetNamespaces(name, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_matches = die_offsets.size();
|
const size_t num_matches = die_offsets.size();
|
||||||
if (num_matches) {
|
if (num_matches) {
|
||||||
for (size_t i = 0; i < num_matches; ++i) {
|
for (size_t i = 0; i < num_matches; ++i) {
|
||||||
|
|
@ -2512,8 +3006,13 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2670,7 +3169,18 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
|
||||||
return type_sp;
|
return type_sp;
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetCompleteObjCClass(type_name, must_be_implementation, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_matches = die_offsets.size();
|
const size_t num_matches = die_offsets.size();
|
||||||
|
|
||||||
|
|
@ -2719,8 +3229,12 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
type_name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2839,7 +3353,41 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
|
||||||
}
|
}
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetTypes(dwarf_decl_ctx, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_matches = die_offsets.size();
|
const size_t num_matches = die_offsets.size();
|
||||||
|
|
||||||
// Get the type system that we are looking to find a type for. We will
|
// Get the type system that we are looking to find a type for. We will
|
||||||
|
|
@ -2929,8 +3477,12 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset,
|
if (m_using_apple_tables) {
|
||||||
type_name.GetStringRef());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3085,7 +3637,25 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
|
||||||
sc.comp_unit->SetVariableList(variables);
|
sc.comp_unit->SetVariableList(variables);
|
||||||
|
|
||||||
DIEArray die_offsets;
|
DIEArray die_offsets;
|
||||||
m_index->GetGlobalVariables(*dwarf_cu, 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);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t num_matches = die_offsets.size();
|
const size_t num_matches = die_offsets.size();
|
||||||
if (num_matches) {
|
if (num_matches) {
|
||||||
for (size_t i = 0; i < num_matches; ++i) {
|
for (size_t i = 0; i < num_matches; ++i) {
|
||||||
|
|
@ -3098,8 +3668,14 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
|
||||||
variables->AddVariableIfUnique(var_sp);
|
variables->AddVariableIfUnique(var_sp);
|
||||||
++vars_added;
|
++vars_added;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
m_index->ReportInvalidDIEOffset(die_ref.die_offset, "");
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3693,7 +4269,27 @@ uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; }
|
||||||
|
|
||||||
void SymbolFileDWARF::DumpIndexes() {
|
void SymbolFileDWARF::DumpIndexes() {
|
||||||
StreamFile s(stdout, false);
|
StreamFile s(stdout, false);
|
||||||
m_index->Dump(s);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
|
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@
|
||||||
// Project includes
|
// Project includes
|
||||||
#include "DWARFDataExtractor.h"
|
#include "DWARFDataExtractor.h"
|
||||||
#include "DWARFDefines.h"
|
#include "DWARFDefines.h"
|
||||||
#include "DWARFIndex.h"
|
#include "HashedNameToDIE.h"
|
||||||
|
#include "NameToDIE.h"
|
||||||
#include "UniqueDWARFASTType.h"
|
#include "UniqueDWARFASTType.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
@ -312,10 +313,6 @@ public:
|
||||||
// the method returns a pointer to the base compile unit.
|
// the method returns a pointer to the base compile unit.
|
||||||
virtual DWARFUnit *GetBaseCompileUnit();
|
virtual DWARFUnit *GetBaseCompileUnit();
|
||||||
|
|
||||||
static bool
|
|
||||||
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
|
|
||||||
const DWARFDIE &die);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
|
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
|
||||||
DIEToTypePtr;
|
DIEToTypePtr;
|
||||||
|
|
@ -343,6 +340,10 @@ protected:
|
||||||
bool DeclContextMatchesThisSymbolFile(
|
bool DeclContextMatchesThisSymbolFile(
|
||||||
const lldb_private::CompilerDeclContext *decl_ctx);
|
const lldb_private::CompilerDeclContext *decl_ctx);
|
||||||
|
|
||||||
|
bool
|
||||||
|
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
|
||||||
|
const DWARFDIE &die);
|
||||||
|
|
||||||
virtual DWARFUnit *
|
virtual DWARFUnit *
|
||||||
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
|
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
|
||||||
|
|
||||||
|
|
@ -389,6 +390,19 @@ protected:
|
||||||
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
|
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
|
||||||
lldb_private::SymbolContextList &sc_list);
|
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
|
virtual lldb::TypeSP
|
||||||
FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx);
|
FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx);
|
||||||
|
|
||||||
|
|
@ -399,9 +413,14 @@ protected:
|
||||||
lldb_private::Symbol *
|
lldb_private::Symbol *
|
||||||
GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name);
|
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,
|
lldb::TypeSP GetTypeForDIE(const DWARFDIE &die,
|
||||||
bool resolve_function_context = false);
|
bool resolve_function_context = false);
|
||||||
|
|
||||||
|
void Index();
|
||||||
|
|
||||||
void DumpIndexes();
|
void DumpIndexes();
|
||||||
|
|
||||||
void SetDebugMapModule(const lldb::ModuleSP &module_sp) {
|
void SetDebugMapModule(const lldb::ModuleSP &module_sp) {
|
||||||
|
|
@ -487,6 +506,10 @@ protected:
|
||||||
std::unique_ptr<DWARFDebugAbbrev> m_abbr;
|
std::unique_ptr<DWARFDebugAbbrev> m_abbr;
|
||||||
std::unique_ptr<DWARFDebugInfo> m_info;
|
std::unique_ptr<DWARFDebugInfo> m_info;
|
||||||
std::unique_ptr<DWARFDebugLine> m_line;
|
std::unique_ptr<DWARFDebugLine> m_line;
|
||||||
|
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_ap;
|
||||||
|
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
|
||||||
|
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
|
||||||
|
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
|
||||||
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
|
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
|
||||||
|
|
||||||
typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP>
|
typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP>
|
||||||
|
|
@ -494,8 +517,17 @@ protected:
|
||||||
DebugMacrosMap m_debug_macros_map;
|
DebugMacrosMap m_debug_macros_map;
|
||||||
|
|
||||||
ExternalTypeModuleMap m_external_type_modules;
|
ExternalTypeModuleMap m_external_type_modules;
|
||||||
std::unique_ptr<lldb_private::DWARFIndex> m_index;
|
NameToDIE m_function_basename_index; // All concrete functions
|
||||||
bool m_fetched_external_modules : 1;
|
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;
|
||||||
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
|
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
|
||||||
|
|
||||||
typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP;
|
typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue