@@ -18,7 +18,6 @@ use sys::c;
1818use sys:: dynamic_lib:: DynamicLibrary ;
1919use sys_common:: backtrace:: Frame ;
2020
21-
2221// Structs holding printing functions and loaders for them
2322// Two versions depending on whether dbghelp.dll has StackWalkEx or not
2423// (the former being in newer Windows versions, the older being in Win7 and before)
@@ -32,23 +31,29 @@ pub struct PrintingFns64 {
3231}
3332
3433pub 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+ ) ?,
4041 } )
4142}
4243pub fn load_printing_fns_64 ( dbghelp : & DynamicLibrary ) -> io:: Result < PrintingFns64 > {
43- Ok ( PrintingFns64 {
44+ Ok ( PrintingFns64 {
4445 resolve_symname : sym ! ( dbghelp, "SymFromAddr" , SymFromAddrFn ) ?,
45- sym_get_line : sym ! ( dbghelp, "SymGetLineFromAddr64" ,
46- SymGetLineFromAddr64Fn ) ?,
46+ sym_get_line : sym ! ( dbghelp, "SymGetLineFromAddr64" , SymGetLineFromAddr64Fn ) ?,
4747 } )
4848}
4949
50+ type SymFromAddrFn =
51+ unsafe extern "system" fn ( c:: HANDLE , u64 , * mut u64 , * mut c:: SYMBOL_INFO ) -> c:: BOOL ;
5052type SymFromInlineContextFn =
5153 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 ;
5257type SymGetLineFromInlineContextFn = unsafe extern "system" fn (
5358 c:: HANDLE ,
5459 u64 ,
@@ -58,73 +63,30 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
5863 * mut c:: IMAGEHLP_LINE64 ,
5964) -> c:: BOOL ;
6065
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-
6666/// Converts a pointer to symbol to its string value.
6767pub fn resolve_symname < F > ( frame : Frame , callback : F , context : & BacktraceContext ) -> io:: Result < ( ) >
6868where
6969 F : FnOnce ( Option < & str > ) -> io:: Result < ( ) > ,
7070{
7171 match context. StackWalkVariant {
7272 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+ }
7575 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)
7777 }
7878 }
7979}
8080
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 < ( ) >
12687where
12788 F : FnOnce ( Option < & str > ) -> io:: Result < ( ) > ,
89+ R : SymbolResolver ,
12890{
12991 unsafe {
13092 let mut info: c:: SYMBOL_INFO = mem:: zeroed ( ) ;
@@ -134,15 +96,22 @@ where
13496 // due to struct alignment.
13597 info. SizeOfStruct = 88 ;
13698
137- let mut displacement = 0u64 ;
138- let ret = SymFromAddr (
99+ let ret = symbol_resolver. resolve_symbol (
139100 context. handle ,
140101 frame. symbol_addr as u64 ,
141- & mut displacement ,
102+ frame . inline_context ,
142103 & mut info,
143104 ) ;
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 {
146115 let ptr = info. Name . as_ptr ( ) as * const c_char ;
147116 CStr :: from_ptr ( ptr) . to_str ( ) . ok ( )
148117 } else {
@@ -152,76 +121,141 @@ where
152121 }
153122}
154123
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+
155170pub fn foreach_symbol_fileline < F > (
156171 frame : Frame ,
157- f : F ,
172+ callback : F ,
158173 context : & BacktraceContext ,
159174) -> io:: Result < bool >
160175where
161176 F : FnMut ( & [ u8 ] , u32 ) -> io:: Result < ( ) > ,
162177{
163178 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+ }
168185 }
169186}
170187
171- fn foreach_symbol_fileline_ex < F > (
172- SymGetLineFromInlineContext : SymGetLineFromInlineContextFn ,
188+ fn foreach_symbol_fileline_iternal < F , G > (
189+ line_getter : G ,
173190 frame : Frame ,
174- mut f : F ,
191+ mut callback : F ,
175192 context : & BacktraceContext ,
176193) -> io:: Result < bool >
177194where
178195 F : FnMut ( & [ u8 ] , u32 ) -> io:: Result < ( ) > ,
196+ G : LineGetter ,
179197{
180198 unsafe {
181199 let mut line: c:: IMAGEHLP_LINE64 = mem:: zeroed ( ) ;
182200 line. SizeOfStruct = :: mem:: size_of :: < c:: IMAGEHLP_LINE64 > ( ) as u32 ;
183201
184- let mut displacement = 0u32 ;
185- let ret = SymGetLineFromInlineContext (
202+ let ret = line_getter. get_line (
186203 context. handle ,
187204 frame. exact_position as u64 ,
188205 frame. inline_context ,
189- 0 ,
190- & mut displacement,
191206 & mut line,
192207 ) ;
193208 if ret == c:: TRUE {
194209 let name = CStr :: from_ptr ( line. Filename ) . to_bytes ( ) ;
195- f ( name, line. LineNumber as u32 ) ?;
210+ callback ( name, line. LineNumber as u32 ) ?;
196211 }
197212 Ok ( false )
198213 }
199214}
200215
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+ }
213225
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+ )
224259 }
225- Ok ( false )
226260 }
227261}
0 commit comments