Skip to content

Commit 9089a79

Browse files
waskyosipma
authored andcommitted
add support for doing blockmapping for trampoline with a continue statement
the previous code didn't handle this case because in a continue statement the trampoline block has two 'post' blocks. this also adds code to report a warning when we find an unhandled trampoline case
1 parent d9c1d3a commit 9089a79

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

chb/relational/FunctionRelationalAnalysis.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)