-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb][Expression] Allow specifying a preferred ModuleList for lookup during expression evaluation #129733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… during expression evaluation
const auto &target = process_sp->GetTarget(); | ||
std::unordered_set<ModuleSP> preferred_modules; | ||
target.GetImages().ForEach([&](const lldb::ModuleSP &m) { | ||
llvm::Regex pattern("libclang_rt.asan_.*_dynamic.dylib"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wrotki is this going to hold in the long-term? Will the locally built compiler-rt always be libclang_rt
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
libclang_rt is here to stay forever I believe.
Can you escape literal dots in the regex (i.e. to be libclang_rt\.asan_.*_dynamic\.dylib
) ? As it is, they're matching any character, which is not intended.
I think it would be better to structure this as a list of SymbolContext's that we search in order, not a set of modules. We keep talking about inventing some syntax in an identifier in the expression parser to say "foo from bar in baz.c", but we never have come up with something workable. The cheap alternative to that is to allow people to specify a list of places to search first when resolving symbols. The places in that list might be a module, but also might be a file or a function, so SymbolContext would be a better container. And it will be more useful if the order were significant. Then at some point we can enhance the
|
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesThe
The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the Full diff: https://github.com/llvm/llvm-project/pull/129733.diff 5 Files Affected:
diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h
index 58f12bf8b64f5..77d53daf80c1b 100644
--- a/lldb/include/lldb/Expression/IRExecutionUnit.h
+++ b/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -17,6 +17,7 @@
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Module.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/ObjectFileJIT.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -161,6 +162,12 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
return m_jitted_global_variables;
}
+ void SetPreferredModules(SymbolContextList const &modules) {
+ for (auto const &m : modules)
+ if (m.module_sp)
+ m_preferred_modules.Append(m.module_sp);
+ }
+
private:
/// Look up the object in m_address_map that contains a given address, find
/// where it was copied to, and return the remote address at the same offset
@@ -396,6 +403,11 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
///< defining no functions using that variable, would do this.) If this
///< is true, any allocations need to be committed immediately -- no
///< opportunity for relocation.
+
+ ///< Any Module in this list will be used for symbol/function lookup
+ ///< before any other module (except for the module corresponding to the
+ ///< current frame).
+ ModuleList m_preferred_modules;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index f31ac381391b4..a4059cdb2a819 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -25,6 +25,7 @@
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/PathMappingList.h"
@@ -332,6 +333,14 @@ class EvaluateExpressionOptions {
m_language = SourceLanguage(language_type);
}
+ void SetPreferredSymbolContexts(SymbolContextList modules) {
+ m_preferred_lookup_contexts = std::move(modules);
+ }
+
+ const SymbolContextList &GetPreferredSymbolContexts() const {
+ return m_preferred_lookup_contexts;
+ }
+
/// Set the language using a pair of language code and version as
/// defined by the DWARF 6 specification.
/// WARNING: These codes may change until DWARF 6 is finalized.
@@ -500,6 +509,11 @@ class EvaluateExpressionOptions {
// originates
mutable std::string m_pound_line_file;
mutable uint32_t m_pound_line_line = 0;
+
+ ///< During expression evaluation, any SymbolContext in this list will be
+ ///< used for symbol/function lookup before any other context (except for
+ ///< the module corresponding to the current frame).
+ SymbolContextList m_preferred_lookup_contexts;
};
// Target
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index c8b4ddf705ec4..06b0cb7769f64 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -52,7 +52,7 @@ IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up,
m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx),
m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS),
m_function_end_load_addr(LLDB_INVALID_ADDRESS),
- m_reported_allocations(false) {}
+ m_reported_allocations(false), m_preferred_modules() {}
lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size,
Status &error) {
@@ -782,8 +782,11 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
}
ModuleList non_local_images = target->GetImages();
- // We'll process module_sp separately, before the other modules.
+ // We'll process module_sp and any preferred modules separately, before the
+ // other modules.
non_local_images.Remove(sc.module_sp);
+ for (size_t i = 0; i < m_preferred_modules.GetSize(); ++i)
+ non_local_images.Remove(m_preferred_modules.GetModuleAtIndex(i));
LoadAddressResolver resolver(target, symbol_was_missing_weak);
@@ -794,9 +797,11 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
for (const ConstString &name : names) {
// The lookup order here is as follows:
// 1) Functions in `sc.module_sp`
- // 2) Functions in the other modules
- // 3) Symbols in `sc.module_sp`
- // 4) Symbols in the other modules
+ // 2) Functions in the preferred modules list
+ // 3) Functions in the other modules
+ // 4) Symbols in `sc.module_sp`
+ // 5) Symbols in the preferred modules list
+ // 6) Symbols in the other modules
if (sc.module_sp) {
SymbolContextList sc_list;
sc.module_sp->FindFunctions(name, CompilerDeclContext(),
@@ -806,6 +811,14 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
return *load_addr;
}
+ {
+ SymbolContextList sc_list;
+ m_preferred_modules.FindFunctions(name, lldb::eFunctionNameTypeFull,
+ function_options, sc_list);
+ if (auto load_addr = resolver.Resolve(sc_list))
+ return *load_addr;
+ }
+
{
SymbolContextList sc_list;
non_local_images.FindFunctions(name, lldb::eFunctionNameTypeFull,
@@ -822,6 +835,14 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
return *load_addr;
}
+ {
+ SymbolContextList sc_list;
+ m_preferred_modules.FindSymbolsWithNameAndType(name, lldb::eSymbolTypeAny,
+ sc_list);
+ if (auto load_addr = resolver.Resolve(sc_list))
+ return *load_addr;
+ }
+
{
SymbolContextList sc_list;
non_local_images.FindSymbolsWithNameAndType(name, lldb::eSymbolTypeAny,
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index f1573bae2651b..cefa226175855 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1539,6 +1539,10 @@ lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
function_name, exe_ctx.GetTargetSP(), sc,
m_compiler->getTargetOpts().Features);
+ if (auto *options = m_expr.GetOptions())
+ execution_unit_sp->SetPreferredModules(
+ options->GetPreferredSymbolContexts());
+
ClangExpressionHelper *type_system_helper =
dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
ClangExpressionDeclMap *decl_map =
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index 41df0e85199ce..b806bbf15ac5f 100644
--- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -8,6 +8,7 @@
#include "MemoryHistoryASan.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/MemoryHistory.h"
#include "Plugins/Process/Utility/HistoryThread.h"
@@ -61,6 +62,25 @@ MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp) {
m_process_wp = process_sp;
}
+///< On Darwin, if LLDB loaded libclang_rt, it's coming from a locally built
+///< compiler-rt, and we should prefer it in favour of the system sanitizers.
+///< This helper searches the target for such a dylib. Returns nullptr if no
+///< such dylib was found.
+static ModuleSP GetPreferredAsanModule(const Target &target) {
+ ModuleSP module;
+ llvm::Regex pattern(R"(libclang_rt\.asan_.*_dynamic\.dylib)");
+ target.GetImages().ForEach([&](const lldb::ModuleSP &m) {
+ if (pattern.match(m->GetFileSpec().GetFilename().GetStringRef())) {
+ module = m;
+ return false;
+ }
+
+ return true;
+ });
+
+ return module;
+}
+
const char *memory_history_asan_command_prefix = R"(
extern "C"
{
@@ -174,6 +194,12 @@ HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
options.SetAutoApplyFixIts(false);
options.SetLanguage(eLanguageTypeObjC_plus_plus);
+ if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
+ SymbolContextList sc_list;
+ sc_list.Append(SymbolContext(std::move(m)));
+ options.SetPreferredSymbolContexts(std::move(sc_list));
+ }
+
ExpressionResults expr_result = UserExpression::Evaluate(
exe_ctx, options, expr.GetString(), "", return_value_sp);
if (expr_result != eExpressionCompleted) {
|
Just realized we also need to adjust |
… InstrumentationRuntime
@@ -161,6 +162,12 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>, | |||
return m_jitted_global_variables; | |||
} | |||
|
|||
void SetPreferredModules(SymbolContextList const &modules) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called SetPreferredModules
but is actually AppendToPreferredModules
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, these are no longer modules
you should change the names to reflect that.
@@ -396,6 +403,11 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>, | |||
///< defining no functions using that variable, would do this.) If this | |||
///< is true, any allocations need to be committed immediately -- no | |||
///< opportunity for relocation. | |||
|
|||
///< Any Module in this list will be used for symbol/function lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, no longer Modules...
lldb/include/lldb/Target/Target.h
Outdated
@@ -332,6 +333,14 @@ class EvaluateExpressionOptions { | |||
m_language = SourceLanguage(language_type); | |||
} | |||
|
|||
void SetPreferredSymbolContexts(SymbolContextList modules) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not modules
You should complete the module -> symbol_context mutatis mutandis. Other than that this seems like the right foundation for adding a user way to control the symbol lookups. |
I kept the list of preferred contexts as a |
Makes sense, the other searches happen earlier on in parsing, so that should be okay. But you still have in a couple of places: void SetPreferredModules(SymbolContextList const &modules) { And then it looks really weird when you iterate over |
sounds good, i renamed those in the latest commit Let me know if i missed anything |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Should maybe file an ER on the lldb issues to plumb this (and the other SymbolContext specifications) through the expression command so some ambitious person could see and do that.
… during expression evaluation (llvm#129733) The `TestMemoryHistory.py`/`TestReportData.py` are currently failing on the x86 macOS CI (started after we upgraded the Xcode SDK on that machien). The LLDB ASAN utility expression is failing to run with following error: ``` (lldb) image lookup -n __asan_get_alloc_stack 1 match found in /usr/lib/system/libsystem_sanitizers.dylib: Address: libsystem_sanitizers.dylib[0x00007ffd11e673f7] (libsystem_sanitizers.dylib.__TEXT.__text + 11287) Summary: libsystem_sanitizers.dylib`__asan_get_alloc_stack 1 match found in /Users/michaelbuch/Git/lldb-build-main-no-modules/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib: Address: libclang_rt.asan_osx_dynamic.dylib[0x0000000000009ec0] (libclang_rt.asan_osx_dynamic.dylib.__TEXT.__text + 34352) Summary: libclang_rt.asan_osx_dynamic.dylib`::__asan_get_alloc_stack(__sanitizer::uptr, __sanitizer::uptr *, __sanitizer::uptr, __sanitizer::u32 *) at asan_debugging.cpp:132 (lldb) memory history 'pointer' Assertion failed: ((uintptr_t)addr == report.access.address), function __asan_get_alloc_stack, file debugger_abi.cpp, line 62. warning: cannot evaluate AddressSanitizer expression: error: Expression execution was interrupted: signal SIGABRT. The process has been returned to the state before expression evaluation. ``` The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol `__asan_get_alloc_stack`, and depending on the order in which they're loaded, we may pick the one from the wrong dylib (this probably changed during the buildbot upgrade and is why it only now started failing). Based on discussion with @wrotki we always want to pick the one that's in the libclang_rt dylib if it was loaded, and libsystem_sanitizers otherwise. This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the `EvaluateExpressionOptions`. We make it a `SymbolContextList` in case we want the lookup contexts to be contexts other than modules (e.g., source files, etc.). In `IRExecutionUnit` we make it a `ModuleList` because it makes the symbol lookup implementation simpler and we only do module lookups here anyway. If we ever need it to be a `SymbolContext`, that transformation shouldn't be too difficult. (cherry picked from commit 542d52b)
… during expression evaluation (llvm#129733) The `TestMemoryHistory.py`/`TestReportData.py` are currently failing on the x86 macOS CI (started after we upgraded the Xcode SDK on that machien). The LLDB ASAN utility expression is failing to run with following error: ``` (lldb) image lookup -n __asan_get_alloc_stack 1 match found in /usr/lib/system/libsystem_sanitizers.dylib: Address: libsystem_sanitizers.dylib[0x00007ffd11e673f7] (libsystem_sanitizers.dylib.__TEXT.__text + 11287) Summary: libsystem_sanitizers.dylib`__asan_get_alloc_stack 1 match found in /Users/michaelbuch/Git/lldb-build-main-no-modules/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib: Address: libclang_rt.asan_osx_dynamic.dylib[0x0000000000009ec0] (libclang_rt.asan_osx_dynamic.dylib.__TEXT.__text + 34352) Summary: libclang_rt.asan_osx_dynamic.dylib`::__asan_get_alloc_stack(__sanitizer::uptr, __sanitizer::uptr *, __sanitizer::uptr, __sanitizer::u32 *) at asan_debugging.cpp:132 (lldb) memory history 'pointer' Assertion failed: ((uintptr_t)addr == report.access.address), function __asan_get_alloc_stack, file debugger_abi.cpp, line 62. warning: cannot evaluate AddressSanitizer expression: error: Expression execution was interrupted: signal SIGABRT. The process has been returned to the state before expression evaluation. ``` The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol `__asan_get_alloc_stack`, and depending on the order in which they're loaded, we may pick the one from the wrong dylib (this probably changed during the buildbot upgrade and is why it only now started failing). Based on discussion with @wrotki we always want to pick the one that's in the libclang_rt dylib if it was loaded, and libsystem_sanitizers otherwise. This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the `EvaluateExpressionOptions`. We make it a `SymbolContextList` in case we want the lookup contexts to be contexts other than modules (e.g., source files, etc.). In `IRExecutionUnit` we make it a `ModuleList` because it makes the symbol lookup implementation simpler and we only do module lookups here anyway. If we ever need it to be a `SymbolContext`, that transformation shouldn't be too difficult.
… during expression evaluation (llvm#129733) The `TestMemoryHistory.py`/`TestReportData.py` are currently failing on the x86 macOS CI (started after we upgraded the Xcode SDK on that machien). The LLDB ASAN utility expression is failing to run with following error: ``` (lldb) image lookup -n __asan_get_alloc_stack 1 match found in /usr/lib/system/libsystem_sanitizers.dylib: Address: libsystem_sanitizers.dylib[0x00007ffd11e673f7] (libsystem_sanitizers.dylib.__TEXT.__text + 11287) Summary: libsystem_sanitizers.dylib`__asan_get_alloc_stack 1 match found in /Users/michaelbuch/Git/lldb-build-main-no-modules/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib: Address: libclang_rt.asan_osx_dynamic.dylib[0x0000000000009ec0] (libclang_rt.asan_osx_dynamic.dylib.__TEXT.__text + 34352) Summary: libclang_rt.asan_osx_dynamic.dylib`::__asan_get_alloc_stack(__sanitizer::uptr, __sanitizer::uptr *, __sanitizer::uptr, __sanitizer::u32 *) at asan_debugging.cpp:132 (lldb) memory history 'pointer' Assertion failed: ((uintptr_t)addr == report.access.address), function __asan_get_alloc_stack, file debugger_abi.cpp, line 62. warning: cannot evaluate AddressSanitizer expression: error: Expression execution was interrupted: signal SIGABRT. The process has been returned to the state before expression evaluation. ``` The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol `__asan_get_alloc_stack`, and depending on the order in which they're loaded, we may pick the one from the wrong dylib (this probably changed during the buildbot upgrade and is why it only now started failing). Based on discussion with @wrotki we always want to pick the one that's in the libclang_rt dylib if it was loaded, and libsystem_sanitizers otherwise. This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the `EvaluateExpressionOptions`. We make it a `SymbolContextList` in case we want the lookup contexts to be contexts other than modules (e.g., source files, etc.). In `IRExecutionUnit` we make it a `ModuleList` because it makes the symbol lookup implementation simpler and we only do module lookups here anyway. If we ever need it to be a `SymbolContext`, that transformation shouldn't be too difficult. (cherry picked from commit 542d52b)
… during expression evaluation (llvm#129733) The `TestMemoryHistory.py`/`TestReportData.py` are currently failing on the x86 macOS CI (started after we upgraded the Xcode SDK on that machien). The LLDB ASAN utility expression is failing to run with following error: ``` (lldb) image lookup -n __asan_get_alloc_stack 1 match found in /usr/lib/system/libsystem_sanitizers.dylib: Address: libsystem_sanitizers.dylib[0x00007ffd11e673f7] (libsystem_sanitizers.dylib.__TEXT.__text + 11287) Summary: libsystem_sanitizers.dylib`__asan_get_alloc_stack 1 match found in /Users/michaelbuch/Git/lldb-build-main-no-modules/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib: Address: libclang_rt.asan_osx_dynamic.dylib[0x0000000000009ec0] (libclang_rt.asan_osx_dynamic.dylib.__TEXT.__text + 34352) Summary: libclang_rt.asan_osx_dynamic.dylib`::__asan_get_alloc_stack(__sanitizer::uptr, __sanitizer::uptr *, __sanitizer::uptr, __sanitizer::u32 *) at asan_debugging.cpp:132 (lldb) memory history 'pointer' Assertion failed: ((uintptr_t)addr == report.access.address), function __asan_get_alloc_stack, file debugger_abi.cpp, line 62. warning: cannot evaluate AddressSanitizer expression: error: Expression execution was interrupted: signal SIGABRT. The process has been returned to the state before expression evaluation. ``` The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol `__asan_get_alloc_stack`, and depending on the order in which they're loaded, we may pick the one from the wrong dylib (this probably changed during the buildbot upgrade and is why it only now started failing). Based on discussion with @wrotki we always want to pick the one that's in the libclang_rt dylib if it was loaded, and libsystem_sanitizers otherwise. This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the `EvaluateExpressionOptions`. We make it a `SymbolContextList` in case we want the lookup contexts to be contexts other than modules (e.g., source files, etc.). In `IRExecutionUnit` we make it a `ModuleList` because it makes the symbol lookup implementation simpler and we only do module lookups here anyway. If we ever need it to be a `SymbolContext`, that transformation shouldn't be too difficult. (cherry picked from commit 542d52b)
The
TestMemoryHistory.py
/TestReportData.py
are currently failing on the x86 macOS CI (started after we upgraded the Xcode SDK on that machien). The LLDB ASAN utility expression is failing to run with following error:The reason for this is that the system sanitizer dylib and the locally built libclang_rt contain the same symbol
__asan_get_alloc_stack
, and depending on the order in which they're loaded, we may pick the one from the wrong dylib (this probably changed during the buildbot upgrade and is why it only now started failing). Based on discussion with @wrotki we always want to pick the one that's in the libclang_rt dylib if it was loaded, and libsystem_sanitizers otherwise.This patch addresses this by adding a "preferred lookup context list" to the expression evaluator. Currently this is only exposed in the
EvaluateExpressionOptions
. We make it aSymbolContextList
in case we want the lookup contexts to be contexts other than modules (e.g., source files, etc.). InIRExecutionUnit
we make it aModuleList
because it makes the symbol lookup implementation simpler and we only do module lookups here anyway. If we ever need it to be aSymbolContext
, that transformation shouldn't be too difficult.