Skip to content

[lldb][Expression] Allow specifying a preferred ModuleList for lookup during expression evaluation #10333

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

Open
wants to merge 2 commits into
base: swift/release/6.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lldb/include/lldb/Expression/IRExecutionUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/IR/Module.h"
#include "llvm/ADT/StringMap.h"

#include "lldb/Core/ModuleList.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/ObjectFileJIT.h"
#include "lldb/Symbol/SymbolContext.h"
Expand Down Expand Up @@ -168,6 +169,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
Expand Down Expand Up @@ -409,6 +416,11 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
///< opportunity for relocation.

llvm::StringMap<uint64_t> m_section_size_map;

///< 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
Expand Down
13 changes: 13 additions & 0 deletions lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,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.
Expand Down Expand Up @@ -579,6 +587,11 @@ class EvaluateExpressionOptions {
mutable std::string m_pound_line_file;
mutable uint32_t m_pound_line_line = 0;
bool m_prepare_playground_stub_functions = true;

///< 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).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix this comment upstream? It's attached to the previous declaration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SymbolContextList m_preferred_lookup_contexts;
};

// Target
Expand Down
32 changes: 27 additions & 5 deletions lldb/source/Expression/IRExecutionUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up,
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() {}

IRExecutionUnit::~IRExecutionUnit() {
std::lock_guard<std::recursive_mutex> global_context_locker(
Expand Down Expand Up @@ -818,8 +818,12 @@ 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));

// BEGIN SWIFT
if (m_in_populate_symtab)
if (lldb::ModuleSP module_sp = m_jit_module_wp.lock())
Expand All @@ -835,9 +839,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(),
Expand All @@ -847,6 +853,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,
Expand All @@ -863,6 +877,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,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 =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_lldb_library(lldbPluginInstrumentationRuntimeUtility
ReportRetriever.cpp
Utility.cpp

LINK_LIBS
lldbBreakpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "ReportRetriever.h"
#include "Utility.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
Expand Down Expand Up @@ -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);
Expand Down
35 changes: 35 additions & 0 deletions lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
Original file line number Diff line number Diff line change
@@ -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)");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regex looks Darwin-specific, but it's not in a Darwin-specific file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
27 changes: 27 additions & 0 deletions lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/asan/TestMemoryHistory.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test(self):
self.asan_tests()

@skipIf(oslist=no_match(["macosx"]))
@skipIfDarwin # rdar://142836595
@skipIf(bugnumber="rdar://144997976")
def test_libsanitizers_asan(self):
try:
self.build(make_targets=["libsanitizers"])
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/asan/TestReportData.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test(self):
self.asan_tests()

@skipIf(oslist=no_match(["macosx"]))
@skipIfDarwin # rdar://142836595
@skipIf(bugnumber="rdar://144997976")
def test_libsanitizers_asan(self):
try:
self.build(make_targets=["libsanitizers"])
Expand Down