about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authormoxian <moxian@google.com>2018-05-18 12:33:23 +0000
committermoxian <moxian@google.com>2018-06-28 21:57:03 +0000
commit9d426ac387f2d42c998349c76ac1c2aea044e0ec (patch)
tree94d2ff88d4b89aca811d2020a4bd9af933d94d37 /src/libstd/sys
parenta0b15012a17594566311ea490eda243b6bd9d92b (diff)
downloadrust-9d426ac387f2d42c998349c76ac1c2aea044e0ec.tar.gz
rust-9d426ac387f2d42c998349c76ac1c2aea044e0ec.zip
Make msvc symbol extraction/printing functions generic.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs240
1 files changed, 137 insertions, 103 deletions
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
index 9cfc2c3d352..d8f0a4d8208 100644
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs
@@ -18,7 +18,6 @@ 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)
@@ -32,23 +31,29 @@ pub struct PrintingFns64 {
 }
 
 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)?,
+    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{
+    Ok(PrintingFns64 {
         resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
-        sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64",
-                     SymGetLineFromAddr64Fn)?,
+        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 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,
@@ -58,11 +63,6 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
     *mut c::IMAGEHLP_LINE64,
 ) -> c::BOOL;
 
-type SymFromAddrFn =
-    unsafe extern "system" fn(c::HANDLE, u64, *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;
-
 /// Converts a pointer to symbol to its string value.
 pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
 where
@@ -70,61 +70,23 @@ where
 {
     match context.StackWalkVariant {
         StackWalkVariant::StackWalkEx(_, ref fns) => {
-            resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context)
-        },
+            resolve_symname_internal(fns.resolve_symname, frame, callback, context)
+        }
         StackWalkVariant::StackWalk64(_, ref fns) => {
-            resolve_symname_from_addr(fns.resolve_symname, frame, callback, context)
+            resolve_symname_internal(fns.resolve_symname, frame, callback, context)
         }
     }
 }
 
-fn resolve_symname_from_inline_context<F>(
-    SymFromInlineContext: SymFromInlineContextFn,
-    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 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_addr<F>(
-    SymFromAddr: SymFromAddrFn,
-    frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+fn resolve_symname_internal<F, R>(
+    symbol_resolver: R,
+    frame: Frame,
+    callback: F,
+    context: &BacktraceContext,
+) -> io::Result<()>
 where
     F: FnOnce(Option<&str>) -> io::Result<()>,
+    R: SymbolResolver,
 {
     unsafe {
         let mut info: c::SYMBOL_INFO = mem::zeroed();
@@ -134,15 +96,22 @@ where
         // due to struct alignment.
         info.SizeOfStruct = 88;
 
-        let mut displacement = 0u64;
-        let ret = SymFromAddr(
+        let ret = symbol_resolver.resolve_symbol(
             context.handle,
             frame.symbol_addr as u64,
-            &mut displacement,
+            frame.inline_context,
             &mut info,
         );
-
-        let symname = if ret == c::TRUE {
+        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 {
@@ -152,76 +121,141 @@ where
     }
 }
 
+trait SymbolResolver {
+    fn resolve_symbol(
+        &self,
+        process: c::HANDLE,
+        symbol_address: u64,
+        inline_context: c::ULONG,
+        info: *mut c::SYMBOL_INFO,
+    ) -> c::BOOL;
+}
+
+impl SymbolResolver for SymFromAddrFn {
+    fn resolve_symbol(
+        &self,
+        process: c::HANDLE,
+        symbol_address: u64,
+        _inline_context: c::ULONG,
+        info: *mut c::SYMBOL_INFO,
+    ) -> c::BOOL {
+        unsafe {
+            let mut displacement = 0u64;
+            self(process, symbol_address, &mut displacement, info)
+        }
+    }
+}
+
+impl SymbolResolver for SymFromInlineContextFn {
+    fn resolve_symbol(
+        &self,
+        process: c::HANDLE,
+        symbol_address: u64,
+        inline_context: c::ULONG,
+        info: *mut c::SYMBOL_INFO,
+    ) -> c::BOOL {
+        unsafe {
+            let mut displacement = 0u64;
+            self(
+                process,
+                symbol_address,
+                inline_context,
+                &mut displacement,
+                info,
+            )
+        }
+    }
+}
+
 pub fn foreach_symbol_fileline<F>(
     frame: Frame,
-    f: F,
+    callback: F,
     context: &BacktraceContext,
 ) -> io::Result<bool>
 where
     F: FnMut(&[u8], u32) -> io::Result<()>,
 {
     match context.StackWalkVariant {
-        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),
+        StackWalkVariant::StackWalkEx(_, ref fns) => {
+            foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context)
+        }
+        StackWalkVariant::StackWalk64(_, ref fns) => {
+            foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context)
+        }
     }
 }
 
-fn foreach_symbol_fileline_ex<F>(
-    SymGetLineFromInlineContext: SymGetLineFromInlineContextFn,
+fn foreach_symbol_fileline_iternal<F, G>(
+    line_getter: G,
     frame: Frame,
-    mut f: F,
+    mut callback: F,
     context: &BacktraceContext,
 ) -> io::Result<bool>
 where
     F: FnMut(&[u8], u32) -> io::Result<()>,
+    G: LineGetter,
 {
     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(
+        let ret = line_getter.get_line(
             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)?;
+            callback(name, line.LineNumber as u32)?;
         }
         Ok(false)
     }
 }
 
-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;
+trait LineGetter {
+    fn get_line(
+        &self,
+        process: c::HANDLE,
+        frame_address: u64,
+        inline_context: c::ULONG,
+        line: *mut c::IMAGEHLP_LINE64,
+    ) -> c::BOOL;
+}
 
-        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)?;
+impl LineGetter for SymGetLineFromAddr64Fn {
+    fn get_line(
+        &self,
+        process: c::HANDLE,
+        frame_address: u64,
+        _inline_context: c::ULONG,
+        line: *mut c::IMAGEHLP_LINE64,
+    ) -> c::BOOL {
+        unsafe {
+            let mut displacement = 0u32;
+            self(process, frame_address, &mut displacement, line)
+        }
+    }
+}
+
+impl LineGetter for SymGetLineFromInlineContextFn {
+    fn get_line(
+        &self,
+        process: c::HANDLE,
+        frame_address: u64,
+        inline_context: c::ULONG,
+        line: *mut c::IMAGEHLP_LINE64,
+    ) -> c::BOOL {
+        unsafe {
+            let mut displacement = 0u32;
+            self(
+                process,
+                frame_address,
+                inline_context,
+                0,
+                &mut displacement,
+                line,
+            )
         }
-        Ok(false)
     }
 }