@@ -48,24 +48,21 @@ pub mod gnu;
4848
4949pub use self :: printing:: { resolve_symname, foreach_symbol_fileline} ;
5050
51- pub fn unwind_backtrace ( frames : & mut [ Frame ] )
52- -> io:: Result < ( usize , BacktraceContext ) >
53- {
51+ pub fn unwind_backtrace ( frames : & mut [ Frame ] ) -> io:: Result < ( usize , BacktraceContext ) > {
5452 let dbghelp = DynamicLibrary :: open ( "dbghelp.dll" ) ?;
5553
5654 // Fetch the symbols necessary from dbghelp.dll
5755 let SymInitialize = sym ! ( dbghelp, "SymInitialize" , SymInitializeFn ) ?;
5856 let SymCleanup = sym ! ( dbghelp, "SymCleanup" , SymCleanupFn ) ?;
59- let StackWalkEx = sym ! ( dbghelp, "StackWalkEx" , StackWalkExFn ) ?;
57+ // StackWalkEx might not be present and we'll fall back to StackWalk64
58+ let ResStackWalkEx = sym ! ( dbghelp, "StackWalkEx" , StackWalkExFn ) ;
59+ let ResStackWalk64 = sym ! ( dbghelp, "StackWalk64" , StackWalk64Fn ) ;
6060
6161 // Allocate necessary structures for doing the stack walk
6262 let process = unsafe { c:: GetCurrentProcess ( ) } ;
6363 let thread = unsafe { c:: GetCurrentThread ( ) } ;
6464 let mut context: c:: CONTEXT = unsafe { mem:: zeroed ( ) } ;
6565 unsafe { c:: RtlCaptureContext ( & mut context) } ;
66- let mut frame: c:: STACKFRAME_EX = unsafe { mem:: zeroed ( ) } ;
67- frame. StackFrameSize = mem:: size_of_val ( & frame) as c:: DWORD ;
68- let image = init_frame ( & mut frame, & context) ;
6966
7067 let backtrace_context = BacktraceContext {
7168 handle : process,
@@ -76,49 +73,139 @@ pub fn unwind_backtrace(frames: &mut [Frame])
7673 // Initialize this process's symbols
7774 let ret = unsafe { SymInitialize ( process, ptr:: null_mut ( ) , c:: TRUE ) } ;
7875 if ret != c:: TRUE {
79- return Ok ( ( 0 , backtrace_context) )
76+ return Ok ( ( 0 , backtrace_context) ) ;
8077 }
8178
8279 // And now that we're done with all the setup, do the stack walking!
83- let mut i = 0 ;
84- unsafe {
85- while i < frames. len ( ) &&
86- StackWalkEx ( image, process, thread, & mut frame, & mut context,
87- ptr:: null_mut ( ) ,
88- ptr:: null_mut ( ) ,
89- ptr:: null_mut ( ) ,
90- ptr:: null_mut ( ) ,
91- 0 ) == c:: TRUE
92- {
93- let addr = ( frame. AddrPC . Offset - 1 ) as * const u8 ;
94-
95- frames[ i] = Frame {
96- symbol_addr : addr,
97- exact_position : addr,
98- inline_context : frame. InlineFrameContext ,
99- } ;
100- i += 1 ;
80+ match ( ResStackWalkEx , ResStackWalk64 ) {
81+ ( Ok ( StackWalkEx ) , _) => {
82+ let mut frame: c:: STACKFRAME_EX = unsafe { mem:: zeroed ( ) } ;
83+ frame. StackFrameSize = mem:: size_of_val ( & frame) as c:: DWORD ;
84+ let image = init_frame_ex ( & mut frame, & context) ;
85+
86+ let mut i = 0 ;
87+ unsafe {
88+ while i < frames. len ( )
89+ && StackWalkEx (
90+ image,
91+ process,
92+ thread,
93+ & mut frame,
94+ & mut context,
95+ ptr:: null_mut ( ) ,
96+ ptr:: null_mut ( ) ,
97+ ptr:: null_mut ( ) ,
98+ ptr:: null_mut ( ) ,
99+ 0 ,
100+ ) == c:: TRUE
101+ {
102+ let addr = ( frame. AddrPC . Offset - 1 ) as * const u8 ;
103+
104+ frames[ i] = Frame {
105+ symbol_addr : addr,
106+ exact_position : addr,
107+ inline_context : frame. InlineFrameContext ,
108+ } ;
109+ i += 1 ;
110+ }
111+ }
112+
113+ Ok ( ( i, backtrace_context) )
101114 }
115+ ( _, Ok ( StackWalk64 ) ) => {
116+ let mut frame: c:: STACKFRAME64 = unsafe { mem:: zeroed ( ) } ;
117+ let image = init_frame_64 ( & mut frame, & context) ;
118+
119+ // Start from -1 to avoid printing this stack frame, which will
120+ // always be exactly the same.
121+ let mut i = 0 ;
122+ unsafe {
123+ while i < frames. len ( )
124+ && StackWalk64 (
125+ image,
126+ process,
127+ thread,
128+ & mut frame,
129+ & mut context,
130+ ptr:: null_mut ( ) ,
131+ ptr:: null_mut ( ) ,
132+ ptr:: null_mut ( ) ,
133+ ptr:: null_mut ( ) ,
134+ ) == c:: TRUE
135+ {
136+ let addr = frame. AddrPC . Offset ;
137+ if addr == frame. AddrReturn . Offset || addr == 0 || frame. AddrReturn . Offset == 0
138+ {
139+ break ;
140+ }
141+
142+ frames[ i] = Frame {
143+ symbol_addr : ( addr - 1 ) as * const u8 ,
144+ exact_position : ( addr - 1 ) as * const u8 ,
145+ inline_context : 0 ,
146+ } ;
147+ i += 1 ;
148+ }
149+ }
150+
151+ Ok ( ( i, backtrace_context) )
152+ }
153+ ( Err ( e) , _) => Err ( e) ,
102154 }
103-
104- Ok ( ( i, backtrace_context) )
105155}
106156
107- type SymInitializeFn =
108- unsafe extern "system" fn ( c:: HANDLE , * mut c_void ,
109- c:: BOOL ) -> c:: BOOL ;
110- type SymCleanupFn =
111- unsafe extern "system" fn ( c:: HANDLE ) -> c:: BOOL ;
157+ type SymInitializeFn = unsafe extern "system" fn ( c:: HANDLE , * mut c_void , c:: BOOL ) -> c:: BOOL ;
158+ type SymCleanupFn = unsafe extern "system" fn ( c:: HANDLE ) -> c:: BOOL ;
159+
160+ type StackWalkExFn = unsafe extern "system" fn (
161+ c:: DWORD ,
162+ c:: HANDLE ,
163+ c:: HANDLE ,
164+ * mut c:: STACKFRAME_EX ,
165+ * mut c:: CONTEXT ,
166+ * mut c_void ,
167+ * mut c_void ,
168+ * mut c_void ,
169+ * mut c_void ,
170+ c:: DWORD ,
171+ ) -> c:: BOOL ;
172+
173+ type StackWalk64Fn = unsafe extern "system" fn (
174+ c:: DWORD ,
175+ c:: HANDLE ,
176+ c:: HANDLE ,
177+ * mut c:: STACKFRAME64 ,
178+ * mut c:: CONTEXT ,
179+ * mut c_void ,
180+ * mut c_void ,
181+ * mut c_void ,
182+ * mut c_void ,
183+ ) -> c:: BOOL ;
112184
113- type StackWalkExFn =
114- unsafe extern "system" fn ( c:: DWORD , c:: HANDLE , c:: HANDLE ,
115- * mut c:: STACKFRAME_EX , * mut c:: CONTEXT ,
116- * mut c_void , * mut c_void ,
117- * mut c_void , * mut c_void , c:: DWORD ) -> c:: BOOL ;
185+ #[ cfg( target_arch = "x86" ) ]
186+ fn init_frame_ex ( frame : & mut c:: STACKFRAME_EX , ctx : & c:: CONTEXT ) -> c:: DWORD {
187+ frame. AddrPC . Offset = ctx. Eip as u64 ;
188+ frame. AddrPC . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
189+ frame. AddrStack . Offset = ctx. Esp as u64 ;
190+ frame. AddrStack . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
191+ frame. AddrFrame . Offset = ctx. Ebp as u64 ;
192+ frame. AddrFrame . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
193+ c:: IMAGE_FILE_MACHINE_I386
194+ }
195+
196+ #[ cfg( target_arch = "x86_64" ) ]
197+ fn init_frame_ex ( frame : & mut c:: STACKFRAME_EX , ctx : & c:: CONTEXT ) -> c:: DWORD {
198+ frame. AddrPC . Offset = ctx. Rip as u64 ;
199+ frame. AddrPC . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
200+ frame. AddrStack . Offset = ctx. Rsp as u64 ;
201+ frame. AddrStack . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
202+ frame. AddrFrame . Offset = ctx. Rbp as u64 ;
203+ frame. AddrFrame . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
204+ c:: IMAGE_FILE_MACHINE_AMD64
205+ }
118206
119207#[ cfg( target_arch = "x86" ) ]
120- fn init_frame ( frame : & mut c:: STACKFRAME_EX ,
121- ctx : & c:: CONTEXT ) -> c:: DWORD {
208+ fn init_frame_64 ( frame : & mut c:: STACKFRAME64 , ctx : & c:: CONTEXT ) -> c:: DWORD {
122209 frame. AddrPC . Offset = ctx. Eip as u64 ;
123210 frame. AddrPC . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
124211 frame. AddrStack . Offset = ctx. Esp as u64 ;
@@ -129,8 +216,7 @@ fn init_frame(frame: &mut c::STACKFRAME_EX,
129216}
130217
131218#[ cfg( target_arch = "x86_64" ) ]
132- fn init_frame ( frame : & mut c:: STACKFRAME_EX ,
133- ctx : & c:: CONTEXT ) -> c:: DWORD {
219+ fn init_frame_64 ( frame : & mut c:: STACKFRAME64 , ctx : & c:: CONTEXT ) -> c:: DWORD {
134220 frame. AddrPC . Offset = ctx. Rip as u64 ;
135221 frame. AddrPC . Mode = c:: ADDRESS_MODE :: AddrModeFlat ;
136222 frame. AddrStack . Offset = ctx. Rsp as u64 ;
0 commit comments