Skip to content

Commit 3afe324

Browse files
author
git apple-llvm automerger
committed
Merge commit '262cfab9ef42' from swift/release/6.2 into stable/20240723
2 parents 94a95ed + 262cfab commit 3afe324

File tree

9 files changed

+235
-41
lines changed

9 files changed

+235
-41
lines changed

lldb/source/Plugins/Language/Swift/SwiftFormatters.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,18 @@ bool lldb_private::formatters::swift::Task_SummaryProvider(
18601860
return 0;
18611861
};
18621862

1863+
addr_t task_addr = get_member("address");
1864+
if (auto process_sp = valobj.GetProcessSP()) {
1865+
if (auto name_or_err = GetTaskName(task_addr, *process_sp)) {
1866+
if (auto maybe_name = *name_or_err)
1867+
stream.Format("\"{0}\" ", *maybe_name);
1868+
} else {
1869+
LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters | LLDBLog::Types),
1870+
name_or_err.takeError(),
1871+
"failed to determine name of task {1:x}: {0}", task_addr);
1872+
}
1873+
}
1874+
18631875
stream.Format("id:{0}", get_member("id"));
18641876

18651877
std::vector<StringRef> flags;

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

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@
3939
#include "lldb/Symbol/FuncUnwinders.h"
4040
#include "lldb/Symbol/Function.h"
4141
#include "lldb/Symbol/VariableList.h"
42+
#include "lldb/Target/Process.h"
4243
#include "lldb/Target/RegisterContext.h"
4344
#include "lldb/Target/UnwindLLDB.h"
45+
#include "lldb/Utility/ConstString.h"
4446
#include "lldb/Utility/ErrorMessages.h"
4547
#include "lldb/Utility/LLDBLog.h"
4648
#include "lldb/Utility/Log.h"
4749
#include "lldb/Utility/OptionParsing.h"
50+
#include "lldb/Utility/Status.h"
4851
#include "lldb/Utility/StructuredData.h"
4952
#include "lldb/Utility/Timer.h"
5053
#include "lldb/ValueObject/ValueObject.h"
@@ -68,6 +71,7 @@
6871
#include "llvm/Support/Error.h"
6972
#include "llvm/Support/FormatAdapters.h"
7073
#include "llvm/Support/Memory.h"
74+
#include <optional>
7175

7276
// FIXME: we should not need this
7377
#include "Plugins/Language/Swift/SwiftFormatters.h"
@@ -2962,4 +2966,109 @@ llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread) {
29622966
return task_addr;
29632967
#endif
29642968
}
2969+
2970+
namespace {
2971+
2972+
/// Lightweight wrapper around TaskStatusRecord pointers, providing:
2973+
/// * traversal over the embedded linnked list of status records
2974+
/// * information contained within records
2975+
///
2976+
/// Currently supports TaskNameStatusRecord. See swift/ABI/TaskStatus.h
2977+
struct TaskStatusRecord {
2978+
Process &process;
2979+
addr_t addr;
2980+
size_t addr_size;
2981+
2982+
TaskStatusRecord(Process &process, addr_t addr)
2983+
: process(process), addr(addr) {
2984+
addr_size = process.GetAddressByteSize();
2985+
}
2986+
2987+
operator bool() const { return addr && addr != LLDB_INVALID_ADDRESS; }
2988+
2989+
// The offset of TaskStatusRecord members. The unit is pointers, and must be
2990+
// converted to bytes based on the target's address size.
2991+
static constexpr unsigned FlagsPointerOffset = 0;
2992+
static constexpr unsigned ParentPointerOffset = 1;
2993+
static constexpr unsigned TaskNamePointerOffset = 2;
2994+
2995+
enum Kind : uint64_t {
2996+
TaskName = 6,
2997+
};
2998+
2999+
uint64_t getKind(Status &status) {
3000+
const offset_t flagsByteOffset = FlagsPointerOffset * addr_size;
3001+
if (status.Success())
3002+
return process.ReadUnsignedIntegerFromMemory(
3003+
addr + flagsByteOffset, addr_size, UINT64_MAX, status);
3004+
return UINT64_MAX;
3005+
}
3006+
3007+
std::optional<std::string> getName(Status &status) {
3008+
if (getKind(status) != Kind::TaskName)
3009+
return {};
3010+
3011+
const offset_t taskNameByteOffset = TaskNamePointerOffset * addr_size;
3012+
addr_t name_addr =
3013+
process.ReadPointerFromMemory(addr + taskNameByteOffset, status);
3014+
if (!status.Success())
3015+
return {};
3016+
3017+
std::string name;
3018+
process.ReadCStringFromMemory(name_addr, name, status);
3019+
if (status.Success())
3020+
return name;
3021+
3022+
return {};
3023+
}
3024+
3025+
addr_t getParent(Status &status) {
3026+
const offset_t parentByteOffset = ParentPointerOffset * addr_size;
3027+
addr_t parent = LLDB_INVALID_ADDRESS;
3028+
if (*this && status.Success())
3029+
parent = process.ReadPointerFromMemory(addr + parentByteOffset, status);
3030+
return parent;
3031+
}
3032+
};
3033+
3034+
/// Lightweight wrapper around Task pointers, providing access to a Task's
3035+
/// active status record. See swift/ABI/Task.h
3036+
struct Task {
3037+
Process &process;
3038+
addr_t addr;
3039+
3040+
operator bool() const { return addr && addr != LLDB_INVALID_ADDRESS; }
3041+
3042+
// The offset of the active TaskStatusRecord pointer. The unit is pointers,
3043+
// and must be converted to bytes based on the target's address size.
3044+
static constexpr unsigned ActiveTaskStatusRecordPointerOffset = 13;
3045+
3046+
TaskStatusRecord getActiveTaskStatusRecord(Status &status) {
3047+
const offset_t activeTaskStatusRecordByteOffset =
3048+
ActiveTaskStatusRecordPointerOffset * process.GetAddressByteSize();
3049+
addr_t status_record = LLDB_INVALID_ADDRESS;
3050+
if (status.Success())
3051+
status_record = process.ReadPointerFromMemory(
3052+
addr + activeTaskStatusRecordByteOffset, status);
3053+
return {process, status_record};
3054+
}
3055+
};
3056+
3057+
}; // namespace
3058+
3059+
llvm::Expected<std::optional<std::string>> GetTaskName(lldb::addr_t task_addr,
3060+
Process &process) {
3061+
Status status;
3062+
Task task{process, task_addr};
3063+
auto status_record = task.getActiveTaskStatusRecord(status);
3064+
while (status_record) {
3065+
if (auto name = status_record.getName(status))
3066+
return *name;
3067+
status_record.addr = status_record.getParent(status);
3068+
}
3069+
if (status.Success())
3070+
return std::nullopt;
3071+
return status.takeError();
3072+
}
3073+
29653074
} // namespace lldb_private

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "lldb/Breakpoint/BreakpointPrecondition.h"
2020
#include "lldb/Core/PluginInterface.h"
2121
#include "lldb/Target/LanguageRuntime.h"
22+
#include "lldb/Target/Process.h"
2223
#include "lldb/lldb-private.h"
2324
#include "swift/Demangling/ManglingFlavor.h"
2425

@@ -901,6 +902,10 @@ GetAsyncUnwindRegisterNumbers(llvm::Triple::ArchType triple);
901902
/// Inspects thread local storage to find the address of the currently executing
902903
/// task.
903904
llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread);
905+
906+
llvm::Expected<std::optional<std::string>> GetTaskName(lldb::addr_t task,
907+
Process &process);
908+
904909
} // namespace lldb_private
905910

906911
#endif // liblldb_SwiftLanguageRuntime_h_

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.cpp

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/Support/Error.h"
10+
#include <optional>
911
#if LLDB_ENABLE_SWIFT
1012

1113
#include "OperatingSystemSwiftTasks.h"
@@ -74,16 +76,11 @@ OperatingSystemSwiftTasks::~OperatingSystemSwiftTasks() = default;
7476

7577
OperatingSystemSwiftTasks::OperatingSystemSwiftTasks(
7678
lldb_private::Process &process)
77-
: OperatingSystem(&process) {
78-
size_t ptr_size = process.GetAddressByteSize();
79-
// Offset of a Task ID inside a Task data structure, guaranteed by the ABI.
80-
// See Job in swift/RemoteInspection/RuntimeInternals.h.
81-
m_job_id_offset = 4 * ptr_size + 4;
82-
}
79+
: OperatingSystem(&process) {}
8380

84-
ThreadSP
85-
OperatingSystemSwiftTasks::FindOrCreateSwiftThread(ThreadList &old_thread_list,
86-
uint64_t task_id) {
81+
ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
82+
ThreadList &old_thread_list, uint64_t task_id,
83+
std::optional<std::string> task_name) {
8784
// Mask higher bits to avoid conflicts with core thread IDs.
8885
uint64_t masked_task_id = 0x0000000f00000000 | task_id;
8986

@@ -92,23 +89,71 @@ OperatingSystemSwiftTasks::FindOrCreateSwiftThread(ThreadList &old_thread_list,
9289
IsOperatingSystemPluginThread(old_thread))
9390
return old_thread;
9491

95-
std::string name = llvm::formatv("Swift Task {0}", task_id);
92+
std::string name;
93+
if (task_name)
94+
name = llvm::formatv("{0} (Task {1})", *task_name, task_id);
95+
else
96+
name = llvm::formatv("Task {0}", task_id);
97+
9698
return std::make_shared<ThreadMemoryProvidingName>(*m_process, masked_task_id,
9799
/*register_data_addr*/ 0,
98100
name);
99101
}
100102

103+
static std::optional<addr_t> FindTaskAddress(Thread &thread) {
104+
llvm::Expected<addr_t> task_addr = GetTaskAddrFromThreadLocalStorage(thread);
105+
if (!task_addr) {
106+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), task_addr.takeError(),
107+
"OperatingSystemSwiftTasks: failed to find task address in "
108+
"thread local storage: {0}");
109+
return {};
110+
}
111+
if (*task_addr == 0 || *task_addr == LLDB_INVALID_ADDRESS)
112+
return std::nullopt;
113+
return *task_addr;
114+
}
115+
116+
static std::optional<uint64_t> FindTaskId(addr_t task_addr, Process &process) {
117+
size_t ptr_size = process.GetAddressByteSize();
118+
// Offset of a Task ID inside a Task data structure, guaranteed by the ABI.
119+
// See Job in swift/RemoteInspection/RuntimeInternals.h.
120+
const offset_t job_id_offset = 4 * ptr_size + 4;
121+
122+
Status error;
123+
// The Task ID is at offset job_id_offset from the Task pointer.
124+
constexpr uint32_t num_bytes_task_id = 4;
125+
auto task_id = process.ReadUnsignedIntegerFromMemory(
126+
task_addr + job_id_offset, num_bytes_task_id, LLDB_INVALID_ADDRESS,
127+
error);
128+
if (error.Fail())
129+
return {};
130+
return task_id;
131+
}
132+
133+
static std::optional<std::string> FindTaskName(addr_t task_addr,
134+
Process &process) {
135+
auto task_name_or_err = GetTaskName(task_addr, process);
136+
if (auto err = task_name_or_err.takeError()) {
137+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
138+
"OperatingSystemSwiftTasks: failed while looking for name "
139+
"of task {1:x}: {0}",
140+
task_addr);
141+
return {};
142+
}
143+
return *task_name_or_err;
144+
}
145+
101146
bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
102147
ThreadList &core_thread_list,
103148
ThreadList &new_thread_list) {
104149
Log *log = GetLog(LLDBLog::OS);
105150
LLDB_LOG(log, "OperatingSystemSwiftTasks: Updating thread list");
106151

107152
for (const ThreadSP &real_thread : core_thread_list.Threads()) {
108-
std::optional<uint64_t> task_id = FindTaskId(*real_thread);
153+
std::optional<addr_t> task_addr = FindTaskAddress(*real_thread);
109154

110155
// If this is not a thread running a Task, add it to the list as is.
111-
if (!task_id) {
156+
if (!task_addr) {
112157
new_thread_list.AddThread(real_thread);
113158
LLDB_LOGF(log,
114159
"OperatingSystemSwiftTasks: thread %" PRIx64
@@ -117,7 +162,16 @@ bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
117162
continue;
118163
}
119164

120-
ThreadSP swift_thread = FindOrCreateSwiftThread(old_thread_list, *task_id);
165+
assert(m_process != nullptr);
166+
std::optional<uint64_t> task_id = FindTaskId(*task_addr, *m_process);
167+
if (!task_id) {
168+
LLDB_LOG(log, "OperatingSystemSwiftTasks: could not get ID of Task {0:x}",
169+
*task_addr);
170+
continue;
171+
}
172+
173+
ThreadSP swift_thread = FindOrCreateSwiftThread(
174+
old_thread_list, *task_id, FindTaskName(*task_addr, *m_process));
121175
swift_thread->SetBackingThread(real_thread);
122176
new_thread_list.AddThread(swift_thread);
123177
LLDB_LOGF(log,
@@ -142,24 +196,4 @@ StopInfoSP OperatingSystemSwiftTasks::CreateThreadStopReason(
142196
return thread->GetStopInfo();
143197
}
144198

145-
std::optional<uint64_t> OperatingSystemSwiftTasks::FindTaskId(Thread &thread) {
146-
llvm::Expected<addr_t> task_addr = GetTaskAddrFromThreadLocalStorage(thread);
147-
if (!task_addr) {
148-
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), task_addr.takeError(),
149-
"OperatingSystemSwiftTasks: failed to find task address in "
150-
"thread local storage: {0}");
151-
return {};
152-
}
153-
154-
Status error;
155-
// The Task ID is at offset m_job_id_offset from the Task pointer.
156-
constexpr uint32_t num_bytes_task_id = 4;
157-
auto task_id = m_process->ReadUnsignedIntegerFromMemory(
158-
*task_addr + m_job_id_offset, num_bytes_task_id, LLDB_INVALID_ADDRESS,
159-
error);
160-
if (error.Fail())
161-
return {};
162-
return task_id;
163-
}
164-
165199
#endif // #if LLDB_ENABLE_SWIFT

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,8 @@ class OperatingSystemSwiftTasks : public OperatingSystem {
4949
/// If a thread for task_id had been created in the last stop, return it.
5050
/// Otherwise, create a new MemoryThread for it.
5151
lldb::ThreadSP FindOrCreateSwiftThread(ThreadList &old_thread_list,
52-
uint64_t task_id);
53-
54-
/// Find the Task ID of the task being executed by `thread`, if any.
55-
std::optional<uint64_t> FindTaskId(Thread &thread);
56-
57-
/// The offset of the Job ID inside a Task data structure.
58-
size_t m_job_id_offset;
52+
uint64_t task_id,
53+
std::optional<std::string> task_name);
5954
};
6055
} // namespace lldb_private
6156

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 -Xfrontend -disable-availability-checking
3+
include Makefile.rules
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import textwrap
2+
import lldb
3+
from lldbsuite.test.decorators import *
4+
from lldbsuite.test.lldbtest import *
5+
from lldbsuite.test import lldbutil
6+
7+
8+
class TestCase(TestBase):
9+
10+
@swiftTest
11+
def test_summary_contains_name(self):
12+
self.build()
13+
lldbutil.run_to_source_breakpoint(
14+
self, "break outside", lldb.SBFileSpec("main.swift")
15+
)
16+
self.expect("v task", patterns=[r'"Chore" id:[1-9]\d*'])
17+
18+
@swiftTest
19+
@skipIfLinux # rdar://151471067
20+
def test_thread_contains_name(self):
21+
self.build()
22+
_, _, thread, _ = lldbutil.run_to_source_breakpoint(
23+
self, "break inside", lldb.SBFileSpec("main.swift")
24+
)
25+
self.assertRegex(thread.name, r"Chore \(Task [1-9]\d*\)")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@main struct Main {
2+
static func main() async {
3+
let task = Task(name: "Chore") {
4+
print("break inside")
5+
_ = readLine()
6+
return 15
7+
}
8+
print("break outside")
9+
_ = await task.value
10+
}
11+
}

lldb/test/API/lang/swift/async/queues/TestSwiftPluginQueues.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def test(self):
1919
self, "BREAK HERE", source_file
2020
)
2121

22-
self.assertIn("Swift Task", thread.GetName())
22+
self.assertRegex(thread.GetName(), r"^Task [1-9]\d*$")
2323

2424
queue_plugin = self.get_queue_from_thread_info_command(False)
2525
queue_backing = self.get_queue_from_thread_info_command(True)

0 commit comments

Comments
 (0)