@@ -26,11 +26,17 @@ use core::ffi::c_void;
26
26
use core:: mem;
27
27
28
28
#[ derive( Clone , Copy ) ]
29
- pub enum Frame {
29
+ pub enum StackFrame {
30
30
New ( STACKFRAME_EX ) ,
31
31
Old ( STACKFRAME64 ) ,
32
32
}
33
33
34
+ #[ derive( Clone , Copy ) ]
35
+ pub struct Frame {
36
+ pub ( crate ) stack_frame : StackFrame ,
37
+ base_address : * mut c_void ,
38
+ }
39
+
34
40
// we're just sending around raw pointers and reading them, never interpreting
35
41
// them so this should be safe to both send and share across threads.
36
42
unsafe impl Send for Frame { }
@@ -49,38 +55,42 @@ impl Frame {
49
55
self . ip ( )
50
56
}
51
57
58
+ pub fn module_base_address ( & self ) -> Option < * mut c_void > {
59
+ Some ( self . base_address )
60
+ }
61
+
52
62
fn addr_pc ( & self ) -> & ADDRESS64 {
53
- match self {
54
- Frame :: New ( new) => & new. AddrPC ,
55
- Frame :: Old ( old) => & old. AddrPC ,
63
+ match self . stack_frame {
64
+ StackFrame :: New ( ref new) => & new. AddrPC ,
65
+ StackFrame :: Old ( ref old) => & old. AddrPC ,
56
66
}
57
67
}
58
68
59
69
fn addr_pc_mut ( & mut self ) -> & mut ADDRESS64 {
60
- match self {
61
- Frame :: New ( new) => & mut new. AddrPC ,
62
- Frame :: Old ( old) => & mut old. AddrPC ,
70
+ match self . stack_frame {
71
+ StackFrame :: New ( ref mut new) => & mut new. AddrPC ,
72
+ StackFrame :: Old ( ref mut old) => & mut old. AddrPC ,
63
73
}
64
74
}
65
75
66
76
fn addr_frame_mut ( & mut self ) -> & mut ADDRESS64 {
67
- match self {
68
- Frame :: New ( new) => & mut new. AddrFrame ,
69
- Frame :: Old ( old) => & mut old. AddrFrame ,
77
+ match self . stack_frame {
78
+ StackFrame :: New ( ref mut new) => & mut new. AddrFrame ,
79
+ StackFrame :: Old ( ref mut old) => & mut old. AddrFrame ,
70
80
}
71
81
}
72
82
73
83
fn addr_stack ( & self ) -> & ADDRESS64 {
74
- match self {
75
- Frame :: New ( new) => & new. AddrStack ,
76
- Frame :: Old ( old) => & old. AddrStack ,
84
+ match self . stack_frame {
85
+ StackFrame :: New ( ref new) => & new. AddrStack ,
86
+ StackFrame :: Old ( ref old) => & old. AddrStack ,
77
87
}
78
88
}
79
89
80
90
fn addr_stack_mut ( & mut self ) -> & mut ADDRESS64 {
81
- match self {
82
- Frame :: New ( new) => & mut new. AddrStack ,
83
- Frame :: Old ( old) => & mut old. AddrStack ,
91
+ match self . stack_frame {
92
+ StackFrame :: New ( ref mut new) => & mut new. AddrStack ,
93
+ StackFrame :: Old ( ref mut old) => & mut old. AddrStack ,
84
94
}
85
95
}
86
96
}
@@ -131,16 +141,21 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
131
141
}
132
142
}
133
143
144
+ let process_handle = GetCurrentProcess ( ) ;
145
+
134
146
// Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64`
135
147
// since it's in theory supported on more systems.
136
148
match ( * dbghelp. dbghelp ( ) ) . StackWalkEx ( ) {
137
149
Some ( StackWalkEx ) => {
138
150
let mut frame = super :: Frame {
139
- inner : Frame :: New ( mem:: zeroed ( ) ) ,
151
+ inner : Frame {
152
+ stack_frame : StackFrame :: New ( mem:: zeroed ( ) ) ,
153
+ base_address : 0 as _ ,
154
+ } ,
140
155
} ;
141
156
let image = init_frame ( & mut frame. inner , & context. 0 ) ;
142
- let frame_ptr = match & mut frame. inner {
143
- Frame :: New ( ptr) => ptr as * mut STACKFRAME_EX ,
157
+ let frame_ptr = match & mut frame. inner . stack_frame {
158
+ StackFrame :: New ( ptr) => ptr as * mut STACKFRAME_EX ,
144
159
_ => unreachable ! ( ) ,
145
160
} ;
146
161
@@ -157,18 +172,23 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
157
172
0 ,
158
173
) == TRUE
159
174
{
175
+ frame. inner . base_address = get_module_base ( process_handle, frame. ip ( ) as _ ) as _ ;
176
+
160
177
if !cb ( & frame) {
161
178
break ;
162
179
}
163
180
}
164
181
}
165
182
None => {
166
183
let mut frame = super :: Frame {
167
- inner : Frame :: Old ( mem:: zeroed ( ) ) ,
184
+ inner : Frame {
185
+ stack_frame : StackFrame :: Old ( mem:: zeroed ( ) ) ,
186
+ base_address : 0 as _ ,
187
+ } ,
168
188
} ;
169
189
let image = init_frame ( & mut frame. inner , & context. 0 ) ;
170
- let frame_ptr = match & mut frame. inner {
171
- Frame :: Old ( ptr) => ptr as * mut STACKFRAME64 ,
190
+ let frame_ptr = match & mut frame. inner . stack_frame {
191
+ StackFrame :: Old ( ptr) => ptr as * mut STACKFRAME64 ,
172
192
_ => unreachable ! ( ) ,
173
193
} ;
174
194
@@ -184,6 +204,8 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
184
204
None ,
185
205
) == TRUE
186
206
{
207
+ frame. inner . base_address = get_module_base ( process_handle, frame. ip ( ) as _ ) as _ ;
208
+
187
209
if !cb ( & frame) {
188
210
break ;
189
211
}
0 commit comments