Skip to content

Commit 4cce7ea

Browse files
authored
Merge pull request #9875 from swiftlang/dl/lldb-Introduce-Swift-task-info-command
[lldb] Introduce Swift "task info" command
2 parents 60d6eec + 140f2c6 commit 4cce7ea

File tree

5 files changed

+137
-1
lines changed

5 files changed

+137
-1
lines changed

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

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "SwiftLanguageRuntime.h"
1414
#include "Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h"
15+
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
1516
#include "ReflectionContextInterface.h"
1617
#include "SwiftMetadataCache.h"
1718

@@ -34,6 +35,7 @@
3435
#include "lldb/Interpreter/CommandObject.h"
3536
#include "lldb/Interpreter/CommandObjectMultiword.h"
3637
#include "lldb/Interpreter/CommandReturnObject.h"
38+
#include "lldb/Symbol/CompilerType.h"
3739
#include "lldb/Symbol/FuncUnwinders.h"
3840
#include "lldb/Symbol/Function.h"
3941
#include "lldb/Symbol/VariableList.h"
@@ -43,6 +45,7 @@
4345
#include "lldb/Utility/LLDBLog.h"
4446
#include "lldb/Utility/Log.h"
4547
#include "lldb/Utility/OptionParsing.h"
48+
#include "lldb/Utility/StructuredData.h"
4649
#include "lldb/Utility/Timer.h"
4750
#include "lldb/ValueObject/ValueObject.h"
4851
#include "lldb/ValueObject/ValueObjectCast.h"
@@ -52,15 +55,18 @@
5255
#include "lldb/lldb-enumerations.h"
5356
#include "swift/AST/ASTMangler.h"
5457
#include "swift/Demangling/Demangle.h"
55-
#include "swift/RemoteInspection/ReflectionContext.h"
5658
#include "swift/RemoteAST/RemoteAST.h"
59+
#include "swift/RemoteInspection/ReflectionContext.h"
60+
#include "swift/Threading/ThreadLocalStorage.h"
5761

5862
#include "clang/AST/ASTContext.h"
5963
#include "clang/AST/DeclCXX.h"
6064

6165
#include "llvm/ADT/StringRef.h"
6266
#include "llvm/BinaryFormat/Dwarf.h"
6367
#include "llvm/Support/raw_ostream.h"
68+
#include "llvm/Support/Error.h"
69+
#include "llvm/Support/FormatAdapters.h"
6470
#include "llvm/Support/Memory.h"
6571

6672
// FIXME: we should not need this
@@ -2181,6 +2187,61 @@ class CommandObjectLanguageSwiftTaskSelect final : public CommandObjectParsed {
21812187
}
21822188
};
21832189

2190+
class CommandObjectLanguageSwiftTaskInfo final : public CommandObjectParsed {
2191+
public:
2192+
CommandObjectLanguageSwiftTaskInfo(CommandInterpreter &interpreter)
2193+
: CommandObjectParsed(interpreter, "info",
2194+
"Print the Task being run on the current thread.") {
2195+
}
2196+
2197+
private:
2198+
void DoExecute(Args &command, CommandReturnObject &result) override {
2199+
if (!m_exe_ctx.GetThreadPtr()) {
2200+
result.AppendError("must be run from a running process and valid thread");
2201+
return;
2202+
}
2203+
2204+
auto task_addr_or_err =
2205+
GetTaskAddrFromThreadLocalStorage(m_exe_ctx.GetThreadRef());
2206+
if (auto error = task_addr_or_err.takeError()) {
2207+
result.AppendError(toString(std::move(error)));
2208+
return;
2209+
}
2210+
2211+
auto ts_or_err = m_exe_ctx.GetTargetRef().GetScratchTypeSystemForLanguage(
2212+
eLanguageTypeSwift);
2213+
if (auto error = ts_or_err.takeError()) {
2214+
result.AppendErrorWithFormatv("could not get Swift type system: {0}",
2215+
llvm::fmt_consume(std::move(error)));
2216+
return;
2217+
}
2218+
2219+
auto *ts = llvm::dyn_cast_or_null<TypeSystemSwiftTypeRef>(ts_or_err->get());
2220+
if (!ts) {
2221+
result.AppendError("could not get Swift type system");
2222+
return;
2223+
}
2224+
2225+
addr_t task_addr = task_addr_or_err.get();
2226+
// TypeMangling for "Swift.UnsafeCurrentTask"
2227+
CompilerType task_type =
2228+
ts->GetTypeFromMangledTypename(ConstString("$sSctD"));
2229+
auto task_sp = ValueObject::CreateValueObjectFromAddress(
2230+
"current_task", task_addr, m_exe_ctx, task_type, false);
2231+
if (auto synthetic_sp = task_sp->GetSyntheticValue())
2232+
task_sp = synthetic_sp;
2233+
2234+
auto error = task_sp->Dump(result.GetOutputStream());
2235+
if (error) {
2236+
result.AppendErrorWithFormatv("failed to print current task: {0}",
2237+
toString(std::move(error)));
2238+
return;
2239+
}
2240+
2241+
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
2242+
}
2243+
};
2244+
21842245
class CommandObjectLanguageSwiftTask final : public CommandObjectMultiword {
21852246
public:
21862247
CommandObjectLanguageSwiftTask(CommandInterpreter &interpreter)
@@ -2193,6 +2254,9 @@ class CommandObjectLanguageSwiftTask final : public CommandObjectMultiword {
21932254
LoadSubCommand(
21942255
"select",
21952256
CommandObjectSP(new CommandObjectLanguageSwiftTaskSelect(interpreter)));
2257+
LoadSubCommand(
2258+
"info",
2259+
CommandObjectSP(new CommandObjectLanguageSwiftTaskInfo(interpreter)));
21962260
}
21972261
};
21982262

@@ -2654,4 +2718,33 @@ std::optional<lldb::addr_t> SwiftLanguageRuntime::TrySkipVirtualParentProlog(
26542718
: sc.function->GetPrologueByteSize();
26552719
return pc_value + prologue_size;
26562720
}
2721+
2722+
llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread) {
2723+
#if !SWIFT_THREADING_USE_RESERVED_TLS_KEYS
2724+
return llvm::createStringError(
2725+
"getting the current task from a thread is not supported");
2726+
#else
2727+
// Compute the thread local storage address for this thread.
2728+
addr_t tsd_addr = LLDB_INVALID_ADDRESS;
2729+
if (auto info_sp = thread.GetExtendedInfo())
2730+
if (auto *info_dict = info_sp->GetAsDictionary())
2731+
info_dict->GetValueForKeyAsInteger("tsd_address", tsd_addr);
2732+
2733+
if (tsd_addr == LLDB_INVALID_ADDRESS)
2734+
return llvm::createStringError("could not read current task from thread");
2735+
2736+
// Offset of the Task pointer in a Thread's local storage.
2737+
Process &process = *thread.GetProcess();
2738+
size_t ptr_size = process.GetAddressByteSize();
2739+
uint64_t task_ptr_offset_in_tls =
2740+
swift::tls_get_key(swift::tls_key::concurrency_task) * ptr_size;
2741+
addr_t task_addr_location = tsd_addr + task_ptr_offset_in_tls;
2742+
Status status;
2743+
addr_t task_addr = process.ReadPointerFromMemory(task_addr_location, status);
2744+
if (status.Fail())
2745+
return llvm::createStringError("could not get current task from thread: %s",
2746+
status.AsCString());
2747+
return task_addr;
2748+
#endif
2749+
}
26572750
} // namespace lldb_private

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,10 @@ struct AsyncUnwindRegisterNumbers {
849849

850850
std::optional<AsyncUnwindRegisterNumbers>
851851
GetAsyncUnwindRegisterNumbers(llvm::Triple::ArchType triple);
852+
853+
/// Inspects thread local storage to find the address of the currently executing
854+
/// task.
855+
llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread);
852856
} // namespace lldb_private
853857

854858
#endif // liblldb_SwiftLanguageRuntime_h_
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS := -parse-as-library
3+
include Makefile.rules
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import TestBase
4+
import lldbsuite.test.lldbutil as lldbutil
5+
6+
import re
7+
8+
9+
def _tail(output):
10+
"""Delete the first line of output text."""
11+
result, _ = re.subn(r"^.*\n", "", output, count=1)
12+
return result
13+
14+
15+
class TestCase(TestBase):
16+
17+
@skipUnlessDarwin
18+
def test(self):
19+
self.build()
20+
lldbutil.run_to_source_breakpoint(
21+
self, "break here", lldb.SBFileSpec("main.swift")
22+
)
23+
self.runCmd("frame variable task")
24+
frame_variable_output = self.res.GetOutput()
25+
self.runCmd("language swift task info")
26+
task_info_output = self.res.GetOutput()
27+
self.assertEqual(_tail(task_info_output), _tail(frame_variable_output))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@main struct Main {
2+
static func main() async {
3+
withUnsafeCurrentTask { task in
4+
if let task {
5+
print("break here")
6+
}
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)