yinghuitan updated this revision to Diff 415183.
yinghuitan added a comment.
Herald added a subscriber: JDevlieghere.
Fix tests line number change after formatting.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D121631/new/
https://reviews.llvm.org/D121631
Files:
include/lldb/Symbol/SymbolFileOnDemand.h
lldb/include/lldb/Core/ModuleList.h
lldb/include/lldb/Symbol/SymbolFile.h
lldb/include/lldb/Symbol/SymbolFileOnDemand.h
lldb/include/lldb/Target/Statistics.h
lldb/include/lldb/Utility/LLDBLog.h
lldb/packages/Python/lldbsuite/test/builders/builder.py
lldb/packages/Python/lldbsuite/test/lldbtest.py
lldb/packages/Python/lldbsuite/test/test_categories.py
lldb/source/Core/CoreProperties.td
lldb/source/Core/Module.cpp
lldb/source/Core/ModuleList.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
lldb/source/Symbol/CMakeLists.txt
lldb/source/Symbol/CompileUnit.cpp
lldb/source/Symbol/SymbolFile.cpp
lldb/source/Symbol/SymbolFileOnDemand.cpp
lldb/source/Target/Statistics.cpp
lldb/source/Utility/LLDBLog.cpp
lldb/test/API/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py
lldb/test/API/functionalities/find-line-entry/TestFindLineEntry.py
lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
lldb/test/API/functionalities/show_location/TestShowLocationDwarf5.py
lldb/test/API/functionalities/type_get_module/TestTypeGetModule.py
lldb/test/API/lang/c/enum_types/TestEnumTypes.py
lldb/test/API/lang/c/global_variables/TestGlobalVariables.py
lldb/test/API/lang/c/shared_lib/TestSharedLib.py
lldb/test/API/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py
lldb/test/API/lang/c/sizeof/TestCSizeof.py
lldb/test/API/lang/c/unicode/TestUnicodeSymbols.py
lldb/test/API/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py
lldb/test/API/lang/cpp/enum_types/TestCPP11EnumTypes.py
lldb/test/API/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py
lldb/test/API/lang/cpp/sizeof/TestCPPSizeof.py
lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py
lldb/test/Shell/SymbolFile/OnDemand/Inputs/basic.cpp
lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.cpp
lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.h
lldb/test/Shell/SymbolFile/OnDemand/Inputs/shared.cpp
lldb/test/Shell/SymbolFile/OnDemand/shared-lib-globals.test
lldb/test/Shell/SymbolFile/OnDemand/shared-lib.test
lldb/test/Shell/SymbolFile/OnDemand/source-breakpoint.test
lldb/test/Shell/SymbolFile/OnDemand/symbolic-breakpoint.test
Index: lldb/test/Shell/SymbolFile/OnDemand/symbolic-breakpoint.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/symbolic-breakpoint.test
@@ -0,0 +1,24 @@
+
+# Test shows that symbolic function breakpoint works with LLDB on demand symbol loading.
+
+# RUN: mkdir -p %t
+# RUN: cd %t
+# RUN: %build %p/Inputs/basic.cpp -o basic.out
+# RUN: %lldb -b -O "settings set symbols.load-on-demand true" -s %s basic.out | FileCheck %s
+
+breakpoint list
+# CHECK: No breakpoints currently set
+
+b bar
+# CHECK: where = {{.*}}`bar(int, int) + {{.*}} at basic.cpp:1
+
+breakpoint list
+# CHECK: where = {{.*}}`bar(int, int) + {{.*}} at basic.cpp:1
+
+run
+# CHECK: stop reason = breakpoint
+
+bt
+# CHECK: {{.*}}`bar(x=33, y=78) at basic.cpp:1
+# CHECK: {{.*}}`foo(x=33, y=78) at basic.cpp:3
+# CHECK: {{.*}}`main(argc=1, argv={{.*}}) at basic.cpp:5
Index: lldb/test/Shell/SymbolFile/OnDemand/source-breakpoint.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/source-breakpoint.test
@@ -0,0 +1,23 @@
+# Test shows that source line breakpoint works with LLDB on demand symbol loading.
+
+# RUN: mkdir -p %t
+# RUN: cd %t
+# RUN: %build %p/Inputs/basic.cpp -o basic.out
+# RUN: %lldb -b -O "settings set symbols.load-on-demand true" -s %s basic.out | FileCheck %s
+
+breakpoint list
+# CHECK: No breakpoints currently set
+
+breakpoint set -f basic.cpp -l 1
+# CHECK: where = {{.*}}`bar(int, int) + {{.*}} at basic.cpp:1
+
+breakpoint list
+# CHECK: file = 'basic.cpp'
+
+run
+# CHECK: stop reason = breakpoint
+
+bt
+# CHECK: {{.*}}`bar(x=33, y=78) at basic.cpp:1
+# CHECK: {{.*}}`foo(x=33, y=78) at basic.cpp:3
+# CHECK: {{.*}}`main(argc=1, argv={{.*}}) at basic.cpp:5
Index: lldb/test/Shell/SymbolFile/OnDemand/shared-lib.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/shared-lib.test
@@ -0,0 +1,37 @@
+# Test shows that source line breakpoint works in multiple shared libraries with LLDB on demand symbol loading.
+
+# REQUIRES: system-linux
+
+# RUN: mkdir -p %t
+# RUN: cd %t
+# RUN: %clang_host -shared -g -fpic %p/Inputs/lib.cpp -o libFoo.so
+# RUN: %clang_host -L%t -g -o shared.out %p/Inputs/shared.cpp -lFoo -Wl,-rpath=%t
+# RUN: %lldb -b -O "settings set symbols.load-on-demand true" -s %s shared.out | FileCheck %s
+
+breakpoint list
+# CHECK: No breakpoints currently set
+
+breakpoint set -f lib.cpp -l 4
+# CHECK: where = {{.*}}`foo() + {{.*}} at lib.cpp:4
+
+breakpoint list
+# CHECK: file = 'lib.cpp', line = 4
+
+run
+# CHECK: stop reason = breakpoint
+# CHECK: foo() at lib.cpp:4
+
+bt
+# CHECK: {{.*}}`foo() at lib.cpp:4
+# CHECK: at shared.cpp:7
+
+breakpoint set -f shared.cpp -l 8
+# CHECK: at shared.cpp:8
+
+breakpoint list
+# CHECK: file = 'lib.cpp', line = 4
+# CHECK: file = 'shared.cpp', line = 8
+
+continue
+# CHECK: stop reason = breakpoint
+# CHECK: at shared.cpp:8
Index: lldb/test/Shell/SymbolFile/OnDemand/shared-lib-globals.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/shared-lib-globals.test
@@ -0,0 +1,29 @@
+# Test shows that global variables works as expected in multiple shared libraries with LLDB on demand symbol loading.
+# The global varialbes in non-hydrated shared library libFoo.so can't be found.
+
+# REQUIRES: system-linux
+
+# RUN: mkdir -p %t
+# RUN: cd %t
+# RUN: %clang_host -shared -g -fpic %p/Inputs/lib.cpp -o libFoo.so
+# RUN: %clang_host -L%t -g -o shared.out %p/Inputs/shared.cpp -lFoo -Wl,-rpath=%t
+# RUN: %lldb -b -O "settings set symbols.load-on-demand true" -s %s shared.out | FileCheck %s
+
+breakpoint list
+# CHECK: No breakpoints currently set
+
+breakpoint set -f shared.cpp -l 8
+# CHECK: at shared.cpp:8
+
+breakpoint list
+# CHECK: file = 'shared.cpp', line = 8
+
+run
+# CHECK: stop reason = breakpoint
+# CHECK: at shared.cpp:8
+
+target variable --shlib shared.out
+# CHECK: (int) ::global_shared = 897
+
+target variable --shlib libFoo.so
+# CHECK-NOT: global_foo
Index: lldb/test/Shell/SymbolFile/OnDemand/Inputs/shared.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/Inputs/shared.cpp
@@ -0,0 +1,9 @@
+#include "lib.h"
+#include <stdio.h>
+
+int global_shared = 897;
+int main(void) {
+ puts("This is a shared library test...");
+ foo();
+ return 0;
+}
Index: lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.h
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.h
@@ -0,0 +1,6 @@
+#ifndef foo_h__
+#define foo_h__
+
+extern void foo(void);
+
+#endif // foo_h__
Index: lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/Inputs/lib.cpp
@@ -0,0 +1,4 @@
+#include <stdio.h>
+
+int global_foo = 321;
+void foo(void) { puts("Hello, I am a shared library"); }
Index: lldb/test/Shell/SymbolFile/OnDemand/Inputs/basic.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/OnDemand/Inputs/basic.cpp
@@ -0,0 +1,5 @@
+int bar(int x, int y) { return x + y + 5; }
+
+int foo(int x, int y) { return bar(x, y) + 12; }
+
+int main(int argc, char **argv) { return foo(33, 78); }
Index: lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py
===================================================================
--- lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py
+++ lldb/test/API/lang/cpp/template-function/TestTemplateFunctions.py
@@ -53,6 +53,6 @@
self.do_test_template_function(True)
@skipIfWindows
- @expectedFailureAll(debug_info=["dwarf", "gmodules", "dwo"])
+ @expectedFailureAll(debug_info=["dwarf", "gmodules", "dwo", "ondemand"])
def test_template_function_without_cast(self):
self.do_test_template_function(False)
Index: lldb/test/API/lang/cpp/sizeof/TestCPPSizeof.py
===================================================================
--- lldb/test/API/lang/cpp/sizeof/TestCPPSizeof.py
+++ lldb/test/API/lang/cpp/sizeof/TestCPPSizeof.py
@@ -7,6 +7,10 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="Type is not parsed in on-demand mode",
+ )
def test(self):
self.build()
self.createTestTarget()
Index: lldb/test/API/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py
===================================================================
--- lldb/test/API/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py
+++ lldb/test/API/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py
@@ -13,6 +13,10 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="Type in shared library is not parsed in on-demand mode",
+ )
# See also llvm.org/pr28948
@expectedFailureAll(
bugnumber="llvm.org/pr50814",
Index: lldb/test/API/lang/cpp/enum_types/TestCPP11EnumTypes.py
===================================================================
--- lldb/test/API/lang/cpp/enum_types/TestCPP11EnumTypes.py
+++ lldb/test/API/lang/cpp/enum_types/TestCPP11EnumTypes.py
@@ -37,6 +37,10 @@
self.expect_expr("var_below_" + suffix, result_type=enum_name, result_value="-3")
self.expect_expr("var_above_" + suffix, result_type=enum_name, result_value="1")
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="Type lookup is expected to fail in on-demand mode",
+ )
@skipIf(dwarf_version=['<', '4'])
def test(self):
self.build()
Index: lldb/test/API/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py
===================================================================
--- lldb/test/API/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py
+++ lldb/test/API/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py
@@ -28,6 +28,13 @@
num_locations))
return bkpt
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="""
+ Function name breakpoint filter by compile unit would disable
+ searching in symbol table.
+ """,
+ )
def test_cpp_breakpoint_cmds(self):
"""Test a sequence of breakpoint command add, list, and delete."""
self.build()
Index: lldb/test/API/lang/c/unicode/TestUnicodeSymbols.py
===================================================================
--- lldb/test/API/lang/c/unicode/TestUnicodeSymbols.py
+++ lldb/test/API/lang/c/unicode/TestUnicodeSymbols.py
@@ -9,6 +9,8 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(debug_info="ondemand",
+ bugnumber="type info is not loaded by default in on-demand mode")
@skipIf(compiler="clang", compiler_version=['<', '7.0'])
def test_union_members(self):
self.build()
Index: lldb/test/API/lang/c/sizeof/TestCSizeof.py
===================================================================
--- lldb/test/API/lang/c/sizeof/TestCSizeof.py
+++ lldb/test/API/lang/c/sizeof/TestCSizeof.py
@@ -7,6 +7,8 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(debug_info="ondemand",
+ bugnumber="type info is not loaded by default in on-demand mode")
def test(self):
self.build()
self.createTestTarget()
Index: lldb/test/API/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py
===================================================================
--- lldb/test/API/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py
+++ lldb/test/API/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py
@@ -13,6 +13,8 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(debug_info="ondemand",
+ bugnumber="debug info is expected to not load for shared library")
@expectedFailureAll(oslist=["windows"])
def test_expr(self):
"""Test that types work when defined in a shared library and forwa/d-declared in the main executable"""
@@ -32,6 +34,8 @@
"(sub_foo)",
"other_element = 3"])
+ @skipIf(debug_info="ondemand",
+ bugnumber="debug info is expected to not load for shared library")
@expectedFailureAll(oslist=["windows"])
@expectedFailure("llvm.org/PR36712")
def test_frame_variable(self):
Index: lldb/test/API/lang/c/shared_lib/TestSharedLib.py
===================================================================
--- lldb/test/API/lang/c/shared_lib/TestSharedLib.py
+++ lldb/test/API/lang/c/shared_lib/TestSharedLib.py
@@ -34,14 +34,20 @@
"expression GetMeASubFoo(my_foo_ptr)",
startstr="(sub_foo *) $")
+ @skipIf(debug_info="ondemand",
+ bugnumber="debug info is expected to not load for shared library")
def test_expr(self):
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
self.common_test_expr(True)
+ @skipIf(debug_info="ondemand",
+ bugnumber="debug info is expected to not load for shared library")
def test_expr_no_preload(self):
"""Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled"""
self.common_test_expr(False)
+ @skipIf(debug_info="ondemand",
+ bugnumber="debug info is expected to not load for shared library")
@expectedFailure("llvm.org/PR36712")
def test_frame_variable(self):
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
Index: lldb/test/API/lang/c/global_variables/TestGlobalVariables.py
===================================================================
--- lldb/test/API/lang/c/global_variables/TestGlobalVariables.py
+++ lldb/test/API/lang/c/global_variables/TestGlobalVariables.py
@@ -117,4 +117,3 @@
VARIABLES_DISPLAYED_CORRECTLY,
matching=False,
substrs=["can't be resolved"])
-
Index: lldb/test/API/lang/c/enum_types/TestEnumTypes.py
===================================================================
--- lldb/test/API/lang/c/enum_types/TestEnumTypes.py
+++ lldb/test/API/lang/c/enum_types/TestEnumTypes.py
@@ -125,7 +125,7 @@
def check_enum_members(self, members):
name_matches = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "kNumDays"]
value_matches = [-3, -2, -1, 0, 1, 2, 3, 4]
-
+
# First test that the list of members from the type works
num_matches = len(name_matches)
self.assertEqual(len(members), num_matches, "enum_members returns the right number of elements")
@@ -134,7 +134,9 @@
self.assertTrue(member.IsValid(), "Got a valid member for idx: %d"%(idx))
self.assertEqual(member.name, name_matches[idx], "Name matches for %d"%(idx))
self.assertEqual(member.signed, value_matches[idx], "Value matches for %d"%(idx))
-
+
+ @skipIf(debug_info="ondemand",
+ bugnumber="Can't find type in on-demand mode")
def test_api(self):
"""Test that the SBTypeEnumMember API's work correctly for enum_test_days"""
self.build()
@@ -158,4 +160,3 @@
self.assertTrue(check_member.IsValid(), "Got a valid member for %s."%(name))
self.assertEqual(name, check_member.name, "Got back the right name")
self.assertEqual(member.unsigned, check_member.unsigned)
-
Index: lldb/test/API/functionalities/type_get_module/TestTypeGetModule.py
===================================================================
--- lldb/test/API/functionalities/type_get_module/TestTypeGetModule.py
+++ lldb/test/API/functionalities/type_get_module/TestTypeGetModule.py
@@ -61,6 +61,8 @@
self.assertTrue(result.IsValid())
return result
+ @skipIf(debug_info="ondemand",
+ bugnumber="Can't find type in on-demand mode")
def test(self):
self.build()
target = lldbutil.run_to_breakpoint_make_target(self)
@@ -72,7 +74,7 @@
comp_unit = self.find_comp_unit(exe_module, 'compile_unit1.c')
cu_type = self.find_type(comp_unit.GetTypes(), 'compile_unit1_type')
self.assertEqual(exe_module, cu_type.GetModule())
-
+
comp_unit = self.find_comp_unit(exe_module, 'compile_unit2.c')
cu_type = self.find_type(comp_unit.GetTypes(), 'compile_unit2_type')
self.assertEqual(exe_module, cu_type.GetModule())
Index: lldb/test/API/functionalities/show_location/TestShowLocationDwarf5.py
===================================================================
--- lldb/test/API/functionalities/show_location/TestShowLocationDwarf5.py
+++ lldb/test/API/functionalities/show_location/TestShowLocationDwarf5.py
@@ -11,6 +11,8 @@
@skipIf(archs="aarch64", oslist="linux",
bugnumber="https://bugs.llvm.org/show_bug.cgi?id=44180")
+ @skipIf(debug_info="ondemand",
+ bugnumber="yaml generated binary does not have symbol table")
def test_source_map(self):
# Set the target soure map to map "./" to the current test directory.
yaml_path = os.path.join(self.getSourceDir(), "a.yaml")
Index: lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
===================================================================
--- lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
+++ lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
@@ -31,6 +31,7 @@
self._check_type(target, "InheritsFromTwo")
@skipIf(bugnumber="pr46284", debug_info="gmodules")
+ @skipIf(bugnumber="FindFirstType() won't work in on-demand", debug_info="ondemand")
@skipIfWindows # Clang emits type info even with -flimit-debug-info
# Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
# by-value functions.
@@ -70,6 +71,7 @@
self.expect_expr("shadowed_one.one", result_value="142")
@skipIf(bugnumber="pr46284", debug_info="gmodules")
+ @skipIf(bugnumber="FindFirstType() won't work in on-demand", debug_info="ondemand")
@skipIfWindows # Clang emits type info even with -flimit-debug-info
# Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
# by-value functions.
@@ -113,6 +115,7 @@
self.expect_expr("get_two().member", result_value="224")
@skipIf(bugnumber="pr46284", debug_info="gmodules")
+ @skipIf(bugnumber="FindFirstType() won't work in on-demand", debug_info="ondemand")
@skipIfWindows # Clang emits type info even with -flimit-debug-info
# Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
# by-value functions.
Index: lldb/test/API/functionalities/find-line-entry/TestFindLineEntry.py
===================================================================
--- lldb/test/API/functionalities/find-line-entry/TestFindLineEntry.py
+++ lldb/test/API/functionalities/find-line-entry/TestFindLineEntry.py
@@ -3,6 +3,7 @@
"""
import lldb
+from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *
@@ -10,6 +11,10 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="Line table parsing is disabled in on-demand mode",
+ )
def test_compile_unit_find_line_entry_index(self):
""" Test the CompileUnit LineEntryIndex lookup API """
self.build()
Index: lldb/test/API/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py
===================================================================
--- lldb/test/API/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py
+++ lldb/test/API/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py
@@ -5,6 +5,7 @@
import lldb
+from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
import lldbsuite.test.lldbutil as lldbutil
@@ -13,6 +14,10 @@
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(
+ debug_info="ondemand",
+ bugnumber="symbolic function for inline function won't work in on-demand mode",
+ )
def test(self):
self.build()
Index: lldb/source/Utility/LLDBLog.cpp
===================================================================
--- lldb/source/Utility/LLDBLog.cpp
+++ lldb/source/Utility/LLDBLog.cpp
@@ -60,6 +60,9 @@
{{"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,
Index: lldb/source/Target/Statistics.cpp
===================================================================
--- lldb/source/Target/Statistics.cpp
+++ lldb/source/Target/Statistics.cpp
@@ -62,6 +62,8 @@
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("symtab_stripped", symtab_stripped);
if (!symfile_path.empty())
module.try_emplace("symbolFilePath", symfile_path);
@@ -183,7 +185,9 @@
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_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 +231,15 @@
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;
+ }
}
symtab_parse_time += module_stat.symtab_parse_time;
symtab_index_time += module_stat.symtab_index_time;
@@ -254,6 +267,9 @@
{"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
{"totalDebugInfoIndexSavedToCache", debug_index_saved},
{"totalDebugInfoByteSize", debug_info_size},
+ {"totalModuleCount", num_modules},
+ {"totalDebugInfoEnabledModules", num_debug_info_enabled_modules},
+ {"totalSymbolTableStrippedModules", num_stripped_modules},
};
return std::move(global_stats);
}
Index: lldb/source/Symbol/SymbolFileOnDemand.cpp
===================================================================
--- /dev/null
+++ lldb/source/Symbol/SymbolFileOnDemand.cpp
@@ -0,0 +1,611 @@
+//===-- 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(
+ lldb::ObjectFileSP objfile_sp, std::unique_ptr<SymbolFile> &&symbol_file)
+ : SymbolFile(std::move(objfile_sp)),
+ m_sym_file_impl(std::move(symbol_file)) {}
+
+SymbolFileOnDemand::~SymbolFileOnDemand() {}
+
+uint32_t SymbolFileOnDemand::CalculateAbilities() {
+ if (!this->m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
+ if (log) {
+ uint32_t abilities = m_sym_file_impl->CalculateAbilities();
+ if (abilities != 0) {
+ LLDB_LOG(log, "{0} abilities would return if hydrated.", abilities);
+ }
+ }
+ return 0;
+ }
+ return m_sym_file_impl->CalculateAbilities();
+}
+
+std::recursive_mutex &SymbolFileOnDemand::GetModuleMutex() const {
+ return m_sym_file_impl->GetModuleMutex();
+}
+
+void SymbolFileOnDemand::InitializeObject() {
+ if (!this->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 (!this->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.",
+ eLanguageTypeUnknown);
+ }
+ }
+ return eLanguageTypeUnknown;
+ }
+ return m_sym_file_impl->ParseLanguage(comp_unit);
+}
+
+XcodeSDK SymbolFileOnDemand::ParseXcodeSDK(CompileUnit &comp_unit) {
+ if (!this->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 (!this->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 (!this->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 (!this->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 (!this->m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ // 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 (!this->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, "Optimized would return if hydrated.");
+ }
+ }
+ return false;
+ }
+ return m_sym_file_impl->ParseIsOptimized(comp_unit);
+}
+
+size_t SymbolFileOnDemand::ParseTypes(CompileUnit &comp_unit) {
+ if (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 ®ex,
+ uint32_t max_matches,
+ VariableList &variables) {
+ if (!this->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 (!this->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 ®ex,
+ bool include_inlines,
+ SymbolContextList &sc_list) {
+ if (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->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 (!this->m_debug_info_enabled) {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is skipped for language type {2}",
+ GetSymbolFileName(), __FUNCTION__, language);
+ return SymbolFile::GetTypeSystemForLanguage(language);
+ }
+ return m_sym_file_impl->GetTypeSystemForLanguage(language);
+}
+
+CompilerDeclContext
+SymbolFileOnDemand::FindNamespace(ConstString name,
+ const CompilerDeclContext &parent_decl_ctx) {
+ if (!this->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 (!this->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 (!this->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 (!this->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 (!this->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();
+}
+
+uint32_t SymbolFileOnDemand::CalculateNumCompileUnits() {
+ Log *log = GetLog();
+ LLDB_LOG(log, "[{0}] {1} is not skipped to support breakpoint hydration",
+ GetSymbolFileName(), __FUNCTION__);
+ // Explicitly allow this API through.
+ return m_sym_file_impl->CalculateNumCompileUnits();
+}
+
+CompUnitSP SymbolFileOnDemand::ParseCompileUnitAtIndex(uint32_t cu_idx) {
+ LLDB_LOG(
+ GetLog(),
+ "[{0}] {1} for cu_idx {2} is not skipped to support breakpoint hydration",
+ GetSymbolFileName(), __FUNCTION__, cu_idx);
+ // Explicitly allow this API through to support source line breakpoint.
+ return m_sym_file_impl->ParseCompileUnitAtIndex(cu_idx);
+}
+
+TypeList &SymbolFileOnDemand::GetTypeList() {
+ // assert(false && "Should never be called");
+ if (!this->m_debug_info_enabled) {
+ LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
+ __FUNCTION__);
+ return SymbolFile::GetTypeList();
+ }
+ return m_sym_file_impl->GetTypeList();
+}
+
+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();
+ }
+}
Index: lldb/source/Symbol/SymbolFile.cpp
===================================================================
--- lldb/source/Symbol/SymbolFile.cpp
+++ 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"
@@ -79,6 +80,15 @@
}
}
if (best_symfile_up) {
+ ObjectFile::Type obj_file_type = objfile_sp->CalculateType();
+ if (ModuleList::GetGlobalModuleListProperties().GetLoadSymbolOnDemand() &&
+ best_symfile_up->GetDebugInfoSize() > 0 &&
+ (obj_file_type == ObjectFile::eTypeExecutable ||
+ obj_file_type == ObjectFile::eTypeSharedLibrary ||
+ obj_file_type == ObjectFile::eTypeDebugInfo)) {
+ best_symfile_up = std::make_unique<SymbolFileOnDemand>(
+ objfile_sp, 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();
Index: lldb/source/Symbol/CompileUnit.cpp
===================================================================
--- lldb/source/Symbol/CompileUnit.cpp
+++ lldb/source/Symbol/CompileUnit.cpp
@@ -287,6 +287,9 @@
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 @@
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
Index: lldb/source/Symbol/CMakeLists.txt
===================================================================
--- lldb/source/Symbol/CMakeLists.txt
+++ lldb/source/Symbol/CMakeLists.txt
@@ -27,6 +27,7 @@
Symbol.cpp
SymbolContext.cpp
SymbolFile.cpp
+ SymbolFileOnDemand.cpp
SymbolVendor.cpp
Symtab.cpp
Type.cpp
Index: lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -65,8 +65,8 @@
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;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -68,7 +68,8 @@
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 {
Index: lldb/source/Core/ModuleList.cpp
===================================================================
--- lldb/source/Core/ModuleList.cpp
+++ lldb/source/Core/ModuleList.cpp
@@ -180,6 +180,12 @@
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)
Index: lldb/source/Core/Module.cpp
===================================================================
--- lldb/source/Core/Module.cpp
+++ lldb/source/Core/Module.cpp
@@ -469,6 +469,8 @@
if (!symfile)
return resolved_flags;
+ symfile->SetLoadDebugInfoEnabled();
+
// Resolve the compile unit, function, block, line table or line entry if
// requested.
if (resolve_scope & eSymbolContextCompUnit ||
Index: lldb/source/Core/CoreProperties.td
===================================================================
--- lldb/source/Core/CoreProperties.td
+++ lldb/source/Core/CoreProperties.td
@@ -33,6 +33,10 @@
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 breakpoint to improve performance.">;
}
let Definition = "debugger" in {
Index: lldb/packages/Python/lldbsuite/test/test_categories.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/test_categories.py
+++ lldb/packages/Python/lldbsuite/test/test_categories.py
@@ -15,7 +15,7 @@
debug_info_categories = [
- 'dwarf', 'dwo', 'dsym', 'gmodules'
+ 'dwarf', 'dwo', 'dsym', 'gmodules', 'ondemand'
]
all_categories = {
@@ -42,6 +42,7 @@
'std-module': 'Tests related to importing the std module',
'stresstest': 'Tests related to stressing lldb limits',
'watchpoint': 'Watchpoint-related tests',
+ 'ondemand': 'Tests that can be run with symbol on-demand loading',
}
Index: lldb/packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -710,6 +710,11 @@
"""Return absolute path to a file in the test's source directory."""
return os.path.join(self.getSourceDir(), name)
+ def getTestCategories(self):
+ test_method = getattr(self, self._testMethodName)
+ if test_method is not None and hasattr(test_method, "categories"):
+ return test_method.categories
+
@classmethod
def setUpCommands(cls):
commands = [
@@ -1796,6 +1801,10 @@
for s in self.setUpCommands():
self.runCmd(s)
+ test_categories = self.getTestCategories()
+ if test_categories is not None and 'ondemand' in test_categories:
+ self.runCmd("settings set symbols.load-on-demand true")
+
if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
Index: lldb/packages/Python/lldbsuite/test/builders/builder.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/builders/builder.py
+++ lldb/packages/Python/lldbsuite/test/builders/builder.py
@@ -129,6 +129,8 @@
return ["MAKE_DSYM=NO", "MAKE_DWO=YES"]
if debug_info == "gmodules":
return ["MAKE_DSYM=NO", "MAKE_GMODULES=YES"]
+ if debug_info == "ondemand":
+ return ["MAKE_DSYM=NO"]
return None
def getBuildCommand(self, debug_info, architecture=None, compiler=None,
Index: lldb/include/lldb/Utility/LLDBLog.h
===================================================================
--- lldb/include/lldb/Utility/LLDBLog.h
+++ lldb/include/lldb/Utility/LLDBLog.h
@@ -47,6 +47,7 @@
Types = Log::ChannelFlag<28>,
Unwind = Log::ChannelFlag<29>,
Watchpoints = Log::ChannelFlag<30>,
+ OnDemand = Log::ChannelFlag<31>,
LLVM_MARK_AS_BITMASK_ENUM(Watchpoints),
};
Index: lldb/include/lldb/Target/Statistics.h
===================================================================
--- lldb/include/lldb/Target/Statistics.h
+++ lldb/include/lldb/Target/Statistics.h
@@ -116,6 +116,8 @@
bool symtab_saved_to_cache = false;
bool debug_info_index_loaded_from_cache = false;
bool debug_info_index_saved_to_cache = false;
+ bool debug_info_enabled = true;
+ bool symtab_stripped = false;
};
struct ConstStringStats {
Index: lldb/include/lldb/Symbol/SymbolFileOnDemand.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Symbol/SymbolFileOnDemand.h
@@ -0,0 +1,209 @@
+//===-- SymbolFileOnDemand.h --------------------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
+#define LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
+
+#include <mutex>
+#include <vector>
+
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Statistics.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+/// SymbolFileOnDemand wraps a real SymbolFile by providing
+/// on demand symbol parsing/indexing to improve performance.
+/// By default SymbolFileOnDemand will skip load the underlying
+/// symbols. Any client can on demand hydrate the underlying
+/// SymbolFile via SetForceLoad() API.
+class SymbolFileOnDemand : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
+public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
+ SymbolFileOnDemand(lldb::ObjectFileSP objfile_sp,
+ std::unique_ptr<SymbolFile> &&symbol_file);
+ virtual ~SymbolFileOnDemand() override;
+
+ // PluginInterface protocol
+ llvm::StringRef GetPluginName() override { return "ondemand"; }
+
+ bool GetLoadDebugInfoEnabled() override { return m_debug_info_enabled; }
+
+ void SetLoadDebugInfoEnabled() override;
+
+ SymbolFile *GetBackingSymbolFile() override { return m_sym_file_impl.get(); }
+
+ uint32_t CalculateAbilities() override;
+
+ std::recursive_mutex &GetModuleMutex() const override;
+
+ lldb::LanguageType
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
+
+ lldb_private::XcodeSDK
+ ParseXcodeSDK(lldb_private::CompileUnit &comp_unit) override;
+
+ void InitializeObject() override;
+
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
+
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
+
+ bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseImportedModules(
+ const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::SourceModule> &imported_modules) override;
+
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
+
+ size_t
+ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
+
+ lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
+
+ bool CompleteType(lldb_private::CompilerType &compiler_type) override;
+
+ lldb_private::CompilerDecl GetDeclForUID(lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUID(lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUID(lldb::user_id_t uid) override;
+
+ void
+ ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
+
+ uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContext &sc) override;
+
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void Dump(lldb_private::Stream &s) override;
+ void DumpClangAST(lldb_private::Stream &s) override;
+
+ void
+ FindGlobalVariables(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches,
+ lldb_private::VariableList &variables) override;
+
+ void FindGlobalVariables(const lldb_private::RegularExpression ®ex,
+ uint32_t max_matches,
+ lldb_private::VariableList &variables) override;
+
+ void FindFunctions(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void FindFunctions(const lldb_private::RegularExpression ®ex,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void GetMangledNamesForFunction(
+ const std::string &scope_qualified_name,
+ std::vector<lldb_private::ConstString> &mangled_names) override;
+
+ void
+ FindTypes(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
+
+ void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
+ lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
+
+ void GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ lldb::TypeClass type_mask,
+ lldb_private::TypeList &type_list) override;
+
+ llvm::Expected<lldb_private::TypeSystem &>
+ GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+ lldb_private::CompilerDeclContext FindNamespace(
+ lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx) override;
+
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
+ ParseCallEdgesInFunction(UserID func_id) override;
+
+ lldb::UnwindPlanSP
+ GetUnwindPlan(const Address &address,
+ const RegisterInfoResolver &resolver) override;
+
+ llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override;
+
+ void PreloadSymbols() override;
+
+ uint64_t GetDebugInfoSize() override;
+ lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override;
+ lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override;
+
+private:
+ Log *GetLog() const { return ::lldb_private::GetLog(LLDBLog::OnDemand); }
+
+ ConstString GetSymbolFileName() {
+ return GetObjectFile()->GetFileSpec().GetFilename();
+ }
+
+protected:
+ uint32_t CalculateNumCompileUnits() override;
+ lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+ lldb_private::TypeList &GetTypeList() override;
+
+private:
+ bool m_debug_info_enabled{false};
+ bool m_preload_symbols{false};
+ std::unique_ptr<SymbolFile> m_sym_file_impl;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
Index: lldb/include/lldb/Symbol/SymbolFile.h
===================================================================
--- lldb/include/lldb/Symbol/SymbolFile.h
+++ lldb/include/lldb/Symbol/SymbolFile.h
@@ -40,6 +40,11 @@
/// LLVM RTTI support.
static char ID;
+public:
+ /// Required to call protected member functions from
+ /// SymbolFileOnDemand via forwarding.
+ friend class SymbolFileOnDemand;
+
public:
/// LLVM RTTI support.
/// \{
@@ -72,6 +77,10 @@
~SymbolFile() override = default;
+ /// SymbolFileOnDemand class overrides this to return the underlying
+ /// backing SymbolFile implementation that loads on-demand.
+ virtual SymbolFile *GetBackingSymbolFile() { return this; }
+
/// Get a mask of what this symbol file supports for the object file
/// that it was constructed with.
///
@@ -123,6 +132,16 @@
/// prior to any other functions in the SymbolFile protocol.
virtual void InitializeObject() {}
+ /// Whether debug info will be loaded or not.
+ ///
+ /// It will be true for most implementations except SymbolFileOnDemand.
+ virtual bool GetLoadDebugInfoEnabled() { return true; }
+
+ /// Specify debug info should be loaded.
+ ///
+ /// It will be no-op for most implementations except SymbolFileOnDemand.
+ virtual void SetLoadDebugInfoEnabled() { return; }
+
// Compile Unit function calls
// Approach 1 - iterator
uint32_t GetNumCompileUnits();
@@ -353,9 +372,7 @@
bool GetDebugInfoIndexWasSavedToCache() const {
return m_index_was_saved_to_cache;
}
- void SetDebugInfoIndexWasSavedToCache() {
- m_index_was_saved_to_cache = true;
- }
+ void SetDebugInfoIndexWasSavedToCache() { m_index_was_saved_to_cache = true; }
/// \}
protected:
Index: lldb/include/lldb/Core/ModuleList.h
===================================================================
--- lldb/include/lldb/Core/ModuleList.h
+++ lldb/include/lldb/Core/ModuleList.h
@@ -68,6 +68,8 @@
FileSpec GetLLDBIndexCachePath() const;
bool SetLLDBIndexCachePath(const FileSpec &path);
+ bool GetLoadSymbolOnDemand();
+
PathMappingList GetSymlinkMappings() const;
};
Index: include/lldb/Symbol/SymbolFileOnDemand.h
===================================================================
--- /dev/null
+++ include/lldb/Symbol/SymbolFileOnDemand.h
@@ -0,0 +1,204 @@
+//===-- SymbolFileOnDemand.h --------------------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
+#define LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
+
+#include <mutex>
+#include <vector>
+
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Statistics.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+/// SymbolFileOnDemand wraps a real SymbolFile by providing
+/// on demand symbol parsing/indexing to improve performance.
+/// By default SymbolFileOnDemand will skip load the underlying
+/// symbols. Any client can on demand hydrate the underlying
+/// SymbolFile via SetForceLoad() API.
+class SymbolFileOnDemand : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
+public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
+ SymbolFileOnDemand(lldb::ObjectFileSP objfile_sp,
+ std::unique_ptr<SymbolFile> &&symbol_file);
+ virtual ~SymbolFileOnDemand() override;
+
+ // PluginInterface protocol
+ llvm::StringRef GetPluginName() override { return "ondemand"; }
+
+ Log *GetLog() const { return ::lldb_private::GetLog(LLDBLog::OnDemand); }
+
+ bool GetLoadDebugInfoEnabled() override { return m_debug_info_enabled; }
+
+ void SetLoadDebugInfoEnabled() override;
+
+ SymbolFile *GetBackingSymbolFile() override { return m_sym_file_impl.get(); }
+
+ uint32_t CalculateAbilities() override;
+
+ std::recursive_mutex &GetModuleMutex() const override;
+
+ lldb::LanguageType
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
+
+ lldb_private::XcodeSDK
+ ParseXcodeSDK(lldb_private::CompileUnit &comp_unit) override;
+
+ void InitializeObject() override;
+
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
+
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
+
+ bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseImportedModules(
+ const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::SourceModule> &imported_modules) override;
+
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
+
+ size_t
+ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
+
+ lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
+
+ bool CompleteType(lldb_private::CompilerType &compiler_type) override;
+
+ lldb_private::CompilerDecl GetDeclForUID(lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUID(lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUID(lldb::user_id_t uid) override;
+
+ void
+ ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
+
+ uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContext &sc) override;
+
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void Dump(lldb_private::Stream &s) override;
+ void DumpClangAST(lldb_private::Stream &s) override;
+
+ void
+ FindGlobalVariables(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches,
+ lldb_private::VariableList &variables) override;
+
+ void FindGlobalVariables(const lldb_private::RegularExpression ®ex,
+ uint32_t max_matches,
+ lldb_private::VariableList &variables) override;
+
+ void FindFunctions(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void FindFunctions(const lldb_private::RegularExpression ®ex,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) override;
+
+ void GetMangledNamesForFunction(
+ const std::string &scope_qualified_name,
+ std::vector<lldb_private::ConstString> &mangled_names) override;
+
+ void
+ FindTypes(lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx,
+ uint32_t max_matches,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
+
+ void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
+ lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
+
+ void GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ lldb::TypeClass type_mask,
+ lldb_private::TypeList &type_list) override;
+
+ llvm::Expected<lldb_private::TypeSystem &>
+ GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+ lldb_private::CompilerDeclContext FindNamespace(
+ lldb_private::ConstString name,
+ const lldb_private::CompilerDeclContext &parent_decl_ctx) override;
+
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
+ ParseCallEdgesInFunction(UserID func_id) override;
+
+ lldb::UnwindPlanSP
+ GetUnwindPlan(const Address &address,
+ const RegisterInfoResolver &resolver) override;
+
+ llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override;
+
+ void PreloadSymbols() override;
+
+ uint64_t GetDebugInfoSize() override;
+ lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override;
+ lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override;
+
+ // TODO: other public functions.
+protected:
+ uint32_t CalculateNumCompileUnits() override;
+ lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+ lldb_private::TypeList &GetTypeList() override;
+
+private:
+ bool m_debug_info_enabled{false};
+ bool m_preload_symbols{false};
+ std::unique_ptr<SymbolFile> m_sym_file_impl;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SYMBOL_SYMBOLFILEONDEMAND_H
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits