Commit Graph

58 Commits

Author SHA1 Message Date
Alessandro Di Federico cf6e02bbef Several new helper functions
* QuickMetadata has been expanded to get a `MDString` or a `MDTuple`
  from a `StringRef`.
* Introducing `skipCasts`, which, given a `Value`, returns the innermost
  part of the expression, skipping over casts.
* Introducing `isCallTo`, which, given an `Instruction`, returns whether
  it's a call to a specific function or not. `getCallTo` is a sister
  function to be used in `if` statements.
* Moving `skip` and `erase_if` in `ir-helpers.h` so that all the
  translation unit can benefit from their usage.
2017-08-12 16:56:22 +02:00
Alessandro Di Federico 24c1df3540 Fix GCC 6.3.0 warnings
This commit fixes some warnings given by GCC 6.3.0.

* Some `assert(false)` are not recognized as `noreturn`ing. They have
  been replaced with `llvm_unreachable`.
* Added `-Wno-ignored-attributes`: attributes are not part the function
  name mangling, and therefore they might create some problems when they
  are involved in template arguments. We don't care.
* Specializations of `readPointer` functions in `binaryfile.h` are now
  `inline`, so they don't appear as "unused" functions.
2017-04-22 00:26:55 +02:00
Alessandro Di Federico 0ba8bb80e2 OSRA: clear BoundedVvalue::Bounds before merging
We used to assert that a `BoundedValue` must not have any entries in the
`Bounds` field before translating a `boost::icl` interval to a
`BoundedValue`. However, if the `Value` associated to the `BoundedValue`
is a `Constant`, we might have an entry in `BoundedValue::Bounds`
immediately after constructing the object. This commit fixes this
problem by simply updating the assertion and clearing the field before
re-populating it.
2017-04-02 17:10:39 +02:00
Alessandro Di Federico 6d9b0c4354 SET: use the appropriate type while materializing
While materializing values in SET through the `OperationStack` we used
to use as a type the type of the value associate to the currently used
`BoundedValue`. This was wrong, this patch uses the type on the free
operand on the top of the `OperationsStack` to perform the required
computations.
2017-03-31 10:10:16 +02:00
Alessandro Di Federico 66ef40f9fe Rewrite OSRA::handleComparison
`OSRA:handleComparison` was too big and complex, it has been mostly
rewritten.

* Create `OSRA::identifyComparisonOperands` which expands the argument
  of the comparison in a list of possible values (constants or
  OSRs). The new way in which we handle possible operands also fixes a
  bug showing up in case a constant OSR was being compared with an LLVM
  constant, which was checked for being a tautology/contradiction,
  preventing the reaching definitions of the operand to be considered
  too.
* Squeeze more information from uge/ugt. Unsigned comparisons lead to
  two pieces information: the result of the comparison itself, and the
  fact the left-hand side is greather than or equal 0. This secondo
  information is precious, but we were not able to exploit it in the
  case the original comparison is already "greater than" or "greater
  than or equal". In fact, `x - 4 > 10` gives us `x >= 4` and `x > 14`,
  which boils down to `x > 14`.  This commit introduces a change that
  handles this case as `NOT x - 4 <= 10` leading to the negation of `x
  >= 4` and `x < 14` which is way more informative.
* Improve `OSRA::mergePredicate` and `OSRA::applyConstraints`
  interfaces.
* In case a comparison instructions leads to multiple constraints on the
  same `Value`, these constraints are now first or-merged together and
  then propagated. This change improves the quality of the analysis in
  certain situations.
2017-03-23 17:58:06 +01:00
Alessandro Di Federico 5b8fb1af14 BoundedValue: support for multiple ranges
This commit introduces radically changes the implementation of
`BoundedValue`: it no longer represents a single, contiguous range, but
an arbitrary number of ranges.

The bounds are now represented through a
`llvm::SmallVector<std::pair<uint64_t, uint64_t>, 3>`.

* Introduce the `BoundedValue::bounds()` method, which allows to iterate
  over all the ranges that a `BoundedValue` represents. The `bounds`
  method returns a `Bounds` object, which can be used as a range
  composed by `BoundsIterator`.
* All the methods dealing with the `BoundedValue`'s bounds have been
  rewritten.
* New debugging information: "bv-merge". Print all the computations
  performed by `BoundedValue::mergeImpl`.
* Drop dead code: `BoundedValue::setBound` and `isPositive`
* Introduce `BoundedValue::isRightOpen` and drop
  `BoundedValue::isSingleRange`
2017-03-23 17:58:05 +01:00
Alessandro Di Federico 4089c203fc Improve OSRA::pathSensitiveMerge
Some subtle bugs have been fixed in `OSRA::pathSensitiveMerge`:

* Do not alter the current `BoundedValue` if merging a component would
  lead to bottom.
* Do not deactivate a reacher in case an incoherent condition is met.
2017-03-23 17:58:05 +01:00
Alessandro Di Federico bddc0d03d6 OSRA: x | bottom = x, not bottom
or-merging bottom with anything used to produce a bottom value, which is
wrong. The non-bottom value should be produced instead.
2017-03-23 17:57:31 +01:00
Alessandro Di Federico 0f70a6ef8a Propagated constraints should be and-merged
Constraints associated to a memory instruction are propagated to
reached loads. However, if a constraint on the same `Value` is already
present, the new constraint should be and-merged, not or-merged.
2017-03-23 17:57:31 +01:00
Alessandro Di Federico 8bb3a38246 Minor improvements
* Introduce some additional helpers
* Spread some `const`ness
* Improve documentation
* New debugging information: "osr-bv". Prints every update operation
  performed in `BVMap::update`.
* Remove dead code
* Whitespace fixes
* Some new TODOs
* Fix some typos in comments
2017-03-23 17:57:30 +01:00
Alessandro Di Federico 850fc09a69 Switch BoundedValue::merge to boost:icl
This commit drops the original handcrafted implementation of
`BoundedValue` merging, in favor of an implementation based on Boost
intervals. The old implementation was the source of intermittend bugs,
using Boost should be a more reliable solution. Moreover, this commit
enables moves us towards supporting multiple ranges in `BoundedValues`.
2017-03-10 08:32:46 +01:00
Alessandro Di Federico 51019ddfba Minor fixes to BoundedValue::merge 2017-03-09 19:47:01 +01:00
Alessandro Di Federico fd10c8d880 Introduce OSRA::dump() 2017-03-09 12:05:59 +01:00
Alessandro Di Federico 87dc88c284 Reorganize OSRA
The main goal of this patch is to reduce the size of
`OSRAPass::runOnFunction()`. To do this we created the `OSRA` class
which handles everything `runOnFunction` was taking care of but without
the ugly lambdas nor being an endless function. Each class of
instruction is now handled by a dedicated function.

This also has the side effect of heavily reducing the amount of clutter
exposed by `OSRAPass` to its users.
2017-03-06 14:31:29 +01:00
Alessandro Di Federico f8c7ebab2d OSRA: ignore unknown signedness in comparisons
When performing a comparison, we try to attach its signedness to the
base OSR it's working on. However, this is not always
effective. Typically, even after this, the OSR remains with an unknown
signedness due to the fact that we don't have information about its
bounded value from all the predecessors, and therefore it goes to top.
2017-03-02 08:21:11 +01:00
Alessandro Di Federico 1bbe758ea3 OSRA: heavily reduce constraint propagation
This commit reduces the amount of constraint we propagate. We do this in
two ways. First, by computing the set of all the instruction that will
ever be affected by the current instruction (recursively). Second, by
preventing propagation on constraints across function calls.

In quick test on `ls` compiled for MIPS we reduce the execution time by
55% of the peak memory usage by 68%. This makes me quite happy.
2016-12-08 21:56:11 +01:00
Alessandro Di Federico 57fa395ccc OSRA: always create an OSR for Trunc/ZExt 2016-12-08 21:56:11 +01:00
Alessandro Di Federico 9cfc716027 Make stores' OSR relative to the stored value 2016-12-04 00:28:58 +01:00
Alessandro Di Federico fe907a38b5 Enforce LHS >= 0 only in ULE and ULT comparisons
Fix a bug which lead to enforce that the left-hand side operand of an
unsigned greater than or greater than or equal comparison was <= 0. This
was the result of some intimate desire for symmetry in my mind which
does not actually exist.
2016-12-04 00:28:57 +01:00
Alessandro Di Federico 4add54fcde Make PSM debugging information more verbose 2016-12-04 00:28:57 +01:00
Alessandro Di Federico 85a39958d7 Increase maximum exploration depth in PSM to 10 2016-12-04 00:28:57 +01:00
Alessandro Di Federico c069700bc5 Keep the CFG simple: do not jump to the dispatcher
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.
2016-12-04 00:28:56 +01:00
Alessandro Di Federico d01ee1f437 Copyright notices, license and credits 2016-09-21 01:45:26 +02:00
Alessandro Di Federico cc87ad607d Introduce NoreturnAnalysis
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.
2016-09-17 15:33:57 +02:00
Alessandro Di Federico e9834e25b9 Exploit the power of unsigned comparisons
An unsigned comparison such as `x - 3 < 5` carries two information: the
first is the obvious one (`x < 8`), but the other one is even more
interesting. In fact any unsigned comparison implies that the LHS is not
negative, therefore we also can state that `x >= 3`. This commit
implements the usage of this information.
2016-09-17 15:33:56 +02:00
Alessandro Di Federico 621095c31a Create OSRs also for trunc and zext instructions 2016-09-17 15:33:56 +02:00
Alessandro Di Federico 65190dc20e OSRA: bugfixes about constant bounded values
* When creating a new `BoundedValue`, check if the value associated to
  it is a `ConstantInt` and if so, initialize the boundaries and the the
  signedness as appropriate.
* Add various checks for the presence of the signedness information
  before using functions that might require it.
2016-09-17 15:33:56 +02:00
Alessandro Di Federico 51d73d6b18 Register analysis passes as such 2016-09-17 15:33:56 +02:00
Alessandro Di Federico 46fe86225b Free memory after analyses
* Clear all the data that's not part of the analysis results at the end
  of the `runOnFunction` method
* Clear all the data that's part of the analysis results when the
  `PassManager` tells us so (`Pass::releaseMemory`)
* Do not use the `clear()` method, since it doesn't release memory
* Add some debugging information
2016-09-17 15:33:56 +02:00
Alessandro Di Federico 7e8ac596b5 Minimize pathSensitiveMerge usage
Record amount of reaching definitions for each load, even in
`ReachedLoads` mode, so that we can run the `pathSensitiveMerge` only
when we're sure we've collected all of them.
2016-09-17 15:33:55 +02:00
Alessandro Di Federico 168bac9079 Merge of BV: handle the [0,1] | [2,3] case 2016-09-17 15:33:55 +02:00
Alessandro Di Federico c1742184e7 OSRA: subscription for the update of load reachers
An instruction can now subscribe for the change of the list of reachers
of a certain load. This is particularly useful in the case of `ICmp`
instructions, which might hold constraints about the reachers of a
certain load without actually being a its user.
2016-09-17 15:33:55 +02:00
Alessandro Di Federico f4d71cf926 OSRA: improve handling of multi-defined loads
Before this commit, loads with multiple definitions were handled by
simply checking if all the definitions agreed. Now we also implement
some logic to put constraints on the new OSR, in case they don't agree.

To do this we implement a path-sensitive algorithm to collect
constraints about the reaching definitions.

This commit also introduce a set of methods to, if possible, apply an
OSR to a BoundedValue, e.g. [1 + 1 * x] will produce a new BoundedValue
whose bounds are shifted of 1 unit.
2016-09-17 15:33:54 +02:00
Alessandro Di Federico 37f54ffc8d Handle some undef cases building ConstantExprs
Some undefined behaviors, which result in `undef` values, are now
handled in `OSR::solveEquation`.
2016-09-17 15:33:54 +02:00
Alessandro Di Federico a372b878bd OSRA constraints: handle reaching definitions
In OSRA, when producing constraints associated to a `ICmpInst`
associated to a load instruction, consider also all of its reaching
definitions.

Moreover, when propagating constraints due to a `Br` instruction, look
for loads which might be affected by the constraints being propagated,
and, if necessary, update them.
2016-09-17 15:33:53 +02:00
Alessandro Di Federico 00a1e49f81 OSRA: handle load/store using reaching definitions
Use information from (`Conditional`)`ReachingDefinitionsPass` to
propagate OSRs and constraints when a load/store instruction is met.
2016-09-17 15:33:53 +02:00
Alessandro Di Federico deae1f841e SimplifyComparisonsPass: transform in analysis
* Add an "s" in the name
* Transform the pass in analysis and let OSRA use it
2016-09-17 15:33:53 +02:00
Alessandro Di Federico fcf9603456 Improve and isolate MemoryAccess
Isolate in its own file so that multiple class can benefit from it and
improve its potential performance.
2016-08-20 03:10:49 +02:00
Alessandro Di Federico ce5aa5507d Remove argument from OSRAPass::identifyOperands
Remove an useless argument from `OSRAPass::identifyOperands` and apply
some whitespace changes.
2016-08-20 03:10:49 +02:00
Alessandro Di Federico e3952732f0 OSRA: add proper support for constant - x
OSRA can now properly handle subtractions whose *first* operand is
constant.
2016-08-20 03:10:49 +02:00
Alessandro Di Federico 850fbf1bbe OSRA: represent constants as BV constraint
Constant OSR are now represented through an OSR such as
[0 + 1 * x with x = (*, c, c)]. Since equality doesn't hold any
signedness information we introduce a new signedness type (available
only in `BoundedValue`), `AnySignedness`, which is similar to
`UnknownSignedness` but does not trigger `isUninitialized() == true`.

In `BVMap` we also introduce the concept of "forced" constraint, i.e. a
constraint that is fixed, cannot be changed or update. Constant stores
will produce this type of constraints.
2016-08-20 03:10:49 +02:00
Alessandro Di Federico bfcb58bade Debug info: replace pointers with sensible names
This commit introduces the `getName` function, which, given a
BasicBlock, an Instruction or a Value, outputs a sensible name. In
particular instructions are now identified as [basic block]:[instruction
index].

`getName` is now used in the various `describe` methods in OSRA.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 8e589238bf Various bugfixes in merging BVs 2016-08-20 03:10:48 +02:00
Alessandro Di Federico ecdfab70a9 OSRA: don't propagate dead stores
Sometimes QEMU writes to register that are never used afterwards,
typically the `cmp` instruction sets several CPU flags which might be
ignored.

This becomes a problem when comparison are performed since they affect
the signedness of a BoundedValue. With this patch, we ignore their
effect if we can prove it's a dead store.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 7d55f3dd6b Handle multiple stores reaching a load
With this patch we basically handle a load as a sort of phi-node, since
we keep track of all the store/loads reaching a certain load, along with
their OSR, so that we can come up with smarter merging policies and
obtain more precise information.

This commit also introduce a change that leads to consider loads as
stores during propagation.  This heavily simplifies the store
propagation logic by considering load instruction as aliasing, and by,
consequently, propagating load (along with stores). This removes
completely the need for the concept of "conflicts".
2016-08-20 03:10:48 +02:00
Alessandro Di Federico d0f5944133 Factor out reusable data structures 2016-08-20 03:10:48 +02:00
Alessandro Di Federico 23818e9da4 OSRA: handle register-relative memory accesses
Introduce the `MemoryAccess` class which represents the source of a
`LoadInst` or the destination of a `StoreInst` for which we want to
propagate an OSR.

This patch handles more elegantly the propagation and introduces support
for propagating OSRs through register + offset memory accesses, in
particular stack pointer- (or base pointer-)relative memory accesses,
which are common in unoptimized code and that led to miss some cases
that we otherwise handle correctly.
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 7d4e95b45e Associate BoundedValue to constant OSRs
The current modeling of constant OSRs prevent their merging on basic
blocks. This was due to the fact they had no `BoundedValue`
associated. This patch fixes this by representing them as:

    [120 + 0 * x, with x = (null, ?)]

instead of:

    [120 + 0 * x, with x = null]
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 08be097123 Fix typos, add an assert, spread some const-ness 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 4547b4731f Drop leftovers from weakness 2016-08-20 03:10:47 +02:00