Skip to content

Control the "step out through thunk" logic explicitly when pushing th… #10183

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

Merged
merged 1 commit into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,12 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
GetThunkKindName(thunk_kind));
AddressRange sym_addr_range(sc.symbol->GetAddress(),
sc.symbol->GetByteSize());
return std::make_shared<ThreadPlanStepInRange>(thread, sym_addr_range, sc,
ThreadPlanSP new_plan_sp = std::make_shared<ThreadPlanStepInRange>(thread, sym_addr_range, sc,
nullptr, eOnlyDuringStepping,
eLazyBoolNo, eLazyBoolNo);
static_cast<ThreadPlanStepInRange *>(new_plan_sp.get())
->GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutPastThunks);
return new_plan_sp;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SWIFT_SOURCES := main.swift
include Makefile.rules

cleanup:
rm -f Makefile *.d

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import lldb
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbtest as lldbtest
import lldbsuite.test.lldbutil as lldbutil
import os
import platform

class TestStepThroughAllocatingInit(lldbtest.TestBase):
mydir = lldbtest.TestBase.compute_mydir(__file__)

@swiftTest
def test_swift_stepping_api(self):
"""Test that step in using the Python API steps through thunk."""
self.build()
self.do_test(True)

@swiftTest
def test_swift_stepping_cli(self):
"""Same test with the cli - it goes a slightly different path than
the API."""
self.build()
self.do_test(False)

def setUp(self):
lldbtest.TestBase.setUp(self)
self.main_source = "main.swift"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
# If you are running against a debug swift you are going to
# end up stepping into the stdlib and that will make stepping
# tests impossible to write. So avoid that.

if platform.system() == 'Darwin':
lib_name = "libswiftCore.dylib"
else:
lib_name = "libswiftCore.so"

self.dbg.HandleCommand(
"settings set "
"target.process.thread.step-avoid-libraries {}".format(lib_name))

def do_test(self, use_api):
"""Tests that we can step reliably in swift code."""
exe_name = "a.out"
exe = self.getBuildArtifact(exe_name)

target, process, thread, breakpoint = lldbutil.run_to_source_breakpoint(self,
'Break here to step into init', self.main_source_spec)

# Step into the function.
if use_api:
thread.StepInto()
else:
self.runCmd("thread step-in")
frame_0 = thread.frames[0]
self.assertIn('Foo.init()', frame_0.GetFunctionName())

# Check that our parent frame is indeed allocating_init (otherwise we aren't
# testing what we think we're testing...
frame_1 = thread.frames[1]
self.assertIn("allocating_init", frame_1.GetFunctionName())

# Step one line so some_string is initialized, make sure we can
# get its value:
thread.StepOver()
frame_0 = thread.frames[0]
self.assertIn('Foo.init()', frame_0.GetFunctionName())
var = frame_0.FindVariable("some_string")
self.assertTrue(var.GetError().Success())
self.assertEqual(var.GetSummary(), '"foo"')

# Now make sure that stepping out steps past the thunk:
thread.StepOut()
frame_0 = thread.frames[0]
self.assertIn("doSomething", frame_0.GetFunctionName())
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Foo {
init() {
let some_string = "foo"
print(some_string)
}
}

func bar(_ _: Foo) {
print("bar")
}

func doSomething()
{
let f = Foo() // Break here to step into init
bar(f)
}

doSomething()