Pipeline definition
ReOxide can reconfigure the decompilation pipeline by using the default.yaml
file in the parent directory of the plugins
directory, e.g. /home/user/.local/share/Reoxide
. If this file does not exist, reoxided
copies it here on startup. This file has the same pipeline that Ghidra uses to decompile code:
- action: start
group: base
- action: constbase
group: base
- action: normalizesetup
group: normalanalysis
- action: defaultparams
group: base
- action: extrapopsetup
group: base
- action: prototypetypes
group: protorecovery
- action: funclink
group: protorecovery
- action: funclink_outonly
group: noproto
- action_group: fullloop
actions:
- action_group: mainloop
actions:
- action: unreachable
group: base
...
The structure of this pipeline mirrors the definition of the universal action described in the overview of the Ghidra decompilation pipeline. Four different types of entries describe the pipeline:
action
: A GhidraAction
rule
: A GhidraRule
action_group
: A grouping ofAction
objectspool
: A grouping ofRule
objects
When adding an action
or rule
entry to the yaml
file, you need to specify a name and a group. The following example shows the first action
entry, the action with the name start
:
- action: start
group: base
The ReOxide manager will search all loaded plugins for this name on startup and then construct the action from this plugin. All plugins currently share a global namespace and the libcore.so
plugin defines the start
action. We also see that the action definition specifies base
as its target group. This causes the execution of the action apply
function when Ghidra selects the base
group during construction of a default action. If you want to make sure that an action executes during the decompile
default action, the default groups documentation lists all groups enabled by this action. The definition of rules follows the same pattern, except only pool
entries allow listing rules.
Action and rule containers
The action_group
entry structures the control-flow of the actions inside the group. Because Ghidra currently initializes all action groups with the Action::rule_repeatapply
flag, the action group restarts if any of the rules apply. Examine the following excerpt from the default pipeline:
...
- action_group: fullloop
actions:
- action_group: mainloop
actions:
- action: unreachable
group: base
- action: varnodeprops
group: base
- action: heritage
group: base
- action: paramdouble
group: protorecovery
...
Ghidra defines fullloop
as outermost action group, making it the primary loop of the pipeline. Since we can treat an action_group
the same as a normal action
, we can use the mainloop
as an action inside the fullloop
group. The mainloop
group then consists of actual action
objects. This means, for every change an action
makes inside mainloop
, the mainloop
restarts. Conversely, if mainloop
applied any changes, the outer fullloop
will also restart after the mainloop
execution finished.
In a similar manner, pool
objects group rule
objects. We can treat pool
objects the same as an action
, but the pool
itself can only hold rule
objects. The following excerpt shows one of the default pipeline pools:
...
- action: infertypes
group: typerecovery
- action_group: stackstall
actions:
- pool: oppool1
rules:
- rule: earlyremoval
group: deadcode
- rule: termorder
group: analysis
- rule: selectcse
group: analysis
- rule: collect_terms
group: analysis
- rule: pullsub_multi
group: analysis
- rule: pullsub_indirect
group: analysis
- rule: push_multi
group: nodejoin
...
The oppool1
pool works the same way as the action_group
. The contained rules apply to P-Code opcodes and the pool tries to apply these rules repeatedly until they do not trigger any further changes. In comparison to the action
object, pool
and action_group
do not have a group
attribute. This means they do not have a default group and Ghidra cannot disable entire action groups or pools. Instead, if the specified default action does not include, for example, the deadcode
group, the earlyremoval
rule in the excerpt will not run. Conversely, the looping structure of action groups and pools still stays the same, even if they no longer contain any actions or groups.