@@ -384,7 +384,6 @@ def block_analyses(self) -> Mapping[str, BlockRelationalAnalysis]:
384384 trampoline = self .has_trampoline ()
385385 if trampoline is not None :
386386 self .setup_trampoline_analysis (trampoline )
387-
388387 else :
389388 trampoline_minimal_pair_2_and_3 = self .has_minimal_pair_2_and_3_trampoline ()
390389 if trampoline_minimal_pair_2_and_3 is not None :
@@ -406,6 +405,8 @@ def setup_trampoline_analysis(self, b: str) -> None:
406405 tpre [0 ] in cfg2unmapped
407406 and tpost [0 ] in cfg2unmapped
408407 and tpre [0 ] in cfg1unmapped ):
408+ # Case where trampoline has an early return and a fallthrough case
409+ # (what we mark as the exit block)
409410 roles : Dict [str , "BasicBlock" ] = {}
410411 roles ["entry" ] = self .basic_blocks2 [tpre [0 ]]
411412 roles ["exit" ] = self .basic_blocks2 [tpost [0 ]]
@@ -416,6 +417,50 @@ def setup_trampoline_analysis(self, b: str) -> None:
416417 self .basic_blocks1 [tpre [0 ]],
417418 self .app2 ,
418419 roles )
420+ else :
421+ chklogger .logger .warning ("Found unhandled trampoline case. Should be an early return "
422+ "trampoline (pre %s, post %s), but the blocks are not "
423+ "in the unmapped lists. cfg1: %s, cfg2: %s" ,
424+ tpre [0 ], tpost [0 ], cfg1unmapped , cfg2unmapped )
425+ elif len (tpre ) == 1 and len (tpost ) == 2 :
426+ # Trampoline has a continue statement.
427+ # One of the post blocks is the fallthrough/exit, one is the loop continuation.
428+ # Need to figure out which one is which
429+ if not 'continuepath' in trampoline .roles :
430+ chklogger .logger .error ("Found unsupported trampoline case, "
431+ "There are 2 post trampoline blocks %s but no continuepath role %s" ,
432+ tpost , trampoline .roles )
433+ return
434+
435+ cont = self .basic_blocks2 [trampoline .roles ['continuepath' ]]
436+ cont_post = self .cfg2 .edges [cont .baddr ]
437+ if len (cont_post ) != 1 :
438+ chklogger .logger .error ("Found unsupported trampoline case, "
439+ "continue block %s has more than one outgoing edges: %s" ,
440+ cont .baddr , cont_post )
441+ return
442+ fallthrough = self .basic_blocks2 [trampoline .roles ['fallthrough' ]]
443+ fallthrough_post = self .cfg2 .edges [fallthrough .baddr ]
444+ if len (fallthrough_post ) != 1 :
445+ chklogger .logger .error ("Found unsupported trampoline case, "
446+ "fallthrough block %s has more than one outgoing edges: %s" ,
447+ fallthrough .baddr , fallthrough_post )
448+ return
449+
450+ roles : Dict [str , "BasicBlock" ] = {}
451+ roles ["entry" ] = self .basic_blocks2 [tpre [0 ]]
452+ roles ["exit" ] = self .basic_blocks2 [fallthrough_post [0 ]]
453+ for (role , addr ) in trampoline .roles .items ():
454+ roles [role ] = self .basic_blocks2 [addr ]
455+ self ._blockanalyses [tpre [0 ]] = BlockRelationalAnalysis (
456+ self .app1 ,
457+ self .basic_blocks1 [tpre [0 ]],
458+ self .app2 ,
459+ roles )
460+ else :
461+ chklogger .logger .warning ("Found unhandled trampoline case. Have %d pre-blocks "
462+ "%d post-blocks. pre: %s, post %s" ,
463+ len (tpre ), len (tpost ), tpre , tpost )
419464
420465 def setup_minimal_pair_2_and_3_trampoline_analysis (self , b : str ) -> None :
421466 chklogger .logger .info ("Setup minimal_pair_2_and_3_trampoline at %s" , b )
0 commit comments