Replace the stub implementation of invalidation with the proper
implementation. A ReadPathCache is added to each global so that it can
keep tracks of what target are associated to which read paths.
This commit switches the approach with which we run the ABI analyses: we
now run them until we reach a fixed point. This enables proper
interprocedural propagation of arguments and return values.
Basically, we now inject reads before call sites, so that, if a function
immediately calls another one, the arguments of the callee are
propagated to the caller.
This commit also updates the logic with which we propagate function
prototypes (and names) to callers. The main advantage of this, is that
function wrappers (in particular, PLT entries) now have the same name as
the function they wrap.
The collection points of several ABI analyses where incorrect. Several
analyses that should have collected data only from entry points were
collecting data from any node in the graph.
Up until now, we did not need different !dbg/DISubprogram
attached to each isolated llvm::Function, but for the
purpose of MLIR lowering, we need it.
On the LLVM IR level, we used to reuse root's DISubpgram,
and we have not being attaching !dbg/DISubprogram to the
isolated functions at all (just to llvm::Instructions),
but that was an hack in order to avoid some LLVM verify
checks, since LLVM IR expects !dbg attachments to calls of
functions that could be inlined, but by avoid !dbg on the
Function itself, it won't verify !dbg attachments on the
instructions, since it will assume it has no debug info in
it. When it comes to MLIR, it expects different !dbg
attached to each function, in order to process debug info
in it, so that is the reason we cannot rely on the root
DISubprogram only anymore.
getJumpTargetBlock takes llvm::BasicBlock * as argument, but doesn't
need to modify it, so const it adds const to it and other functions that
are used by getJumpTargetBlock: findJumpTarget, isTranslated, getType,
isJumpTarget.
The goal of this update is to propagate prototypes of functions called
in wrappers to this wrappers.
When some function hasn't it's own prototype, but the only thing it does
is calling another function, DetectABI pass sets callee prototype as
caller prototype also.
This behaviour is limited to callers that:
1. have only one basic block
2. end with call
3. don't write arguments of callee
4. don't modify stack pointer
5. don't write to memory.
`ValueMaterializer` is a rewrite of what was called `AdvancedValueInfo`
which follows the same principles.
The main benefits over the old version is:
* We materialize the data-flow graph and the CFG of the relevant part of
root. This makes debugging significantly easier.
* We drop the old MonotoneFramework infrastructure in favor of
getMaximalFixedPoint.
* We significantly reduce the amount of queries we make to
AdvancedValueInfo.
We used to ignore CFEPs that matched the starting address of a basic
block of a previously detect function.
We now also exclude such CFEPs even if the candidate is *part* of an
existing block.
This is done mainly so that downstream passes do not need to run
`CollectCFG` to store information that has already been computed but not
serialized.
This come at the cost of computing the CFG also of functions we don't
want to analyze in `DetectABI`.
We used to only color instructions in the same BasicBlock as the call to
`newpc`. However, an instruction in the original binary can span
multiple BasicBlocks.