@@ -18,7 +18,6 @@ use sys::c;
18
18
use sys:: dynamic_lib:: DynamicLibrary ;
19
19
use sys_common:: backtrace:: Frame ;
20
20
21
-
22
21
// Structs holding printing functions and loaders for them
23
22
// Two versions depending on whether dbghelp.dll has StackWalkEx or not
24
23
// (the former being in newer Windows versions, the older being in Win7 and before)
@@ -32,23 +31,29 @@ pub struct PrintingFns64 {
32
31
}
33
32
34
33
pub fn load_printing_fns_ex ( dbghelp : & DynamicLibrary ) -> io:: Result < PrintingFnsEx > {
35
- Ok ( PrintingFnsEx {
36
- resolve_symname : sym ! ( dbghelp, "SymFromInlineContext" ,
37
- SymFromInlineContextFn ) ?,
38
- sym_get_line : sym ! ( dbghelp, "SymGetLineFromInlineContext" ,
39
- SymGetLineFromInlineContextFn ) ?,
34
+ Ok ( PrintingFnsEx {
35
+ resolve_symname : sym ! ( dbghelp, "SymFromInlineContext" , SymFromInlineContextFn ) ?,
36
+ sym_get_line : sym ! (
37
+ dbghelp,
38
+ "SymGetLineFromInlineContext" ,
39
+ SymGetLineFromInlineContextFn
40
+ ) ?,
40
41
} )
41
42
}
42
43
pub fn load_printing_fns_64 ( dbghelp : & DynamicLibrary ) -> io:: Result < PrintingFns64 > {
43
- Ok ( PrintingFns64 {
44
+ Ok ( PrintingFns64 {
44
45
resolve_symname : sym ! ( dbghelp, "SymFromAddr" , SymFromAddrFn ) ?,
45
- sym_get_line : sym ! ( dbghelp, "SymGetLineFromAddr64" ,
46
- SymGetLineFromAddr64Fn ) ?,
46
+ sym_get_line : sym ! ( dbghelp, "SymGetLineFromAddr64" , SymGetLineFromAddr64Fn ) ?,
47
47
} )
48
48
}
49
49
50
+ type SymFromAddrFn =
51
+ unsafe extern "system" fn ( c:: HANDLE , u64 , * mut u64 , * mut c:: SYMBOL_INFO ) -> c:: BOOL ;
50
52
type SymFromInlineContextFn =
51
53
unsafe extern "system" fn ( c:: HANDLE , u64 , c:: ULONG , * mut u64 , * mut c:: SYMBOL_INFO ) -> c:: BOOL ;
54
+
55
+ type SymGetLineFromAddr64Fn =
56
+ unsafe extern "system" fn ( c:: HANDLE , u64 , * mut u32 , * mut c:: IMAGEHLP_LINE64 ) -> c:: BOOL ;
52
57
type SymGetLineFromInlineContextFn = unsafe extern "system" fn (
53
58
c:: HANDLE ,
54
59
u64 ,
@@ -58,73 +63,30 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
58
63
* mut c:: IMAGEHLP_LINE64 ,
59
64
) -> c:: BOOL ;
60
65
61
- type SymFromAddrFn =
62
- unsafe extern "system" fn ( c:: HANDLE , u64 , * mut u64 , * mut c:: SYMBOL_INFO ) -> c:: BOOL ;
63
- type SymGetLineFromAddr64Fn =
64
- unsafe extern "system" fn ( c:: HANDLE , u64 , * mut u32 , * mut c:: IMAGEHLP_LINE64 ) -> c:: BOOL ;
65
-
66
66
/// Converts a pointer to symbol to its string value.
67
67
pub fn resolve_symname < F > ( frame : Frame , callback : F , context : & BacktraceContext ) -> io:: Result < ( ) >
68
68
where
69
69
F : FnOnce ( Option < & str > ) -> io:: Result < ( ) > ,
70
70
{
71
71
match context. StackWalkVariant {
72
72
StackWalkVariant :: StackWalkEx ( _, ref fns) => {
73
- resolve_symname_from_inline_context ( fns. resolve_symname , frame, callback, context)
74
- } ,
73
+ resolve_symname_internal ( fns. resolve_symname , frame, callback, context)
74
+ }
75
75
StackWalkVariant :: StackWalk64 ( _, ref fns) => {
76
- resolve_symname_from_addr ( fns. resolve_symname , frame, callback, context)
76
+ resolve_symname_internal ( fns. resolve_symname , frame, callback, context)
77
77
}
78
78
}
79
79
}
80
80
81
- fn resolve_symname_from_inline_context < F > (
82
- SymFromInlineContext : SymFromInlineContextFn ,
83
- frame : Frame , callback : F , context : & BacktraceContext ) -> io:: Result < ( ) >
84
- where
85
- F : FnOnce ( Option < & str > ) -> io:: Result < ( ) > ,
86
- {
87
- unsafe {
88
- let mut info: c:: SYMBOL_INFO = mem:: zeroed ( ) ;
89
- info. MaxNameLen = c:: MAX_SYM_NAME as c_ulong ;
90
- // the struct size in C. the value is different to
91
- // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
92
- // due to struct alignment.
93
- info. SizeOfStruct = 88 ;
94
-
95
- let mut displacement = 0u64 ;
96
- let ret = SymFromInlineContext (
97
- context. handle ,
98
- frame. symbol_addr as u64 ,
99
- frame. inline_context ,
100
- & mut displacement,
101
- & mut info,
102
- ) ;
103
- let valid_range =
104
- if ret == c:: TRUE && frame. symbol_addr as usize >= info. Address as usize {
105
- if info. Size != 0 {
106
- ( frame. symbol_addr as usize ) < info. Address as usize + info. Size as usize
107
- } else {
108
- true
109
- }
110
- } else {
111
- false
112
- } ;
113
- let symname = if valid_range {
114
- let ptr = info. Name . as_ptr ( ) as * const c_char ;
115
- CStr :: from_ptr ( ptr) . to_str ( ) . ok ( )
116
- } else {
117
- None
118
- } ;
119
- callback ( symname)
120
- }
121
- }
122
-
123
- fn resolve_symname_from_addr < F > (
124
- SymFromAddr : SymFromAddrFn ,
125
- frame : Frame , callback : F , context : & BacktraceContext ) -> io:: Result < ( ) >
81
+ fn resolve_symname_internal < F , R > (
82
+ symbol_resolver : R ,
83
+ frame : Frame ,
84
+ callback : F ,
85
+ context : & BacktraceContext ,
86
+ ) -> io:: Result < ( ) >
126
87
where
127
88
F : FnOnce ( Option < & str > ) -> io:: Result < ( ) > ,
89
+ R : SymbolResolver ,
128
90
{
129
91
unsafe {
130
92
let mut info: c:: SYMBOL_INFO = mem:: zeroed ( ) ;
@@ -134,15 +96,22 @@ where
134
96
// due to struct alignment.
135
97
info. SizeOfStruct = 88 ;
136
98
137
- let mut displacement = 0u64 ;
138
- let ret = SymFromAddr (
99
+ let ret = symbol_resolver. resolve_symbol (
139
100
context. handle ,
140
101
frame. symbol_addr as u64 ,
141
- & mut displacement ,
102
+ frame . inline_context ,
142
103
& mut info,
143
104
) ;
144
-
145
- let symname = if ret == c:: TRUE {
105
+ let valid_range = if ret == c:: TRUE && frame. symbol_addr as usize >= info. Address as usize {
106
+ if info. Size != 0 {
107
+ ( frame. symbol_addr as usize ) < info. Address as usize + info. Size as usize
108
+ } else {
109
+ true
110
+ }
111
+ } else {
112
+ false
113
+ } ;
114
+ let symname = if valid_range {
146
115
let ptr = info. Name . as_ptr ( ) as * const c_char ;
147
116
CStr :: from_ptr ( ptr) . to_str ( ) . ok ( )
148
117
} else {
@@ -152,76 +121,141 @@ where
152
121
}
153
122
}
154
123
124
+ trait SymbolResolver {
125
+ fn resolve_symbol (
126
+ & self ,
127
+ process : c:: HANDLE ,
128
+ symbol_address : u64 ,
129
+ inline_context : c:: ULONG ,
130
+ info : * mut c:: SYMBOL_INFO ,
131
+ ) -> c:: BOOL ;
132
+ }
133
+
134
+ impl SymbolResolver for SymFromAddrFn {
135
+ fn resolve_symbol (
136
+ & self ,
137
+ process : c:: HANDLE ,
138
+ symbol_address : u64 ,
139
+ _inline_context : c:: ULONG ,
140
+ info : * mut c:: SYMBOL_INFO ,
141
+ ) -> c:: BOOL {
142
+ unsafe {
143
+ let mut displacement = 0u64 ;
144
+ self ( process, symbol_address, & mut displacement, info)
145
+ }
146
+ }
147
+ }
148
+
149
+ impl SymbolResolver for SymFromInlineContextFn {
150
+ fn resolve_symbol (
151
+ & self ,
152
+ process : c:: HANDLE ,
153
+ symbol_address : u64 ,
154
+ inline_context : c:: ULONG ,
155
+ info : * mut c:: SYMBOL_INFO ,
156
+ ) -> c:: BOOL {
157
+ unsafe {
158
+ let mut displacement = 0u64 ;
159
+ self (
160
+ process,
161
+ symbol_address,
162
+ inline_context,
163
+ & mut displacement,
164
+ info,
165
+ )
166
+ }
167
+ }
168
+ }
169
+
155
170
pub fn foreach_symbol_fileline < F > (
156
171
frame : Frame ,
157
- f : F ,
172
+ callback : F ,
158
173
context : & BacktraceContext ,
159
174
) -> io:: Result < bool >
160
175
where
161
176
F : FnMut ( & [ u8 ] , u32 ) -> io:: Result < ( ) > ,
162
177
{
163
178
match context. StackWalkVariant {
164
- StackWalkVariant :: StackWalkEx ( _, ref fns) =>
165
- foreach_symbol_fileline_ex ( fns. sym_get_line , frame, f, context) ,
166
- StackWalkVariant :: StackWalk64 ( _, ref fns) =>
167
- foreach_symbol_fileline_64 ( fns. sym_get_line , frame, f, context) ,
179
+ StackWalkVariant :: StackWalkEx ( _, ref fns) => {
180
+ foreach_symbol_fileline_iternal ( fns. sym_get_line , frame, callback, context)
181
+ }
182
+ StackWalkVariant :: StackWalk64 ( _, ref fns) => {
183
+ foreach_symbol_fileline_iternal ( fns. sym_get_line , frame, callback, context)
184
+ }
168
185
}
169
186
}
170
187
171
- fn foreach_symbol_fileline_ex < F > (
172
- SymGetLineFromInlineContext : SymGetLineFromInlineContextFn ,
188
+ fn foreach_symbol_fileline_iternal < F , G > (
189
+ line_getter : G ,
173
190
frame : Frame ,
174
- mut f : F ,
191
+ mut callback : F ,
175
192
context : & BacktraceContext ,
176
193
) -> io:: Result < bool >
177
194
where
178
195
F : FnMut ( & [ u8 ] , u32 ) -> io:: Result < ( ) > ,
196
+ G : LineGetter ,
179
197
{
180
198
unsafe {
181
199
let mut line: c:: IMAGEHLP_LINE64 = mem:: zeroed ( ) ;
182
200
line. SizeOfStruct = :: mem:: size_of :: < c:: IMAGEHLP_LINE64 > ( ) as u32 ;
183
201
184
- let mut displacement = 0u32 ;
185
- let ret = SymGetLineFromInlineContext (
202
+ let ret = line_getter. get_line (
186
203
context. handle ,
187
204
frame. exact_position as u64 ,
188
205
frame. inline_context ,
189
- 0 ,
190
- & mut displacement,
191
206
& mut line,
192
207
) ;
193
208
if ret == c:: TRUE {
194
209
let name = CStr :: from_ptr ( line. Filename ) . to_bytes ( ) ;
195
- f ( name, line. LineNumber as u32 ) ?;
210
+ callback ( name, line. LineNumber as u32 ) ?;
196
211
}
197
212
Ok ( false )
198
213
}
199
214
}
200
215
201
- fn foreach_symbol_fileline_64 < F > (
202
- SymGetLineFromAddr64 : SymGetLineFromAddr64Fn ,
203
- frame : Frame ,
204
- mut f : F ,
205
- context : & BacktraceContext ,
206
- ) -> io:: Result < bool >
207
- where
208
- F : FnMut ( & [ u8 ] , u32 ) -> io:: Result < ( ) > ,
209
- {
210
- unsafe {
211
- let mut line: c:: IMAGEHLP_LINE64 = mem:: zeroed ( ) ;
212
- line. SizeOfStruct = :: mem:: size_of :: < c:: IMAGEHLP_LINE64 > ( ) as u32 ;
216
+ trait LineGetter {
217
+ fn get_line (
218
+ & self ,
219
+ process : c:: HANDLE ,
220
+ frame_address : u64 ,
221
+ inline_context : c:: ULONG ,
222
+ line : * mut c:: IMAGEHLP_LINE64 ,
223
+ ) -> c:: BOOL ;
224
+ }
213
225
214
- let mut displacement = 0u32 ;
215
- let ret = SymGetLineFromAddr64 (
216
- context. handle ,
217
- frame. exact_position as u64 ,
218
- & mut displacement,
219
- & mut line,
220
- ) ;
221
- if ret == c:: TRUE {
222
- let name = CStr :: from_ptr ( line. Filename ) . to_bytes ( ) ;
223
- f ( name, line. LineNumber as u32 ) ?;
226
+ impl LineGetter for SymGetLineFromAddr64Fn {
227
+ fn get_line (
228
+ & self ,
229
+ process : c:: HANDLE ,
230
+ frame_address : u64 ,
231
+ _inline_context : c:: ULONG ,
232
+ line : * mut c:: IMAGEHLP_LINE64 ,
233
+ ) -> c:: BOOL {
234
+ unsafe {
235
+ let mut displacement = 0u32 ;
236
+ self ( process, frame_address, & mut displacement, line)
237
+ }
238
+ }
239
+ }
240
+
241
+ impl LineGetter for SymGetLineFromInlineContextFn {
242
+ fn get_line (
243
+ & self ,
244
+ process : c:: HANDLE ,
245
+ frame_address : u64 ,
246
+ inline_context : c:: ULONG ,
247
+ line : * mut c:: IMAGEHLP_LINE64 ,
248
+ ) -> c:: BOOL {
249
+ unsafe {
250
+ let mut displacement = 0u32 ;
251
+ self (
252
+ process,
253
+ frame_address,
254
+ inline_context,
255
+ 0 ,
256
+ & mut displacement,
257
+ line,
258
+ )
224
259
}
225
- Ok ( false )
226
260
}
227
261
}
0 commit comments