@@ -45,6 +45,7 @@ enum class ThunkKind {
4545 AllocatingInit,
4646 PartialApply,
4747 ObjCAttribute,
48+ NonObjCAttributeOnCtor,
4849 Reabstraction,
4950 ProtocolConformance,
5051};
@@ -55,6 +56,7 @@ enum class ThunkAction {
5556 StepIntoConformance,
5657 StepIntoAllocatingInit,
5758 StepThrough,
59+ RunToObjcCInteropCtor,
5860};
5961
6062} // namespace
@@ -313,6 +315,10 @@ static ThunkKind GetThunkKind(Symbol *symbol) {
313315 switch (main_node->getKind ()) {
314316 case Node::Kind::ObjCAttribute:
315317 return ThunkKind::ObjCAttribute;
318+ case Node::Kind::NonObjCAttribute:
319+ if (hasChild (nodes, Node::Kind::Constructor))
320+ return ThunkKind::NonObjCAttributeOnCtor;
321+ break ;
316322 case Node::Kind::ProtocolWitness:
317323 if (hasChild (main_node, Node::Kind::ProtocolConformance))
318324 return ThunkKind::ProtocolConformance;
@@ -342,6 +348,8 @@ static const char *GetThunkKindName(ThunkKind kind) {
342348 return " GetThunkTarget" ;
343349 case ThunkKind::ObjCAttribute:
344350 return " GetThunkTarget" ;
351+ case ThunkKind::NonObjCAttributeOnCtor:
352+ return " RunToObjcCInteropCtor" ;
345353 case ThunkKind::Reabstraction:
346354 return " GetThunkTarget" ;
347355 case ThunkKind::ProtocolConformance:
@@ -363,6 +371,8 @@ static ThunkAction GetThunkAction(ThunkKind kind) {
363371 return ThunkAction::StepThrough;
364372 case ThunkKind::ProtocolConformance:
365373 return ThunkAction::StepIntoConformance;
374+ case ThunkKind::NonObjCAttributeOnCtor:
375+ return ThunkAction::RunToObjcCInteropCtor;
366376 }
367377}
368378
@@ -419,6 +429,66 @@ CreateRunThroughTaskSwitchingTrampolines(Thread &thread,
419429 return nullptr ;
420430}
421431
432+ // / Demangle `symbol_name` and extracts the text at the node described by
433+ // / `node_path`, if it exists; otherwise, returns an empty string.
434+ static std::string FindClassName (StringRef symbol_name,
435+ llvm::ArrayRef<Node::Kind> node_path) {
436+ swift::Demangle::Context ctx;
437+ NodePointer demangled_node =
438+ SwiftLanguageRuntime::DemangleSymbolAsNode (symbol_name, ctx);
439+
440+ if (!demangled_node) {
441+ std::string symbol_name_str = symbol_name.str ();
442+ LLDB_LOGF (GetLog (LLDBLog::Step),
443+ " SwiftLanguageRuntime: failed to demangle %s." ,
444+ symbol_name_str.c_str ());
445+ return " " ;
446+ }
447+ NodePointer class_node = childAtPath (demangled_node, node_path);
448+ if (!class_node || !class_node->hasText ()) {
449+ std::string node_str = getNodeTreeAsString (demangled_node);
450+ LLDB_LOGF (GetLog (LLDBLog::Step),
451+ " SwiftLanguageRuntime: failed to extract name from "
452+ " demangle node: %s" ,
453+ node_str.c_str ());
454+ return " " ;
455+ }
456+ return class_node->getText ().str ();
457+ }
458+
459+ // / If sc_list is non-empty, returns a plan that runs to any of its addresses.
460+ // / Otherwise, returns nullptr.
461+ static ThreadPlanSP
462+ CreateThreadPlanRunToSCInList (Thread &thread, const SymbolContextList &sc_list,
463+ bool stop_others) {
464+ std::vector<addr_t > load_addresses;
465+ Target &target = thread.GetProcess ()->GetTarget ();
466+ for (const SymbolContext &sc : sc_list) {
467+ const Symbol *ctor_symbol = sc.symbol ;
468+ if (ctor_symbol)
469+ load_addresses.push_back (ctor_symbol->GetLoadAddress (&target));
470+ }
471+
472+ if (load_addresses.empty ()) {
473+ LLDB_LOG (GetLog (LLDBLog::Step),
474+ " SwiftLanguageRuntime: empty sc_list found." );
475+ return {};
476+ }
477+ return std::make_shared<ThreadPlanRunToAddress>(thread, load_addresses,
478+ stop_others);
479+ }
480+
481+ // / Search all modules for `target_func` and creates a RunToAddress plan
482+ // / targeting all symbols found.
483+ static ThreadPlanSP CreateRunToAddressPlan (StringRef target_func,
484+ Thread &thread, bool stop_others) {
485+ ModuleList modules = thread.GetProcess ()->GetTarget ().GetImages ();
486+ SymbolContextList sc_list;
487+ modules.FindFunctionSymbols (ConstString (target_func), eFunctionNameTypeFull,
488+ sc_list);
489+ return CreateThreadPlanRunToSCInList (thread, sc_list, stop_others);
490+ }
491+
422492static lldb::ThreadPlanSP GetStepThroughTrampolinePlan (Thread &thread,
423493 bool stop_others) {
424494 // Here are the trampolines we have at present.
@@ -475,19 +545,32 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
475545 log->Printf (
476546 " Stepped to thunk \" %s\" (kind: %s) stepping to target: \" %s\" ." ,
477547 symbol_name, GetThunkKindName (thunk_kind), thunk_target.c_str ());
548+ return CreateRunToAddressPlan (thunk_target, thread, stop_others);
549+ }
550+ case ThunkAction::RunToObjcCInteropCtor: {
551+ static constexpr auto class_path = {
552+ Node::Kind::Constructor, Node::Kind::Class, Node::Kind::Identifier};
553+ std::string class_name = FindClassName (symbol_name, class_path);
554+ if (class_name.empty ()) {
555+ LLDB_LOGF (log,
556+ " SwiftLanguageRuntime: could not derive class name from symbol "
557+ " \" %s\" ." ,
558+ symbol_name);
559+ return nullptr ;
560+ }
561+ std::string ctor_name = llvm::formatv (" {0} init" , class_name);
562+ LLDB_LOGF (log,
563+ " SwiftLanguageRuntime: running to objective C constructor \" %s\" "
564+ " from swift." ,
565+ ctor_name.c_str ());
478566
479- ModuleList modules = thread.GetProcess ()->GetTarget ().GetImages ();
480567 SymbolContextList sc_list;
481- modules.FindFunctionSymbols (ConstString (thunk_target),
482- eFunctionNameTypeFull, sc_list);
483- if (sc_list.GetSize () == 1 && sc_list[0 ].symbol ) {
484- Symbol &thunk_symbol = *sc_list[0 ].symbol ;
485- Address target_address = thunk_symbol.GetAddress ();
486- if (target_address.IsValid ())
487- return std::make_shared<ThreadPlanRunToAddress>(thread, target_address,
488- stop_others);
489- }
490- return nullptr ;
568+ ModuleFunctionSearchOptions options{/* include_symbols*/ true ,
569+ /* include_inlines*/ true };
570+ ModuleList modules = thread.GetProcess ()->GetTarget ().GetImages ();
571+ modules.FindFunctions (RegularExpression (ctor_name), options, sc_list);
572+
573+ return CreateThreadPlanRunToSCInList (thread, sc_list, stop_others);
491574 }
492575 case ThunkAction::StepIntoConformance: {
493576 // The TTW symbols encode the protocol conformance requirements
@@ -582,37 +665,19 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
582665 }
583666 case ThunkAction::StepIntoAllocatingInit: {
584667 LLDB_LOGF (log, " Stepping into allocating init: \" %s\" " , symbol_name);
585- swift::Demangle::Context ctx;
586- NodePointer demangled_node =
587- SwiftLanguageRuntime::DemangleSymbolAsNode (symbol_name, ctx);
588-
589668 using Kind = Node::Kind;
590- NodePointer class_node = childAtPath (
591- demangled_node, {Kind::Allocator, Kind::Class, Kind::Identifier});
592- if (!class_node || !class_node->hasText ()) {
593- std::string node_str = getNodeTreeAsString (demangled_node);
594- LLDB_LOGF (log,
595- " Failed to extract constructor name from demangle node: %s" ,
596- node_str.c_str ());
669+ static constexpr auto class_path = {Kind::Allocator, Kind::Class,
670+ Kind::Identifier};
671+ std::string class_name = FindClassName (symbol_name, class_path);
672+ if (class_name.empty ())
597673 return nullptr ;
598- }
599674
600675 ModuleFunctionSearchOptions options{/* include_symbols*/ true ,
601676 /* include_inlines*/ true };
602- std::string ctor_name = llvm::formatv (" {0}.init" , class_node-> getText () );
677+ std::string ctor_name = llvm::formatv (" {0}.init" , class_name );
603678 SymbolContextList sc_list;
604679 sc.module_sp ->FindFunctions (RegularExpression (ctor_name), options, sc_list);
605- std::vector<addr_t > load_addresses;
606- Target &target = thread.GetProcess ()->GetTarget ();
607- for (const SymbolContext &ctor_sc : sc_list) {
608- const Symbol *ctor_symbol = ctor_sc.symbol ;
609- if (ctor_symbol)
610- load_addresses.push_back (ctor_symbol->GetLoadAddress (&target));
611- }
612- if (load_addresses.empty ())
613- return nullptr ;
614- return std::make_shared<ThreadPlanRunToAddress>(thread, load_addresses,
615- stop_others);
680+ return CreateThreadPlanRunToSCInList (thread, sc_list, stop_others);
616681 }
617682 case ThunkAction::StepThrough: {
618683 if (log)
0 commit comments