Author: Michael Buch
Date: 2025-03-06T21:07:22Z
New Revision: 542d52b1e8a0a7e04538f608487603124c70e1ab

URL: 
https://github.com/llvm/llvm-project/commit/542d52b1e8a0a7e04538f608487603124c70e1ab
DIFF: 
https://github.com/llvm/llvm-project/commit/542d52b1e8a0a7e04538f608487603124c70e1ab.diff

LOG: [lldb][Expression] Allow specifying a preferred ModuleList for lookup 
during expression evaluation (#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.

Added: 
    lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
    lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h

Modified: 
    lldb/include/lldb/Expression/IRExecutionUnit.h
    lldb/include/lldb/Target/Target.h
    lldb/source/Expression/IRExecutionUnit.cpp
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
    lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
    lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
    lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Expression/IRExecutionUnit.h 
b/lldb/include/lldb/Expression/IRExecutionUnit.h
index 58f12bf8b64f5..10bd1a0f46cf0 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 AppendPreferredSymbolContexts(SymbolContextList const &contexts) {
+    for (auto const &ctx : contexts)
+      if (ctx.module_sp)
+        m_preferred_modules.Append(ctx.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..98273fb7e1c97 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 contexts) {
+    m_preferred_lookup_contexts = std::move(contexts);
+  }
+
+  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..5a78ce8fa7688 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->AppendPreferredSymbolContexts(
+        options->GetPreferredSymbolContexts());
+
   ClangExpressionHelper *type_system_helper =
       dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
   ClangExpressionDeclMap *decl_map =

diff  --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt 
b/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
index dcca47fb0e253..705fe1503fae2 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_library(lldbPluginInstrumentationRuntimeUtility
   ReportRetriever.cpp
+  Utility.cpp
 
   LINK_LIBS
     lldbBreakpoint

diff  --git 
a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp 
b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
index d61c59776eee6..96489248022eb 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "ReportRetriever.h"
+#include "Utility.h"
 
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Debugger.h"
@@ -82,6 +83,12 @@ ReportRetriever::RetrieveReportData(const ProcessSP 
process_sp) {
   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));
+  }
+
   ValueObjectSP return_value_sp;
   ExecutionContext exe_ctx;
   frame_sp->CalculateExecutionContext(exe_ctx);

diff  --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp 
b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
new file mode 100644
index 0000000000000..3cbd03b24297a
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
@@ -0,0 +1,35 @@
+//===-- Utility.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 "Utility.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Target.h"
+
+namespace lldb_private {
+
+///< 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.
+lldb::ModuleSP GetPreferredAsanModule(const Target &target) {
+  lldb::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;
+}
+
+} // namespace lldb_private

diff  --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h 
b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
new file mode 100644
index 0000000000000..813a0c107989e
--- /dev/null
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
@@ -0,0 +1,27 @@
+//===-- Utility.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_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
+#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
+
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private {
+
+class Target;
+
+///< 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
+///< when running InstrumentationRuntime utility expressions that use symbols
+///< from the sanitizer libraries. This helper searches the target for such a
+///< dylib. Returns nullptr if no such dylib was found.
+lldb::ModuleSP GetPreferredAsanModule(const Target &target);
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H

diff  --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp 
b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index 41df0e85199ce..afaaa57b09587 100644
--- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -8,8 +8,10 @@
 
 #include "MemoryHistoryASan.h"
 
+#include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/MemoryHistory.h"
 
+#include "Plugins/InstrumentationRuntime/Utility/Utility.h"
 #include "Plugins/Process/Utility/HistoryThread.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
@@ -174,6 +176,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) {


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to