diff options
| author | moxian <moxian@google.com> | 2018-05-18 12:33:23 +0000 |
|---|---|---|
| committer | moxian <moxian@google.com> | 2018-06-28 21:57:03 +0000 |
| commit | 9d426ac387f2d42c998349c76ac1c2aea044e0ec (patch) | |
| tree | 94d2ff88d4b89aca811d2020a4bd9af933d94d37 /src/libstd/sys | |
| parent | a0b15012a17594566311ea490eda243b6bd9d92b (diff) | |
| download | rust-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.rs | 240 |
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) } } |
