@@ -45,44 +45,50 @@ namespace detail {
4545 }
4646
4747 std::vector<frame_ptr> trace;
48+ bool handled_leaf = false ;
4849 while (trace.size () < max_depth) {
4950 DWORD64 image_base;
50- PRUNTIME_FUNCTION function_entry = RtlLookupFunctionEntry (context_pc (context), &image_base, NULL );
51+ auto pc = context_pc (context);
52+ PRUNTIME_FUNCTION function_entry = RtlLookupFunctionEntry (pc, &image_base, NULL );
5153 if (!function_entry) {
52- break ;
54+ if (handled_leaf) {
55+ break ;
56+ }
57+ handled_leaf = true ;
5358 }
5459 if (skip) {
5560 skip--;
5661 } else {
57- // Same adjustment as StackWalk64
58- trace.push_back (to_frame_ptr (context_pc (context)) - 1 );
62+ trace.push_back (to_frame_ptr (pc) - 1 );
63+ }
64+ if (function_entry) {
65+ PVOID handler_data;
66+ DWORD64 establisher_frame;
67+ RtlVirtualUnwind (
68+ UNW_FLAG_NHANDLER,
69+ image_base,
70+ pc,
71+ function_entry,
72+ &context,
73+ &handler_data,
74+ &establisher_frame,
75+ NULL
76+ );
77+ } else {
78+ // Leaf functions may not have unwind / .pdata entries. Handle that case here.
79+ // We only come here once and handled_leaf = true is set above
80+ // https://learn.microsoft.com/en-us/cpp/build/arm-exception-handling?view=msvc-170
81+ // https://searchfox.org/firefox-main/source/mozglue/misc/StackWalk.cpp#653-655
82+ // https://github.com/dotnet/runtime/blob/133c7bde3fb7dd914f423ffb3e408cc61787e0bb/src/coreclr/vm/stackwalk.cpp#L573-L600
83+ #if defined(_M_X64) || defined(__x86_64__)
84+ context.Rip = *reinterpret_cast <DWORD64*>(context.Rsp );
85+ context.Rsp += sizeof (DWORD64);
86+ #elif defined(_M_ARM64) || defined(__aarch64__)
87+ context.Pc = context.Lr ;
88+ #else
89+ #error "Unsupported arch for leaf function handling"
90+ #endif
5991 }
60- #if defined(_M_X64) || defined(__x86_64__)
61- PVOID handler_data;
62- DWORD64 establisher_frame;
63- RtlVirtualUnwind (
64- UNW_FLAG_NHANDLER,
65- image_base,
66- context_pc (context),
67- function_entry,
68- &context,
69- &handler_data,
70- &establisher_frame,
71- NULL
72- );
73- #elif defined(_M_ARM64) || defined(__aarch64__)
74- BOOLEAN in_function;
75- FRAME_POINTERS establisher_frame;
76- RtlVirtualUnwind (
77- image_base,
78- context_pc (context),
79- function_entry,
80- &context,
81- &in_function,
82- &establisher_frame,
83- NULL
84- );
85- #endif
8692 if (context_pc (context) == 0 ) {
8793 break ;
8894 }
0 commit comments