diff options
| author | moxian <moxian@google.com> | 2018-05-13 08:41:24 +0000 |
|---|---|---|
| committer | moxian <moxian@google.com> | 2018-06-28 21:56:53 +0000 |
| commit | c0b280f5f594fc6ff34ddcf35aa26cc46a073808 (patch) | |
| tree | dda3df1edd67f3c2c7f07380b0c44e3e2e091953 /src/libstd/sys/windows | |
| parent | 3245a475ab92b5ab77cf69e336279420c86a83eb (diff) | |
| download | rust-c0b280f5f594fc6ff34ddcf35aa26cc46a073808.tar.gz rust-c0b280f5f594fc6ff34ddcf35aa26cc46a073808.zip | |
Load backtrace-related functions only once
.. and pass them around in BacktraceContext.
Diffstat (limited to 'src/libstd/sys/windows')
| -rw-r--r-- | src/libstd/sys/windows/backtrace/mod.rs | 45 | ||||
| -rw-r--r-- | src/libstd/sys/windows/backtrace/printing/mod.rs | 14 | ||||
| -rw-r--r-- | src/libstd/sys/windows/backtrace/printing/msvc.rs | 59 |
3 files changed, 77 insertions, 41 deletions
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 884ec4e9fad..23bb4ab6dfe 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -47,6 +47,7 @@ mod printing; pub mod gnu; pub use self::printing::{foreach_symbol_fileline, resolve_symname}; +use self::printing::{load_printing_fns_ex, load_printing_fns_64}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -55,21 +56,23 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - // enum for holding the StackWalk function. Different from StackWalkVariant - // below, since there's no need to pass the function itself into - // the BacktraceContext - enum sw_fn_local { - SWExFn(StackWalkExFn), - SW64Fn(StackWalk64Fn), - } + // StackWalkEx might not be present and we'll fall back to StackWalk64 - let (StackWalkFn, variant) = - sym!(dbghelp, "StackWalkEx", StackWalkExFn) - .map(|f| (sw_fn_local::SWExFn(f), StackWalkVariant::StackWalkEx)) - .or_else(|_| - sym!(dbghelp, "StackWalk64", StackWalk64Fn) - .map(|f| (sw_fn_local::SW64Fn(f), StackWalkVariant::StackWalk64)) - )?; + let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) { + Ok(StackWalkEx) => + StackWalkVariant::StackWalkEx( + StackWalkEx, + load_printing_fns_ex(&dbghelp)?, + ), + Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) { + Ok(StackWalk64) => + StackWalkVariant::StackWalk64( + StackWalk64, + load_printing_fns_64(&dbghelp)?, + ), + Err(..) => return Err(e), + }, + }; // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; @@ -77,7 +80,7 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let backtrace_context = BacktraceContext { handle: process, SymCleanup, - StackWalkVariant: variant, + StackWalkVariant: sw_var, dbghelp, }; @@ -88,9 +91,9 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon } // And now that we're done with all the setup, do the stack walking! - match StackWalkFn { - sw_fn_local::SWExFn(f) => set_frames_ex(f, frames, backtrace_context, process), - sw_fn_local::SW64Fn(f) => set_frames_64(f, frames, backtrace_context, process), + match backtrace_context.StackWalkVariant { + StackWalkVariant::StackWalkEx(f, _) => set_frames_ex(f, frames, backtrace_context, process), + StackWalkVariant::StackWalk64(f, _) => set_frames_64(f, frames, backtrace_context, process), } } @@ -259,8 +262,8 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { } enum StackWalkVariant { - StackWalkEx, - StackWalk64, + StackWalkEx(StackWalkExFn, printing::PrintingFnsEx), + StackWalk64(StackWalk64Fn, printing::PrintingFns64), } @@ -268,8 +271,10 @@ pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, // Only used in printing for msvc and not gnu + // The gnu version is effectively a ZST dummy. #[allow(dead_code)] StackWalkVariant: StackWalkVariant, + // keeping DynamycLibrary loaded until its functions no longer needed #[allow(dead_code)] dbghelp: DynamicLibrary, } diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs index 3e566f6e2bd..251d5028aea 100644 --- a/src/libstd/sys/windows/backtrace/printing/mod.rs +++ b/src/libstd/sys/windows/backtrace/printing/mod.rs @@ -15,6 +15,20 @@ mod printing; #[cfg(target_env = "gnu")] mod printing { pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; + + // dummy functions to mirror those present in msvc version. + use sys::dynamic_lib::DynamicLibrary; + use io; + pub struct PrintingFnsEx {} + pub struct PrintingFns64 {} + pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> { + Ok(PrintingFnsEx{}) + } + pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result<PrintingFns64> { + Ok(PrintingFns64{}) + } } pub use self::printing::{foreach_symbol_fileline, resolve_symname}; +pub use self::printing::{load_printing_fns_ex, load_printing_fns_64, + PrintingFnsEx, PrintingFns64}; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 9d7accb7ad7..9cfc2c3d352 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -15,8 +15,38 @@ use mem; 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 SymFromInlineContextFn = unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; type SymGetLineFromInlineContextFn = unsafe extern "system" fn( @@ -39,14 +69,11 @@ where F: FnOnce(Option<&str>) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymFromInlineContext = - sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?; - resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context) + StackWalkVariant::StackWalkEx(_, ref fns) => { + resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context) }, - StackWalkVariant::StackWalk64 => { - let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; - resolve_symname_from_addr(SymFromAddr, frame, callback, context) + StackWalkVariant::StackWalk64(_, ref fns) => { + resolve_symname_from_addr(fns.resolve_symname, frame, callback, context) } } } @@ -134,20 +161,10 @@ where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymGetLineFromInlineContext = - sym!(&context.dbghelp, "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?; - foreach_symbol_fileline_ex(SymGetLineFromInlineContext, - frame, f, context) - }, - StackWalkVariant::StackWalk64 => { - let SymGetLineFromAddr64 = - sym!(&context.dbghelp, "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?; - foreach_symbol_fileline_64(SymGetLineFromAddr64, - frame, f, context) - } + StackWalkVariant::StackWalkEx(_, ref fns) => + foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context), + StackWalkVariant::StackWalk64(_, ref fns) => + foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context), } } |
