Skip to content

Commit 345eddf

Browse files
[lldb][swift] Create thread plan for stepping through Allocating Init
These trampolines have a well defined target, which can be extracted from the demangle tree. A similar strategy is already adopted for stepping into conformance code. This allows LLDB to create a StepThrough plan with a target symbol, instead of a plan that keep taking steps until it reaches some interesting location. We already had a test for this, but we rely on the "step avoid libraries" setting to emulate the case of "avoid libraries without debug info". However, they are not exactly equivalent, so the test mislead us into believing stepping was working. A future patch should try to fold the setting-checking code into ThreadPlanShouldStopHere::DefaultShouldStopCallback. With this patch, the test now works regardless of whether debug info is present or not.
1 parent c89ea13 commit 345eddf

File tree

3 files changed

+31
-21
lines changed

3 files changed

+31
-21
lines changed

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

+31-7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ enum class ThunkAction {
5353
Unknown = 0,
5454
GetThunkTarget,
5555
StepIntoConformance,
56+
StepIntoAllocatingInit,
5657
StepThrough,
5758
};
5859

@@ -336,7 +337,7 @@ static const char *GetThunkKindName(ThunkKind kind) {
336337
case ThunkKind::Unknown:
337338
return "Unknown";
338339
case ThunkKind::AllocatingInit:
339-
return "StepThrough";
340+
return "StepIntoAllocatingInit";
340341
case ThunkKind::PartialApply:
341342
return "GetThunkTarget";
342343
case ThunkKind::ObjCAttribute:
@@ -353,7 +354,7 @@ static ThunkAction GetThunkAction(ThunkKind kind) {
353354
case ThunkKind::Unknown:
354355
return ThunkAction::Unknown;
355356
case ThunkKind::AllocatingInit:
356-
return ThunkAction::StepThrough;
357+
return ThunkAction::StepIntoAllocatingInit;
357358
case ThunkKind::PartialApply:
358359
return ThunkAction::GetThunkTarget;
359360
case ThunkKind::ObjCAttribute:
@@ -589,17 +590,40 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
589590
thread, sym_addr_range, sc, function_name.c_str(), eOnlyDuringStepping,
590591
eLazyBoolNo, eLazyBoolNo);
591592
}
593+
case ThunkAction::StepIntoAllocatingInit: {
594+
LLDB_LOGF(log, "Stepping into allocating init: \"%s\"", symbol_name);
595+
swift::Demangle::Context ctx;
596+
NodePointer demangled_node =
597+
SwiftLanguageRuntime::DemangleSymbolAsNode(symbol_name, ctx);
598+
599+
using Kind = Node::Kind;
600+
NodePointer function_node = childAtPath(
601+
demangled_node, {Kind::Allocator, Kind::Class, Kind::Identifier});
602+
if (!function_node || !function_node->hasText()) {
603+
std::string node_str = getNodeTreeAsString(demangled_node);
604+
LLDB_LOGF(log,
605+
"Failed to extract constructor name from demangle node: %s",
606+
node_str.c_str());
607+
return nullptr;
608+
}
609+
StringRef class_name = function_node->getText();
610+
std::string ctor_name = (class_name + ".init").str();
611+
AddressRange sym_addr_range(sc.symbol->GetAddress(),
612+
sc.symbol->GetByteSize());
613+
ThreadPlanSP new_plan_sp = std::make_shared<ThreadPlanStepInRange>(
614+
thread, sym_addr_range, sc, ctor_name.c_str(), eOnlyDuringStepping,
615+
eLazyBoolNo, eLazyBoolNo);
616+
return new_plan_sp;
617+
}
592618
case ThunkAction::StepThrough: {
593619
if (log)
594620
log->Printf("Stepping through thunk: %s kind: %s", symbol_name,
595621
GetThunkKindName(thunk_kind));
596622
AddressRange sym_addr_range(sc.symbol->GetAddress(),
597623
sc.symbol->GetByteSize());
598-
ThreadPlanSP new_plan_sp = std::make_shared<ThreadPlanStepInRange>(thread, sym_addr_range, sc,
599-
nullptr, eOnlyDuringStepping,
600-
eLazyBoolNo, eLazyBoolNo);
601-
static_cast<ThreadPlanStepInRange *>(new_plan_sp.get())
602-
->GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutPastThunks);
624+
ThreadPlanSP new_plan_sp = std::make_shared<ThreadPlanStepInRange>(
625+
thread, sym_addr_range, sc, nullptr, eOnlyDuringStepping, eLazyBoolNo,
626+
eLazyBoolNo);
603627
return new_plan_sp;
604628
}
605629
}

lldb/test/API/lang/swift/cxx_interop/backward/stepping/TestSwiftBackwardInteropStepping.py

-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ def test_method_step_over_class(self):
5353
thread = self.setup('Break here for method - class')
5454
self.check_step_over(thread, 'testMethod')
5555

56-
@expectedFailureAll(bugnumber="rdar://106670255")
5756
@swiftTest
5857
def test_init_step_in_class(self):
5958
thread = self.setup('Break here for constructor - class')
@@ -115,7 +114,6 @@ def test_method_step_over_struct_class(self):
115114
thread = self.setup('Break here for method - struct')
116115
self.check_step_over(thread, 'testMethod')
117116

118-
@expectedFailureAll(bugnumber="rdar://106670255")
119117
@swiftTest
120118
def test_init_step_in_struct_class(self):
121119
thread = self.setup('Break here for constructor - struct')

lldb/test/API/lang/swift/step_through_allocating_init/TestStepThroughAllocatingInit.py

-12
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,6 @@ def setUp(self):
2525
lldbtest.TestBase.setUp(self)
2626
self.main_source = "main.swift"
2727
self.main_source_spec = lldb.SBFileSpec(self.main_source)
28-
# If you are running against a debug swift you are going to
29-
# end up stepping into the stdlib and that will make stepping
30-
# tests impossible to write. So avoid that.
31-
32-
if platform.system() == 'Darwin':
33-
lib_name = "libswiftCore.dylib"
34-
else:
35-
lib_name = "libswiftCore.so"
36-
37-
self.dbg.HandleCommand(
38-
"settings set "
39-
"target.process.thread.step-avoid-libraries {}".format(lib_name))
4028

4129
def do_test(self, use_api):
4230
"""Tests that we can step reliably in swift code."""

0 commit comments

Comments
 (0)