Commit Graph

1 Commits

Author SHA1 Message Date
Chris Smowton 4c0bc6435b Symex: distinguish reachability from the state guard
Previously the state guard being false was taken to indicate unreachable code,
and different causes of unreachability were handled inconsistently:

* ASSUME false implied unreachability but had no effect on the guard
* --unwind or --depth being exceeded usually meant setting the guard false

This meant that expensive code downstream of an ASSUME false *was* executed, but the state
guard was maintained as usual including shrinking the guard when branches converge, while
--unwind or --depth limit breaks led to code *not* being executed (vital for these options
to function properly) but the state guard grew ever larger because the part that had gone
missing (been set to false) never got merged back in.

This commit distinguishes the two concepts: the "reachable" flag is set false whenever a
limit break OR and ASSUME false happens, but state guard maintenance continues as normal.
A new symex_unreachable_goto tries to find some way through the CFG back to reachable code;
when it can't due to loops *then* it sets the state guard to false, signifying our not
being able to figure out where the guard ought to be merged back in.

This means that ASSUME false instructions now correctly truncate execution and are
recognised as unreachable code for the purposes of state merging (leading to better
constant propagation downstream), but in some cases we may see more guard growth
because code downstream of an ASSUME false is executed less rigorously that before,
which could result in the guard not being merged or being merged later than it otherwise
would have been.

Depth and unwind limit breaks behave roughly as before, except that there is some chance
the state guard will be merged rather than discarded, reducing costs downstream.
2019-09-26 15:26:59 +01:00