crytic / rattle

evm binary static analysis
https://www.trailofbits.com/presentations/rattle/
344 stars 41 forks source link

Optimize operations #4

Closed withzombies closed 6 years ago

withzombies commented 6 years ago

There are many constant operations that we don't optimize.

Pretty much every address load has 2-5 operations that can be optimized:

<SSA::Block offset:0x84>
   %20 = SLOAD(#1)
   %21 = CALLER()
   %22 = EXP(#2, #a0)
   %23 = SUB(%22, #1)
   %24 = AND(%23, %21)
withzombies commented 6 years ago

Initial work here: 8edd7768e9983220047da3ee30ee680dcfe6fe4c

pgoodman commented 6 years ago

If you had a global variable of all SSAConcreteValues, then your constant folding could work as follows: 1) Add all users of all concrete values to a work list 2) Initialize a next work list, and a progress var (you have it called dirty now) 3) For everything in our current work list: i) Get the list of users of the thing ii) Call peephole_optimize (I suggest renaming to fold_constant_expressions). iii) If folding happened, then extend the next work list with the users from (3.ii) and mark progress as being made 4) If progress was made, then set the work list to be the next work list from (2), and go to (2).

pgoodman commented 6 years ago

Peephole optimization is typically done on short sequences of instructions, e.g. converting an shl or imul and an add with an lea.

withzombies commented 6 years ago

Your approach to constant folding is to prevent excess work, right? It shouldn't be difficult, I could just modify the SSAConcreteValue constructor and destructor to manage the list membership.

The approach I'm using now works but has to loop over all the instructions dozens of times. I also have a max count to prevent infinite loops due to folding bugs.