aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/windows/backtrace/printing/msvc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ctr-std/src/sys/windows/backtrace/printing/msvc.rs')
-rw-r--r--ctr-std/src/sys/windows/backtrace/printing/msvc.rs196
1 files changed, 158 insertions, 38 deletions
diff --git a/ctr-std/src/sys/windows/backtrace/printing/msvc.rs b/ctr-std/src/sys/windows/backtrace/printing/msvc.rs
index 967df1c..c8b946b 100644
--- a/ctr-std/src/sys/windows/backtrace/printing/msvc.rs
+++ b/ctr-std/src/sys/windows/backtrace/printing/msvc.rs
@@ -10,29 +10,108 @@
use ffi::CStr;
use io;
-use libc::{c_ulong, c_char};
+use libc::{c_char, c_ulong};
use mem;
-use sys::c;
use sys::backtrace::BacktraceContext;
+use sys::backtrace::StackWalkVariant;
+use sys::c;
+use sys::dynamic_lib::DynamicLibrary;
use sys_common::backtrace::Frame;
+// Structs holding printing functions and loaders for them
+// Two versions depending on whether dbghelp.dll has StackWalkEx or not
+// (the former being in newer Windows versions, the older being in Win7 and before)
+pub struct PrintingFnsEx {
+ resolve_symname: SymFromInlineContextFn,
+ sym_get_line: SymGetLineFromInlineContextFn,
+}
+pub struct PrintingFns64 {
+ resolve_symname: SymFromAddrFn,
+ sym_get_line: SymGetLineFromAddr64Fn,
+}
+
+pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
+ Ok(PrintingFnsEx {
+ resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
+ sym_get_line: sym!(
+ dbghelp,
+ "SymGetLineFromInlineContext",
+ SymGetLineFromInlineContextFn
+ )?,
+ })
+}
+pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
+ Ok(PrintingFns64 {
+ resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
+ sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
+ })
+}
+
+type SymFromAddrFn =
+ unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
type SymFromInlineContextFn =
- unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
- *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
-type SymGetLineFromInlineContextFn =
- unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
- u64, *mut c::DWORD, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+ unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
+
+type SymGetLineFromAddr64Fn =
+ unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
+ c::HANDLE,
+ u64,
+ c::ULONG,
+ u64,
+ *mut c::DWORD,
+ *mut c::IMAGEHLP_LINE64,
+) -> c::BOOL;
/// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame,
- callback: F,
- context: &BacktraceContext) -> io::Result<()>
- where F: FnOnce(Option<&str>) -> io::Result<()>
+pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+where
+ F: FnOnce(Option<&str>) -> io::Result<()>,
{
- let SymFromInlineContext = sym!(&context.dbghelp,
- "SymFromInlineContext",
- SymFromInlineContextFn)?;
+ match context.StackWalkVariant {
+ StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
+ |process: c::HANDLE,
+ symbol_address: u64,
+ inline_context: c::ULONG,
+ info: *mut c::SYMBOL_INFO| unsafe {
+ let mut displacement = 0u64;
+ (fns.resolve_symname)(
+ process,
+ symbol_address,
+ inline_context,
+ &mut displacement,
+ info,
+ )
+ },
+ frame,
+ callback,
+ context,
+ ),
+ StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
+ |process: c::HANDLE,
+ symbol_address: u64,
+ _inline_context: c::ULONG,
+ info: *mut c::SYMBOL_INFO| unsafe {
+ let mut displacement = 0u64;
+ (fns.resolve_symname)(process, symbol_address, &mut displacement, info)
+ },
+ frame,
+ callback,
+ context,
+ ),
+ }
+}
+fn resolve_symname_internal<F, R>(
+ mut symbol_resolver: R,
+ frame: Frame,
+ callback: F,
+ context: &BacktraceContext,
+) -> io::Result<()>
+where
+ F: FnOnce(Option<&str>) -> io::Result<()>,
+ R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
+{
unsafe {
let mut info: c::SYMBOL_INFO = mem::zeroed();
info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
@@ -41,14 +120,13 @@ pub fn resolve_symname<F>(frame: Frame,
// due to struct alignment.
info.SizeOfStruct = 88;
- let mut displacement = 0u64;
- let ret = SymFromInlineContext(context.handle,
- frame.symbol_addr as u64,
- frame.inline_context,
- &mut displacement,
- &mut info);
- let valid_range = if ret == c::TRUE &&
- frame.symbol_addr as usize >= info.Address as usize {
+ let ret = symbol_resolver(
+ context.handle,
+ frame.symbol_addr as u64,
+ frame.inline_context,
+ &mut info,
+ );
+ let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
if info.Size != 0 {
(frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
} else {
@@ -67,30 +145,72 @@ pub fn resolve_symname<F>(frame: Frame,
}
}
-pub fn foreach_symbol_fileline<F>(frame: Frame,
- mut f: F,
- context: &BacktraceContext)
- -> io::Result<bool>
- where F: FnMut(&[u8], u32) -> io::Result<()>
+pub fn foreach_symbol_fileline<F>(
+ frame: Frame,
+ callback: F,
+ context: &BacktraceContext,
+) -> io::Result<bool>
+where
+ F: FnMut(&[u8], u32) -> io::Result<()>,
{
- let SymGetLineFromInlineContext = sym!(&context.dbghelp,
- "SymGetLineFromInlineContext",
- SymGetLineFromInlineContextFn)?;
+ match context.StackWalkVariant {
+ StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
+ |process: c::HANDLE,
+ frame_address: u64,
+ inline_context: c::ULONG,
+ line: *mut c::IMAGEHLP_LINE64| unsafe {
+ let mut displacement = 0u32;
+ (fns.sym_get_line)(
+ process,
+ frame_address,
+ inline_context,
+ 0,
+ &mut displacement,
+ line,
+ )
+ },
+ frame,
+ callback,
+ context,
+ ),
+ StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
+ |process: c::HANDLE,
+ frame_address: u64,
+ _inline_context: c::ULONG,
+ line: *mut c::IMAGEHLP_LINE64| unsafe {
+ let mut displacement = 0u32;
+ (fns.sym_get_line)(process, frame_address, &mut displacement, line)
+ },
+ frame,
+ callback,
+ context,
+ ),
+ }
+}
+fn foreach_symbol_fileline_iternal<F, G>(
+ mut line_getter: G,
+ frame: Frame,
+ mut callback: F,
+ context: &BacktraceContext,
+) -> io::Result<bool>
+where
+ F: FnMut(&[u8], u32) -> io::Result<()>,
+ G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
+{
unsafe {
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
- let mut displacement = 0u32;
- let ret = SymGetLineFromInlineContext(context.handle,
- frame.exact_position as u64,
- frame.inline_context,
- 0,
- &mut displacement,
- &mut line);
+ let ret = line_getter(
+ context.handle,
+ frame.exact_position as u64,
+ frame.inline_context,
+ &mut line,
+ );
if ret == c::TRUE {
let name = CStr::from_ptr(line.Filename).to_bytes();
- f(name, line.LineNumber as u32)?;
+ callback(name, line.LineNumber as u32)?;
}
Ok(false)
}