Commit Graph

8 Commits

Author SHA1 Message Date
Alessandro Di Federico 61cfbdfc56 Introduce support for dynamic binaries
This commit introduces support for dynamic programs. The current
implementation translate the main binary and uses native libraries. This
works only if the target architecture is the same as the source
one. Currently we only handle x86-64.

* The `ExternalJumpsHandler` class has been introduced. It basically
  takes care of extending the dispatcher handling the case in which the
  program counter is an address outside the range of executable
  addresses of the input program. In this case, a `setjmp` is perfomed,
  the CPU state is serialized to physical registers and jump to the
  value of the program counter is performed.

  Once the target code will try to return to the translated program, a
  segmentation fault will be triggered, a `longjmp` is performed and the
  CPU state is deserialized so that the execution can resume (from the
  dispatcher).

* `early-linked.c` has been introduced. Its purposes is to provide
  declarations of variables and functions defined in `support.c`. In the
  past, we had to manually create these definitions, a cumbersome and
  error prone we now avoid by letting `clang` compile `early-linked.c`
  and then linking it in.

* The old `support.h` is now known as `commonconstants.h`. `support.h`
  now contains declarations that have to be consumed by
  `early-linked.c`.

* Each architecture now provides additional information:

  1. Which registers are part of the ABI and have to be preserved. If
     necessary the QEMU name can be provided. For each register it's
     also possible to provide their position within the `mcontext_t`
     structure, provided by the signal handler.
  2. Three assembly snippets, one to write a register, one to read it
     and one perform an indirect jump.

  Some of this information is also exposed in the output module as
  metadata.

* `support.c` now installs a SIGSEGV signal handler. Since pages that
  were originally executable are no longer executable, jumping there
  (typically, from a library) will trigger a SIGSEGV that we will
  handle. This allows us to properly deserialize the CPU state and
  resume execution of the translate code.

* Now also a dynamic version of each test program is translated and
  tested.

* The `merge-dynamic.py` script has been introduced: it takes case of
  rewriting the translated binary so to tell the linker to performe both
  the relocations of the translate program and the relocations of the
  original program. It does so by rewriting a large portion of the
  sections employed by the dynamic linker such as `.dynamic`, `.dynsym`
  and so on.

* The `compile-time-constants.py` script has been introduced: it a
  user-specified compiler on a source file producing an object
  file. This object file is inspected and the value of global read-only
  variables is produced in a CSV.
2018-05-29 15:10:51 +02:00
Alessandro Di Federico 79013ee6d0 support.c: ensure 256-bits alignment of the stack
This ensure floating point memory accesses work properly on x86. In the
past this was working only in certain cases depending on the number of
entries in the auxiliary vector, arguments and environment variables.
2018-05-29 08:43:17 +02:00
Andrea Gussoni cf42e497aa Introduce the Function Isolation Pass
This commit introduces the Function Isolation Pass. We use the
information provided by the Function Boundaries Detection Pass to
organize the code that `revamb` places inside the `root` function in
different LLVM functions. To do this we obviously need to introduce some
changes and tricks to handle the execution of the translated program.

The main idea is to have two different realms (one where the isolated
functions live, one in which we have basically the old root function).
We start the execution from the realm of the *non isolated* functions,
and we transfer, as soon as possible, the execution to the *isolated
functions* realm. We then have a fallback mechanism to restore the
execution in the right place in the *non isolated* functions realm, and
so on.

The largest change, besides the re-organization of the code in different
functions, is the use of the exception handling mechanism provided by
the LLVM framework in order to be able to manage the switch between the
two realms.

We also introduce the `support.h` header file, which contains a couple
of definitions used by `support.c` and that need to be shared with some
of the components involved in the translation process. We have defined
some helper functions, directly in C, that we use both for handling the
exception mechanism and for giving extra debug informations when an
exception is raised.

The `revamb-dump` utility now supports the `-i` option to specify the
path were to save the new LLVM module.

The `translate` utility now supports the `-i` option that produces a
binary in which the function isolation has been applied.

We also introduced some tests that apply the function isolation pass to
the `Runtime/` tests already present. In this way we can verify that the
translation and the following function isolation preserve the behavior
of the program.

When serializing the new LLVM module we regenerate the metadata used for
debug purposes, and for doing this, since we not longer have only the
`root` function, we have changed some details in the `DebugHelper` class
in order to be able to emit the metadata for all the functions of our
interest in a single shot.
2018-04-22 15:19:36 +02:00
Thorbjörn Schulz 2f55d4ba76 Added i386 support
Added the necessary information for i386 support and a call to a helper
function initializing the global descriptor table at runtime.
2018-01-28 14:07:31 +01:00
Alessandro Di Federico 4c8689016b Set default stack size to 16 MiB 2017-04-27 16:46:22 +02:00
Alessandro Di Federico 4789524a1d Reorganize the tracing system
`support.c` used to have a basic tracing system which would print on `stderr`
all the program counters. This commit reorganizes this system so that it has a
buffer, whose size can be specified through the `REVAMB_TRACE_BUFFER_SIZE`
environment variable, and it's possible to specify the output file
`REVAMB_TRACE_PATH`. The new tracing system also supports flushing the buffers
in case of clean exit of crash.

We also cleaned up `support.c`.
2017-03-02 08:21:11 +01:00
Alessandro Di Federico dae2f7e696 Compile support.c to LLVM IR
`support.c` used to be compiled using the system compiler and then
linked to the module generated by `revamb` as a separate translation
unit. This commit introduces a change that lets `clang` compile
`support.c`. This will allow us to make the CSV static, which should
enable more aggressive optimizations.

* Change the signature of the `root` function so that it accepts an
  argument: the initial value of the stack pointer, which the main is
  supposed to set up. QEMU now provides us with the offset of the stack
  pointer.
* Let the build system compile `support.c` for each supported
  architecture, both in normal and "tracing" mode.
* Remove the `--tracing` option, this is now handled by `support.c`, in
  particular depending on which version of `support.c` you link, you can
  have tracing enabled or not.
* In `support.c` drop global variables representing the stack pointer,
  we no longer need them.
* In `support.c` fix some warnings while handling the stack on 32-bit
  architectures.
* Extende the `translate` script to handle the new way we link the final
  binary and the tracing mechanism.
2017-03-02 08:21:11 +01:00
Alessandro Di Federico d48715494d Improve installation
* Use "$ORIGIN/../lib/" as RPATH when linking the installed binary
* Install also support material such as "support.c"
* Import the `translate` script for easy end-to-end translation
2016-09-22 22:44:16 +02:00