@@ -2716,6 +2716,37 @@ static llvm::Expected<addr_t> ReadAsyncContextRegisterFromUnwind(
2716
2716
" SwiftLanguageRuntime: Unsupported register location type = %d" , loctype);
2717
2717
}
2718
2718
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
+
2719
2750
// Examine the register state and detect the transition from a real
2720
2751
// stack frame to an AsyncContext frame, or a frame in the middle of
2721
2752
// the AsyncContext chain, and return an UnwindPlan for these situations.
@@ -2776,15 +2807,20 @@ SwiftLanguageRuntime::GetRuntimeUnwindPlan(ProcessSP process_sp,
2776
2807
// for await resume ("Q") funclets ("indirect context").
2777
2808
// 2. The async context for the currently executing async function, for all
2778
2809
// other funclets ("Y" and "Yx" funclets, where "x" is a number).
2779
- bool indirect_context =
2780
- IsSwiftAsyncAwaitResumePartialFunctionSymbol (mangled_name.GetStringRef ());
2781
2810
2782
2811
llvm::Expected<addr_t > async_reg = ReadAsyncContextRegisterFromUnwind (
2783
2812
sc, *process_sp, pc, func_start_addr, *regctx, *regnums);
2784
2813
if (!async_reg)
2785
2814
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
+
2786
2821
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;
2788
2824
if (!async_ctx)
2789
2825
return log_expected (async_ctx.takeError ());
2790
2826
0 commit comments