Commit Graph

3168 Commits

Author SHA1 Message Date
Pietro Fezzardi aecfd8c7f6 ASTBuildAnalysis: handle undefs in InserValueInst 2021-02-02 11:23:53 +01:00
Pietro Fezzardi d01aa3b0fb Move SCEVBaseAddressExplorer to its own file
This enables using it in the decompilation backend.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 088015e11c Forward SCEV and DLA results to decompilation 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 3cbd8f2254 Create AddSCEVBarrierPass
This `FunctionPass` uses the results of `MarkForSerializationPass`, if
present, to wrap some instructions into calls to `revng_scev_barrier_*`
functions.

`revng_scev_barrier_*` functions have names that are deterministically
constructed from the type they wrap.
They have the semantics of an identity function, but we don't provide
the body, so that LLVM's ScalarEvolution Analysis cannot see through
them.

At the moment, the inserted function calls are not manipulated anywhere
else in the codebase, but we plan to use this mechanism in the
decompilation pass to prune the expressions that are converted to
pointer arithmetic.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 23d2f19211 Remove old TODO 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 9d1d6afe6e MarkForSerialization: extract into its own Pass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi f642a0983c Decompiler: make NDuplicates a const reference 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 8be05522e6 MarkForSerialization: improve const-correctness 2021-02-02 11:23:53 +01:00
Pietro Fezzardi d1ada19ca6 CDecompilerBeautify: remove unused Mark parameter 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 2ff7044bb9 Decompiler: forward-declare types coming from DLA
This commits enable the emission of rich types associated with function
signatures. This types are forward-declared in the decompiled C code
before the definition of each decompiled function that uses them.

The types we emit for now are the types that the DLA is able to compute
(if any) for the return values and the arguments of the function.

Such types are not yet used in the body of the function, nor in the
function declaration. These are the next steps to come.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi b9c17362dd Decompiler: handle emission of logical operators
Before this commit, logical operators (&&, ||, !) were never emitted in
C. Bitwise operators were used instead (&, |, ~), relying on the
implicit equivalence of meaning.

This commit enables the emission of logical operators when the operands
are boolean types, making the emitted C more readable.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 476064d855 [DLA] kill structural deduplication of Layouts
Before this commit, the MakeLayout step of the DLA used to deduplicate
structurally equal Layouts. This has turned out to be wrong when going
forward with the emission of types in C.
Being able to tell apart two different types that are structurally equal
is important for the emission of C types. Throwing this information away
with deduplication is bad. This commit disables such deduplication.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi e0f9401ff8 ADT: add HeterogeneousPtrCompare template class
This is a utility class useful to make std::set<std::unique_ptr<T>>
searchable with raw pointers, by using
std::set<std::unique_ptr<T>, HeterogeneousPtrCompare<T>> instead.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi d6c8214d52 Decompiler: improve handling of command line flags
Handling of command line options that specify paths for output files
have been improved in the following ways:
- If the CDecompilerPass is not default-constructed, it already has a
  reference to the stream where outputs must be written. In this case,
  it is wrong to use a command line option to specify the output
  directory. If this happens the program is now able to detect it and to
  terminate with an error.
- If some of the specified paths is not found or has the wrong
  permission, the program fails early.
- On program failure because of one of the above safety checks, the
  program terminates with an informative error message.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi b59c239401 Decompiler: make all command line options Optional
This means that they can be specified only once on the command line.
If they are specified more than once, the program fails with an
informative error.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi ba3fb13dd6 CDecompilerPass: avoid removing calls to newpc
We now have a dedicated pass for that
2021-02-02 11:23:53 +01:00
Pietro Fezzardi ca999a7c3c Add DeclCreator class to unify forward declaration
Before this commit, the logic to generate all the emitted C forward
declarations (types, global variables, and functions) that has to be
printed before each decompiled function was scattered across three
classes: FuncDeclCreationAction, TypeDeclCreationAction, and
GlobalDeclCreationAction.

These are all gone now, because the scattered logic was very confusing
to follow. Now we only have a single class that takes care of
declarations with global scope: DeclCreator.

Thanks to this, I was able to drop a bunch of useless layers of software
engineering used to shape the creation of the declaration as if it was
some kind of clang ASTConsumer, which is pointless.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 1e825a8201 Create IRASTTypeTranslator class
This class handles the creation of type declarations in clang's AST, and
holds the relationships between llvm Types and Values with those clang's
type declarations.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi cbbbdf660f [DLA] propagate DLA results to CDecompilerPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 44564c2ba7 [DLA] export layouts to DLAPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 52d0d9aeb2 [DLA] Move Layouts declarations in separate files
This is a preliminary step for allowing DLAPass to export the computed
layouts as analysis results.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 84d9dd1533 ASTBuildAnalysis: enable print negative literals 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 59076db31b [DLA] Avoid instance links for unsupported offsets
This commit prevents the creation of instance links for offsets that we
don't support yet, during the CreateIntraProceduralTypes DLAStep.
This makes possible to avoid explicitly handling those cases in many
DLASteps, such as ComputeUpperMemberAccess,
ComputeNonInterferingComponents, and DLAMakeLayouts.

The offsets that are not supported yet are:
- all negative offsets
- all strided offsets with non-strictly-positive stride values
- all strided offsets with non-strictly-positive stride values
- all strided offsets with known negative trip-count

Some beneficial side-effects of avoiding the creation of such links are:
- the total number of edges on the graph is reduced, reducing the worst
  case depth of most visits
- it's impossible to create types with null or negative size (that we
  wouldn't know how to emit in C)
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 730854aa1c [DLA] Add CreateNonInterferingComponents DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 6ae374b5f0 [DLA] Add InterferingInfo to LayoutTypeSystemNode
This is a flag used to mark a given `LayoutTypeSystemNode`.
It represents the fact that the children nodes are either all
interfering with each other, non-interfering with each other, or
unknown.

This information will be filled-in by the
`ComputeNonInterferingComponents` step, and will be used from the
`MakeLayouts` step to decide if the children of the node will be emitted
as fields of a union (interfering) or fields of a struct
(non-interfering).
2021-02-02 11:23:53 +01:00
Pietro Fezzardi c40b3c5386 [DLA] Add LayoutTypeSystem::createArtificialLayout
This method allows to create artificial layouts that are not directly
associated to `llvm::Value`s.
Because of this missing association with `Value`s, the artificial
layouts are not retrievable by using the public `getOrCreateLayoutType`
and `getLayoutType` methods of `LayoutTypeSystem`, but they will be
accessible only by walking the graph.

The capability to add layouts that are not associated to `llvm::Value`s
is necessary for the future implementation of the DLA Step:
`ComputeNonInterferingComponents`.
The step will add artificial layouts to represent non-intefering
components.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 46a504b9ea [DLA] Drop useless method from LayoutTypeSystem 2021-02-02 11:23:53 +01:00
Pietro Fezzardi b980c8bcfc [DLA] Use defaulted operator <=> whenever possible 2021-02-02 11:23:53 +01:00
Pietro Fezzardi cdca33a99f [DLA] Guard costly verify calls with VerifyLog 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 6119e54e1b [DLA] Add MakeLayouts DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 8d02bec310 [DLA] Add ComputeUpperMemberAccess DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi e259397b4e [DLA] Add PruneLayoutNodesWithoutLayout DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 8fdfe8e169 [DLA] Add MakeInheritanceTree DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi fc7296a302 [DLA] Add RemoveTransitiveInheritanceEdges DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 22ebf9cf52 [DLA] Add CollapseIdentityAndInheritanceCC DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 94ca753808 [DLA] Add CreateIntraProceduralTypes DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi cdee2fb194 [DLA] Add CreateInterProceduralTypes DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 36c89c3118 [DLA] Add pipeline of steps to DLAPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi dda2b5aaa0 [DLA] Add skeleton for DLAPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi fc48930e5e [DLA] Add data structures for dla::TypeSystem 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 52b617a6dd [DLA] Add dla::Step and dla::StepManager
These are the elementary steps of the DataLayoutAnalysis (that is still
to be defined), along with a manager to handle them, their dependencies,
their executions and their invalidations.

In principle, this design could have been implemented inheriting from
`llvm::Pass` and `llvm::legacy::PassManager` (or `llvm::PassInfoMixin`
and `llvm::PMDataManager` for the new step manager).
However, LLVM's passes and managers provide far more complex features
than we need for now, so I decided to keep it simple and roll our own
for now.
We could potentially switch to LLVM stuff later if we need their power.

Some examples of features we don't need for now are:
- capability to pass results from a pass to another that depends on it
- capability to dynamically compute pass dependencies
- capability to dynamically invalidate passes
If some of these become necessary in future, it's a sign that it might
be time to switch to an LLVM-based design

The design is structured as follows.

1) Adding `Step`s to the `StepManager`

The `StepManager` owns the `Step`s, that can be added via the `addStep`
method.
Whenever a new `Step` is added, four properties are checked:
- that all its dependencies have already been added before it;
- that non of its dependencies have been invalidated by the insertion of
  another step that invalidate them.
- that it does not depend on itself
- that it does not invalidate itself
If any of these conditions fail, the `Step` is not added successfully.

Whenever a new `Step` A is added and it invalidates any `Step` B, the
last instance of B added to the `StepManager` before A (if present) is
marked as invalidated.
If one wants to add a new `Step` C that depends on B, it will be
necessary to explicitly add a new instance of A (say A*) before adding
C.
Otherwise, there will be no guarantee that an instance of A executes
before C without being invalidated.

These conditions on invalidations are restrictive but the allow to
specify the dependencies and invalidations that we need for now.
If it turns out we need more complex dependencies and invalidations we
should explore implementing the LLVM-based design.

2) Executing the added `Step`s

After adding the `Step`s to the `StepManger`, they can be executed all
together with the `dla::StepManger::run()` method.

This method runs all the steps in the order they were added by the user
with calls to `addStep`.
The fact that `addStep` strictly ensures that dependencies and
invalidations are respected, guarantees that the execution always works
in the order of `Step`s specified by the user.
It also means that there is no need to check and propagate invalidations
across dependencies between the execution of the `Step`s, because there
is the guarantee that if a `Step` A invalidates `Step` B, another
instance of B will be executed later if some `Step` C needs it, or if
the user has added it explicitly.

When the `dla::StepManager::run()` method returns, all the `Step`s that
were successfully added to the manager have finished running.

3) Implementing a `Step`

Each `Step` has a virtual `runOnTypeSystem` method, that executes the
`Step` and returns true if some change was made, false otherwise.
`TypeSystem` for now is just a forward declaration and all the
implementations of `runOnTypeSystem` simply return true.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 7ff39039a8 Add Liveness Analysis 2021-02-02 11:23:53 +01:00
Pietro Fezzardi a96f98821c [DLA] Add AdjustStackPointerPass FunctionPass
Add a pass that computes the lowest negative offset that is summed in
each isolated function to the local stack pointer returned by a call to
revng_init_local_sp (previously added by PromoteStackPointerPass).
After the computation, all the accesses relative to the stack pointer
are recomputed as if the stack pointer was lowered by the computed
amount.

This is useful to enable the DLA to easily recover layouts that are
placed at negative offsets from the stack pointer.
The reason is that the DLA in its current form does not handle negative
offsets, but at the same time negative offsets are important to recover
the layout of the local variables on the stack.

This pass implicitly depends on running PromoteStackPointerPass.
If PromoteStackPointerPass did not run before the execution of
AdjustStackPointerPass, the latter doesn't do anything.

For demonstration purposes, AdjustStackPointerPass has been implemented
both with LLVM's legacy PassManager and the new PassManager.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi a31bdbd602 [DLA] Add PromoteStackPointerPass 2021-02-02 11:23:53 +01:00
Antonio Frighetto 99274f1a41 GCBI: create wrappers to support old and new PM
The GeneratedCodeBasicInfo class has been disentangled in order to
create wrappers to support both the legacy and the new pass manager.
2021-01-28 17:03:31 +01:00
Antonio Frighetto eacc0b76b2 Refactor GCBI
Changes include:
- `getFunctionCall` has been moved in IRHelpers.h
- `getFallthrough` and `getFunctionCallCallee`
  have been simplified and added in IRHelpers.h (their old versions
  have been removed respectively from FCI.h and revng.h)
- `FCI::getCall` and `FCI::isCall` have been removed
  due to redundancy with `getFunctionCall`.
2021-01-28 17:03:30 +01:00
Massimo Fioravanti 8ba9930638 Invert inheritance of GenericGraph nodes
GenericGraphs no longer require CRTP.
2021-01-27 19:46:53 +01:00
Alessandro Di Federico b544e214b8 ProgramCounterHandler: CSVs are internal
This commit fixes a bug that lead to be unable to instantiate from a
`Module` `ProgramCounterHandler`. The reason for this was that
`ProgramCounterHandler` was using `Module::getGlobalVariable` which, by
default, ignores variables with internal linkage.
2021-01-27 19:46:53 +01:00
Alessandro Di Federico 38031f2f8a Import preliminary model
This commit imports:

* support for (de-)serializing tuple-like objects in YAML
* the Model data structure
* the {Load,Serialize}ModelPass
2021-01-27 19:46:53 +01:00
Alessandro Di Federico 28cb935d39 ZipMapIterator: handle dishomogeneous containers
ZipMapIterator can now handle containers of different type, as long as
their keys are comparable.
2021-01-27 19:46:52 +01:00