Skip to content

Commit 7a1d357

Browse files
authored
Attempt to load jit frames (#274)
1 parent 7f0f4b2 commit 7a1d357

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ cfg_if::cfg_if! {
1515
pub use self::winapi::HINSTANCE;
1616
pub use self::winapi::FARPROC;
1717
pub use self::winapi::LPSECURITY_ATTRIBUTES;
18+
#[cfg(target_pointer_width = "64")]
19+
pub use self::winapi::PUNWIND_HISTORY_TABLE;
20+
#[cfg(target_pointer_width = "64")]
21+
pub use self::winapi::PRUNTIME_FUNCTION;
1822

1923
mod winapi {
2024
pub use winapi::ctypes::*;
@@ -35,6 +39,10 @@ cfg_if::cfg_if! {
3539
pub type HINSTANCE = *mut c_void;
3640
pub type FARPROC = *mut c_void;
3741
pub type LPSECURITY_ATTRIBUTES = *mut c_void;
42+
#[cfg(target_pointer_width = "64")]
43+
pub type PRUNTIME_FUNCTION = *mut c_void;
44+
#[cfg(target_pointer_width = "64")]
45+
pub type PUNWIND_HISTORY_TABLE = *mut c_void;
3846
}
3947
}
4048

@@ -374,6 +382,17 @@ ffi! {
374382
}
375383
}
376384

385+
#[cfg(target_pointer_width = "64")]
386+
ffi! {
387+
extern "system" {
388+
pub fn RtlLookupFunctionEntry(
389+
ControlPc: DWORD64,
390+
ImageBase: PDWORD64,
391+
HistoryTable: PUNWIND_HISTORY_TABLE,
392+
) -> PRUNTIME_FUNCTION;
393+
}
394+
}
395+
377396
#[cfg(target_arch = "aarch64")]
378397
ffi! {
379398
#[repr(C, align(16))]

0 commit comments

Comments
 (0)