The gigahorse framework offers various ways to tune its underlying algorithms.
Gigahorse features different context sensitivity algorithms:
TransactionalWithShrinkingContext
: The default context sensitivity of Gigahorse. Composite, including a public entry point component and a variable depth selective context component approximating private function calls and returns. Differs from the transactional context, due to its ability to shrink significantly, dropping elements that should no longer provide additional precision.TransactionalContext
: The context sensitivity presented in the Elipmoc paper. Composite, including a public entry point component and a variable depth selective context component approximating private function calls and returns.CallSiteContext
: Call(or block)-site context sensitivity with a variable depth.CallSiteContextPlus
: The above call-site context including a public function component.SelectiveContext
: Selective call-site context only including with dynamic jumps.SelectiveContextPlus
: The above selective context including a public function component.
You can run the decompilation pipeline with a different context sensitivity algorithm using the -M flag. Changing the context-sensitivity algorithm using the default 2-step pipeline is not suggested as it will override the default for both configurations. As an example, the command below will run the example contract using call-site context sensitivity:
python3.8 gigahorse.py examples/long_running.hex --disable_scalable_fallback -M "CONTEXT_SENSITIVITY=CallSiteContext"
In addition the -cd
flag can be used to provide a different maximum context depth.
You can use the --early_cloning
flag to enable the cloning of blocks that are likely to introduce imprecision to the decompilation output. Can end up producing a more precise decompilation output, but on average makes decompilation take 1.5x as much time. This flag currently enabled by default.
You can use the --enable_limitsize
flag to enable souffle's limitsize directive abruptly stoping the execution of certain key/heavy relations.
WARNING: Using limitsize will also stop the execution of other relations in the same stratum, can affect the decompilation output in unexpected ways.
By default, the gigahorse pipeline contains a stage inlining small functions, in order to produce a more high-level IR for subsequent client analyses.
The inlining stage can be disabled using the --disable_inline
flag.
You can use the --debug
(shows souffle
warnings/errors, outputs datalog relations using the DEBUG_OUTPUT()
macro) and -i
(runs souffle
in interpreted mode) flags when developing gigahorse or client analyses.
To use this framework for development purposes (e.g., writing security analyses), an understanding of the analysis pipeline will be helpful. This section describes one common use case --- that of visualizing the CFG of the lifted IR. The pipeline will consist of the manual execution of following three steps:
- Fact generation
- Run main.dl using Souffle
- Visualize results
In order to proceed, make sure that LD_LIBRARY_PATH
and LIBRARY_PATH
are set:
$ cd souffle-addon
$ export LD_LIBRARY_PATH=`pwd` # or wherever you want to put the resulting libfunctors.so
$ export LIBRARY_PATH=`pwd` # or wherever you want to put the resulting libfunctors.so
We suggest adding LD_LIBRARY_PATH
and LIBRARY_PATH
to your .bashrc
file
Now let's manually execute the pipeline above:
$ ./generatefacts <contract> facts # fact generation (translates EVM bytecode into relational format)
$ souffle -F facts logic/main.dl # runs the main decompilation step (written as a Datalog program)
$ clients/visualizeout.py # visualizes the IR and outputs (all outputs of Datalog programs are in a relational format)