Skip to content

Commit 78ce006

Browse files
committed
Fix rtlvirtualunwind implementation for arm and implement leaf function handling
1 parent 1cd0279 commit 78ce006

File tree

1 file changed

+36
-30
lines changed

1 file changed

+36
-30
lines changed

src/unwind/unwind_with_rtlvirtualunwind.cpp

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)