[Lldb-commits] [lldb] 2b0c886 - Refine the reporting mechanism for interruption.
Jim Ingham via lldb-commits
lldb-commits at lists.llvm.org
Thu Jul 6 16:19:33 PDT 2023
Author: Jim Ingham
Date: 2023-07-06T16:19:19-07:00
New Revision: 2b0c8865421287a30ddda0f459f17f76bfeb1358
URL: https://github.com/llvm/llvm-project/commit/2b0c8865421287a30ddda0f459f17f76bfeb1358
DIFF: https://github.com/llvm/llvm-project/commit/2b0c8865421287a30ddda0f459f17f76bfeb1358.diff
LOG: Refine the reporting mechanism for interruption.
Also, make it possible for new Targets which haven't been added to
the TargetList yet to check for interruption, and add a few more
places in building modules where we can check for interruption.
Differential Revision: https://reviews.llvm.org/D154542
Added:
Modified:
lldb/include/lldb/Core/Debugger.h
lldb/include/lldb/Target/TargetList.h
lldb/source/API/SBFrame.cpp
lldb/source/Commands/CommandCompletions.cpp
lldb/source/Commands/CommandObjectFrame.cpp
lldb/source/Commands/CommandObjectTarget.cpp
lldb/source/Commands/CommandObjectThread.cpp
lldb/source/Core/Debugger.cpp
lldb/source/Core/Module.cpp
lldb/source/Interpreter/CommandInterpreter.cpp
lldb/source/Target/StackFrameList.cpp
lldb/source/Target/Target.cpp
lldb/source/Target/TargetList.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 3996c4c58e2baf..239429b75c4260 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -43,6 +43,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Threading.h"
#include <cassert>
@@ -85,6 +86,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
eBroadcastSymbolChange = (1 << 3),
};
+ using DebuggerList = std::vector<lldb::DebuggerSP>;
+
static ConstString GetStaticBroadcasterClass();
/// Get the public broadcaster for this debugger.
@@ -411,12 +414,75 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
/// If you are on the RunCommandInterpreter thread, it will check the
/// command interpreter state, and if it is on another thread it will
/// check the debugger Interrupt Request state.
+ /// \param[in] cur_func
+ /// For reporting if the interruption was requested. Don't provide this by
+ /// hand, use INTERRUPT_REQUESTED so this gets done consistently.
///
+ /// \param[in] formatv
+ /// A formatv string for the interrupt message. If the elements of the
+ /// message are expensive to compute, you can use the no-argument form of
+ /// InterruptRequested, then make up the report using REPORT_INTERRUPTION.
+ ///
/// \return
/// A boolean value, if \b true an interruptible operation should interrupt
/// itself.
+ template <typename... Args>
+ bool InterruptRequested(const char *cur_func,
+ const char *formatv, Args &&... args) {
+ bool ret_val = InterruptRequested();
+ if (ret_val) {
+ if (!formatv)
+ formatv = "Unknown message";
+ if (!cur_func)
+ cur_func = "<UNKNOWN>";
+ ReportInterruption(InterruptionReport(cur_func,
+ llvm::formatv(formatv,
+ std::forward<Args>(args)...)));
+ }
+ return ret_val;
+ }
+
+
+ /// This handy define will keep you from having to generate a report for the
+ /// interruption by hand. Use this except in the case where the arguments to
+ /// the message description are expensive to compute.
+#define INTERRUPT_REQUESTED(debugger, ...) \
+ (debugger).InterruptRequested(__func__, __VA_ARGS__)
+
+ // This form just queries for whether to interrupt, and does no reporting:
bool InterruptRequested();
+
+ // FIXME: Do we want to capture a backtrace at the interruption point?
+ class InterruptionReport {
+ public:
+ InterruptionReport(std::string function_name, std::string description) :
+ m_function_name(std::move(function_name)),
+ m_description(std::move(description)),
+ m_interrupt_time(std::chrono::system_clock::now()),
+ m_thread_id(llvm::get_threadid()) {}
+
+ InterruptionReport(std::string function_name,
+ const llvm::formatv_object_base &payload);
+
+ template <typename... Args>
+ InterruptionReport(std::string function_name,
+ const char *format, Args &&... args) :
+ InterruptionReport(function_name, llvm::formatv(format, std::forward<Args>(args)...)) {}
+
+ std::string m_function_name;
+ std::string m_description;
+ const std::chrono::time_point<std::chrono::system_clock> m_interrupt_time;
+ const uint64_t m_thread_id;
+ };
+ void ReportInterruption(const InterruptionReport &report);
+#define REPORT_INTERRUPTION(debugger, ...) \
+ (debugger).ReportInterruption(Debugger::InterruptionReport(__func__, \
+ __VA_ARGS__))
+ static DebuggerList DebuggersRequestingInterruption();
+
+public:
+
// This is for use in the command interpreter, when you either want the
// selected target, or if no target is present you want to prime the dummy
// target with entities that will be copied over to new targets.
diff --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h
index a1d5a84511e020..f38a209d2b6684 100644
--- a/lldb/include/lldb/Target/TargetList.h
+++ b/lldb/include/lldb/Target/TargetList.h
@@ -184,6 +184,12 @@ class TargetList : public Broadcaster {
void SetSelectedTarget(const lldb::TargetSP &target);
lldb::TargetSP GetSelectedTarget();
+
+ /// Returns whether any module, including ones in the process of being
+ /// added, contains this module. I don't want to give direct access to
+ /// these not yet added target, but for interruption purposes, we might
+ /// need to ask whether this target contains this module.
+ bool AnyTargetContainsModule(Module &module);
TargetIterable Targets() {
return TargetIterable(m_target_list, m_target_list_mutex);
@@ -191,6 +197,7 @@ class TargetList : public Broadcaster {
private:
collection m_target_list;
+ std::unordered_set<lldb::TargetSP> m_in_process_target_list;
mutable std::recursive_mutex m_target_list_mutex;
uint32_t m_selected_target_idx;
@@ -206,6 +213,12 @@ class TargetList : public Broadcaster {
lldb::PlatformSP &platform_sp,
lldb::TargetSP &target_sp);
+ void RegisterInProcessTarget(lldb::TargetSP target_sp);
+
+ void UnregisterInProcessTarget(lldb::TargetSP target_sp);
+
+ bool IsTargetInProcess(lldb::TargetSP target_sp);
+
void AddTargetInternal(lldb::TargetSP target_sp, bool do_select);
void SetSelectedTargetInternal(uint32_t index);
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index e31297446007a9..a19ce63bab1510 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -813,12 +813,13 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
if (variable_list) {
const size_t num_variables = variable_list->GetSize();
if (num_variables) {
+ size_t num_produced = 0;
for (const VariableSP &variable_sp : *variable_list) {
- if (dbg.InterruptRequested()) {
- Log *log = GetLog(LLDBLog::Host);
- LLDB_LOG(log, "Interrupted SBFrame::GetVariables");
+ if (INTERRUPT_REQUESTED(dbg,
+ "Interrupted getting frame variables with {0} of {1} "
+ "produced.", num_produced, num_variables))
return {};
- }
+
if (variable_sp) {
bool add_variable = false;
switch (variable_sp->GetScope()) {
@@ -862,6 +863,7 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
}
}
}
+ num_produced++;
}
}
if (recognized_arguments) {
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 21ffba5fa1f3d8..4d7e3d7f2497bb 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -735,7 +735,7 @@ void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter,
lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i);
StreamString strm;
// Dumping frames can be slow, allow interruption.
- if (dbg.InterruptRequested())
+ if (INTERRUPT_REQUESTED(dbg, "Interrupted in frame completion"))
break;
frame_sp->Dump(&strm, false, true);
request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index db31b159f430d7..3f68425e91d3c3 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -326,21 +326,29 @@ class CommandObjectFrameSelect : public CommandObjectParsed {
}
} else if (*m_options.relative_frame_offset > 0) {
// I don't want "up 20" where "20" takes you past the top of the stack
- // to produce
- // an error, but rather to just go to the top. So I have to count the
- // stack here...
- const uint32_t num_frames = thread->GetStackFrameCount();
- if (static_cast<int32_t>(num_frames - frame_idx) >
- *m_options.relative_frame_offset)
- frame_idx += *m_options.relative_frame_offset;
+ // to produce an error, but rather to just go to the top. OTOH, start
+ // by seeing if the requested frame exists, in which case we can avoid
+ // counting the stack here...
+ const uint32_t frame_requested = frame_idx
+ + *m_options.relative_frame_offset;
+ StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
+ if (frame_sp)
+ frame_idx = frame_requested;
else {
- if (frame_idx == num_frames - 1) {
- // If we are already at the top of the stack, just warn and don't
- // reset the frame.
- result.AppendError("Already at the top of the stack.");
- return false;
- } else
- frame_idx = num_frames - 1;
+ // The request went past the stack, so handle that case:
+ const uint32_t num_frames = thread->GetStackFrameCount();
+ if (static_cast<int32_t>(num_frames - frame_idx) >
+ *m_options.relative_frame_offset)
+ frame_idx += *m_options.relative_frame_offset;
+ else {
+ if (frame_idx == num_frames - 1) {
+ // If we are already at the top of the stack, just warn and don't
+ // reset the frame.
+ result.AppendError("Already at the top of the stack.");
+ return false;
+ } else
+ frame_idx = num_frames - 1;
+ }
}
}
} else {
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 868dc8726650f9..1b40651b7a4345 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -2005,8 +2005,11 @@ class CommandObjectTargetModulesDumpSymtab
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump all symtabs with {0} "
+ "of {1} dumped.", num_dumped, num_modules))
break;
+
num_dumped++;
DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
module_sp.get(), m_options.m_sort_order,
@@ -2032,8 +2035,11 @@ class CommandObjectTargetModulesDumpSymtab
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump symtab list with {0} of {1} dumped.",
+ num_dumped, num_matches))
break;
+
num_dumped++;
DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
module_sp.get(), m_options.m_sort_order,
@@ -2093,8 +2099,11 @@ class CommandObjectTargetModulesDumpSections
result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
num_modules);
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump all sections with {0} of {1} dumped",
+ image_idx, num_modules))
break;
+
num_dumped++;
DumpModuleSections(
m_interpreter, result.GetOutputStream(),
@@ -2111,8 +2120,11 @@ class CommandObjectTargetModulesDumpSections
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump section list with {0} of {1} dumped.",
+ i, num_matches))
break;
+
Module *module = module_list.GetModulePointerAtIndex(i);
if (module) {
num_dumped++;
@@ -2228,7 +2240,7 @@ class CommandObjectTargetModulesDumpClangAST
result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n",
num_modules);
for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast"))
break;
if (SymbolFile *sf = module_sp->GetSymbolFile())
sf->DumpClangAST(result.GetOutputStream());
@@ -2253,8 +2265,11 @@ class CommandObjectTargetModulesDumpClangAST
}
for (size_t i = 0; i < num_matches; ++i) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump clang ast list with {0} of {1} dumped.",
+ i, num_matches))
break;
+
Module *m = module_list.GetModulePointerAtIndex(i);
if (SymbolFile *sf = m->GetSymbolFile())
sf->DumpClangAST(result.GetOutputStream());
@@ -2302,8 +2317,11 @@ class CommandObjectTargetModulesDumpSymfile
result.GetOutputStream().Format(
"Dumping debug symbols for {0} modules.\n", num_modules);
for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dumping all "
+ "debug symbols with {0} of {1} modules dumped",
+ num_dumped, num_modules))
break;
+
if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get()))
num_dumped++;
}
@@ -2318,7 +2336,9 @@ class CommandObjectTargetModulesDumpSymfile
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping {0} "
+ "of {1} requested modules",
+ i, num_matches))
break;
Module *module = module_list.GetModulePointerAtIndex(i);
if (module) {
@@ -2382,11 +2402,16 @@ class CommandObjectTargetModulesDumpLineTable
const ModuleList &target_modules = target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- if (target_modules.GetSize() > 0) {
+ size_t num_modules = target_modules.GetSize();
+ if (num_modules > 0) {
uint32_t num_dumped = 0;
for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
- if (GetDebugger().InterruptRequested())
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump all line tables with "
+ "{0} of {1} dumped", num_dumped,
+ num_modules))
break;
+
if (DumpCompileUnitLineTable(
m_interpreter, result.GetOutputStream(), module_sp.get(),
file_spec,
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 66a33f5882c471..64f3edcad5639d 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -228,8 +228,11 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads {
thread->GetIndexID());
return false;
}
- if (m_options.m_extended_backtrace && !GetDebugger().InterruptRequested()) {
- DoExtendedBacktrace(thread, result);
+ if (m_options.m_extended_backtrace) {
+ if (!INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupt skipped extended backtrace")) {
+ DoExtendedBacktrace(thread, result);
+ }
}
return true;
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 196038baa6d80a..3e92c125aa4ee6 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -99,10 +99,9 @@ static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
#pragma mark Static Functions
-typedef std::vector<DebuggerSP> DebuggerList;
static std::recursive_mutex *g_debugger_list_mutex_ptr =
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
-static DebuggerList *g_debugger_list_ptr =
+static Debugger::DebuggerList *g_debugger_list_ptr =
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
static llvm::ThreadPool *g_thread_pool = nullptr;
@@ -1276,6 +1275,33 @@ bool Debugger::InterruptRequested() {
return GetCommandInterpreter().WasInterrupted();
}
+Debugger::InterruptionReport::InterruptionReport(std::string function_name,
+ const llvm::formatv_object_base &payload) :
+ m_function_name(std::move(function_name)),
+ m_interrupt_time(std::chrono::system_clock::now()),
+ m_thread_id(llvm::get_threadid()) {
+ llvm::raw_string_ostream desc(m_description);
+ desc << payload << "\n";
+}
+
+void Debugger::ReportInterruption(const InterruptionReport &report) {
+ // For now, just log the description:
+ Log *log = GetLog(LLDBLog::Host);
+ LLDB_LOG(log, "Interruption: {0}", report.m_description);
+}
+
+Debugger::DebuggerList Debugger::DebuggersRequestingInterruption() {
+ DebuggerList result;
+ if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
+ for (auto debugger_sp : *g_debugger_list_ptr) {
+ if (debugger_sp->InterruptRequested())
+ result.push_back(debugger_sp);
+ }
+ }
+ return result;
+}
+
size_t Debugger::GetNumDebuggers() {
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index a4ba09ef564186..be61f6f138c00b 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1047,10 +1047,38 @@ void Module::FindTypes(
symbols->FindTypes(pattern, languages, searched_symbol_files, types);
}
+static Debugger::DebuggerList
+DebuggersOwningModuleRequestingInterruption(Module &module) {
+ Debugger::DebuggerList requestors
+ = Debugger::DebuggersRequestingInterruption();
+ Debugger::DebuggerList interruptors;
+ if (requestors.empty())
+ return interruptors;
+
+ for (auto debugger_sp : requestors) {
+ if (!debugger_sp->InterruptRequested())
+ continue;
+ if (debugger_sp->GetTargetList()
+ .AnyTargetContainsModule(module))
+ interruptors.push_back(debugger_sp);
+ }
+ return interruptors;
+}
+
SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {
if (!m_did_load_symfile.load()) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_did_load_symfile.load() && can_create) {
+ Debugger::DebuggerList interruptors
+ = DebuggersOwningModuleRequestingInterruption(*this);
+ if (!interruptors.empty()) {
+ for (auto debugger_sp : interruptors) {
+ REPORT_INTERRUPTION(*(debugger_sp.get()),
+ "Interrupted fetching symbols for module {0}",
+ this->GetFileSpec());
+ }
+ return nullptr;
+ }
ObjectFile *obj_file = GetObjectFile();
if (obj_file != nullptr) {
LLDB_SCOPED_TIMER();
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 3d3ab7b73b19f8..f78fc728c898b0 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -1894,7 +1894,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
LLDB_LOGF(log, "Processing command: %s", command_line);
LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
- if (GetDebugger().InterruptRequested()) {
+ if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) {
result.AppendError("... Interrupted");
return false;
}
@@ -3071,7 +3071,8 @@ void CommandInterpreter::PrintCommandOutput(IOHandler &io_handler,
}
std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
- if (had_output && GetDebugger().InterruptRequested())
+ if (had_output && INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted dumping command output"))
stream->Printf("\n... Interrupted.\n");
stream->Flush();
}
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 81e7b00ee995d9..2841f512439ada 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -509,11 +509,11 @@ bool StackFrameList::GetFramesUpTo(uint32_t end_idx,
} else {
// Check for interruption when building the frames.
// Do the check in idx > 0 so that we'll always create a 0th frame.
- if (allow_interrupt && dbg.InterruptRequested()) {
- Log *log = GetLog(LLDBLog::Host);
- LLDB_LOG(log, "Interrupted %s", __FUNCTION__);
- was_interrupted = true;
- break;
+ if (allow_interrupt
+ && INTERRUPT_REQUESTED(dbg, "Interrupted having fetched {0} frames",
+ m_frames.size())) {
+ was_interrupted = true;
+ break;
}
const bool success =
@@ -965,11 +965,11 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
// Check for interruption here. If we're fetching arguments, this loop
// can go slowly:
Debugger &dbg = m_thread.GetProcess()->GetTarget().GetDebugger();
- if (dbg.InterruptRequested()) {
- Log *log = GetLog(LLDBLog::Host);
- LLDB_LOG(log, "Interrupted %s", __FUNCTION__);
+ if (INTERRUPT_REQUESTED(dbg,
+ "Interrupted dumping stack for thread {0:hex} with {1} shown.",
+ m_thread.GetID(), num_frames_displayed))
break;
- }
+
if (!frame_sp->GetStatus(strm, show_frame_info,
num_frames_with_source > (first_frame - frame_idx),
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index e91fb380443538..6b255e084b28b7 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2236,7 +2236,6 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
// each library in parallel.
if (GetPreloadSymbols())
module_sp->PreloadSymbols();
-
llvm::SmallVector<ModuleSP, 1> replaced_modules;
for (ModuleSP &old_module_sp : old_modules) {
if (m_images.GetIndexForModule(old_module_sp.get()) !=
@@ -4205,6 +4204,10 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) {
}
bool TargetProperties::GetPreloadSymbols() const {
+ if (INTERRUPT_REQUESTED(m_target->GetDebugger(),
+ "Interrupted checking preload symbols")) {
+ return false;
+ }
const uint32_t idx = ePropertyPreloadSymbols;
return GetPropertyAtIndexAs<bool>(
idx, g_target_properties[idx].default_uint_value != 0);
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 1424fd05f21573..376b15ca706bee 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -325,6 +325,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
return error;
}
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
+ debugger.GetTargetList().RegisterInProcessTarget(target_sp);
target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
if (user_exe_path_is_bundle)
exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
@@ -336,6 +337,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
// No file was specified, just create an empty target with any arch if a
// valid arch was specified
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
+ debugger.GetTargetList().RegisterInProcessTarget(target_sp);
}
if (!target_sp)
@@ -513,6 +515,7 @@ uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
lldbassert(!llvm::is_contained(m_target_list, target_sp) &&
"target already exists it the list");
+ UnregisterInProcessTarget(target_sp);
m_target_list.push_back(std::move(target_sp));
if (do_select)
SetSelectedTargetInternal(m_target_list.size() - 1);
@@ -540,3 +543,35 @@ lldb::TargetSP TargetList::GetSelectedTarget() {
m_selected_target_idx = 0;
return GetTargetAtIndex(m_selected_target_idx);
}
+
+bool TargetList::AnyTargetContainsModule(Module &module) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ for (const auto &target_sp : m_target_list) {
+ if (target_sp->GetImages().FindModule(&module))
+ return true;
+ }
+ for (const auto &target_sp: m_in_process_target_list) {
+ if (target_sp->GetImages().FindModule(&module))
+ return true;
+ }
+ return false;
+}
+
+ void TargetList::RegisterInProcessTarget(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ std::unordered_set<TargetSP>::iterator iter;
+ bool was_added;
+ std::tie(iter, was_added) = m_in_process_target_list.insert(target_sp);
+ assert(was_added && "Target pointer was left in the in-process map");
+ }
+
+ void TargetList::UnregisterInProcessTarget(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ bool was_present = m_in_process_target_list.erase(target_sp);
+ assert(was_present && "Target pointer being removed was not registered");
+ }
+
+ bool TargetList::IsTargetInProcess(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ return m_in_process_target_list.count(target_sp) == 1;
+ }
More information about the lldb-commits
mailing list