27
27
use io:: prelude:: * ;
28
28
29
29
use dynamic_lib:: DynamicLibrary ;
30
- use ffi:: CStr ;
31
30
use intrinsics;
32
31
use io;
33
32
use libc;
34
- use mem;
35
33
use path:: Path ;
36
34
use ptr;
37
- use str;
38
35
use sync:: StaticMutex ;
39
36
40
- use sys_common:: backtrace:: * ;
37
+ macro_rules! sym{ ( $lib: expr, $e: expr, $t: ident) => ( unsafe {
38
+ let lib = $lib;
39
+ match lib. symbol( $e) {
40
+ Ok ( f) => $crate:: mem:: transmute:: <* mut u8 , $t>( f) ,
41
+ Err ( ..) => return Ok ( ( ) )
42
+ }
43
+ } ) }
44
+
45
+ #[ cfg( target_env = "msvc" ) ]
46
+ #[ path = "printing/msvc.rs" ]
47
+ mod printing;
48
+
49
+ #[ cfg( target_env = "gnu" ) ]
50
+ #[ path = "printing/gnu.rs" ]
51
+ mod printing;
41
52
42
53
#[ allow( non_snake_case) ]
43
54
extern "system" {
@@ -302,23 +313,15 @@ pub fn write(w: &mut Write) -> io::Result<()> {
302
313
// Open up dbghelp.dll, we don't link to it explicitly because it can't
303
314
// always be found. Additionally, it's nice having fewer dependencies.
304
315
let path = Path :: new ( "dbghelp.dll" ) ;
305
- let lib = match DynamicLibrary :: open ( Some ( & path) ) {
316
+ let dbghelp = match DynamicLibrary :: open ( Some ( & path) ) {
306
317
Ok ( lib) => lib,
307
318
Err ( ..) => return Ok ( ( ) ) ,
308
319
} ;
309
320
310
- macro_rules! sym{ ( $e: expr, $t: ident) => ( unsafe {
311
- match lib. symbol( $e) {
312
- Ok ( f) => mem:: transmute:: <* mut u8 , $t>( f) ,
313
- Err ( ..) => return Ok ( ( ) )
314
- }
315
- } ) }
316
-
317
321
// Fetch the symbols necessary from dbghelp.dll
318
- let SymFromAddr = sym ! ( "SymFromAddr" , SymFromAddrFn ) ;
319
- let SymInitialize = sym ! ( "SymInitialize" , SymInitializeFn ) ;
320
- let SymCleanup = sym ! ( "SymCleanup" , SymCleanupFn ) ;
321
- let StackWalk64 = sym ! ( "StackWalk64" , StackWalk64Fn ) ;
322
+ let SymInitialize = sym ! ( & dbghelp, "SymInitialize" , SymInitializeFn ) ;
323
+ let SymCleanup = sym ! ( & dbghelp, "SymCleanup" , SymCleanupFn ) ;
324
+ let StackWalk64 = sym ! ( & dbghelp, "StackWalk64" , StackWalk64Fn ) ;
322
325
323
326
// Allocate necessary structures for doing the stack walk
324
327
let process = unsafe { GetCurrentProcess ( ) } ;
@@ -334,7 +337,9 @@ pub fn write(w: &mut Write) -> io::Result<()> {
334
337
let _c = Cleanup { handle : process, SymCleanup : SymCleanup } ;
335
338
336
339
// And now that we're done with all the setup, do the stack walking!
337
- let mut i = 0 ;
340
+ // Start from -1 to avoid printing this stack frame, which will
341
+ // always be exactly the same.
342
+ let mut i = -1 ;
338
343
try!( write ! ( w, "stack backtrace:\n " ) ) ;
339
344
while StackWalk64 ( image, process, thread, & mut frame, & mut context,
340
345
ptr:: null_mut ( ) ,
@@ -346,28 +351,10 @@ pub fn write(w: &mut Write) -> io::Result<()> {
346
351
frame. AddrReturn . Offset == 0 { break }
347
352
348
353
i += 1 ;
349
- try!( write ! ( w, " {:2}: {:#2$x}" , i, addr, HEX_WIDTH ) ) ;
350
- let mut info: SYMBOL_INFO = unsafe { intrinsics:: init ( ) } ;
351
- info. MaxNameLen = MAX_SYM_NAME as libc:: c_ulong ;
352
- // the struct size in C. the value is different to
353
- // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
354
- // due to struct alignment.
355
- info. SizeOfStruct = 88 ;
356
-
357
- let mut displacement = 0u64 ;
358
- let ret = SymFromAddr ( process, addr as u64 , & mut displacement,
359
- & mut info) ;
360
-
361
- if ret == libc:: TRUE {
362
- try!( write ! ( w, " - " ) ) ;
363
- let ptr = info. Name . as_ptr ( ) as * const libc:: c_char ;
364
- let bytes = unsafe { CStr :: from_ptr ( ptr) . to_bytes ( ) } ;
365
- match str:: from_utf8 ( bytes) {
366
- Ok ( s) => try!( demangle ( w, s) ) ,
367
- Err ( ..) => try!( w. write_all ( & bytes[ ..bytes. len ( ) -1 ] ) ) ,
368
- }
354
+
355
+ if i >= 0 {
356
+ try!( printing:: print ( w, i, addr-1 , & dbghelp, process) ) ;
369
357
}
370
- try!( w. write_all ( & [ '\n' as u8 ] ) ) ;
371
358
}
372
359
373
360
Ok ( ( ) )
0 commit comments