Commit Graph

1642 Commits

Author SHA1 Message Date
Alessandro Di Federico e82635ee0b Introduce function_call-related helpers 2018-09-17 19:20:17 +02:00
Alessandro Di Federico 8eb532d73c Introduce StreamWrapper
`StreamWrapper` is a class that wraps a stream of any type. It has a
`flush` method, that, when called with a `std::stringstream` copies all
of its content in the wrapped stream.

The main reason for having `StreamWrapper` is being able to have a
`dumpInternal` method in a `.cpp` file while preserving a
stream-agnostic `dump` method in the header.
2018-09-17 19:20:17 +02:00
Alessandro Di Federico e6bc62f760 Twine: use them only as const Twine & arguments
`Twine`s are very cool but very subtle objects. You basically have to
use them as `const Twine &` arguments only. In fact, a Twine keeps a
reference to objects whose lifetime corresponds to the current
statament. Therefore, a `Twine` can easily end up holding a reference to
invalid objects.

This commit fixes a bug in function isolation (which would show up only
if optimizations are enabled) due to a misusage of
`Twine`. Additionally, it reduces its usage to safe places in
`statistics.h`. Finally, we added an assertion in `check-conventions.sh`
to ensure that no variables of type `Twine` are ever declared.
2018-09-17 19:20:17 +02:00
Alessandro Di Federico 25278f2e03 revamb-dump: -T option for dumping statistics
revamb-dump was missing the `-T` option.
2018-09-17 19:20:17 +02:00
Alessandro Di Federico 770d61b00f Drop assertion on QueueImpl 2018-09-17 19:20:17 +02:00
Alessandro Di Federico 0121ddfde4 Minor whitespace and formatting changes 2018-09-17 19:20:17 +02:00
Alessandro Di Federico c9c884d809 Introduce SmallMap::erase 2018-08-31 09:00:33 +02:00
Alessandro Di Federico fb7ad64070 CMake: one argument per line
This commit simply reduces the length of lines in CMake by splitting the
statements over multiple lines. This is particularly useful when listing
the translation units composing a program/library. In fact, it makes
merge much easier.
2018-08-31 09:00:33 +02:00
Alessandro Di Federico ee2ab2978e Reorganize enums in namespaces with functions
`enum`s throw their entries into the parent scope. `enum class` can work
around this issue, however, `enum class` cannot have methods. Since we
often need to have `getName` and `fromName` functions for the enums, we
now create a namespace for each enum that contain a number of helper
functions.
2018-08-31 09:00:33 +02:00
Alessandro Di Federico 82ab7869d9 Doxygen: parse files from git ls-files
Doxygen doc used to look for source files in the source root directory
only. We now use `git ls-files` to figure out which files need to be
part of the documentation.
2018-08-31 09:00:33 +02:00
Alessandro Di Federico 2c7e0ee50b Drop some leftover "Lol" variables 2018-08-31 09:00:33 +02:00
Alessandro Di Federico 6b39f031e1 Generate as much debug info as possible in tests 2018-08-31 08:42:31 +02:00
Alessandro Di Federico 51009347a2 Introduce CounterMap for collecting statistics
The `CounterMap` class allows to increment a counter associated to an
arbitrary key. This is useful for printing out statistics, e.g., per
`Function` or `BasicBlock`.
2018-08-31 08:42:31 +02:00
Alessandro Di Federico 198ccd83b7 OSRA: handle the bswap intrinsic 2018-08-31 08:42:31 +02:00
Alessandro Di Federico 149da95610 OSRA: ignore constants wider than 64 bits 2018-08-20 16:08:07 +02:00
Alessandro Di Federico f6753e7287 Make getModule(nullptr) return nullptr 2018-08-20 16:08:07 +02:00
Alessandro Di Federico a114f60299 New JTReason: ReturnAddress 2018-08-20 16:08:07 +02:00
Alessandro Di Federico d31af260c1 revamb-dump: stop Callgrind while loading LLVM IR 2018-08-20 16:08:07 +02:00
Niccolò Izzo 92253e23b2 Fixed typos in revamb documentation 2018-08-18 17:14:02 +02:00
Alessandro Di Federico 9a85cc3a04 Introduce check-conventions.sh, .clang-format
`.clang-format` is the configuration file for the `clang-format` tool,
which can help us to enforce a consistent coding style.

`check-conventions.sh` is a a simple bash script that checks (using
mostly `git grep`) if, after running `clang-format`, there are some
undesired situations such as lines ending with "(" or "<".

This script should produce no output before a merge request is
merged. However, currently this is not the case, therefore the script
should be used mostly for new code (in particular, files) only.
2018-08-18 17:09:23 +02:00
Alessandro Di Federico a0f4e0bb41 Introduce new assertion framework
A set of assertion-related functions has been introduced:

* `revng_abort(message)`: aborts, in release builds too.
* `revng_check(what, message)`: asserts `what`, in release builds
  too. Also emits a `__builtin_assume`, that can lead to additional
  optimizations in clang.
* `revng_unreahcable(message)`: identical to `revng_abort`, but in
  release builds emits `__built_unreachable`.
* `revng_assert(what, message)`: asserts in debug builds, otherwise
  emits `sizeof(what)` (to suppress unused variable warnings) and
  `__builtin_assume`.

The adoption of these function has the following benefits:

* Nice stack traces.
* The developer can choose to enforce an `assert` (or an `unreachable`)
  at release-time too by using `check`/`abort`.
* Most warnings about unused variables in release mode should be gone.
* When using clang, the `assert`s become `assume`s, which might enable
  additional optimizations (with no run-time costs).
* The `assert(Condition && "Reason")` trick is no longer needed, we now
  have a proper argument.
2018-08-18 16:25:40 +02:00
Alessandro Di Federico aa0d846bfc Merge branch 'feature/pie' 2018-08-18 11:46:30 +02:00
Alessandro Di Federico f2e1ea68f1 OSRA: improve handling of equality comparisons
Equality comparisons used to be ignored more often than required due to
the fact that they give no hint on the signedness of the tracked value.

This commits removes some assertions and improves the handling of OSRs
without a known signedness. In particular, now, inequalities can be
solved even in absence of signedness information, as long as the result
that you would get with a signed OSR and an unsigned OSR matches (i.e.,
the signedness doesn't matter).
2018-08-18 10:50:05 +02:00
Alessandro Di Federico 88e2a6eff1 OSRA: improve handling of unsigned comparisons
We used to have a special handling of unsigned comparisons, since we
assumed that each side of the comparison had to be greater than or equal
to zero. This commit further widens the cases in which this is
useful. Specifically, if both the comparison we're dealing with and the
greater-than-or-equal-to-zero comparison don't have an upper bound, we
flip one of the two in a way that ensure that they represent a closed
interval. Then, if the flipped comparison is the former, we reflip the
final result.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico 8773186ef1 OSRA: handle identical-but-negated conditions
If a conditional branch propagates a constraint on a value that is
exactly the opposite with respect to its current constraint, we simply
ignore it, since simply flipping the condition (and the destination
basic blocks) would do the same.

In future, we should propagate a contradiction on the appropriate
branch.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico 85a000089f merge-dynamic.py: generate .hash section
We used to ignore the `.gnu.hash` section, however it turns out to be
fundamental in case the ELF we're working on *defines* one or more
symbols. This has not been a problem so far since we usually work with
the main executable only, which, usually, doesn't define any dynamic
symbol. However, for example, `ls` "defines" a `getoptind` symbol (more
accurately, it clones it from libc).

To handle this situation, we replace the `.gnu.hash` with a minimal
`.hash` section. Basically, the `.hash` section should contain an hash
table. However, currently, we just create an hash table with a single
entry, which immediately triggers scanning the chain of entries
colliding in the (only) entry.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico b4b0b7bce9 FCI: API for fallthrough BasicBlocks
The `FunctionCallIdentification` pass now has an API to get the
fallthrough basic block of a function call basic block and to check
whether a certain basic block/address is the fallthrough of a function
call.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico 2d23bb525b Introduce dump for OSR and BoundedValue
This commit introduces a `dump` method for `OSR` and `BoundedValue` for
easier debugging within gdb. It also introduces `debug_function`, a
definition that wraps attributes to ensure the function is emitted even
if unused and emitted as a standalone function that can be called from
gdb.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico c4965a811b OSRA: fix iteration over BV with no upper bound
`BoundsIterator` had an issue in case there was the need to iterat over
bounds reaching the upper bound of an integer: the increment would
generate an overflow that would go undetected and, therefore, lead to an
infinite loop.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico fbfa6a9b6d OSRA: a BV is constant only if not negated 2018-08-17 21:55:48 +02:00
Alessandro Di Federico 6a6cfff17d Introduce support for dynamic objects (PIE)
This commit introduces support for dynamic objects. We do not support
translating dynamic libraries yet, therefore this commit introduces
support for PIE programs.

At the current stage, QEMU does not provide us explicit information
about an instruction using the program counter, but introduces its value
as an immediate. As a consequence, we cannot support arbitrary
relocation. For this reason, we statically relocate the program to a
fixed address (`0x50000000` by default, but it can be customized through
the `--base` argument). Therefore, all the addresses read from ELF data
structure need to be relocated.

Code compiled with `-fPIC` cannot store in global data the address of a
function, since it will be relocated at run-time. This means that the
global data harvesting won't bring any benefit. On the other hand, going
through dynamic symbols can be hugely beneficial. Same argument for
`*_RELATIVE` relocations.

The `merge-dynamic.py` script has been improved to find the appropriate
spot to put the rewritten program/section and headers and the dynamic
sections (the kernel is peeky on them).

Finally the `setRegister` function has been introduced in the module
produced by `revamb`. This function allows to keep CSVs static and, at
the same time, it allow `support.c` to set them. This is particularly
useful when we want to call the `root` function with specific values in
the registers (e.g., during for fuzzing purposes) or, as it's the case
for PIE, to synchronize the value of the FS register, which is
initialized by the dynamic loader, before execution gets to the `main`
function in `support.c`.
2018-08-17 21:55:48 +02:00
Alessandro Di Federico 59e84c658e Consider absolute memory accesses in RDA
The reaching definition analysis now considers loads and stores from and
to absolute addresses.

This improves the identification of target of indirect jumps in x86-64
PIC code.
2018-08-04 17:46:23 +02:00
Pietro Fezzardi 703139b1a3 Fix the name of the QEMU syscall helper for i386 2018-07-10 16:55:28 +02:00
Pietro Fezzardi ecbbc2ea52 Fix offsets computed in computeAggregatedOffsets()
This function computes the CSV that may be accessed from a call in root.
Before this commit, it assumed that all the load and store had to be
aligned with the underlying variables. This happens to be too strict an
assumption, and it is relaxed in this commit.

When a load or a store is not aligned with the underlying type, this
commit introduces code to mark all the spanned CSV as accessed.
This is information is then attached to the call site in root as
metadata, as it already happened before.
2018-07-10 16:49:59 +02:00
Pietro Fezzardi 068d61c5b8 Fix assertion in CSVOffsets::combine() 2018-06-27 16:20:21 -07:00
Alessandro Di Federico 1b93235522 Merge branch 'feature/s390x-support' 2018-06-19 08:17:12 +02:00
Pietro Fezzardi a1d5fc34a3 Add support for s390x 2018-06-12 19:04:51 +02:00
Pietro Fezzardi c32aef429f Handle conditional jumps depending on SelectInst
The Simple Expression Tracker now correctly identifies direct jumps
whose destination is selected with a `SelectInst`.
2018-06-12 19:04:51 +02:00
Alessandro Di Federico a47cb7e96f Merge branch 'feature/cpustate-access-analysis' 2018-05-31 17:14:43 +02:00
Alessandro Di Federico 87d9396ff0 Augment search path with /usr/share/revamb 2018-05-31 17:04:16 +02:00
Alessandro Di Federico 2d32074075 Remove cross-compiler autodetection 2018-05-31 17:04:16 +02:00
Pietro Fezzardi 0844c16cd8 Add type-based analysis to CPUStateAccessAnalysis
This commit improves the capabilities of the `CPUStateAccessAnalysis`.
In particular, it is capable of handling GEPs that access arrays at
unknown offsets. This is a common operation in QEMU helpers, because it
is often used to access some elements in the array of GPRs using indexes
that are not known at translate-time. Handling this case allows us to
shrink the size of the generated translated code, because we only
generate accesses at valid offsets in the arrays instead of handling all
the possible wild accesses in the CPU State.
2018-05-31 17:04:16 +02:00
Pietro Fezzardi f90f9451fa Add CPUStateAccessAnalysisPass
This commit adds a new analysis pass: `CPUStateAccessAnalysisPass`.

This pass currently performs 4 operations.

1. A preliminary analysis of the call graph, to select the functions
   that are reachable from the root function through direct calls.  All
   the other performed operations are executed on this set of reachable
   functions.

2. An interprocedural forward taint analysis, starting from the uses of
   `env`, the global variable pointing to the QEMU struct continaint the
   CPU. This analysis taints all the instructions that use the address
   of `env`, until a load or a store is met. If a load or a store uses a
   tainted Value as address it means that it is accessing a CSV at a
   given offset (which at this point is still unknown).

3. An interprocedural offset analysis, which deduces the possible
   offsets used by every tainted load/store to access the CSV. This
   analysis initially works backwards, exploring all the Values that
   contribute at the computation of the addresses used by tainted
   load/stores. Once it finds all the sources, it starts propagating the
   values forward, collecting the offsets computed along the way. It
   does this until it reaches the tainted load/stores again. At that
   point the analysis knows all the possible offsets used by each
   tainted load/store to access the CPU state.

4. The results of the previous steps are used to do 3 things:

  * marking all the indirect calls with tainted arguments as illegal;
    this is necessary because those calls may access the CPU State in
    unpredictable ways;
  * attaching metadata to all the call sites to QEMU helpers in the root
    function; these metadata provide information on which parts of the
    CPU State may be accessed from that call site, which is a
    potentially useful information for users of libtinycode that we also
    plan to use in other parts of revamb;
  * substituting loads, stores, and memcpys to and from the CPU state
    with accesses to global variables; this operation effectively
    replaces what was previously done by the CorrectCPUStateUsagePass,
    which is now obsolete and was removed in this commit.
2018-05-31 17:04:16 +02:00
Pietro Fezzardi 83992ba4c3 Add -Wno-error=unused-local-typedefs 2018-05-30 12:45:45 +02:00
Pietro Fezzardi 150a7a9145 Add function getCallee to ir-helpers.h
This function takes a `Instruction *` pointing to a `CallInst`, and
returns a `Function *` to the Callee if it's a direct call, skipping all
the bitcasts if any.
If the argument is not a `CallInst`, or it's not a direct call, it
returns `nullptr`.
2018-05-30 12:45:45 +02:00
Pietro Fezzardi 6ebae61635 Improve writeToLog() specialization for Value *
Now it prints "nullptr" if the `Value *` is null, instead of trying to
dereference it to print the name of the pointed `Value`.
2018-05-30 12:45:45 +02:00
Pietro Fezzardi f707b04530 Add assertion in Logger<>::unindent()
Check that the calling `unindent()` never reduces the indentation
"below" zero, causing `IndentLevel` to wrap around to high numbers.
If it drops below zero it's a bug anyway, so assert!
2018-05-30 12:45:45 +02:00
Pietro Fezzardi 0959492392 Improve getTypeAtOffset()
This commit does 6 things on `getTypeAtOffset()`:

1. it changes the second argument from `StructType *TheStruct` to a more
   generic argument `Type *VarType`, making it capable of working on any
   type;
2. it removes recursion, substituting it with a while loop;
3. it removes the now useless `Depth` argument;
4. it changes the return type to `std::pair<IntegerType *, unsigned>`,
   because this was the assumption that all the callers did anyways;
5. it guards all the unexpected types with an assertion;
6. it purposely avoids to guard pointer types with assertions, as a
   workaround for a specific situation documented in detail in the new
   comments.
2018-05-30 12:45:45 +02:00
Pietro Fezzardi c940b116a7 Use getTypeAllocSize() instead of getTypeSizeInBits()
The function `getTypeSizeInBits()` was wrongly used in many places when
reasoning about memory allocation, memory accesses, and memory offsets,
The result was often divided by 8 (possibly losing spare bits) or even
multiplied by 8, which makes no sense.
These uses were error prone, even if they didn't cause problems yet.
The `getTypeAllocSize()` is better suited for these uses, because it
returns the number of bytes necessary to allocate an object of the given
Type.
2018-05-30 12:45:45 +02:00
Alessandro Di Federico 0dc77e104f Introduce statistics
This class introduces the `RunningStatistics` class, which allows to
compute the mean and standard deviation of a set of numbers. These
values are computed incrementally and can be associated to a name. The
values computed by `RunningStatistics` can be dumped upon regular
program termination, `SIGABRT` and `SIGINT`. In practice they are
printed at the end of the program execution, even in case of asserts and
`Ctrl + C`. Moreover, `SIGUSR1` is used to trigger printing the
statistics without crashing the program.
2018-05-30 12:45:45 +02:00