Skip to content

Commit 8ff78c3

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

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

src/backtrace/dbghelp.rs

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

96+
// On x86_64 and ARM64 we opt to not use the default `Sym*` functions from
97+
// dbghelp for getting the function table and module base. Instead we use
98+
// the `RtlLookupFunctionEntry` function in kernel32 which will account for
99+
// JIT compiler frames as well. These should be equivalent, but using
100+
// `Rtl*` allows us to backtrace through JIT frames.
101+
cfg_if::cfg_if! {
102+
if #[cfg(target_pointer_width = "64")] {
103+
use core::ptr;
104+
105+
unsafe extern "system" fn function_table_access(_process: HANDLE, addr: DWORD64) -> PVOID {
106+
let mut base = 0;
107+
RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut()).cast()
108+
}
109+
110+
unsafe extern "system" fn get_module_base(_process: HANDLE, addr: DWORD64) -> DWORD64 {
111+
let mut base = 0;
112+
RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut());
113+
base
114+
}
115+
} else {
116+
let function_table_access = dbghelp.SymFunctionTableAccess64();
117+
let get_module_base = dbghelp.SymGetModuleBase64();
118+
}
119+
}
120+
96121
// Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64`
97122
// since it's in theory supported on more systems.
98123
match (*dbghelp.dbghelp()).StackWalkEx() {
@@ -113,8 +138,8 @@ pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
113138
frame_ptr,
114139
&mut context.0 as *mut CONTEXT as *mut _,
115140
None,
116-
Some(dbghelp.SymFunctionTableAccess64()),
117-
Some(dbghelp.SymGetModuleBase64()),
141+
Some(function_table_access),
142+
Some(get_module_base),
118143
None,
119144
0,
120145
) == TRUE
@@ -141,8 +166,8 @@ pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
141166
frame_ptr,
142167
&mut context.0 as *mut CONTEXT as *mut _,
143168
None,
144-
Some(dbghelp.SymFunctionTableAccess64()),
145-
Some(dbghelp.SymGetModuleBase64()),
169+
Some(function_table_access),
170+
Some(get_module_base),
146171
None,
147172
) == TRUE
148173
{

src/windows.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ cfg_if::cfg_if! {
1515
pub use self::winapi::HINSTANCE;
1616
pub use self::winapi::FARPROC;
1717
pub use self::winapi::LPSECURITY_ATTRIBUTES;
18+
pub use self::winapi::PUNWIND_HISTORY_TABLE;
19+
pub use self::winapi::PRUNTIME_FUNCTION;
1820

1921
mod winapi {
2022
pub use winapi::ctypes::*;
@@ -35,6 +37,8 @@ cfg_if::cfg_if! {
3537
pub type HINSTANCE = *mut c_void;
3638
pub type FARPROC = *mut c_void;
3739
pub type LPSECURITY_ATTRIBUTES = *mut c_void;
40+
pub type PRUNTIME_FUNCTION = *mut c_void;
41+
pub type PUNWIND_HISTORY_TABLE = *mut c_void;
3842
}
3943
}
4044

@@ -374,6 +378,17 @@ ffi! {
374378
}
375379
}
376380

381+
#[cfg(target_pointer_width = "64")]
382+
ffi! {
383+
extern "system" {
384+
pub fn RtlLookupFunctionEntry(
385+
ControlPc: DWORD64,
386+
ImageBase: PDWORD64,
387+
HistoryTable: PUNWIND_HISTORY_TABLE,
388+
) -> PRUNTIME_FUNCTION;
389+
}
390+
}
391+
377392
#[cfg(target_arch = "aarch64")]
378393
ffi! {
379394
#[repr(C, align(16))]

0 commit comments

Comments
 (0)