-
Notifications
You must be signed in to change notification settings - Fork 332
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
[lldb] Swift OS plugin #9839
base: stable/20240723
Are you sure you want to change the base?
[lldb] Swift OS plugin #9839
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -91,6 +91,10 @@ const char *SwiftLanguageRuntime::GetStandardLibraryBaseName() { | |||||
return "swiftCore"; | ||||||
} | ||||||
|
||||||
const char *SwiftLanguageRuntime::GetConcurrencyLibraryBaseName() { | ||||||
return "swift_Concurrency"; | ||||||
} | ||||||
|
||||||
static ConstString GetStandardLibraryName(Process &process) { | ||||||
// This result needs to be stored in the constructor. | ||||||
PlatformSP platform_sp(process.GetTarget().GetPlatform()); | ||||||
|
@@ -100,6 +104,14 @@ static ConstString GetStandardLibraryName(Process &process) { | |||||
return {}; | ||||||
} | ||||||
|
||||||
static ConstString GetConcurrencyLibraryName(Process &process) { | ||||||
PlatformSP platform_sp = process.GetTarget().GetPlatform(); | ||||||
if (platform_sp) | ||||||
return platform_sp->GetFullNameForDylib( | ||||||
ConstString(SwiftLanguageRuntime::GetConcurrencyLibraryBaseName())); | ||||||
return {}; | ||||||
} | ||||||
|
||||||
ConstString SwiftLanguageRuntime::GetStandardLibraryName() { | ||||||
return ::GetStandardLibraryName(*m_process); | ||||||
} | ||||||
|
@@ -109,6 +121,12 @@ static bool IsModuleSwiftRuntime(lldb_private::Process &process, | |||||
return module.GetFileSpec().GetFilename() == GetStandardLibraryName(process); | ||||||
} | ||||||
|
||||||
static bool IsModuleSwiftConcurrency(lldb_private::Process &process, | ||||||
lldb_private::Module &module) { | ||||||
return module.GetFileSpec().GetFilename() == | ||||||
GetConcurrencyLibraryName(process); | ||||||
} | ||||||
|
||||||
AppleObjCRuntimeV2 * | ||||||
SwiftLanguageRuntime::GetObjCRuntime(lldb_private::Process &process) { | ||||||
if (auto objc_runtime = ObjCLanguageRuntime::Get(process)) { | ||||||
|
@@ -131,6 +149,11 @@ static bool IsStaticSwiftRuntime(Module &image) { | |||||
return image.FindFirstSymbolWithNameAndType(swift_reflection_version_sym); | ||||||
} | ||||||
|
||||||
static bool IsStaticSwiftConcurrency(Module &image) { | ||||||
static const ConstString task_switch_symbol("_swift_task_switch"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rationale here was also just to keep uniformity with the other identical helper functions in this file. But also the call |
||||||
return image.FindFirstSymbolWithNameAndType(task_switch_symbol); | ||||||
} | ||||||
|
||||||
/// \return the Swift or Objective-C runtime found in the loaded images. | ||||||
static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) { | ||||||
AppleObjCRuntimeV2 *objc_runtime = nullptr; | ||||||
|
@@ -168,6 +191,52 @@ static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) { | |||||
return runtime_image; | ||||||
} | ||||||
|
||||||
ModuleSP SwiftLanguageRuntime::FindConcurrencyModule(Process &process) { | ||||||
ModuleSP concurrency_module; | ||||||
process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) { | ||||||
if (candidate && IsModuleSwiftConcurrency(process, *candidate)) { | ||||||
concurrency_module = candidate; | ||||||
return false; | ||||||
} | ||||||
return true; | ||||||
}); | ||||||
if (concurrency_module) | ||||||
return concurrency_module; | ||||||
|
||||||
// Do a more expensive search for a statically linked Swift runtime. | ||||||
process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) { | ||||||
if (candidate && IsStaticSwiftConcurrency(*candidate)) { | ||||||
concurrency_module = candidate; | ||||||
return false; | ||||||
} | ||||||
return true; | ||||||
}); | ||||||
return concurrency_module; | ||||||
} | ||||||
|
||||||
std::optional<uint32_t> | ||||||
SwiftLanguageRuntime::FindConcurrencyDebugVersion(Process &process) { | ||||||
ModuleSP concurrency_module = FindConcurrencyModule(process); | ||||||
if (!concurrency_module) | ||||||
return {}; | ||||||
|
||||||
const Symbol *version_symbol = | ||||||
concurrency_module->FindFirstSymbolWithNameAndType( | ||||||
ConstString("_swift_concurrency_debug_internal_layout_version")); | ||||||
if (!version_symbol) | ||||||
return 0; | ||||||
|
||||||
addr_t symbol_addr = version_symbol->GetLoadAddress(&process.GetTarget()); | ||||||
if (symbol_addr == LLDB_INVALID_ADDRESS) | ||||||
return {}; | ||||||
Status error; | ||||||
uint64_t version = process.ReadUnsignedIntegerFromMemory( | ||||||
symbol_addr, /*width*/ 4, /*fail_value=*/0, error); | ||||||
if (error.Fail()) | ||||||
return {}; | ||||||
return version; | ||||||
} | ||||||
|
||||||
static std::optional<lldb::addr_t> | ||||||
FindSymbolForSwiftObject(Process &process, RuntimeKind runtime_kind, | ||||||
StringRef object, const SymbolType sym_type) { | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -303,6 +303,7 @@ class ThreadPlanRunToAddressOnAsyncCtx : public ThreadPlan { | |
auto &target = thread.GetProcess()->GetTarget(); | ||
m_funclet_bp = target.CreateBreakpoint(destination_addr, true, false); | ||
m_funclet_bp->SetBreakpointKind("async-run-to-funclet"); | ||
m_funclet_bp->SetThreadID(thread.GetID()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to refresh reviewer's memories: this is the thread plan to "run through a task switch and stop when we schedule this same async function again. This plan now sets thread specific breakpoints, since they are now task breakpoints! If we somehow push this type of plan without having the OS plugin, we are at a risk of breaking in the wrong task. But if the plugin is not there and there are tasks, we are going to have much bigger problems anyway. For example, this code has been associated with a lot of LLDB crashes because it triggers stack plan migration (this is a downstream-only thing that becomes dead code with this patch, and I'll delete it in a follow up PR) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be this an inline comment in the source file ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would argue that in this case we don't need any comments, because this is just the "natural" thing to do. If anything, it is the old implementation that deserved a comment, as it was essentially making all threads stop. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand what you're saying with this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just noticed that the writing was indeed confusing, my bad. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A follow up patch will remove this plan in favor of the RunToBreakpointPlan |
||
} | ||
|
||
bool ValidatePlan(Stream *error) override { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
if (LLDB_ENABLE_PYTHON) | ||
add_subdirectory(Python) | ||
add_subdirectory(SwiftTasks) | ||
endif() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
add_lldb_library(lldbPluginOperatingSystemSwiftTasks PLUGIN | ||
OperatingSystemSwiftTasks.cpp | ||
|
||
LINK_LIBS | ||
lldbCore | ||
lldbInterpreter | ||
lldbSymbol | ||
lldbTarget | ||
lldbValueObject | ||
lldbPluginProcessUtility | ||
lldbPluginSwiftLanguageRuntime | ||
) |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,155 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
//===-- OperatingSystemSwiftTasks.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 | ||||||||||||||||||||||||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||||||||||||||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
#if LLDB_ENABLE_SWIFT | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
#include "OperatingSystemSwiftTasks.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "Plugins/Process/Utility/ThreadMemory.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Core/Debugger.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Core/Module.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Core/PluginManager.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Target/Process.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Target/Thread.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Target/ThreadList.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
#include "lldb/Utility/LLDBLog.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
#include <memory> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
using namespace lldb; | ||||||||||||||||||||||||||||||||||||||||||||||||||
using namespace lldb_private; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_PLUGIN_DEFINE(OperatingSystemSwiftTasks) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
void OperatingSystemSwiftTasks::Initialize() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
PluginManager::RegisterPlugin(GetPluginNameStatic(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
GetPluginDescriptionStatic(), CreateInstance, | ||||||||||||||||||||||||||||||||||||||||||||||||||
nullptr); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
void OperatingSystemSwiftTasks::Terminate() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
PluginManager::UnregisterPlugin(CreateInstance); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
OperatingSystem *OperatingSystemSwiftTasks::CreateInstance(Process *process, | ||||||||||||||||||||||||||||||||||||||||||||||||||
bool force) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!process || !process->GetTarget().GetSwiftUseTasksPlugin()) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Log *log = GetLog(LLDBLog::OS); | ||||||||||||||||||||||||||||||||||||||||||||||||||
std::optional<uint32_t> concurrency_version = | ||||||||||||||||||||||||||||||||||||||||||||||||||
SwiftLanguageRuntime::FindConcurrencyDebugVersion(*process); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!concurrency_version) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOG(log, | ||||||||||||||||||||||||||||||||||||||||||||||||||
"OperatingSystemSwiftTasks: did not find concurrency module."); | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (*concurrency_version <= 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return new OperatingSystemSwiftTasks(*process); | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOGF(log, | ||||||||||||||||||||||||||||||||||||||||||||||||||
"OperatingSystemSwiftTasks: got a concurrency version symbol of %u", | ||||||||||||||||||||||||||||||||||||||||||||||||||
*concurrency_version); | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::StringRef OperatingSystemSwiftTasks::GetPluginDescriptionStatic() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return "Operating system plug-in converting Swift Tasks into Threads."; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
OperatingSystemSwiftTasks::~OperatingSystemSwiftTasks() = default; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
OperatingSystemSwiftTasks::OperatingSystemSwiftTasks( | ||||||||||||||||||||||||||||||||||||||||||||||||||
lldb_private::Process &process) | ||||||||||||||||||||||||||||||||||||||||||||||||||
: OperatingSystem(&process) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
size_t ptr_size = process.GetAddressByteSize(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
// Offset of a Task ID inside a Task data structure, guaranteed by the ABI. | ||||||||||||||||||||||||||||||||||||||||||||||||||
// See Job in swift/RemoteInspection/RuntimeInternals.h. | ||||||||||||||||||||||||||||||||||||||||||||||||||
m_task_id_offset = 4 * ptr_size + 4; | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the job id? if so should the name reflect that? also if so, do we know if we can ignore the task's upper 32 bit identifier? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on what I saw in the runtime code, I think it's safe to do so. It is what is being done in other tools anyway. I'll rename this to "job id"! |
||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list, | ||||||||||||||||||||||||||||||||||||||||||||||||||
ThreadList &core_thread_list, | ||||||||||||||||||||||||||||||||||||||||||||||||||
ThreadList &new_thread_list) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
Log *log = GetLog(LLDBLog::OS); | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOG(log, "OperatingSystemSwiftTasks: Updating thread list"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
for (const ThreadSP &real_thread : core_thread_list.Threads()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
std::optional<uint64_t> task_id = FindTaskId(*real_thread); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
// If this is not a thread running a Task, add it to the list as is. | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!task_id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
new_thread_list.AddThread(real_thread); | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOGF(log, | ||||||||||||||||||||||||||||||||||||||||||||||||||
"OperatingSystemSwiftTasks: thread %" PRIx64 | ||||||||||||||||||||||||||||||||||||||||||||||||||
" is not executing a Task", | ||||||||||||||||||||||||||||||||||||||||||||||||||
real_thread->GetID()); | ||||||||||||||||||||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
// Mask higher bits to avoid conflicts with core thread IDs. | ||||||||||||||||||||||||||||||||||||||||||||||||||
uint64_t masked_task_id = 0x0000000f00000000 | *task_id; | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice hack :p There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be honest I don't think we need to / should do this, because conflicts are handled without issues... it is just a way to visually know we have a fake thread. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how are the conflicts handled? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a couple of lines down, on line 100 |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
ThreadSP swift_thread = [&]() -> ThreadSP { | ||||||||||||||||||||||||||||||||||||||||||||||||||
// If we already had a thread for this Task in the last stop, re-use it. | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (ThreadSP old_thread = old_thread_list.FindThreadByID(masked_task_id); | ||||||||||||||||||||||||||||||||||||||||||||||||||
IsOperatingSystemPluginThread(old_thread)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+100
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First time I'm seeing this syntax :p Don't you want to run the second part of the if condition only if the first one if valid ?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return old_thread; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
std::string name = llvm::formatv("Swift Task {0:x}", *task_id); | ||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::StringRef queue_name = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||
return std::make_shared<ThreadMemory>(*m_process, masked_task_id, name, | ||||||||||||||||||||||||||||||||||||||||||||||||||
queue_name, | ||||||||||||||||||||||||||||||||||||||||||||||||||
/*register_data_addr*/ 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||
}(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+98
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lambda through me off. Is there something I'm missing that it can't be an if/else?
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
swift_thread->SetBackingThread(real_thread); | ||||||||||||||||||||||||||||||||||||||||||||||||||
new_thread_list.AddThread(swift_thread); | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOGF(log, | ||||||||||||||||||||||||||||||||||||||||||||||||||
"OperatingSystemSwiftTasks: mapping thread IDs: %" PRIx64 | ||||||||||||||||||||||||||||||||||||||||||||||||||
" -> %" PRIx64, | ||||||||||||||||||||||||||||||||||||||||||||||||||
real_thread->GetID(), swift_thread->GetID()); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
void OperatingSystemSwiftTasks::ThreadWasSelected(Thread *thread) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
RegisterContextSP OperatingSystemSwiftTasks::CreateRegisterContextForThread( | ||||||||||||||||||||||||||||||||||||||||||||||||||
Thread *thread, addr_t reg_data_addr) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!thread || !IsOperatingSystemPluginThread(thread->shared_from_this())) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||
return thread->GetRegisterContext(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
StopInfoSP OperatingSystemSwiftTasks::CreateThreadStopReason( | ||||||||||||||||||||||||||||||||||||||||||||||||||
lldb_private::Thread *thread) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return thread->GetStopInfo(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
std::optional<uint64_t> OperatingSystemSwiftTasks::FindTaskId(Thread &thread) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Expected<addr_t> task_addr = GetTaskAddrFromThreadLocalStorage(thread); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!task_addr) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), task_addr.takeError(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
"OperatingSystemSwiftTasks: failed to find task address in " | ||||||||||||||||||||||||||||||||||||||||||||||||||
"thread local storage: {0}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
return {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Status error; | ||||||||||||||||||||||||||||||||||||||||||||||||||
// The Task ID is at offset m_task_id_offset from the Task pointer. | ||||||||||||||||||||||||||||||||||||||||||||||||||
constexpr uint32_t num_bytes_task_id = 4; | ||||||||||||||||||||||||||||||||||||||||||||||||||
auto task_id = m_process->ReadUnsignedIntegerFromMemory( | ||||||||||||||||||||||||||||||||||||||||||||||||||
*task_addr + m_task_id_offset, num_bytes_task_id, LLDB_INVALID_ADDRESS, | ||||||||||||||||||||||||||||||||||||||||||||||||||
error); | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (error.Fail()) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||
return task_id; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
#endif // #if LLDB_ENABLE_SWIFT |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
//===-- OperatingSystemSwiftTasks.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 liblldb_OperatingSystemSwiftTasks_h_ | ||
#define liblldb_OperatingSystemSwiftTasks_h_ | ||
|
||
#if LLDB_ENABLE_SWIFT | ||
|
||
#include "lldb/Target/OperatingSystem.h" | ||
|
||
namespace lldb_private { | ||
class OperatingSystemSwiftTasks : public OperatingSystem { | ||
public: | ||
OperatingSystemSwiftTasks(Process &process); | ||
~OperatingSystemSwiftTasks() override; | ||
|
||
static OperatingSystem *CreateInstance(Process *process, bool force); | ||
static void Initialize(); | ||
static void Terminate(); | ||
static llvm::StringRef GetPluginNameStatic() { return "swift"; } | ||
static llvm::StringRef GetPluginDescriptionStatic(); | ||
|
||
/// PluginInterface Methods | ||
|
||
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } | ||
|
||
/// OperatingSystem Methods | ||
|
||
bool UpdateThreadList(ThreadList &old_thread_list, | ||
ThreadList &real_thread_list, | ||
ThreadList &new_thread_list) override; | ||
|
||
void ThreadWasSelected(Thread *thread) override; | ||
|
||
lldb::RegisterContextSP | ||
CreateRegisterContextForThread(Thread *thread, | ||
lldb::addr_t reg_data_addr) override; | ||
|
||
lldb::StopInfoSP CreateThreadStopReason(Thread *thread) override; | ||
|
||
bool DoesPluginReportAllThreads() override { return false; } | ||
|
||
private: | ||
/// Find the Task ID of the task being executed by `thread`, if any. | ||
std::optional<uint64_t> FindTaskId(Thread &thread); | ||
|
||
/// The offset of the Task ID inside a Task data structure. | ||
size_t m_task_id_offset; | ||
}; | ||
} // namespace lldb_private | ||
|
||
#endif // LLDB_ENABLE_SWIFT | ||
|
||
#endif // liblldb_OperatingSystemSwiftTasks_h_ |
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.
nit: Can this return a
StringRef
orStringLiteral
?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.
It could, for sure, but it would break with the pattern of the other functions above. We can do a cleanup and change all of them in a separate PR