You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.6 KiB
212 lines
7.6 KiB
4 months ago
|
//===-- AppleDWARFIndex.cpp -----------------------------------------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h"
|
||
|
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
|
||
|
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
|
||
|
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
|
||
|
|
||
|
#include "lldb/Core/Module.h"
|
||
|
#include "lldb/Symbol/Function.h"
|
||
|
|
||
|
using namespace lldb_private;
|
||
|
using namespace lldb;
|
||
|
|
||
|
std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
|
||
|
Module &module, DWARFDataExtractor apple_names,
|
||
|
DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
|
||
|
DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
|
||
|
auto apple_names_table_up = std::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 =
|
||
|
std::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 = std::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 = std::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_namespaces_table_up ||
|
||
|
apple_types_table_up || apple_objc_table_up)
|
||
|
return std::make_unique<AppleDWARFIndex>(
|
||
|
module, std::move(apple_names_table_up),
|
||
|
std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
|
||
|
std::move(apple_objc_table_up));
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetGlobalVariables(
|
||
|
ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_names_up)
|
||
|
return;
|
||
|
m_apple_names_up->FindByName(
|
||
|
basename.GetStringRef(),
|
||
|
DIERefCallback(callback, basename.GetStringRef()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetGlobalVariables(
|
||
|
const RegularExpression ®ex,
|
||
|
llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_names_up)
|
||
|
return;
|
||
|
|
||
|
DWARFMappedHash::DIEInfoArray hash_data;
|
||
|
m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
|
||
|
// This is not really the DIE name.
|
||
|
DWARFMappedHash::ExtractDIEArray(hash_data,
|
||
|
DIERefCallback(callback, regex.GetText()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetGlobalVariables(
|
||
|
const DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_names_up)
|
||
|
return;
|
||
|
|
||
|
DWARFMappedHash::DIEInfoArray hash_data;
|
||
|
m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), cu.GetNextUnitOffset(),
|
||
|
hash_data);
|
||
|
DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetObjCMethods(
|
||
|
ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_objc_up)
|
||
|
return;
|
||
|
m_apple_objc_up->FindByName(
|
||
|
class_name.GetStringRef(),
|
||
|
DIERefCallback(callback, class_name.GetStringRef()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetCompleteObjCClass(
|
||
|
ConstString class_name, bool must_be_implementation,
|
||
|
llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_types_up)
|
||
|
return;
|
||
|
m_apple_types_up->FindCompleteObjCClassByName(
|
||
|
class_name.GetStringRef(),
|
||
|
DIERefCallback(callback, class_name.GetStringRef()),
|
||
|
must_be_implementation);
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetTypes(
|
||
|
ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_types_up)
|
||
|
return;
|
||
|
m_apple_types_up->FindByName(name.GetStringRef(),
|
||
|
DIERefCallback(callback, name.GetStringRef()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetTypes(
|
||
|
const DWARFDeclContext &context,
|
||
|
llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
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,
|
||
|
DIERefCallback(callback, type_name.GetStringRef()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (has_tag) {
|
||
|
// When searching for a scoped type (for example,
|
||
|
// "std::vector<int>::const_iterator") searching for the innermost
|
||
|
// name alone ("const_iterator") could yield many false
|
||
|
// positives. By searching for the parent type ("vector<int>")
|
||
|
// first we can avoid extracting type DIEs from object files that
|
||
|
// would fail the filter anyway.
|
||
|
if (!has_qualified_name_hash && (context.GetSize() > 1) &&
|
||
|
(context[1].tag == DW_TAG_class_type ||
|
||
|
context[1].tag == DW_TAG_structure_type)) {
|
||
|
if (m_apple_types_up->FindByName(context[1].name,
|
||
|
[&](DIERef ref) { return false; }))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (log)
|
||
|
m_module.LogMessage(log, "FindByNameAndTag()");
|
||
|
m_apple_types_up->FindByNameAndTag(
|
||
|
type_name.GetStringRef(), tag,
|
||
|
DIERefCallback(callback, type_name.GetStringRef()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_apple_types_up->FindByName(
|
||
|
type_name.GetStringRef(),
|
||
|
DIERefCallback(callback, type_name.GetStringRef()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetNamespaces(
|
||
|
ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_namespaces_up)
|
||
|
return;
|
||
|
m_apple_namespaces_up->FindByName(
|
||
|
name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetFunctions(
|
||
|
ConstString name, SymbolFileDWARF &dwarf,
|
||
|
const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
|
||
|
llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
|
||
|
return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf,
|
||
|
parent_decl_ctx, name_type_mask, callback);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::GetFunctions(
|
||
|
const RegularExpression ®ex,
|
||
|
llvm::function_ref<bool(DWARFDIE die)> callback) {
|
||
|
if (!m_apple_names_up)
|
||
|
return;
|
||
|
|
||
|
DWARFMappedHash::DIEInfoArray hash_data;
|
||
|
m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
|
||
|
DWARFMappedHash::ExtractDIEArray(hash_data,
|
||
|
DIERefCallback(callback, regex.GetText()));
|
||
|
}
|
||
|
|
||
|
void AppleDWARFIndex::Dump(Stream &s) {
|
||
|
if (m_apple_names_up)
|
||
|
s.PutCString(".apple_names index present\n");
|
||
|
if (m_apple_namespaces_up)
|
||
|
s.PutCString(".apple_namespaces index present\n");
|
||
|
if (m_apple_types_up)
|
||
|
s.PutCString(".apple_types index present\n");
|
||
|
if (m_apple_objc_up)
|
||
|
s.PutCString(".apple_objc index present\n");
|
||
|
// TODO: Dump index contents
|
||
|
}
|