Skip to content

Commit b891125

Browse files
committed
Fix panic in backtrace symbolication on win7
Since #569 was merged, symbolication of backtraces would panic on Windows 7, due to using symbols that do not exist in the version of dbghelp.dll that ships there (Windows 7 ships with dbghelp.dll version 6.1, but the symbols were only added in version 6.2). This commit checks for the presence of the newer symbols, and if they are not found, falls back to the old resolution method.
1 parent aa0a5e2 commit b891125

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

src/dbghelp.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ use core::ptr;
3434
mod dbghelp {
3535
use crate::windows::*;
3636
pub use winapi::um::dbghelp::{
37-
StackWalk64, StackWalkEx, SymFunctionTableAccess64, SymGetModuleBase64, SymGetOptions,
38-
SymInitializeW, SymSetOptions,
37+
StackWalk64, StackWalkEx, SymFromAddrW, SymFunctionTableAccess64, SymGetLineFromAddrW64,
38+
SymGetModuleBase64, SymGetOptions, SymInitializeW, SymSetOptions,
3939
};
4040

4141
extern "system" {
@@ -233,6 +233,18 @@ dbghelp! {
233233
CurContext: LPDWORD,
234234
CurFrameIndex: LPDWORD
235235
) -> BOOL;
236+
fn SymFromAddrW(
237+
hProcess: HANDLE,
238+
Address: DWORD64,
239+
Displacement: PDWORD64,
240+
Symbol: PSYMBOL_INFOW
241+
) -> BOOL;
242+
fn SymGetLineFromAddrW64(
243+
hProcess: HANDLE,
244+
dwAddr: DWORD64,
245+
pdwDisplacement: PDWORD,
246+
Line: PIMAGEHLP_LINEW64
247+
) -> BOOL;
236248
}
237249
}
238250

src/symbolize/dbghelp.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,45 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
7878
Err(()) => return, // oh well...
7979
};
8080

81+
let resolve_inner = if (*dbghelp.dbghelp()).SymAddrIncludeInlineTrace().is_some() {
82+
// We are on a version of dbghelp 6.2+, which contains the more modern
83+
// Inline APIs.
84+
resolve_with_inline
85+
} else {
86+
// We are on an older version of dbghelp which doesn't contain the Inline
87+
// APIs.
88+
resolve_legacy
89+
};
8190
match what {
82-
ResolveWhat::Address(_) => resolve_with_inline(&dbghelp, what.address_or_ip(), None, cb),
91+
ResolveWhat::Address(_) => resolve_inner(&dbghelp, what.address_or_ip(), None, cb),
8392
ResolveWhat::Frame(frame) => {
84-
resolve_with_inline(&dbghelp, frame.ip(), frame.inner.inline_context(), cb)
93+
resolve_inner(&dbghelp, frame.ip(), frame.inner.inline_context(), cb)
8594
}
8695
}
8796
}
8897

98+
/// Resolve the address using the legacy dbghelp API.
99+
///
100+
/// This should work all the way down to Windows XP. The inline context is
101+
/// ignored, since this concept was only introduced in dbghelp 6.2+.
102+
unsafe fn resolve_legacy(
103+
dbghelp: &dbghelp::Init,
104+
addr: *mut c_void,
105+
_inline_context: Option<DWORD>,
106+
cb: &mut dyn FnMut(&super::Symbol),
107+
) {
108+
let addr = super::adjust_ip(addr) as DWORD64;
109+
do_resolve(
110+
|info| dbghelp.SymFromAddrW()(GetCurrentProcess(), addr, &mut 0, info),
111+
|line| dbghelp.SymGetLineFromAddrW64()(GetCurrentProcess(), addr, &mut 0, line),
112+
cb,
113+
)
114+
}
115+
116+
/// Resolve the address using the modern dbghelp APIs.
117+
///
118+
/// Note that calling this function requires having dbghelp 6.2+ loaded - and
119+
/// will panic otherwise.
89120
unsafe fn resolve_with_inline(
90121
dbghelp: &dbghelp::Init,
91122
addr: *mut c_void,

0 commit comments

Comments
 (0)