Skip to content

Commit 9c662b1

Browse files
Merge pull request #9839 Swift OS plugin
[lldb] Swift OS plugin
2 parents 3160bd8 + dd46e67 commit 9c662b1

File tree

13 files changed

+439
-72
lines changed

13 files changed

+439
-72
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ class TargetProperties : public Properties {
199199

200200
AutoBool GetSwiftPCMValidation() const;
201201

202+
bool GetSwiftUseTasksPlugin() const;
203+
202204
Args GetSwiftPluginServerForPath() const;
203205

204206
bool GetSwiftAutoImportFrameworks() const;

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ const char *SwiftLanguageRuntime::GetStandardLibraryBaseName() {
9191
return "swiftCore";
9292
}
9393

94+
const char *SwiftLanguageRuntime::GetConcurrencyLibraryBaseName() {
95+
return "swift_Concurrency";
96+
}
97+
9498
static ConstString GetStandardLibraryName(Process &process) {
9599
// This result needs to be stored in the constructor.
96100
PlatformSP platform_sp(process.GetTarget().GetPlatform());
@@ -100,6 +104,14 @@ static ConstString GetStandardLibraryName(Process &process) {
100104
return {};
101105
}
102106

107+
static ConstString GetConcurrencyLibraryName(Process &process) {
108+
PlatformSP platform_sp = process.GetTarget().GetPlatform();
109+
if (platform_sp)
110+
return platform_sp->GetFullNameForDylib(
111+
ConstString(SwiftLanguageRuntime::GetConcurrencyLibraryBaseName()));
112+
return {};
113+
}
114+
103115
ConstString SwiftLanguageRuntime::GetStandardLibraryName() {
104116
return ::GetStandardLibraryName(*m_process);
105117
}
@@ -109,6 +121,12 @@ static bool IsModuleSwiftRuntime(lldb_private::Process &process,
109121
return module.GetFileSpec().GetFilename() == GetStandardLibraryName(process);
110122
}
111123

124+
static bool IsModuleSwiftConcurrency(lldb_private::Process &process,
125+
lldb_private::Module &module) {
126+
return module.GetFileSpec().GetFilename() ==
127+
GetConcurrencyLibraryName(process);
128+
}
129+
112130
AppleObjCRuntimeV2 *
113131
SwiftLanguageRuntime::GetObjCRuntime(lldb_private::Process &process) {
114132
if (auto objc_runtime = ObjCLanguageRuntime::Get(process)) {
@@ -131,6 +149,11 @@ static bool IsStaticSwiftRuntime(Module &image) {
131149
return image.FindFirstSymbolWithNameAndType(swift_reflection_version_sym);
132150
}
133151

152+
static bool IsStaticSwiftConcurrency(Module &image) {
153+
static const ConstString task_switch_symbol("_swift_task_switch");
154+
return image.FindFirstSymbolWithNameAndType(task_switch_symbol);
155+
}
156+
134157
/// \return the Swift or Objective-C runtime found in the loaded images.
135158
static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) {
136159
AppleObjCRuntimeV2 *objc_runtime = nullptr;
@@ -168,6 +191,52 @@ static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) {
168191
return runtime_image;
169192
}
170193

194+
ModuleSP SwiftLanguageRuntime::FindConcurrencyModule(Process &process) {
195+
ModuleSP concurrency_module;
196+
process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) {
197+
if (candidate && IsModuleSwiftConcurrency(process, *candidate)) {
198+
concurrency_module = candidate;
199+
return false;
200+
}
201+
return true;
202+
});
203+
if (concurrency_module)
204+
return concurrency_module;
205+
206+
// Do a more expensive search for a statically linked Swift runtime.
207+
process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) {
208+
if (candidate && IsStaticSwiftConcurrency(*candidate)) {
209+
concurrency_module = candidate;
210+
return false;
211+
}
212+
return true;
213+
});
214+
return concurrency_module;
215+
}
216+
217+
std::optional<uint32_t>
218+
SwiftLanguageRuntime::FindConcurrencyDebugVersion(Process &process) {
219+
ModuleSP concurrency_module = FindConcurrencyModule(process);
220+
if (!concurrency_module)
221+
return {};
222+
223+
const Symbol *version_symbol =
224+
concurrency_module->FindFirstSymbolWithNameAndType(
225+
ConstString("_swift_concurrency_debug_internal_layout_version"));
226+
if (!version_symbol)
227+
return 0;
228+
229+
addr_t symbol_addr = version_symbol->GetLoadAddress(&process.GetTarget());
230+
if (symbol_addr == LLDB_INVALID_ADDRESS)
231+
return {};
232+
Status error;
233+
uint64_t version = process.ReadUnsignedIntegerFromMemory(
234+
symbol_addr, /*width*/ 4, /*fail_value=*/0, error);
235+
if (error.Fail())
236+
return {};
237+
return version;
238+
}
239+
171240
static std::optional<lldb::addr_t>
172241
FindSymbolForSwiftObject(Process &process, RuntimeKind runtime_kind,
173242
StringRef object, const SymbolType sym_type) {
@@ -2724,7 +2793,11 @@ llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread) {
27242793
#else
27252794
// Compute the thread local storage address for this thread.
27262795
addr_t tsd_addr = LLDB_INVALID_ADDRESS;
2727-
if (auto info_sp = thread.GetExtendedInfo())
2796+
2797+
// Look through backing threads when inspecting TLS.
2798+
Thread &real_thread =
2799+
thread.GetBackingThread() ? *thread.GetBackingThread() : thread;
2800+
if (auto info_sp = real_thread.GetExtendedInfo())
27282801
if (auto *info_dict = info_sp->GetAsDictionary())
27292802
info_dict->GetValueForKeyAsInteger("tsd_address", tsd_addr);
27302803

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ class SwiftLanguageRuntime : public LanguageRuntime {
9898
static SwiftLanguageRuntime *Get(lldb::ProcessSP process_sp) {
9999
return SwiftLanguageRuntime::Get(process_sp.get());
100100
}
101+
102+
/// Returns the Module containing the Swift Concurrency runtime, if it exists.
103+
static lldb::ModuleSP FindConcurrencyModule(Process &process);
104+
105+
/// Returns the version of the swift concurrency runtime debug layout.
106+
/// If no Concurrency module is found, or if errors occur, nullopt is
107+
/// returned.
108+
/// Returns 0 for versions of the module prior to the introduction
109+
/// of versioning.
110+
static std::optional<uint32_t> FindConcurrencyDebugVersion(Process &process);
101111
/// \}
102112

103113
/// PluginInterface protocol.
@@ -481,6 +491,8 @@ class SwiftLanguageRuntime : public LanguageRuntime {
481491
static const char *GetErrorBackstopName();
482492
ConstString GetStandardLibraryName();
483493
static const char *GetStandardLibraryBaseName();
494+
static const char *GetConcurrencyLibraryBaseName();
495+
484496
static bool IsSwiftClassName(const char *name);
485497
/// Determines wether \c variable is the "self" object.
486498
static bool IsSelf(Variable &variable);

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -290,75 +290,6 @@ static ThunkAction GetThunkAction(ThunkKind kind) {
290290
}
291291
}
292292

293-
/// A thread plan to run to a specific address on a specific async context.
294-
class ThreadPlanRunToAddressOnAsyncCtx : public ThreadPlan {
295-
public:
296-
/// Creates a thread plan to run to destination_addr of an async function
297-
/// whose context is async_ctx.
298-
ThreadPlanRunToAddressOnAsyncCtx(Thread &thread, addr_t destination_addr,
299-
addr_t async_ctx)
300-
: ThreadPlan(eKindGeneric, "run-to-funclet", thread, eVoteNoOpinion,
301-
eVoteNoOpinion),
302-
m_destination_addr(destination_addr), m_expected_async_ctx(async_ctx) {
303-
auto &target = thread.GetProcess()->GetTarget();
304-
m_funclet_bp = target.CreateBreakpoint(destination_addr, true, false);
305-
m_funclet_bp->SetBreakpointKind("async-run-to-funclet");
306-
}
307-
308-
bool ValidatePlan(Stream *error) override {
309-
if (m_funclet_bp->HasResolvedLocations())
310-
return true;
311-
312-
// If we failed to resolve any locations, this plan is invalid.
313-
m_funclet_bp->GetTarget().RemoveBreakpointByID(m_funclet_bp->GetID());
314-
return false;
315-
}
316-
317-
void GetDescription(Stream *s, lldb::DescriptionLevel level) override {
318-
s->PutCString("ThreadPlanRunToAddressOnAsyncCtx to address = ");
319-
s->PutHex64(m_destination_addr);
320-
s->PutCString(" with async ctx = ");
321-
s->PutHex64(m_expected_async_ctx);
322-
}
323-
324-
/// This plan explains the stop if the current async context is the async
325-
/// context this plan was created with.
326-
bool DoPlanExplainsStop(Event *event) override {
327-
if (!HasTID())
328-
return false;
329-
return GetCurrentAsyncContext() == m_expected_async_ctx;
330-
}
331-
332-
/// If this plan explained the stop, it always stops: its sole purpose is to
333-
/// run to the breakpoint it set on the right async function invocation.
334-
bool ShouldStop(Event *event) override {
335-
SetPlanComplete();
336-
return true;
337-
}
338-
339-
/// If this plan said ShouldStop, then its job is complete.
340-
bool MischiefManaged() override {
341-
return IsPlanComplete();
342-
}
343-
344-
bool WillStop() override { return false; }
345-
lldb::StateType GetPlanRunState() override { return eStateRunning; }
346-
bool StopOthers() override { return false; }
347-
void DidPop() override {
348-
m_funclet_bp->GetTarget().RemoveBreakpointByID(m_funclet_bp->GetID());
349-
}
350-
351-
private:
352-
addr_t GetCurrentAsyncContext() {
353-
auto frame_sp = GetThread().GetStackFrameAtIndex(0);
354-
return frame_sp->GetStackID().GetCallFrameAddress();
355-
}
356-
357-
addr_t m_destination_addr;
358-
addr_t m_expected_async_ctx;
359-
BreakpointSP m_funclet_bp;
360-
};
361-
362293
/// Given a thread that is stopped at the start of swift_task_switch, create a
363294
/// thread plan that runs to the address of the resume function.
364295
static ThreadPlanSP
@@ -383,8 +314,8 @@ CreateRunThroughTaskSwitchThreadPlan(Thread &thread,
383314
if (!async_ctx)
384315
return {};
385316

386-
return std::make_shared<ThreadPlanRunToAddressOnAsyncCtx>(
387-
thread, resume_fn_ptr, async_ctx);
317+
return std::make_shared<ThreadPlanRunToAddress>(thread, resume_fn_ptr,
318+
/*stop_others*/ false);
388319
}
389320

390321
/// Creates a thread plan to step over swift runtime functions that can trigger
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
if (LLDB_ENABLE_PYTHON)
22
add_subdirectory(Python)
3+
add_subdirectory(SwiftTasks)
34
endif()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_lldb_library(lldbPluginOperatingSystemSwiftTasks PLUGIN
2+
OperatingSystemSwiftTasks.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbInterpreter
7+
lldbSymbol
8+
lldbTarget
9+
lldbValueObject
10+
lldbPluginProcessUtility
11+
lldbPluginSwiftLanguageRuntime
12+
)

0 commit comments

Comments
 (0)