Skip to content

Commit c8c8184

Browse files
committed
Attempt to load jit frames
1 parent 7f0f4b2 commit c8c8184

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/backtrace/dbghelp.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,32 @@ pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
9393
Err(()) => return, // oh well...
9494
};
9595

96+
// On x86_64 (and probably ARM64? need to verify at some point) we opt to
97+
// not use the default `Sym*` functions from dbghelp for getting the
98+
// function table and module base. Instead we use the
99+
// `RtlLookupFunctionEntry` function in kernel32 which will account for JIT
100+
// compiler frames as well. These should be equivalent, but using `Rtl*`
101+
// allows us to backtrace through JIT frames.
102+
cfg_if::cfg_if! {
103+
if #[cfg(target_arch = "x86_64")] {
104+
use core::ptr;
105+
106+
unsafe extern "system" fn function_table_access(_process: HANDLE, addr: DWORD64) -> PVOID {
107+
let mut base = 0;
108+
RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut()).cast()
109+
}
110+
111+
unsafe extern "system" fn get_module_base(_process: HANDLE, addr: DWORD64) -> DWORD64 {
112+
let mut base = 0;
113+
RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut());
114+
base
115+
}
116+
} else {
117+
let function_table_access = dbghelp.SymFunctionTableAccess64();
118+
let get_module_base = dbghelp.SymGetModuleBase64();
119+
}
120+
}
121+
96122
// Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64`
97123
// since it's in theory supported on more systems.
98124
match (*dbghelp.dbghelp()).StackWalkEx() {
@@ -113,8 +139,8 @@ pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
113139
frame_ptr,
114140
&mut context.0 as *mut CONTEXT as *mut _,
115141
None,
116-
Some(dbghelp.SymFunctionTableAccess64()),
117-
Some(dbghelp.SymGetModuleBase64()),
142+
Some(function_table_access),
143+
Some(get_module_base),
118144
None,
119145
0,
120146
) == TRUE
@@ -141,8 +167,8 @@ pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
141167
frame_ptr,
142168
&mut context.0 as *mut CONTEXT as *mut _,
143169
None,
144-
Some(dbghelp.SymFunctionTableAccess64()),
145-
Some(dbghelp.SymGetModuleBase64()),
170+
Some(function_table_access),
171+
Some(get_module_base),
146172
None,
147173
) == TRUE
148174
{

src/windows.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ cfg_if::cfg_if! {
3535
pub type HINSTANCE = *mut c_void;
3636
pub type FARPROC = *mut c_void;
3737
pub type LPSECURITY_ATTRIBUTES = *mut c_void;
38+
pub type PRUNTIME_FUNCTION = *mut c_void;
39+
pub type PUNWIND_HISTORY_TABLE = *mut c_void;
3840
}
3941
}
4042

@@ -152,9 +154,12 @@ macro_rules! ffi {
152154
ffi!($($rest)*);
153155
);
154156

155-
(extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
157+
(extern "system" { $($(#[$attr:meta])* pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
156158
extern "system" {
157-
$(pub fn $name($($args)*) -> $ret;)*
159+
$(
160+
$(#[$attr])*
161+
pub fn $name($($args)*) -> $ret;
162+
)*
158163
}
159164

160165
$(
@@ -371,6 +376,12 @@ ffi! {
371376
dwMilliseconds: DWORD,
372377
bAlertable: BOOL,
373378
) -> DWORD;
379+
#[cfg(target_arch = "x86_64")]
380+
pub fn RtlLookupFunctionEntry(
381+
ControlPc: DWORD64,
382+
ImageBase: PDWORD64,
383+
HistoryTable: PUNWIND_HISTORY_TABLE,
384+
) -> PRUNTIME_FUNCTION;
374385
}
375386
}
376387

0 commit comments

Comments
 (0)