Skip to content

Commit e475665

Browse files
committed
Implement leaf function handling
1 parent 1ecc274 commit e475665

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

src/unwind/unwind_with_rtlvirtualunwind.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,30 +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-
PVOID handler_data;
61-
DWORD64 establisher_frame;
62-
RtlVirtualUnwind(
63-
UNW_FLAG_NHANDLER,
64-
image_base,
65-
context_pc(context),
66-
function_entry,
67-
&context,
68-
&handler_data,
69-
&establisher_frame,
70-
NULL
71-
);
7292
if(context_pc(context) == 0) {
7393
break;
7494
}

0 commit comments

Comments
 (0)