about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authormoxian <moxian@google.com>2018-05-13 08:41:24 +0000
committermoxian <moxian@google.com>2018-06-28 21:56:53 +0000
commitc0b280f5f594fc6ff34ddcf35aa26cc46a073808 (patch)
treedda3df1edd67f3c2c7f07380b0c44e3e2e091953 /src/libstd/sys/windows
parent3245a475ab92b5ab77cf69e336279420c86a83eb (diff)
downloadrust-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.rs45
-rw-r--r--src/libstd/sys/windows/backtrace/printing/mod.rs14
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs59
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),
     }
 }