We used to have a normalized address space formed only functions,
skipping all the holes. This was employed to identify "skipping
jumps". However, this method was ineffective, and we changed the
definition of skipping jump as a jump skipping over CFEPs that are
highly likely to be actual functions.
This commit removes the leftovers of the normalized address space
computation, which was also the cause of a bug in function detection.
This commit introduces two new passes:
* `GeneratedCodeBasicInfo`: recovers from the IR some basic information
like the size of delay slots in the input architecture, the name of
the program counter and so on. It can also identify the type of a
basic block (e.g., dispatcher, jump target...). *
* `FunctionCallIdentification`: identifies function calls and injects a
marker before the associated terminator instruction.
The idea of these two passes is to try to progressively move information
we used to keep in `JumpTargetManager` into the IR, so that it is more
easily accessible and passes do not need a reference to `JTM`.
In particular by having markers for function calls available during jump
target discovery we don't have to have duplicated and suboptimal
implementation of `isCall`.
This commit also introduce some additional helper functions and an
helper class to quickly.
This commit improves the `NoreturnAnalysis` by inflating the set of
killer basic blocks using the set of basic blocks post-dominated by the
set of killer basic blocks. To do so, we temporarily replace the
successor of all the killer basic blocks with a single basic block (the
"sink") and then computed the set of basic blocks it post-dominates.
To improve the precision of our analysis we work on the CFG in
`NoFunctionCallsCFG` form, so we don't "infect" functions called by kill
basic blocks. However, since we work in this CFG form, we need to
manually collect the list of basic blocks calling a killer function and
compute the set of basic blocks they post-dominate.
`NoFunctionCallsCFG` is a form of the CFG where all the function call
edges are replaced with jumps to the return address. This is beneficial
in certain analysis to pretend we're working on a function-level.
To implement such a form of CFG we now emit right before the terminator
of each caller basic block a call to the "function_call" function
passing as the first parameter the callee basic block and as the second
one the return basic block. Using this function calls, switching to
`NoFunctionCallsCFG` and back becomes straightforward.
Every time we don't know where an indirect jump can go, we used to emit
a jump to the dispatcher, however this complicates our analyses, in
particular the computed dominator tree provides less useful information
than it could.
This commit transforms all the jumps to the dispatcher into jumps to a
"anypc" basic block which during analysis just contains an unreachable
instruction, but during finalization this instruction is replaced with a
jump to the dispatcher. A similar (temporary) situation is for the
"unexpectepc" case.
This commit also makes the `visit(Sucessors|Predecessors)` functions
more idiomatic by employing a trait for black lists.
Create a MDNode for each identified function and associate to the
terminator instruction of each basic block a list containing a reference
to the MDNodes identifying the functions it belongs to.
This commit introduces the `noreturn` analysis, whose aim is to detect
all the basic blocks the are doomed to lead to a `noreturn` syscall such
as `execve` or `exit`.
* Implement `NoreturnAnalysis`.
* Include and initialize in the `Architecture` data structure all the
necessary information to detect `noreturn` syscalls. Specifically, the
name of the QEMU helper for syscalls, the name of the register holding
the syscall number and the syscall numbers representing `noreturn`
syscalls.
* `ReachingDefinitionsPass`: make reaching definitions available both in
reaching definitions mode and reached loads mode. This part needs
further cleanup. We also might be willing to implement this with a
`Boost.Bimap`.
* Use `SET` to collect information useful for the
`NoreturnAnalysis`. Also restructure how the `OperationsStack` works
to be more streamlined and keep track of multiple information about
the instruction currently being tracked.