19
19
20
20
use super :: super :: { dbghelp, windows:: * } ;
21
21
use super :: { BytesOrWideString , ResolveWhat , SymbolName } ;
22
- use core:: char;
23
22
use core:: ffi:: c_void;
24
23
use core:: marker;
25
24
use core:: mem;
@@ -91,7 +90,7 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
91
90
ResolveWhat :: Frame ( frame) => {
92
91
resolve_with_inline ( & dbghelp, frame. ip ( ) , frame. inner . inline_context ( ) , cb)
93
92
}
94
- }
93
+ } ;
95
94
}
96
95
97
96
#[ cfg( target_vendor = "win7" ) ]
@@ -116,7 +115,7 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
116
115
ResolveWhat :: Frame ( frame) => {
117
116
resolve_inner ( & dbghelp, frame. ip ( ) , frame. inner . inline_context ( ) , cb)
118
117
}
119
- }
118
+ } ;
120
119
}
121
120
122
121
/// Resolve the address using the legacy dbghelp API.
@@ -147,22 +146,28 @@ unsafe fn resolve_with_inline(
147
146
addr : * mut c_void ,
148
147
inline_context : Option < DWORD > ,
149
148
cb : & mut dyn FnMut ( & super :: Symbol ) ,
150
- ) {
149
+ ) -> Option < ( ) > {
151
150
let current_process = GetCurrentProcess ( ) ;
151
+ // Ensure we have the functions we need. Return if any aren't found.
152
+ let SymFromInlineContextW = ( * dbghelp. dbghelp ( ) ) . SymFromInlineContextW ( ) ?;
153
+ let SymGetLineFromInlineContextW = ( * dbghelp. dbghelp ( ) ) . SymGetLineFromInlineContextW ( ) ?;
152
154
153
155
let addr = super :: adjust_ip ( addr) as DWORD64 ;
154
156
155
157
let ( inlined_frame_count, inline_context) = if let Some ( ic) = inline_context {
156
158
( 0 , ic)
157
159
} else {
158
- let mut inlined_frame_count = dbghelp. SymAddrIncludeInlineTrace ( ) ( current_process, addr) ;
160
+ let SymAddrIncludeInlineTrace = ( * dbghelp. dbghelp ( ) ) . SymAddrIncludeInlineTrace ( ) ?;
161
+ let SymQueryInlineTrace = ( * dbghelp. dbghelp ( ) ) . SymQueryInlineTrace ( ) ?;
162
+
163
+ let mut inlined_frame_count = SymAddrIncludeInlineTrace ( current_process, addr) ;
159
164
160
165
let mut inline_context = 0 ;
161
166
162
167
// If there is are inlined frames but we can't load them for some reason OR if there are no
163
168
// inlined frames, then we disregard inlined_frame_count and inline_context.
164
169
if ( inlined_frame_count > 0
165
- && dbghelp . SymQueryInlineTrace ( ) (
170
+ && SymQueryInlineTrace (
166
171
current_process,
167
172
addr,
168
173
0 ,
@@ -184,22 +189,14 @@ unsafe fn resolve_with_inline(
184
189
185
190
for inline_context in inline_context..last_inline_context {
186
191
do_resolve (
187
- |info| {
188
- dbghelp. SymFromInlineContextW ( ) ( current_process, addr, inline_context, & mut 0 , info)
189
- } ,
192
+ |info| SymFromInlineContextW ( current_process, addr, inline_context, & mut 0 , info) ,
190
193
|line| {
191
- dbghelp. SymGetLineFromInlineContextW ( ) (
192
- current_process,
193
- addr,
194
- inline_context,
195
- 0 ,
196
- & mut 0 ,
197
- line,
198
- )
194
+ SymGetLineFromInlineContextW ( current_process, addr, inline_context, 0 , & mut 0 , line)
199
195
} ,
200
196
cb,
201
197
) ;
202
198
}
199
+ Some ( ( ) )
203
200
}
204
201
205
202
unsafe fn do_resolve (
@@ -225,26 +222,27 @@ unsafe fn do_resolve(
225
222
// the real value.
226
223
let name_len = :: core:: cmp:: min ( info. NameLen as usize , info. MaxNameLen as usize - 1 ) ;
227
224
let name_ptr = info. Name . as_ptr ( ) . cast :: < u16 > ( ) ;
228
- let name = slice:: from_raw_parts ( name_ptr, name_len) ;
229
225
230
226
// Reencode the utf-16 symbol to utf-8 so we can use `SymbolName::new` like
231
227
// all other platforms
232
- let mut name_len = 0 ;
233
- let mut name_buffer = [ 0 ; 256 ] ;
234
- {
235
- let mut remaining = & mut name_buffer[ ..] ;
236
- for c in char:: decode_utf16 ( name. iter ( ) . cloned ( ) ) {
237
- let c = c. unwrap_or ( char:: REPLACEMENT_CHARACTER ) ;
238
- let len = c. len_utf8 ( ) ;
239
- if len < remaining. len ( ) {
240
- c. encode_utf8 ( remaining) ;
241
- let tmp = remaining;
242
- remaining = & mut tmp[ len..] ;
243
- name_len += len;
244
- } else {
245
- break ;
246
- }
247
- }
228
+ let mut name_buffer = [ 0_u8 ; 256 ] ;
229
+ let mut name_len = WideCharToMultiByte (
230
+ CP_UTF8 ,
231
+ 0 ,
232
+ name_ptr,
233
+ name_len as i32 ,
234
+ name_buffer. as_mut_ptr ( ) . cast :: < i8 > ( ) ,
235
+ name_buffer. len ( ) as i32 ,
236
+ core:: ptr:: null_mut ( ) ,
237
+ core:: ptr:: null_mut ( ) ,
238
+ ) as usize ;
239
+ if name_len == 0 {
240
+ // If the returned length is zero that means the buffer wasn't big enough.
241
+ // However, the buffer will be filled with as much as will fit.
242
+ name_len = name_buffer. len ( ) ;
243
+ } else if name_len > name_buffer. len ( ) {
244
+ // This can't happen.
245
+ return ;
248
246
}
249
247
let name = ptr:: addr_of!( name_buffer[ ..name_len] ) ;
250
248
0 commit comments