Skip to content

Commit 5418e44

Browse files
[lldb] Skip prologue when stepping through swift_task_switch
Plans stepping through a swift_task_switch are often the last sub-plan for a StepOver action, meaning the plan's destination is also the PC where users will take control of the program. As such, it is crucial that these plans skip over the prologue of their destination function, otherwise most variables won't be in scope. Because x86 and arm diverge on the codegen for `}` in a scope, I had to add a `print` statement in the for loop of the affected test. (cherry picked from commit 3ed5f1d)
1 parent 08fc52a commit 5418e44

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,18 @@ CreateRunThroughTaskSwitchThreadPlan(Thread &thread,
394394
return {};
395395

396396
resume_fn_ptr = thread.GetProcess()->FixCodeAddress(resume_fn_ptr);
397-
return std::make_shared<ThreadPlanRunToAddress>(thread, resume_fn_ptr,
397+
398+
llvm::Expected<uint64_t> maybe_prologue_size =
399+
FindPrologueSize(*thread.GetProcess(), resume_fn_ptr);
400+
401+
uint64_t dest_address =
402+
resume_fn_ptr + (maybe_prologue_size ? *maybe_prologue_size : 0);
403+
404+
if (!maybe_prologue_size)
405+
LLDB_LOG_ERROR(GetLog(LLDBLog::Step), maybe_prologue_size.takeError(),
406+
"{1}::{0}", __FUNCTION__);
407+
408+
return std::make_shared<ThreadPlanRunToAddress>(thread, dest_address,
398409
/*stop_others*/ false);
399410
}
400411

lldb/test/API/lang/swift/async/stepping/step_over/TestSwiftAsyncStepOver.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
@skipIfAsan # rdar://138777205
88
class TestCase(lldbtest.TestBase):
99

10+
def check_x_is_available(self, frame):
11+
x_var = frame.FindVariable("x")
12+
self.assertTrue(x_var.IsValid(), f"Failed to find x in {frame}")
13+
self.assertEqual(x_var.GetValueAsUnsigned(), 30)
14+
1015
def check_is_in_line(self, thread, linenum):
1116
frame = thread.frames[0]
1217
line_entry = frame.GetLineEntry()
@@ -25,10 +30,11 @@ def test(self):
2530
bkpt.SetEnabled(False) # avoid hitting multiple locations in async breakpoints
2631

2732
expected_line_nums = [4] # print(x)
28-
expected_line_nums += [5, 6, 7, 5, 6, 7, 5] # two runs over the loop
29-
expected_line_nums += [8, 9] # if line + if block
33+
expected_line_nums += [5, 6, 7, 8, 5, 6, 7, 8, 5] # two runs over the loop
34+
expected_line_nums += [9, 10] # if line + if block
3035
for expected_line_num in expected_line_nums:
3136
thread.StepOver()
3237
stop_reason = thread.GetStopReason()
3338
self.assertStopReason(stop_reason, lldb.eStopReasonPlanComplete)
3439
self.check_is_in_line(thread, expected_line_num)
40+
self.check_x_is_available(thread.frames[0])

lldb/test/API/lang/swift/async/stepping/step_over/main.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
print(x)
55
for i in 1...2 {
66
await f()
7+
print("hello!")
78
}
89
if (await f() == 30) {
910
print("here!")

0 commit comments

Comments
 (0)