about summary refs log tree commit diff
diff options
context:
space:
mode:
authormoxian <moxian@google.com>2018-05-13 04:38:43 +0000
committermoxian <moxian@google.com>2018-06-28 21:56:48 +0000
commit3245a475ab92b5ab77cf69e336279420c86a83eb (patch)
tree58636f02c381d690a2ad0f99e05a3935d39b3115
parentd39c66bf4ff2b49957edadf10afcc4050c3fc60b (diff)
downloadrust-3245a475ab92b5ab77cf69e336279420c86a83eb.tar.gz
rust-3245a475ab92b5ab77cf69e336279420c86a83eb.zip
Split separate stackwalk variants into their own functions
.. rather than having them be one giant match statement.
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs194
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs248
2 files changed, 238 insertions, 204 deletions
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
index 8e879e0f49e..884ec4e9fad 100644
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ b/src/libstd/sys/windows/backtrace/mod.rs
@@ -46,7 +46,7 @@ mod printing;
 #[path = "backtrace_gnu.rs"]
 pub mod gnu;
 
-pub use self::printing::{resolve_symname, foreach_symbol_fileline};
+pub use self::printing::{foreach_symbol_fileline, resolve_symname};
 
 pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
     let dbghelp = DynamicLibrary::open("dbghelp.dll")?;
@@ -54,19 +54,30 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon
     // Fetch the symbols necessary from dbghelp.dll
     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 ResStackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn);
-    let ResStackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
+    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))
+        )?;
 
     // Allocate necessary structures for doing the stack walk
     let process = unsafe { c::GetCurrentProcess() };
-    let thread = unsafe { c::GetCurrentThread() };
-    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
-    unsafe { c::RtlCaptureContext(&mut context) };
 
     let backtrace_context = BacktraceContext {
         handle: process,
         SymCleanup,
+        StackWalkVariant: variant,
         dbghelp,
     };
 
@@ -77,81 +88,102 @@ 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 (ResStackWalkEx, ResStackWalk64) {
-        (Ok(StackWalkEx), _) => {
-            let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() };
-            frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD;
-            let image = init_frame_ex(&mut frame, &context);
-
-            let mut i = 0;
-            unsafe {
-                while i < frames.len()
-                    && StackWalkEx(
-                        image,
-                        process,
-                        thread,
-                        &mut frame,
-                        &mut context,
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                        0,
-                    ) == c::TRUE
-                {
-                    let addr = (frame.AddrPC.Offset - 1) as *const u8;
-
-                    frames[i] = Frame {
-                        symbol_addr: addr,
-                        exact_position: addr,
-                        inline_context: frame.InlineFrameContext,
-                    };
-                    i += 1;
-                }
-            }
+    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),
+    }
+}
 
-            Ok((i, backtrace_context))
+fn set_frames_ex(
+    StackWalkEx: StackWalkExFn,
+    frames: &mut [Frame],
+    backtrace_context: BacktraceContext,
+    process: c::HANDLE,
+) -> io::Result<(usize, BacktraceContext)> {
+    let thread = unsafe { c::GetCurrentProcess() };
+    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
+    unsafe { c::RtlCaptureContext(&mut context) };
+
+    let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() };
+    frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD;
+    let image = init_frame_ex(&mut frame, &context);
+
+    let mut i = 0;
+    unsafe {
+        while i < frames.len()
+            && StackWalkEx(
+                image,
+                process,
+                thread,
+                &mut frame,
+                &mut context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                0,
+            ) == c::TRUE
+        {
+            let addr = (frame.AddrPC.Offset - 1) as *const u8;
+
+            frames[i] = Frame {
+                symbol_addr: addr,
+                exact_position: addr,
+                inline_context: frame.InlineFrameContext,
+            };
+            i += 1;
         }
-        (_, Ok(StackWalk64)) => {
-            let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
-            let image = init_frame_64(&mut frame, &context);
-
-            // Start from -1 to avoid printing this stack frame, which will
-            // always be exactly the same.
-            let mut i = 0;
-            unsafe {
-                while i < frames.len()
-                    && StackWalk64(
-                        image,
-                        process,
-                        thread,
-                        &mut frame,
-                        &mut context,
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                        ptr::null_mut(),
-                    ) == c::TRUE
-                {
-                    let addr = frame.AddrPC.Offset;
-                    if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0
-                    {
-                        break;
-                    }
-
-                    frames[i] = Frame {
-                        symbol_addr: (addr - 1) as *const u8,
-                        exact_position: (addr - 1) as *const u8,
-                        inline_context: 0,
-                    };
-                    i += 1;
-                }
+    }
+
+    Ok((i, backtrace_context))
+}
+
+fn set_frames_64(
+    StackWalk64: StackWalk64Fn,
+    frames: &mut [Frame],
+    backtrace_context: BacktraceContext,
+    process: c::HANDLE,
+) -> io::Result<(usize, BacktraceContext)> {
+    let thread = unsafe { c::GetCurrentProcess() };
+    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
+    unsafe { c::RtlCaptureContext(&mut context) };
+
+    let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
+    let image = init_frame_64(&mut frame, &context);
+
+    // Start from -1 to avoid printing this stack frame, which will
+    // always be exactly the same.
+    let mut i = 0;
+    unsafe {
+        while i < frames.len()
+            && StackWalk64(
+                image,
+                process,
+                thread,
+                &mut frame,
+                &mut context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+            ) == c::TRUE
+        {
+            let addr = frame.AddrPC.Offset;
+            if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0
+            {
+                break;
             }
 
-            Ok((i, backtrace_context))
+            frames[i] = Frame {
+                symbol_addr: (addr - 1) as *const u8,
+                exact_position: (addr - 1) as *const u8,
+                inline_context: 0,
+            };
+            i += 1;
         }
-        (Err(e), _) => Err(e),
     }
+
+    Ok((i, backtrace_context))
 }
 
 type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL;
@@ -226,16 +258,26 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD {
     c::IMAGE_FILE_MACHINE_AMD64
 }
 
+enum StackWalkVariant {
+    StackWalkEx,
+    StackWalk64,
+}
+
+
 pub struct BacktraceContext {
     handle: c::HANDLE,
     SymCleanup: SymCleanupFn,
     // Only used in printing for msvc and not gnu
     #[allow(dead_code)]
+    StackWalkVariant: StackWalkVariant,
+    #[allow(dead_code)]
     dbghelp: DynamicLibrary,
 }
 
 impl Drop for BacktraceContext {
     fn drop(&mut self) {
-        unsafe { (self.SymCleanup)(self.handle); }
+        unsafe {
+            (self.SymCleanup)(self.handle);
+        }
     }
 }
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
index e26d95a4f9d..9d7accb7ad7 100644
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs
@@ -13,13 +13,12 @@ use io;
 use libc::{c_char, c_ulong};
 use mem;
 use sys::backtrace::BacktraceContext;
+use sys::backtrace::StackWalkVariant;
 use sys::c;
 use sys_common::backtrace::Frame;
 
 type SymFromInlineContextFn =
     unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *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,
@@ -39,57 +38,26 @@ pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext)
 where
     F: FnOnce(Option<&str>) -> io::Result<()>,
 {
-    match (
-        sym!(
-            &context.dbghelp,
-            "SymFromInlineContext",
-            SymFromInlineContextFn
-        ),
-        sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn),
-    ) {
-        (Ok(SymFromInlineContext), _) => unsafe {
-            let mut info: c::SYMBOL_INFO = mem::zeroed();
-            info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
-            // the struct size in C.  the value is different to
-            // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
-            // due to struct alignment.
-            info.SizeOfStruct = 88;
+    match context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx => {
+            let SymFromInlineContext =
+                sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?;
+            resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context)
+        },
+        StackWalkVariant::StackWalk64 => {
+            let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?;
+            resolve_symname_from_addr(SymFromAddr, frame, callback, context)
+        }
+    }
+}
 
-            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 {
-                    if info.Size != 0 {
-                        (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
-                    } else {
-                        true
-                    }
-                } else {
-                    false
-                };
-            let symname = if valid_range {
-                let ptr = info.Name.as_ptr() as *const c_char;
-                CStr::from_ptr(ptr).to_str().ok()
-            } else {
-                None
-            };
-            callback(symname)
+fn resolve_symname_from_inline_context<F>(
+    SymFromInlineContext: SymFromInlineContextFn,
+    frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
 {
-    match (
-        sym!(
-            &context.dbghelp,
-            "SymFromInlineContext",
-            SymFromInlineContextFn
-        ),
-        sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn),
-    ) {
-        (Ok(SymFromInlineContext), _) => unsafe {
+    unsafe {
             let mut info: c::SYMBOL_INFO = mem::zeroed();
             info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
             // the struct size in C.  the value is different to
@@ -122,97 +90,121 @@ where
                 None
             };
             callback(symname)
-        },
-        (_, Ok(SymFromAddr)) => unsafe {
-            } else {
-                None
-            };
-            callback(symname)
-        },
-        (_, Ok(SymFromAddr)) => unsafe {
-            let mut info: c::SYMBOL_INFO = mem::zeroed();
-            info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
-            // the struct size in C.  the value is different to
-            // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
-            // due to struct alignment.
-            info.SizeOfStruct = 88;
+        }
+}
 
-            let mut displacement = 0u64;
-            let ret = SymFromAddr(
-                context.handle,
-                frame.symbol_addr as u64,
-                &mut displacement,
-                &mut info,
-            );
+fn resolve_symname_from_addr<F>(
+    SymFromAddr: SymFromAddrFn,
+    frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
+{
+    unsafe {
+        let mut info: c::SYMBOL_INFO = mem::zeroed();
+        info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
+        // the struct size in C.  the value is different to
+        // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
+        // due to struct alignment.
+        info.SizeOfStruct = 88;
 
-            let symname = if ret == c::TRUE {
-                let ptr = info.Name.as_ptr() as *const c_char;
-                CStr::from_ptr(ptr).to_str().ok()
-            } else {
-                None
-            };
-            callback(symname)
-        },
-        (Err(e), _) => Err(e),
+        let mut displacement = 0u64;
+        let ret = SymFromAddr(
+            context.handle,
+            frame.symbol_addr as u64,
+            &mut displacement,
+            &mut info,
+        );
+
+        let symname = if ret == c::TRUE {
+            let ptr = info.Name.as_ptr() as *const c_char;
+            CStr::from_ptr(ptr).to_str().ok()
+        } else {
+            None
+        };
+        callback(symname)
     }
 }
 
 pub fn foreach_symbol_fileline<F>(
     frame: Frame,
+    f: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+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)
+        }
+    }
+}
+
+fn foreach_symbol_fileline_ex<F>(
+    SymGetLineFromInlineContext: SymGetLineFromInlineContextFn,
+    frame: Frame,
     mut f: F,
     context: &BacktraceContext,
 ) -> io::Result<bool>
 where
     F: FnMut(&[u8], u32) -> io::Result<()>,
 {
-    match (
-        sym!(
-            &context.dbghelp,
-            "SymGetLineFromInlineContext",
-            SymGetLineFromInlineContextFn
-        ),
-        sym!(
-            &context.dbghelp,
-            "SymGetLineFromAddr64",
-            SymGetLineFromAddr64Fn
-        ),
-    ) {
-        (Ok(SymGetLineFromInlineContext), _) => unsafe {
-            let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
-            line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
+    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,
-            );
-            if ret == c::TRUE {
-                let name = CStr::from_ptr(line.Filename).to_bytes();
-                f(name, line.LineNumber as u32)?;
-            }
-            Ok(false)
-        },
-        (_, Ok(SymGetLineFromAddr64)) => 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,
+        );
+        if ret == c::TRUE {
+            let name = CStr::from_ptr(line.Filename).to_bytes();
+            f(name, line.LineNumber as u32)?;
+        }
+        Ok(false)
+    }
+}
 
-            let mut displacement = 0u32;
-            let ret = SymGetLineFromAddr64(
-                context.handle,
-                frame.exact_position as u64,
-                &mut displacement,
-                &mut line,
-            );
-            if ret == c::TRUE {
-                let name = CStr::from_ptr(line.Filename).to_bytes();
-                f(name, line.LineNumber as u32)?;
-            }
-            Ok(false)
-        },
-        (Err(e), _) => Err(e),
+fn foreach_symbol_fileline_64<F>(
+    SymGetLineFromAddr64: SymGetLineFromAddr64Fn,
+    frame: Frame,
+    mut f: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
+{
+    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 = SymGetLineFromAddr64(
+            context.handle,
+            frame.exact_position as u64,
+            &mut displacement,
+            &mut line,
+        );
+        if ret == c::TRUE {
+            let name = CStr::from_ptr(line.Filename).to_bytes();
+            f(name, line.LineNumber as u32)?;
+        }
+        Ok(false)
     }
 }