Commit Graph

14 Commits

Author SHA1 Message Date
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
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
Alessandro Di Federico e031583308 Set CSVs linkage to internal
This simple commit should improve performance of the generated program
sensibly. Basically all the global variables will have internal linkage
from now on (unless the `--external` parameter is specified on the
command line). This way, the compiler will be able to avoid load/store
instructions when leaving code in the current translation unit.
2017-04-03 15:57:50 +02:00
Alessandro Di Federico d01ee1f437 Copyright notices, license and credits 2016-09-21 01:45:26 +02:00
Alessandro Di Federico 710954ee51 Use a single, shared, cast for local temporaries 2016-08-20 03:10:45 +02:00
Alessandro Di Federico ff52a06c74 Unify return values for opcode translations
Now `CodeGenerator::translate`, `CodeGenerator::translateCall` and
`CodeGenerator::newInstruction` all return
`CodeGenerator::TranslationResult` which covers all the possible results
that the caller needs to handle such abort, stop translation, force a
new basic block or simply proceed.

This patch also prevents reading a PTC temporary that has never been
written (typically due to a mistranslation) by emitting an abort.
2016-08-20 03:10:45 +02:00
Alessandro Di Federico 6acc701b54 Documentation and some refactoring 2016-08-20 03:10:45 +02:00
Alessandro Di Federico cda7bbd94e Extend support for partial CPU state reads/writes
This patch implements `VariableManager::storeToCPUStateOffset` and
`VariableManager::loadFromCPUStateOffset`, which handle in a single
point all the accesses by offset to the CPU state.

* `getTypeAtOffset`: introduce a feature to easily debug how we compute
  which field is at a specified offset in the CPU state (`--debug
  type-at-offset`).
* Let `getTypeAtOffset` and its wrappers return the offset inside a
  field of the CPU state (useful when accessing the third byte of an
  integer).
* Use a dedicated class for the `CorrectCPUStateUsage` worklist
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 318b478a92 Attach local temporaries to newpc calls
Pass local temporaries' allocas as parameters to newpc, so they can't be
promoted to SSA values by SROA, which creates problem when a basic block
must be split between a use and a def of such a value.
2016-02-02 16:48:32 +01:00
Alessandro Di Federico e59edd4109 Improve code pointer harvesting using GVN
If EarlyCSE didn't produce any new code pointer, we use
GlobalValueNumbering which usually leads to better results, in
particular if we remove `newpc` markers and if it can make use of alias
information, which we introduce to let the compiler know that
loads/stores to the CPU state will never alias loads/stores to normal
memory.

* Before generating any load/store instruction mark it with the
  appropriate aliasing information.
* Update `JumpTargetManager::harvest` to run GVN
* Move the `Visited` set of `JumpTargetsFromConstantsPass` in
  `JumpTargetManager`, even if currently we clear it at each invocation
  of the pass
2016-01-30 11:14:20 +01:00
Alessandro Di Federico 475adf963c Update VariableManager's DataLayout after linking 2016-01-30 11:02:07 +01:00
Alessandro Di Federico 3c0fce0ba0 Transform calls to cpu_loop_exit to cpu_loop
`cpu_loop_exit` is used by QEMU to get back control from the translated
code while running an helper. Here we complete the inversion of the
hierarchy by transforming calls to `cpu_loop_exit` into calls to our
customized `cpu_loop`, which will handle syscalls and the like.

Since originally `cpu_loop_exit` was a noreturn function, we also need to
ensure that the semantic of its usage is preserved. We do this by setting
a global variable (`cpu_loop_exiting`) right after the call to
`cpu_loop_exit` and forcing the whole call stack to return immediately
if it's true.

* Introduce `CpuLoopExitPass`: replace all the calls to
  `cpu_loop_exit` with a call to `cpu_loop`, a store true to
  `cpu_loop_exiting` and a return. Then take all the callers and make
  them return if `cpu_loop_exiting` is set. Once we get to the translated
  function just reset `cpu_loop_exiting` to false.
* Introduce `VariableManager::computeEnvAddress`: generate code to
  compute the offset of env . This computation is useful when
  reference to the CPU state must be arificially introduced. This code
  will be flattened by `CorrectCPUStateUsagePass` later.
2016-01-04 21:47:26 +01:00
Alessandro Di Federico 6338f3b0b8 Link with helpers and adjust their CPU state usage
* Move initialization and management of the structure describing the CPU
  state (CPUStateType) into variablemanager.cpp.
* Support parts of CPU state outside "env" (e.g. the MIPSCPU
  structure). Now "env" has an offset into the possibly larger CPU state
  which we have to take into account where appropriate (see
  VariableManager::envOffset).
* Link the helpers module into the generated module, including only what
  is needed.
* Create some "no-op" or "abort" function corresponding to QEMU functions
  not included in the helper module (e.g. logging and abort functions).
* Implement the CorrectCPUStateUsagePass pass, which starts from the
  "env" global variable and looks for all its usages recursively, keeping
  track of where pointers are pointing into the CPU state data structure,
  and replaces all the load/stores with the global variable corresponding
  to that specific field of the CPU state.
* After the linking phase, run SROA, the pass to adjust the CPU usage and
  DCE.
* Let global variables have common linkage.
2015-12-04 23:44:46 +01:00
Alessandro Di Federico 5d130b7072 Split ptctollvmir.cpp into multiple files 2015-11-24 15:21:17 +01:00