Commit Graph

1429 Commits

Author SHA1 Message Date
Alessandro Di Federico 8de52cb9b8 skipCasts: handle Instructions and ConstantExprs 2018-05-29 08:38:24 +02:00
Alessandro Di Federico d169d37ca5 s/static inline/inline/ in .h file 2018-05-29 08:37:14 +02:00
Alessandro Di Federico aa38255149 Output a CSV file with the required libraries
This commit makes `revamb` produce a new file `.ll.need.csv` containing
a list of all the dynamic libraries required by the input program. This
will be transformed by the 'csv-to-ld-options` (was:
`li-csv-to-ld-options`) into the appropriate linking options.
2018-05-29 08:35:24 +02:00
Alessandro Di Federico 0bd4204e07 In tests, use the translate script 2018-05-29 08:35:24 +02:00
Alessandro Di Federico 470ca264ad Convert bool arguments to int
The `argparse` library treats boolean arguments as
integers. Specifically, each time a boolean argument is meet the
associated variable is incremented. This led to weird behaviors having
`2` being converted to `false`. Using `int` as a type solves this issue.
2018-05-29 08:35:24 +02:00
Alessandro Di Federico 5f8249ce33 Disable warning about virtual destructors
This commit disables a warning emitted by recent clang versions that is
triggered on libstdc++.
2018-05-29 08:19:02 +02:00
Alessandro Di Federico 3ec2148f5f Merge branch 'feature/function-isolation' 2018-04-22 15:40:46 +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
Andrea Gussoni 171db849bf Use getCallTo in getBasicBlockPC
We now take advantage of the `getCallTo` helper function in the
`getBasicBlockPC` function defined in `ir-helpes.h`
2018-03-19 12:01:05 +01:00
Andrea Gussoni 608b96b59b Fix ReturnPC type
Solved a bug that always allocated an `i32` for representing the return
address PC in the `function_call` helper (third parameter).

Now we allocate an `i64` or an `i32` depending on the input architecture
of the translated binary.
2018-03-19 12:01:05 +01:00
Pietro Fezzardi bb6659268c Fix ISA recognition in translate script
The header of an ELF file contains two bytes representing the ISA.
These two bytes are offset 0x12 in the file, which is offset 18, not
offset 17 like it was in the script.
2018-02-01 09:00:26 +01:00
Alessandro Di Federico bbd3471266 Suppress signedness comparison warnings in tests 2018-01-28 14:08:45 +01: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
Pietro Fezzardi 5d9aa31c50 Remove useless type GenericFunctor
`GenericFunctor` is substituted with the `std::integral_constant`
template. This also allows us to remove code that requires C++14.

It also removes the now useless cmake tests on the compiler flag
`-Wno-error=noexcept-type` that was introduced to disable fatal warnings
on the type `GenericFunctor`.
Now that this type has been removed the check is not necessary anymore,
because the `std::integral_constant` template used now does not cause
the warning.
So we can go back to enabling the fatal warnings.
2018-01-18 18:21:33 +01:00
Andrea Gussoni 97ed77d2b4 Remove leading dot from segment variable names
Changed the names of the global variables (removed the leading `.`)
representing the segments of the binary, in order to prevent errors with
duplicated names when recompiling a binary with `llc` in debug mode.
2018-01-17 22:33:07 +01:00
Alessandro Di Federico 3aed484a28 Fix li-csv-to-ld-options warning message
We used to check if the value of `/proc/sys/vm/mmap_min_addr` is at
least as high as the minimum segment of the input binary. If this is not
the case the linked program will segfault at run-time without much
explanation.

However, in truth, we need to be able to map also the page before the
lowest page the original binary mapped. The main reason for this is to
have space for the (outer) ELF header.

It turns out that on many distros the default minimum value is
`0x10000`, which happens to be exactly the same address at which ARM
binaries mmap their lowest page. This lead to no warning, but a segfault
at run-time.

The AWK script now checks for the correct value, and also suggests the
correct value.

In the future, we might want to create a new segment for the outer ELF
header and position it elsewhere in the address space.
2018-01-17 21:38:23 +01:00
Andrea Gussoni 4e871c6fa8 Refactored initialization of compilation flags
We now take advantage of a macro to add a series of compilation flags,
macro that also takes care of checking that the flags are supported by
the compiler.

This patch has been developed by Alessandro Di Federico.
2018-01-17 21:11:58 +01:00
Andrea Gussoni 0735acd2a0 Add checks for no-pie flag for cross-compilers
The check to see if a compiler supports the `no-pie` flag was done only
for the main C compiler, and not for the cross-compilers used for
creating the executables for the different supported architectures.

This commit introduces the aforementioned missing checks.

In addition instead of hard-coding the flags to check in the CMakeLists
file we have a list that we pass each time we instantiate a project for
the cross-compilers, and we check for the availability of all the flags.

In order to do this we need to apply a sort of serialization and
deserialization to avoid the "unpack" of the list passed as argument to
the external project (that is implemented as a `;` separated string).

Also implemented a fix suggested in the merge request for a line that
mistakenly added the `TEST_CFLAGS` variable to the `NO_PIE` variable.
2018-01-17 21:11:41 +01:00
Alessandro Di Federico abd3154c03 Warn the user if mmap_min_addr is too high
Many Linux distributions prevent programs from mapping memory pages at
low addresses. This can lead the translated program to segfault without
any additional explanation. This happens in particular with ARM
binaries, which tend to have the first segment allocated at very low
addresses.

This behavior can be configured through
`/proc/sys/vm/mmap_min_addr`. This commit introduces a warning to the
user in the `li-csv-to-ld-options` script in case a segment with an
address lower than `mmap_min_addr` is requested.
2017-10-29 10:46:07 +01:00
Alessandro Di Federico cb8b34013e Enable -no-pie only if the compiler supports it
A previous commit introduced `-no-pie` to disable PIE in GCC versions
higher than 5.2. However, earlier versions don't support such an option.
This commit introduces the necessary detection mechanism to enable it or
not.
2017-10-28 17:59:57 +02:00
Niccolò Izzo ef30e87a93 Provide value_type in LazySmallBitVector
This commit introduces `value_type` in `LazySmallBitVector` to fix
compilation error on Boost versions newer than 1.65.
The bug was triggered in unit tests.
2017-10-28 17:11:22 +02:00
Pietro Fezzardi 55eb769aae Add -no-pie to compiler flags
Add this flag to the flags used for Runtime tests and to the flags used
in the translate script.

Recent GCC versions (`gcc-7` and later) enable PIE by default, and
`-fno-pie` apparently is not enough to disable it.
2017-08-29 00:34:26 +02:00
Pietro Fezzardi 9824a1b635 Make -Wnoexcept-type non-fatal, if present
This warning was introduced with gcc-7 to (quoting the documentation)
"Warn if the C++1z feature making noexcept part of a function type
changes the mangled name of a symbol relative to C++14. Enabled by -Wabi
and -Wc++1z-compat.".

It is triggered from the `GenericFunctor` class template. It can be
safely made not fatal, because this class template is not exposed
outside and the whole project is currently compiled with the same C++
standard compiler flags.

This commit adds machinery to `CMakeLists.txt` to make the warning not
fatal, but only if present. Disabling it when not present would trigger
build errors.
2017-08-29 00:27:43 +02:00
Alessandro Di Federico 069ae70d3e Fix handling of devirtualized calls
When we have an indirect call (or jump) we are sometimes able to
identify one or more possible targets, therefore, as an optimization,
before performing the indirect jump we check if the target is one of the
expected ones.

This optimization however was creating two issues with the handling of
indirect function calls: 1) the call to the `function_call` marker was
no longer positioned right before the terminator and 2) the function
call was no longer identified as an indirect function call but as call
to `anyPC`. This commit fixes these two issues.

These issues have been identified thanks to a report from Andrea
Gussoni.
2017-08-13 16:47:18 +02:00
Alessandro Di Federico f6b869bd12 Merge branch 'feature/stack-analysis' 2017-08-12 16:57:51 +02:00
Alessandro Di Federico a5af28621b Introducing the stack analysis
The stack analysis is the foundation to obtain accurate information
about the body of a function, which registers are callee-saved,
arguments, return values and so on.

It is implemented as a pass to run in revamb-dump.

This commit also introduces analysis tests specific to what we aim to
obtain from the analysis and also some basic unit tests for data
structures related to the stack analysis.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico d409390084 Unit testing for LazySmallBitVector
This commit introduces the unit test infrastructure, and a first unit
test suite for `LazySmallBitVector`.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico 794e8797b5 Introduce LazySmallBitVector
`LazySmallBitVector` is a bit set data structure which holds up to 31/63
bits in place (depending on the pointer size), and if more than that is
needed, the required space is automatically allocated on the heap.

`LazySmallBitVector` also features lazyness, meaning that any bit index
that has never been set will return `false`, while every time a certain
bit needs to be set the data structure is automatically enlarged, if
necessary.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico b3ba517c8b Minor whitespace fixes and cleanups 2017-08-12 16:56:23 +02:00
Alessandro Di Federico e8e9ffe71a NoReturnAnalysis: track killer's reason
The `NoReturnAnalysis` now tracks, through metadata, not just the fact
that a basic block is a killer basic block, but also the reason why it
is. This let's the user know whether it's a killer because leads to an
actual killer basic block or because it is a killer syscall/endless
loop.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico edc6fe118c JTM::setCFGForm: ignore indirect calls 2017-08-12 16:56:23 +02:00
Alessandro Di Federico 00f7016c70 Let GeneratedCodeBasicInfo provide more info
`GeneratedCodeBasicInfo` now exposes the instruction alignment of the
current architecture, the stack pointer register, the size of the PC
register, a reference to `anyPC` and correctly handles the
`DispatcherFail` basic block.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico 1729ab6d0b FunctionCallIdentification: detect link register
This commit extendes the FunctionCallIdentification pass to identify,
for each function call, where the return address is stored, i.e., the
link register. If the the return address is stored on the top of the
stack then the link register is `nullptr`.

This information is encoded as an extra argument to the marker
`function_call`.

This commit also makes the pass ignore dispatcher-related basic blocks
and ensures that calls to `function_call` are placed *before* calls to
`exitTB` so that they won't get purged.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico 030f4c66c8 Return instructions jump to the dispatcher 2017-08-12 16:56:23 +02:00
Alessandro Di Federico 47104c0fb4 Replace getNext with nextNonMarker
Most of the times, when we need to get the next instruction, we actually
want to skip over "marker" function calls (e.g., calls to `newpc` and
`function_call`). `nextNonMarker` does exactly this.

`FunctionCallIdentification::isCall` and `JumpTargetManager::setCFGForm`
have also been extended to correctly handle such situations.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico 486f289e56 revamb-dump: introduce verbose debug information 2017-08-12 16:56:23 +02:00
Alessandro Di Federico 91773b41e2 Serialize jump target reasons after FBD
Serialization (in the form of the `revamb.jt.reasons` metadata) of the
reason why a certain address is a jump target has been moved from
`JumpTargetManager::finalizeJumpTargets` to a new function
(`JumpTargetManager::createJTReasonMD`) which is invoked after the
function boundaries detection algorithm has been run.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico ce09875c36 Make translateIndirectJumps private
`JumpTargetManager::translateIndirectJumps` has been pushed into
`JumpTargetManager::finalizeJumpTargets`. Moreover, an safety check
about the removal of `exitTB` has been introduced.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico b1590dfd6d Record stack register in architecture description 2017-08-12 16:56:23 +02:00
Alessandro Di Federico 355b8c8ad3 Tag the default case of the dispatcher
The basic block handling the default case of the dispatcher used not to
be tagged with `revamb.block.type`, now it is.
2017-08-12 16:56:23 +02:00
Alessandro Di Federico 9c0c9995dd Improve the QueueImpl API
This commit introduces the `head` and `clear` methods for `QueueImpl`
(i.e., `UniquedQueue` and `OnceQueue`).
2017-08-12 16:56:23 +02:00
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 9cb8d45552 Indirect function calls might end with unreachable 2017-08-12 16:56:22 +02:00
Alessandro Di Federico 45c02dc1a2 Drop alloca's bitcasts
`alloca` instruction are passed as variadic arguments to `newpc` to
prevent the optimizer from moving code around them. We used to cast them
all to `i8*`, however these casts where breaking the convention of
having all the `alloca` instructions at the beginning of the function.

Since these casts were not really necessary, they have now been dropped.
2017-08-12 16:34:40 +02:00
Alessandro Di Federico f5a950ad26 Move assertModuleIsMaterialized to debug.cpp 2017-08-12 11:28:07 +02:00
Alessandro Di Federico cad55f6331 Export jump target reasons in metadata
This commit introduces a new metadata (`revamb.jt.reasons`) containing a
list of reasons why the initial PC of the current basic block has been
identified as a jump target.
2017-08-01 09:14:01 +02:00
Alessandro Di Federico b6702d6ea7 Tag return basic blocks with func.return metadata 2017-08-01 09:14:01 +02:00
Alessandro Di Federico 1f1ca01df5 Set pipefail in the translate script 2017-08-01 09:00:47 +02:00
Alessandro Di Federico 9db62b288c Handle .bss-only data segment
This commit fixes an assertion triggered by the fact that a segment
includes exclusively zero-initialized data (i.e., size on file is 0,
memory size is not). In this case LLVM detects the fact that the global
variable associated to the segment is composed exclusively composed by
0s and uses a `ConstantAggregateZero` as an initializer instead of a
`ConstantDataArray`.

Currently the solution is ignore that data, however, in the future it
might be beneficial to be able to read data from `.bss`, even if we just
have zeros there.

Thanks to Thorbjoern Schulz for reporting this bug.
2017-07-07 15:39:01 +02:00
Alessandro Di Federico 4c8689016b Set default stack size to 16 MiB 2017-04-27 16:46:22 +02:00