1919
2020use super :: super :: { dbghelp, windows:: * } ;
2121use super :: { BytesOrWideString , ResolveWhat , SymbolName } ;
22- use core:: char;
2322use core:: ffi:: c_void;
2423use core:: marker;
2524use core:: mem;
@@ -91,7 +90,7 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
9190 ResolveWhat :: Frame ( frame) => {
9291 resolve_with_inline ( & dbghelp, frame. ip ( ) , frame. inner . inline_context ( ) , cb)
9392 }
94- }
93+ } ;
9594}
9695
9796#[ cfg( target_vendor = "win7" ) ]
@@ -116,7 +115,7 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
116115 ResolveWhat :: Frame ( frame) => {
117116 resolve_inner ( & dbghelp, frame. ip ( ) , frame. inner . inline_context ( ) , cb)
118117 }
119- }
118+ } ;
120119}
121120
122121/// Resolve the address using the legacy dbghelp API.
@@ -147,22 +146,28 @@ unsafe fn resolve_with_inline(
147146 addr : * mut c_void ,
148147 inline_context : Option < DWORD > ,
149148 cb : & mut dyn FnMut ( & super :: Symbol ) ,
150- ) {
149+ ) -> Option < ( ) > {
151150 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 ( ) ?;
152154
153155 let addr = super :: adjust_ip ( addr) as DWORD64 ;
154156
155157 let ( inlined_frame_count, inline_context) = if let Some ( ic) = inline_context {
156158 ( 0 , ic)
157159 } 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) ;
159164
160165 let mut inline_context = 0 ;
161166
162167 // If there is are inlined frames but we can't load them for some reason OR if there are no
163168 // inlined frames, then we disregard inlined_frame_count and inline_context.
164169 if ( inlined_frame_count > 0
165- && dbghelp . SymQueryInlineTrace ( ) (
170+ && SymQueryInlineTrace (
166171 current_process,
167172 addr,
168173 0 ,
@@ -184,22 +189,14 @@ unsafe fn resolve_with_inline(
184189
185190 for inline_context in inline_context..last_inline_context {
186191 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) ,
190193 |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)
199195 } ,
200196 cb,
201197 ) ;
202198 }
199+ Some ( ( ) )
203200}
204201
205202unsafe fn do_resolve (
@@ -225,26 +222,27 @@ unsafe fn do_resolve(
225222 // the real value.
226223 let name_len = :: core:: cmp:: min ( info. NameLen as usize , info. MaxNameLen as usize - 1 ) ;
227224 let name_ptr = info. Name . as_ptr ( ) . cast :: < u16 > ( ) ;
228- let name = slice:: from_raw_parts ( name_ptr, name_len) ;
229225
230226 // Reencode the utf-16 symbol to utf-8 so we can use `SymbolName::new` like
231227 // 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 ;
248246 }
249247 let name = ptr:: addr_of!( name_buffer[ ..name_len] ) ;
250248
0 commit comments