aboutsummaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Core/CoreProperties.td4
-rw-r--r--lldb/source/Core/Module.cpp7
-rw-r--r--lldb/source/Core/ModuleList.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp15
-rw-r--r--lldb/source/Symbol/CMakeLists.txt1
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp5
-rw-r--r--lldb/source/Symbol/SymbolFile.cpp19
-rw-r--r--lldb/source/Symbol/SymbolFileOnDemand.cpp590
-rw-r--r--lldb/source/Target/Statistics.cpp20
-rw-r--r--lldb/source/Utility/LLDBLog.cpp3
13 files changed, 667 insertions, 14 deletions
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 494cc47..2ca432a 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -33,6 +33,10 @@ let Definition = "modulelist" in {
Global,
DefaultUnsignedValue<7>,
Desc<"The expiration time in days for a file. When a file hasn't been accessed for the specified amount of days, it is removed from the cache. A value of 0 disables the expiration-based pruning.">;
+ def LoadSymbolOnDemand: Property<"load-on-demand", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"Enable on demand symbol loading in LLDB. LLDB will load debug info on demand for each module based on various conditions (e.g. matched breakpoint, resolved stack frame addresses and matched global variables/function symbols in symbol table) to improve performance. Please refer to docs/use/ondemand.rst for details.">;
}
let Definition = "debugger" in {
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index f68d82c..e89d5ec 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -475,6 +475,7 @@ uint32_t Module::ResolveSymbolContextForAddress(
resolve_scope & eSymbolContextBlock ||
resolve_scope & eSymbolContextLineEntry ||
resolve_scope & eSymbolContextVariable) {
+ symfile->SetLoadDebugInfoEnabled();
resolved_flags |=
symfile->ResolveSymbolContext(so_addr, resolve_scope, sc);
}
@@ -1405,7 +1406,6 @@ void Module::PreloadSymbols() {
// Now let the symbol file preload its data and the symbol table will be
// available without needing to take the module lock.
sym_file->PreloadSymbols();
-
}
void Module::SetSymbolFileFileSpec(const FileSpec &file) {
@@ -1711,6 +1711,9 @@ DataFileCache *Module::GetIndexCache() {
return nullptr;
// NOTE: intentional leak so we don't crash if global destructor chain gets
// called as other threads still use the result of this function
- static DataFileCache *g_data_file_cache = new DataFileCache(ModuleList::GetGlobalModuleListProperties().GetLLDBIndexCachePath().GetPath());
+ static DataFileCache *g_data_file_cache =
+ new DataFileCache(ModuleList::GetGlobalModuleListProperties()
+ .GetLLDBIndexCachePath()
+ .GetPath());
return g_data_file_cache;
}
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index e30764f..1692a37 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -180,6 +180,12 @@ PathMappingList ModuleListProperties::GetSymlinkMappings() const {
return m_symlink_paths;
}
+bool ModuleListProperties::GetLoadSymbolOnDemand() {
+ const uint32_t idx = ePropertyLoadSymbolOnDemand;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_modulelist_properties[idx].default_uint_value != 0);
+}
+
ModuleList::ModuleList() : m_modules(), m_modules_mutex() {}
ModuleList::ModuleList(const ModuleList &rhs) : m_modules(), m_modules_mutex() {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
index 6707d47..5131584 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -68,7 +68,8 @@ DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl(
const DWARFIndex &index, llvm::function_ref<bool(DWARFDIE die)> callback,
llvm::StringRef name)
: m_index(index),
- m_dwarf(*llvm::cast<SymbolFileDWARF>(index.m_module.GetSymbolFile())),
+ m_dwarf(*llvm::cast<SymbolFileDWARF>(
+ index.m_module.GetSymbolFile()->GetBackingSymbolFile())),
m_callback(callback), m_name(name) {}
bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index 5d99649..ad22078 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -65,8 +65,8 @@ bool DebugNamesDWARFIndex::ProcessEntry(
llvm::Optional<DIERef> ref = ToDIERef(entry);
if (!ref)
return true;
- SymbolFileDWARF &dwarf =
- *llvm::cast<SymbolFileDWARF>(m_module.GetSymbolFile());
+ SymbolFileDWARF &dwarf = *llvm::cast<SymbolFileDWARF>(
+ m_module.GetSymbolFile()->GetBackingSymbolFile());
DWARFDIE die = dwarf.GetDIE(*ref);
if (!die)
return true;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5252c5f..2c6ab62 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3987,8 +3987,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
if (m_debug_map_symfile == nullptr) {
lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
if (module_sp) {
- m_debug_map_symfile =
- static_cast<SymbolFileDWARFDebugMap *>(module_sp->GetSymbolFile());
+ m_debug_map_symfile = llvm::cast<SymbolFileDWARFDebugMap>(
+ module_sp->GetSymbolFile()->GetBackingSymbolFile());
}
}
return m_debug_map_symfile;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index b466f33..e323635 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -801,7 +801,8 @@ bool PDBASTParser::CompleteTypeFromPDB(
if (uid_it == m_forward_decl_to_uid.end())
return true;
- auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ auto symbol_file = static_cast<SymbolFilePDB *>(
+ m_ast.GetSymbolFile()->GetBackingSymbolFile());
if (!symbol_file)
return false;
@@ -835,7 +836,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
if (it != m_uid_to_decl.end())
return it->second;
- auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ auto symbol_file = static_cast<SymbolFilePDB *>(
+ m_ast.GetSymbolFile()->GetBackingSymbolFile());
if (!symbol_file)
return nullptr;
@@ -1001,7 +1003,8 @@ PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) {
return result;
}
- auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ auto symbol_file = static_cast<SymbolFilePDB *>(
+ m_ast.GetSymbolFile()->GetBackingSymbolFile());
if (!symbol_file)
return nullptr;
@@ -1041,7 +1044,8 @@ clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
if (specs.empty())
return m_ast.GetTranslationUnitDecl();
- auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ auto symbol_file = static_cast<SymbolFilePDB *>(
+ m_ast.GetSymbolFile()->GetBackingSymbolFile());
if (!symbol_file)
return m_ast.GetTranslationUnitDecl();
@@ -1094,7 +1098,8 @@ clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
void PDBASTParser::ParseDeclsForDeclContext(
const clang::DeclContext *decl_context) {
- auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ auto symbol_file = static_cast<SymbolFilePDB *>(
+ m_ast.GetSymbolFile()->GetBackingSymbolFile());
if (!symbol_file)
return;
diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt
index d40fe41..3646f789 100644
--- a/lldb/source/Symbol/CMakeLists.txt
+++ b/lldb/source/Symbol/CMakeLists.txt
@@ -27,6 +27,7 @@ add_lldb_library(lldbSymbol
Symbol.cpp
SymbolContext.cpp
SymbolFile.cpp
+ SymbolFileOnDemand.cpp
SymbolVendor.cpp
Symtab.cpp
Type.cpp
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 7c840d8..3ce908b 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -287,6 +287,9 @@ void CompileUnit::ResolveSymbolContext(
if (num_file_indexes == 0)
return;
+ // Found a matching source file in this compile unit load its debug info.
+ GetModule()->GetSymbolFile()->SetLoadDebugInfoEnabled();
+
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table == nullptr) {
@@ -312,7 +315,7 @@ void CompileUnit::ResolveSymbolContext(
line_idx = line_table->FindLineEntryIndexByFileIndex(
0, file_indexes, src_location_spec, &line_entry);
}
-
+
// If "exact == true", then "found_line" will be the same as "line". If
// "exact == false", the "found_line" will be the closest line entry
// with a line number greater than "line" and we will use this for our
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index 440c228..e69150e 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFileOnDemand.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
@@ -77,6 +78,24 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFileSP objfile_sp) {
}
}
if (best_symfile_up) {
+ // If symbol on-demand is enabled the winning symbol file parser is
+ // wrapped with SymbolFileOnDemand so that hydration of the debug info
+ // can be controlled to improve performance.
+ //
+ // Currently the supported on-demand symbol files include:
+ // executables, shared libraries and debug info files.
+ //
+ // To reduce unnecessary wrapping files with zero debug abilities are
+ // skipped.
+ ObjectFile::Type obj_file_type = objfile_sp->CalculateType();
+ if (ModuleList::GetGlobalModuleListProperties().GetLoadSymbolOnDemand() &&
+ best_symfile_abilities > 0 &&
+ (obj_file_type == ObjectFile::eTypeExecutable ||
+ obj_file_type == ObjectFile::eTypeSharedLibrary ||
+ obj_file_type == ObjectFile::eTypeDebugInfo)) {
+ best_symfile_up =
+ std::make_unique<SymbolFileOnDemand>(std::move(best_symfile_up));
+ }
// Let the winning symbol file parser initialize itself more completely
// now that it has been chosen
best_symfile_up->InitializeObject();
diff --git a/lldb/source/Symbol/SymbolFileOnDemand.cpp b/lldb/source/Symbol/SymbolFileOnDemand.cpp
new file mode 100644
index 0000000..5c2cbc7
--- /dev/null
+++ b/lldb/source/Symbol/SymbolFileOnDemand.cpp
@@ -0,0 +1,590 @@
+//===-- SymbolFileDWARFDebugMap.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 "lldb/Symbol/SymbolFileOnDemand.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+
+char SymbolFileOnDemand::ID;
+
+SymbolFileOnDemand::SymbolFileOnDemand(
+ std::unique_ptr<SymbolFile> &&symbol_file)
+ : m_sym_file_impl(std::move(symbol_file)) {}
+
+SymbolFileOnDemand::~SymbolFileOnDemand() {}
+
+uint32_t SymbolFileOnDemand::CalculateAbilities() {
+ // Explicitly allow ability checking to pass though.
+ // This should be a cheap operation.
+ return m_sym_file_impl->CalculateAbilities();
+}
+
+std::recursive_mutex &SymbolFileOnDemand::GetModuleMutex() const {
+ return m_sym_file_impl->GetModuleMutex();
+}
+
+void SymbolFileOnDemand::InitializeObject() {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->InitializeObject();
+}
+
+lldb::LanguageType SymbolFileOnDemand::ParseLanguage(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ lldb::LanguageType langType = m_sym_file_impl->ParseLanguage(comp_unit);
+ if (langType != eLanguageTypeUnknown)
+ LLDB_LOG(log, "Language {0} would return if hydrated.", langType);
+ }
+ return eLanguageTypeUnknown;
+ }
+ return m_sym_file_impl->ParseLanguage(comp_unit);
+}
+
+XcodeSDK SymbolFileOnDemand::ParseXcodeSDK(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ XcodeSDK defaultValue{};
+ if (log) {
+ XcodeSDK sdk = m_sym_file_impl->ParseXcodeSDK(comp_unit);
+ if (!(sdk == defaultValue))
+ LLDB_LOG(log, "SDK {0} would return if hydrated.", sdk.GetString());
+ }
+ return defaultValue;
+ }
+ return m_sym_file_impl->ParseXcodeSDK(comp_unit);
+}
+
+size_t SymbolFileOnDemand::ParseFunctions(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ParseFunctions(comp_unit);
+}
+
+bool SymbolFileOnDemand::ParseLineTable(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return false;
+ }
+ return m_sym_file_impl->ParseLineTable(comp_unit);
+}
+
+bool SymbolFileOnDemand::ParseDebugMacros(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return false;
+ }
+ return m_sym_file_impl->ParseDebugMacros(comp_unit);
+}
+
+bool SymbolFileOnDemand::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ // Return false to not early exit.
+ return false;
+ }
+ return m_sym_file_impl->ForEachExternalModule(comp_unit, visited_symbol_files,
+ lambda);
+}
+
+bool SymbolFileOnDemand::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
+ LLDB_LOG(GetLog(),
+ "[{0}] {1} is not skipped: explicitly allowed to support breakpoint",
+ GetSymbolFileName(), __FUNCTION__);
+ // Explicitly allow this API through to support source line breakpoint.
+ return m_sym_file_impl->ParseSupportFiles(comp_unit, support_files);
+}
+
+bool SymbolFileOnDemand::ParseIsOptimized(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ bool optimized = m_sym_file_impl->ParseIsOptimized(comp_unit);
+ if (optimized) {
+ LLDB_LOG(log, "Would return optimized if hydrated.");
+ }
+ }
+ return false;
+ }
+ return m_sym_file_impl->ParseIsOptimized(comp_unit);
+}
+
+size_t SymbolFileOnDemand::ParseTypes(CompileUnit &comp_unit) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ParseTypes(comp_unit);
+}
+
+bool SymbolFileOnDemand::ParseImportedModules(
+ const lldb_private::SymbolContext &sc,
+ std::vector<SourceModule> &imported_modules) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ std::vector<SourceModule> tmp_imported_modules;
+ bool succeed =
+ m_sym_file_impl->ParseImportedModules(sc, tmp_imported_modules);
+ if (succeed)
+ LLDB_LOG(log, "{0} imported modules would be parsed if hydrated.",
+ tmp_imported_modules.size());
+ }
+ return false;
+ }
+ return m_sym_file_impl->ParseImportedModules(sc, imported_modules);
+}
+
+size_t SymbolFileOnDemand::ParseBlocksRecursive(Function &func) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ParseBlocksRecursive(func);
+}
+
+size_t SymbolFileOnDemand::ParseVariablesForContext(const SymbolContext &sc) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ParseVariablesForContext(sc);
+}
+
+Type *SymbolFileOnDemand::ResolveTypeUID(lldb::user_id_t type_uid) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ Type *resolved_type = m_sym_file_impl->ResolveTypeUID(type_uid);
+ if (resolved_type)
+ LLDB_LOG(log, "Type would be parsed for {0} if hydrated.", type_uid);
+ }
+ return nullptr;
+ }
+ return m_sym_file_impl->ResolveTypeUID(type_uid);
+}
+
+llvm::Optional<SymbolFile::ArrayInfo>
+SymbolFileOnDemand::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return llvm::None;
+ }
+ return m_sym_file_impl->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
+}
+
+bool SymbolFileOnDemand::CompleteType(CompilerType &compiler_type) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return false;
+ }
+ return m_sym_file_impl->CompleteType(compiler_type);
+}
+
+CompilerDecl SymbolFileOnDemand::GetDeclForUID(lldb::user_id_t type_uid) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ CompilerDecl parsed_decl = m_sym_file_impl->GetDeclForUID(type_uid);
+ if (parsed_decl != CompilerDecl()) {
+ LLDB_LOG(log, "CompilerDecl {0} would be parsed for {1} if hydrated.",
+ parsed_decl.GetName(), type_uid);
+ }
+ }
+ return CompilerDecl();
+ }
+ return m_sym_file_impl->GetDeclForUID(type_uid);
+}
+
+CompilerDeclContext
+SymbolFileOnDemand::GetDeclContextForUID(lldb::user_id_t type_uid) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return CompilerDeclContext();
+ }
+ return m_sym_file_impl->GetDeclContextForUID(type_uid);
+}
+
+CompilerDeclContext
+SymbolFileOnDemand::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return CompilerDeclContext();
+ }
+ return m_sym_file_impl->GetDeclContextContainingUID(type_uid);
+}
+
+void SymbolFileOnDemand::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->ParseDeclsForContext(decl_ctx);
+}
+
+uint32_t
+SymbolFileOnDemand::ResolveSymbolContext(const Address &so_addr,
+ SymbolContextItem resolve_scope,
+ SymbolContext &sc) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ResolveSymbolContext(so_addr, resolve_scope, sc);
+}
+
+uint32_t SymbolFileOnDemand::ResolveSymbolContext(
+ const SourceLocationSpec &src_location_spec,
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->ResolveSymbolContext(src_location_spec, resolve_scope,
+ sc_list);
+}
+
+void SymbolFileOnDemand::Dump(lldb_private::Stream &s) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->Dump(s);
+}
+
+void SymbolFileOnDemand::DumpClangAST(lldb_private::Stream &s) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->DumpClangAST(s);
+}
+
+void SymbolFileOnDemand::FindGlobalVariables(const RegularExpression &regex,
+ uint32_t max_matches,
+ VariableList &variables) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->FindGlobalVariables(regex, max_matches, variables);
+}
+
+void SymbolFileOnDemand::FindGlobalVariables(
+ ConstString name, const CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches, VariableList &variables) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ Symtab *symtab = GetSymtab();
+ if (!symtab) {
+ LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",
+ GetSymbolFileName(), __FUNCTION__);
+ return;
+ }
+ Symbol *sym = symtab->FindFirstSymbolWithNameAndType(
+ name, eSymbolTypeData, Symtab::eDebugAny, Symtab::eVisibilityAny);
+ if (!sym) {
+ LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",
+ GetSymbolFileName(), __FUNCTION__);
+ return;
+ }
+ LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",
+ GetSymbolFileName(), __FUNCTION__);
+
+ // Found match in symbol table hydrate debug info and
+ // allow the FindGlobalVariables to go through.
+ SetLoadDebugInfoEnabled();
+ }
+ return m_sym_file_impl->FindGlobalVariables(name, parent_decl_ctx,
+ max_matches, variables);
+}
+
+void SymbolFileOnDemand::FindFunctions(const RegularExpression &regex,
+ bool include_inlines,
+ SymbolContextList &sc_list) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ Symtab *symtab = GetSymtab();
+ if (!symtab) {
+ LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",
+ GetSymbolFileName(), __FUNCTION__);
+ return;
+ }
+ std::vector<uint32_t> symbol_indexes;
+ symtab->AppendSymbolIndexesMatchingRegExAndType(
+ regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny,
+ symbol_indexes);
+ if (symbol_indexes.empty()) {
+ LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",
+ GetSymbolFileName(), __FUNCTION__);
+ return;
+ }
+ LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",
+ GetSymbolFileName(), __FUNCTION__);
+
+ // Found match in symbol table hydrate debug info and
+ // allow the FindFucntions to go through.
+ SetLoadDebugInfoEnabled();
+ }
+ return m_sym_file_impl->FindFunctions(regex, include_inlines, sc_list);
+}
+
+void SymbolFileOnDemand::FindFunctions(
+ ConstString name, const CompilerDeclContext &parent_decl_ctx,
+ FunctionNameType name_type_mask, bool include_inlines,
+ SymbolContextList &sc_list) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+
+ Symtab *symtab = GetSymtab();
+ if (!symtab) {
+ LLDB_LOG(log, "[{0}] {1}({2}) is skipped - fail to get symtab",
+ GetSymbolFileName(), __FUNCTION__, name);
+ return;
+ }
+
+ SymbolContextList sc_list_helper;
+ symtab->FindFunctionSymbols(name, name_type_mask, sc_list_helper);
+ if (sc_list_helper.GetSize() == 0) {
+ LLDB_LOG(log, "[{0}] {1}({2}) is skipped - fail to find match in symtab",
+ GetSymbolFileName(), __FUNCTION__, name);
+ return;
+ }
+ LLDB_LOG(log, "[{0}] {1}({2}) is NOT skipped - found match in symtab",
+ GetSymbolFileName(), __FUNCTION__, name);
+
+ // Found match in symbol table hydrate debug info and
+ // allow the FindFucntions to go through.
+ SetLoadDebugInfoEnabled();
+ }
+ return m_sym_file_impl->FindFunctions(name, parent_decl_ctx, name_type_mask,
+ include_inlines, sc_list);
+}
+
+void SymbolFileOnDemand::GetMangledNamesForFunction(
+ const std::string &scope_qualified_name,
+ std::vector<ConstString> &mangled_names) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
+ __FUNCTION__, scope_qualified_name);
+ return;
+ }
+ return m_sym_file_impl->GetMangledNamesForFunction(scope_qualified_name,
+ mangled_names);
+}
+
+void SymbolFileOnDemand::FindTypes(
+ ConstString name, const CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ TypeMap &types) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
+ __FUNCTION__, name);
+ return;
+ }
+ return m_sym_file_impl->FindTypes(name, parent_decl_ctx, max_matches,
+ searched_symbol_files, types);
+}
+
+void SymbolFileOnDemand::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->FindTypes(pattern, languages, searched_symbol_files,
+ types);
+}
+
+void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope,
+ TypeClass type_mask, TypeList &type_list) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->GetTypes(sc_scope, type_mask, type_list);
+}
+
+llvm::Expected<TypeSystem &>
+SymbolFileOnDemand::GetTypeSystemForLanguage(LanguageType language) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped for language type {2}",
+ GetSymbolFileName(), __FUNCTION__, language);
+ return llvm::make_error<llvm::StringError>(
+ "GetTypeSystemForLanguage is skipped by SymbolFileOnDemand",
+ llvm::inconvertibleErrorCode());
+ }
+ return m_sym_file_impl->GetTypeSystemForLanguage(language);
+}
+
+CompilerDeclContext
+SymbolFileOnDemand::FindNamespace(ConstString name,
+ const CompilerDeclContext &parent_decl_ctx) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
+ __FUNCTION__, name);
+ return SymbolFile::FindNamespace(name, parent_decl_ctx);
+ }
+ return m_sym_file_impl->FindNamespace(name, parent_decl_ctx);
+}
+
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
+SymbolFileOnDemand::ParseCallEdgesInFunction(UserID func_id) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ std::vector<std::unique_ptr<lldb_private::CallEdge>> call_edges =
+ m_sym_file_impl->ParseCallEdgesInFunction(func_id);
+ if (call_edges.size() > 0) {
+ LLDB_LOG(log, "{0} call edges would be parsed for {1} if hydrated.",
+ call_edges.size(), func_id.GetID());
+ }
+ }
+ return {};
+ }
+ return m_sym_file_impl->ParseCallEdgesInFunction(func_id);
+}
+
+lldb::UnwindPlanSP
+SymbolFileOnDemand::GetUnwindPlan(const Address &address,
+ const RegisterInfoResolver &resolver) {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return nullptr;
+ }
+ return m_sym_file_impl->GetUnwindPlan(address, resolver);
+}
+
+llvm::Expected<lldb::addr_t>
+SymbolFileOnDemand::GetParameterStackSize(Symbol &symbol) {
+ if (!m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ llvm::Expected<lldb::addr_t> stack_size =
+ m_sym_file_impl->GetParameterStackSize(symbol);
+ if (stack_size) {
+ LLDB_LOG(log, "{0} stack size would return for symbol {1} if hydrated.",
+ *stack_size, symbol.GetName());
+ }
+ }
+ return SymbolFile::GetParameterStackSize(symbol);
+ }
+ return m_sym_file_impl->GetParameterStackSize(symbol);
+}
+
+void SymbolFileOnDemand::PreloadSymbols() {
+ m_preload_symbols = true;
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return;
+ }
+ return m_sym_file_impl->PreloadSymbols();
+}
+
+uint64_t SymbolFileOnDemand::GetDebugInfoSize() {
+ // Always return the real debug info size.
+ LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return m_sym_file_impl->GetDebugInfoSize();
+}
+
+StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoParseTime() {
+ // Always return the real parse time.
+ LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return m_sym_file_impl->GetDebugInfoParseTime();
+}
+
+StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoIndexTime() {
+ // Always return the real index time.
+ LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return m_sym_file_impl->GetDebugInfoIndexTime();
+}
+
+void SymbolFileOnDemand::SetLoadDebugInfoEnabled() {
+ if (m_debug_info_enabled)
+ return;
+ LLDB_LOG(GetLog(), "[{0}] Hydrate debug info", GetSymbolFileName());
+ m_debug_info_enabled = true;
+ InitializeObject();
+ if (m_preload_symbols)
+ PreloadSymbols();
+}
+
+uint32_t SymbolFileOnDemand::GetNumCompileUnits() {
+ LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",
+ GetSymbolFileName(), __FUNCTION__);
+ return m_sym_file_impl->GetNumCompileUnits();
+}
+
+CompUnitSP SymbolFileOnDemand::GetCompileUnitAtIndex(uint32_t idx) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",
+ GetSymbolFileName(), __FUNCTION__);
+ return m_sym_file_impl->GetCompileUnitAtIndex(idx);
+}
+
+uint32_t SymbolFileOnDemand::GetAbilities() {
+ if (!m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return 0;
+ }
+ return m_sym_file_impl->GetAbilities();
+}
diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp
index 28800f9..b8ad25e 100644
--- a/lldb/source/Target/Statistics.cpp
+++ b/lldb/source/Target/Statistics.cpp
@@ -62,6 +62,8 @@ json::Value ModuleStats::ToJSON() const {
debug_info_index_loaded_from_cache);
module.try_emplace("debugInfoIndexSavedToCache",
debug_info_index_saved_to_cache);
+ module.try_emplace("debugInfoEnabled", debug_info_enabled);
+ module.try_emplace("symbolTableStripped", symtab_stripped);
if (!symfile_path.empty())
module.try_emplace("symbolFilePath", symfile_path);
@@ -183,7 +185,10 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
std::vector<ModuleStats> modules;
std::lock_guard<std::recursive_mutex> guard(
Module::GetAllocationModuleCollectionMutex());
- const size_t num_modules = Module::GetNumberAllocatedModules();
+ const uint64_t num_modules = Module::GetNumberAllocatedModules();
+ uint32_t num_debug_info_enabled_modules = 0;
+ uint32_t num_modules_has_debug_info = 0;
+ uint32_t num_stripped_modules = 0;
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
ModuleStats module_stat;
@@ -227,6 +232,15 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
for (const auto &symbol_module: symbol_modules.Modules())
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
+ module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
+ if (module_stat.symtab_stripped)
+ ++num_stripped_modules;
+ module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
+ module_stat.debug_info_size > 0;
+ if (module_stat.debug_info_enabled)
+ ++num_debug_info_enabled_modules;
+ if (module_stat.debug_info_size > 0)
+ ++num_modules_has_debug_info;
}
symtab_parse_time += module_stat.symtab_parse_time;
symtab_index_time += module_stat.symtab_index_time;
@@ -254,6 +268,10 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
{"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
{"totalDebugInfoIndexSavedToCache", debug_index_saved},
{"totalDebugInfoByteSize", debug_info_size},
+ {"totalModuleCount", num_modules},
+ {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
+ {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
+ {"totalSymbolTableStripped", num_stripped_modules},
};
return std::move(global_stats);
}
diff --git a/lldb/source/Utility/LLDBLog.cpp b/lldb/source/Utility/LLDBLog.cpp
index 4b535c1..71c534a 100644
--- a/lldb/source/Utility/LLDBLog.cpp
+++ b/lldb/source/Utility/LLDBLog.cpp
@@ -60,6 +60,9 @@ static constexpr Log::Category g_categories[] = {
{{"types"}, {"log type system related activities"}, LLDBLog::Types},
{{"unwind"}, {"log stack unwind activities"}, LLDBLog::Unwind},
{{"watch"}, {"log watchpoint related activities"}, LLDBLog::Watchpoints},
+ {{"on-demand"},
+ {"log symbol on-demand related activities"},
+ LLDBLog::OnDemand},
};
static Log::Channel g_log_channel(g_categories,