Skip to content

Commit 15cfb0f

Browse files
committed
[lldb][Expression] Allow specifying a preferred ModuleList for lookup 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)
1 parent 08670c0 commit 15cfb0f

File tree

9 files changed

+134
-5
lines changed

9 files changed

+134
-5
lines changed

lldb/include/lldb/Expression/IRExecutionUnit.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/IR/Module.h"
2020
#include "llvm/ADT/StringMap.h"
2121

22+
#include "lldb/Core/ModuleList.h"
2223
#include "lldb/Expression/IRMemoryMap.h"
2324
#include "lldb/Expression/ObjectFileJIT.h"
2425
#include "lldb/Symbol/SymbolContext.h"
@@ -168,6 +169,12 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
168169
return m_jitted_global_variables;
169170
}
170171

172+
void AppendPreferredSymbolContexts(SymbolContextList const &contexts) {
173+
for (auto const &ctx : contexts)
174+
if (ctx.module_sp)
175+
m_preferred_modules.Append(ctx.module_sp);
176+
}
177+
171178
private:
172179
/// Look up the object in m_address_map that contains a given address, find
173180
/// where it was copied to, and return the remote address at the same offset
@@ -409,6 +416,11 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
409416
///< opportunity for relocation.
410417

411418
llvm::StringMap<uint64_t> m_section_size_map;
419+
420+
///< Any Module in this list will be used for symbol/function lookup
421+
///< before any other module (except for the module corresponding to the
422+
///< current frame).
423+
ModuleList m_preferred_modules;
412424
};
413425

414426
} // namespace lldb_private

lldb/include/lldb/Target/Target.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,14 @@ class EvaluateExpressionOptions {
375375
m_language = SourceLanguage(language_type);
376376
}
377377

378+
void SetPreferredSymbolContexts(SymbolContextList contexts) {
379+
m_preferred_lookup_contexts = std::move(contexts);
380+
}
381+
382+
const SymbolContextList &GetPreferredSymbolContexts() const {
383+
return m_preferred_lookup_contexts;
384+
}
385+
378386
/// Set the language using a pair of language code and version as
379387
/// defined by the DWARF 6 specification.
380388
/// WARNING: These codes may change until DWARF 6 is finalized.
@@ -579,6 +587,11 @@ class EvaluateExpressionOptions {
579587
mutable std::string m_pound_line_file;
580588
mutable uint32_t m_pound_line_line = 0;
581589
bool m_prepare_playground_stub_functions = true;
590+
591+
///< During expression evaluation, any SymbolContext in this list will be
592+
///< used for symbol/function lookup before any other context (except for
593+
///< the module corresponding to the current frame).
594+
SymbolContextList m_preferred_lookup_contexts;
582595
};
583596

584597
// Target

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up,
5656
m_sym_ctx(sym_ctx), m_did_jit(false),
5757
m_function_load_addr(LLDB_INVALID_ADDRESS),
5858
m_function_end_load_addr(LLDB_INVALID_ADDRESS),
59-
m_reported_allocations(false) {}
59+
m_reported_allocations(false), m_preferred_modules() {}
6060

6161
IRExecutionUnit::~IRExecutionUnit() {
6262
std::lock_guard<std::recursive_mutex> global_context_locker(
@@ -818,8 +818,12 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
818818
}
819819

820820
ModuleList non_local_images = target->GetImages();
821-
// We'll process module_sp separately, before the other modules.
821+
// We'll process module_sp and any preferred modules separately, before the
822+
// other modules.
822823
non_local_images.Remove(sc.module_sp);
824+
for (size_t i = 0; i < m_preferred_modules.GetSize(); ++i)
825+
non_local_images.Remove(m_preferred_modules.GetModuleAtIndex(i));
826+
823827
// BEGIN SWIFT
824828
if (m_in_populate_symtab)
825829
if (lldb::ModuleSP module_sp = m_jit_module_wp.lock())
@@ -835,9 +839,11 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
835839
for (const ConstString &name : names) {
836840
// The lookup order here is as follows:
837841
// 1) Functions in `sc.module_sp`
838-
// 2) Functions in the other modules
839-
// 3) Symbols in `sc.module_sp`
840-
// 4) Symbols in the other modules
842+
// 2) Functions in the preferred modules list
843+
// 3) Functions in the other modules
844+
// 4) Symbols in `sc.module_sp`
845+
// 5) Symbols in the preferred modules list
846+
// 6) Symbols in the other modules
841847
if (sc.module_sp) {
842848
SymbolContextList sc_list;
843849
sc.module_sp->FindFunctions(name, CompilerDeclContext(),
@@ -847,6 +853,14 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
847853
return *load_addr;
848854
}
849855

856+
{
857+
SymbolContextList sc_list;
858+
m_preferred_modules.FindFunctions(name, lldb::eFunctionNameTypeFull,
859+
function_options, sc_list);
860+
if (auto load_addr = resolver.Resolve(sc_list))
861+
return *load_addr;
862+
}
863+
850864
{
851865
SymbolContextList sc_list;
852866
non_local_images.FindFunctions(name, lldb::eFunctionNameTypeFull,
@@ -863,6 +877,14 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
863877
return *load_addr;
864878
}
865879

880+
{
881+
SymbolContextList sc_list;
882+
m_preferred_modules.FindSymbolsWithNameAndType(name, lldb::eSymbolTypeAny,
883+
sc_list);
884+
if (auto load_addr = resolver.Resolve(sc_list))
885+
return *load_addr;
886+
}
887+
866888
{
867889
SymbolContextList sc_list;
868890
non_local_images.FindSymbolsWithNameAndType(name, lldb::eSymbolTypeAny,

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,10 @@ lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
14831483
function_name, exe_ctx.GetTargetSP(), sc,
14841484
m_compiler->getTargetOpts().Features);
14851485

1486+
if (auto *options = m_expr.GetOptions())
1487+
execution_unit_sp->AppendPreferredSymbolContexts(
1488+
options->GetPreferredSymbolContexts());
1489+
14861490
ClangExpressionHelper *type_system_helper =
14871491
dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
14881492
ClangExpressionDeclMap *decl_map =

lldb/source/Plugins/InstrumentationRuntime/Utility/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_lldb_library(lldbPluginInstrumentationRuntimeUtility
22
ReportRetriever.cpp
3+
Utility.cpp
34

45
LINK_LIBS
56
lldbBreakpoint

lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "ReportRetriever.h"
10+
#include "Utility.h"
1011

1112
#include "lldb/Breakpoint/StoppointCallbackContext.h"
1213
#include "lldb/Core/Debugger.h"
@@ -82,6 +83,12 @@ ReportRetriever::RetrieveReportData(const ProcessSP process_sp) {
8283
options.SetAutoApplyFixIts(false);
8384
options.SetLanguage(eLanguageTypeObjC_plus_plus);
8485

86+
if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
87+
SymbolContextList sc_list;
88+
sc_list.Append(SymbolContext(std::move(m)));
89+
options.SetPreferredSymbolContexts(std::move(sc_list));
90+
}
91+
8592
ValueObjectSP return_value_sp;
8693
ExecutionContext exe_ctx;
8794
frame_sp->CalculateExecutionContext(exe_ctx);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===-- Utility.cpp -------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Utility.h"
10+
11+
#include "lldb/Core/Module.h"
12+
#include "lldb/Target/Target.h"
13+
14+
namespace lldb_private {
15+
16+
///< On Darwin, if LLDB loaded libclang_rt, it's coming from a locally built
17+
///< compiler-rt, and we should prefer it in favour of the system sanitizers.
18+
///< This helper searches the target for such a dylib. Returns nullptr if no
19+
///< such dylib was found.
20+
lldb::ModuleSP GetPreferredAsanModule(const Target &target) {
21+
lldb::ModuleSP module;
22+
llvm::Regex pattern(R"(libclang_rt\.asan_.*_dynamic\.dylib)");
23+
target.GetImages().ForEach([&](const lldb::ModuleSP &m) {
24+
if (pattern.match(m->GetFileSpec().GetFilename().GetStringRef())) {
25+
module = m;
26+
return false;
27+
}
28+
29+
return true;
30+
});
31+
32+
return module;
33+
}
34+
35+
} // namespace lldb_private
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Utility.h -----------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
10+
#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
11+
12+
#include "lldb/lldb-forward.h"
13+
14+
namespace lldb_private {
15+
16+
class Target;
17+
18+
///< On Darwin, if LLDB loaded libclang_rt, it's coming from a locally built
19+
///< compiler-rt, and we should prefer it in favour of the system sanitizers
20+
///< when running InstrumentationRuntime utility expressions that use symbols
21+
///< from the sanitizer libraries. This helper searches the target for such a
22+
///< dylib. Returns nullptr if no such dylib was found.
23+
lldb::ModuleSP GetPreferredAsanModule(const Target &target);
24+
25+
} // namespace lldb_private
26+
27+
#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H

lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
#include "MemoryHistoryASan.h"
1010

11+
#include "lldb/Symbol/SymbolContext.h"
1112
#include "lldb/Target/MemoryHistory.h"
1213

14+
#include "Plugins/InstrumentationRuntime/Utility/Utility.h"
1315
#include "Plugins/Process/Utility/HistoryThread.h"
1416
#include "lldb/Core/Debugger.h"
1517
#include "lldb/Core/Module.h"
@@ -174,6 +176,12 @@ HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
174176
options.SetAutoApplyFixIts(false);
175177
options.SetLanguage(eLanguageTypeObjC_plus_plus);
176178

179+
if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
180+
SymbolContextList sc_list;
181+
sc_list.Append(SymbolContext(std::move(m)));
182+
options.SetPreferredSymbolContexts(std::move(sc_list));
183+
}
184+
177185
ExpressionResults expr_result = UserExpression::Evaluate(
178186
exe_ctx, options, expr.GetString(), "", return_value_sp);
179187
if (expr_result != eExpressionCompleted) {

0 commit comments

Comments
 (0)