@@ -224,18 +224,40 @@ pub fn find_functions(pe: &PE) -> Result<Vec<Function>> {
224224 . filter ( |& va| heuristics:: is_probably_code ( & pe. module , & decoder, va) ) ,
225225 ) ;
226226
227- let thunks = find_thunks ( pe, & imports, & function_starts) ?;
228-
229227 // ensure that all functions pointed to by a thunk are a function.
230228 // some of these target functions may not be recongized by other passes.
231- for thunk in thunks. values ( ) {
232- if let ThunkTarget :: Function ( target) = thunk. target {
233- debug ! ( "found new function candidate from thunk target: 0x{target:x}" ) ;
234- function_starts. insert ( target) ;
229+ //
230+ // we keep searching until we reach a fixed point,
231+ // to ensure we account for thunks to thunks to functions.
232+ let mut thunk_candidates = function_starts. clone ( ) ;
233+ let mut thunks: BTreeMap < VA , Thunk > = Default :: default ( ) ;
234+ while thunk_candidates. is_empty ( ) . not ( ) {
235+ let confirmed_thunks = find_thunks ( pe, & imports, & thunk_candidates) ?;
236+
237+ // these are all the addresses pointed to by thunks,
238+ // which we need to ensure are functions.
239+ let function_thunk_targets = confirmed_thunks
240+ . values ( )
241+ . filter_map ( |thunk| match thunk. target {
242+ ThunkTarget :: Function ( target) => Some ( target) ,
243+ ThunkTarget :: Import ( _) => None ,
244+ } )
245+ . collect :: < Vec < VA > > ( ) ;
246+
247+ thunks. extend ( confirmed_thunks. into_iter ( ) ) ;
248+
249+ let mut next_candidates: BTreeSet < VA > = Default :: default ( ) ;
250+ for & target in function_thunk_targets. iter ( ) {
251+ if function_starts. insert ( target) {
252+ debug ! ( "found new function candidate from thunk target: 0x{target:x}" ) ;
253+ next_candidates. insert ( target) ;
254+ // next loop we'll check if this target is a thunk, too.
255+ }
235256 }
257+
258+ debug ! ( "found {} thunk candidates this round" , next_candidates. len( ) ) ;
259+ thunk_candidates = next_candidates;
236260 }
237- // TODO: in theory, we want to do this iteratively, until we reach a fixed
238- // point, to account for thunks to thunks to functions.
239261
240262 debug ! ( "functions: found {} function candidates" , function_starts. len( ) ) ;
241263 debug ! ( "functions: found {} thunks" , thunks. len( ) ) ;
@@ -265,6 +287,7 @@ pub fn find_function_starts(pe: &PE) -> Result<Vec<VA>> {
265287 . into_iter ( )
266288 . filter_map ( |f| match f {
267289 Function :: Local ( va) => Some ( va) ,
290+ Function :: Thunk ( Thunk { address : va, .. } ) => Some ( va) ,
268291 _ => None ,
269292 } )
270293 . collect ( ) )
0 commit comments