Update the `OriginalBB` map (which will be later used for retrieving the
original basic block linked to a certain BBNode) during nested
`RegionCFG` creation and during flattening, which are steps that modify
the allocation of the `BBNode` objects.
The `RegionCFG::initialize` method is now a template method, which
accepts as input any kind of object which exposes the `GraphTraits`.
In this way we can build a `RegionCFG` object not only starting from
LLVM IR, which can be very useful for testing purpose.
Since we also removed the information about the original
`llvm::BasicBlock` inside the `BasicBlockNode`, we need to keep this
link to later feed this information to the GHAST in an external data
structure (potentially a `std::map`).
The `BasicBlockNode` does not contain anymore any pointer to the
`llvm::BasicBlock` object that generated the `BasicBlockNode`.
This change is necessary for decoupling completely the `BasicBlockNode`
and `RegionCFG` classes from the LLVM IR, so that we can build up a
`RegionCFG` from any object which implements the `GraphTraits`.
The `RegionCFG` does not contain anymore a map between
`llvm::BasicBlock` and `BasicBlockNode`.
Once we compute the set of backedges, they should be fixed and should
not change during the restructuring phase, otherwise we may end-up
inserting loops including outlined node if the information about the
backedges changes completely during the analysis (edge that were
backedges and for which a corresponding SCS was computed become forward
edges, and viceversa, and this behaviors break our assumptions that
outlined node do not take part in loops ever).
This means that we need to keep updated the set of backedges computed at
the beginning instead of recomputing it at each restructuring iteration.
We need to take particular care in updating the information in presence
of the default `SetNode` inserted in case of an entry dispatcher.
The actual implementation is pretty naive, and the update of the
`Backedges` `std::set` is for sure not optimal, we should consider using
a `std::multimap` for it.
We should also consider updating the reverse postorder instead of
recomputing it, but at it seems that recomputing it may cause
sub-optimal restructuring, but no errors should be triggered.
New SCS merge step for situations in which we have an abnormal edge
exiting from an SCS.
This criterion, during the preprocessing of the metaregions, if an SCS
with an abnormal retreating edge is found (an abnormal retreating is a
retreating edge which target is outside the scope of the current SCS
under analysis), merges the metaregion under analysis with the one which
has been created starting from the backedge.
This preprocessing phase is made in a fixed point fashion.
When creating the collapsed node, remember to add in the substitution
phase of the old nodes of the regions (relative to the outer regions),
also any nodes added as default `SetNode`s for any entry dispatcher
inserted.
Add an assert which verify that all the targets of the retreating edges
fall inside the SCS under analysis.
Add other asserts to verify that the graphs passed to the comb pass are
acyclic after restructuring.
The `removeNotReachables` method now can take care of removing any
reference of the removed nodes from any `MetaRegion` which contains any
reference to it.
Now avoiding `predecessors()` iterator invalidation and enforcing
bounds check when using `ClonedMap` during first iteration outlining.
Also avoiding usage of `FirstCandidate` once the real head of a
`RegionCFG` has been elected (only `Head` ptr should be used).
Moved a lot of passes that apply optimizations on the AST in the
decompilation pass.
All the optimization functions are now in a dedicated file
(`CDecompilerBeautify.cpp`) and the only function used as interface with
the `CDecompilerAction` pass is the `beautifyAST` function.
This means that now the simplifications will be applied on the already
flattened AST.
Some basic transformations have been left in the `RestructureCFG` pass,
to avoid having an AST of poor quality as output of the pass.
Removed the `Switch` BBNode, which was used to create the intermediates
nodes for making an original `switch` node a nested tree of `if` checks.
Also removed the `IfEqual` AST node, which was used to represent the
intermediate check nodes in the AST, for later reconstructing the
original `Switch` node in the AST, when possible.
Now considering the fact that the body of a loop may become empty if
some simplification take place (e.g. we match a `while` whose body is
composed only by a check with `break` and `continue` branches).
When a `while` loop is matched and promoted, add to every `continue`
node in the current scope the instructions needed for the computation of
the loop condition.
Match `do-while` and `while` loops, transform the in our AST preserving the
information about the `IfNode` which computes the condition of loop, and
emit them in the decompiled code.
Also added a pass which removes useless continue nodes.
Now in the `SCS` identification phase, when creating a SCS, if we
contain a node which is the source of another (sub)SCS, we also include
that SCS in the current SCS (in order to increase the number of nested
subregions).
The exception to this situation is when the source of the
other SCS is the head of the region itself under analysis.
Now, during the simplification of short-circuits the so called
`de-optimization` is also applied to the corresponding `RegionCFGTree`.
This allows us to avoid loss of information during the iterative
refinement phase, which basically divides for ever the existencies of
two nodes that have been cloned starting from a single original one.
We now perform the AST serialization directly on file, without using
stderr. In this way we can follow the evolution of simplifications and
changes to the AST tree.
Improved the `dumpOnDotFile` function to take as a parameter also a
sub-folder name.
Modified the `inflate` function to dump on file the graphs after each
modification.
This change makes `CMakeLists.txt` files less verbose and allows proper
registration of debug `Logger`s from revamb `Support` library,
enabling their use without manually enabling them.
This also means that they can be properly enabled with command line
arguments and that we can remove some hacks in the code that was put in
place to work around this limitation.
First concept of short-circuit simplification.
The `isEqual` operator between ASTNodes is very limited (it does only
check if two nodes originate from the same `BasicBlock` in the original
IR.
Outlined the removal of nodes not reachable from the entry node in an
external function. This is useful to reuse the function not only for the
main graph, but also for the collapsed regions.
In this way we can remove not reachable nodes in the inner regions, such
as dandling `break` and `continue` nodes (found in an endless loop).
This fix enables the correct updating of the backedges present in the
graph, since each transformation pass could in principle modify some of
the backedges present in the graph