@@ -2716,6 +2716,37 @@ static llvm::Expected<addr_t> ReadAsyncContextRegisterFromUnwind(
27162716 " SwiftLanguageRuntime: Unsupported register location type = %d" , loctype);
27172717}
27182718
2719+ // / Returns true if the async register should be dereferenced once to obtain the
2720+ // / CFA of the currently executing function. This is the case at the start of
2721+ // / "Q" funclets, before the low level code changes the meaning of the async
2722+ // / register to not require the indirection.
2723+ // / This implementation detects the transition point by comparing the
2724+ // / continuation pointer in the async context with the currently executing
2725+ // / funclet given by the SymbolContext sc. If they are the same, the PC is
2726+ // / before the transition point.
2727+ // / FIXME: this fails in some recursive async functions. See: rdar://139676623
2728+ static llvm::Expected<bool > IsIndirectContext (Process &process,
2729+ StringRef mangled_name,
2730+ addr_t async_reg,
2731+ SymbolContext &sc) {
2732+ if (!SwiftLanguageRuntime::IsSwiftAsyncAwaitResumePartialFunctionSymbol (
2733+ mangled_name))
2734+ return false ;
2735+
2736+ llvm::Expected<addr_t > continuation_ptr = ReadPtrFromAddr (
2737+ process, async_reg, /* offset*/ process.GetAddressByteSize ());
2738+ if (!continuation_ptr)
2739+ return continuation_ptr.takeError ();
2740+
2741+ if (sc.function )
2742+ return sc.function ->GetAddressRange ().ContainsLoadAddress (
2743+ *continuation_ptr, &process.GetTarget ());
2744+ assert (sc.symbol );
2745+ Address continuation_addr;
2746+ continuation_addr.SetLoadAddress (*continuation_ptr, &process.GetTarget ());
2747+ return sc.symbol ->ContainsFileAddress (continuation_addr.GetFileAddress ());
2748+ }
2749+
27192750// Examine the register state and detect the transition from a real
27202751// stack frame to an AsyncContext frame, or a frame in the middle of
27212752// the AsyncContext chain, and return an UnwindPlan for these situations.
@@ -2776,15 +2807,20 @@ SwiftLanguageRuntime::GetRuntimeUnwindPlan(ProcessSP process_sp,
27762807 // for await resume ("Q") funclets ("indirect context").
27772808 // 2. The async context for the currently executing async function, for all
27782809 // other funclets ("Y" and "Yx" funclets, where "x" is a number).
2779- bool indirect_context =
2780- IsSwiftAsyncAwaitResumePartialFunctionSymbol (mangled_name.GetStringRef ());
27812810
27822811 llvm::Expected<addr_t > async_reg = ReadAsyncContextRegisterFromUnwind (
27832812 sc, *process_sp, pc, func_start_addr, *regctx, *regnums);
27842813 if (!async_reg)
27852814 return log_expected (async_reg.takeError ());
2815+
2816+ llvm::Expected<bool > maybe_indirect_context =
2817+ IsIndirectContext (*process_sp, mangled_name, *async_reg, sc);
2818+ if (!maybe_indirect_context)
2819+ return log_expected (maybe_indirect_context.takeError ());
2820+
27862821 llvm::Expected<addr_t > async_ctx =
2787- indirect_context ? ReadPtrFromAddr (*m_process, *async_reg) : *async_reg;
2822+ *maybe_indirect_context ? ReadPtrFromAddr (*m_process, *async_reg)
2823+ : *async_reg;
27882824 if (!async_ctx)
27892825 return log_expected (async_ctx.takeError ());
27902826
0 commit comments