Commit Graph

1218 Commits

Author SHA1 Message Date
Alessandro Di Federico 9cbcef37d5 Disallow #if [01]
Sometimes code is commented using preprocessor directives. This is fine
for temporary testing stuffs, but it should never end up in a commit.
2019-01-18 08:38:46 +01:00
Alessandro Di Federico 034621e2ec monotone-framework.py: restore Python 3 compat
Due to a minor error, `monotone-framework.py` loss its Python 3
compatibility. This commit fixes the situation.
2019-01-09 22:31:26 +01:00
Alessandro Di Federico 1fb8b1a6ec Merge branch 'feature/improve-performance' 2018-12-17 08:51:45 +01:00
Alessandro Di Federico 7ead8d68cc Collect simple literals (return addresses) as JTs
This commit fixes a problem that led to use SET to discover very very
simple jump targets: the return addresses of functions call.

Since in this situation, for each call, we needed to run SET, this
commit leads to a *huge* improvements in terms of translation
performance.

This commit also enforces renaming of the translated basic blocks after
they get split and update the ground truth for several analysis tests.
2018-12-17 08:15:45 +01:00
Alessandro Di Federico 9ce805415b Improve Reaching Definitions Analysis
The Reaching Definitions Analysis used to ignore all the memory access
that were not relative to a CSV or an `alloca`. In certain situations,
in particular in x86 which makes heavy use of the stack, this led to
miss certain links that were vital for a correct identification of
certain jump targets.

As an example consider the following example:

    cmp    DWORD PTR [rbx+0x8],0x5
    ja     4bc5c8 <uw_update_context_1+0x148>
    mov    eax,DWORD PTR [rbx+0x8]
    movsxd rax,DWORD PTR [r12+rax*4]
    add    rax,r12
    jmp    rax

The constaint on `rbx+0x8` is not propagated to the use after the jump,
due to a missing link.

This commit fixes this by tracking all the memory accesses within the
expressive power of the `MemoryAccess` class, in particular those
expressed as register plus offset.

Additionally, this commit also makes RDA consider as reaching
definitions for a `load` only those definitions that match exactly the
load address, while previously we were considering all the `mayAlias`
definitions. This situation, in combination with the previous change,
led to have paths with multiple reaching definitions, which was
problematic for the path sensitive merge.

Finally, we consider a definition to be clobbered only if there's an
exact store to the esame address, instead of a store on an aliasing
address.
2018-12-17 08:15:45 +01:00
Pietro Fezzardi dbb25bef2c Apply information about CSV aliasing
This commit introduces alias information to state that memory accesses
relative to CSVs do not alias memory accesses of the original program.
2018-12-17 08:15:45 +01:00
Alessandro Di Federico ef2d16db15 Install headers and libraries 2018-12-15 08:34:36 +01:00
Alessandro Di Federico 8877946be3 Handle codeless programs
Programs without code (e.g., no executable segment) led to miss the
`env` variable, making the `CpuLoopExitPass` fail. This commit, fixes
the problem by simply populating the `cpu_loop_exit` function with a
`ret`.
2018-12-15 08:34:36 +01:00
Alessandro Di Federico ac5dea43b4 Reduce exceptions thrown (e.g., due to tail calls)
In function isolation, every time we met a jump to an unexpected basic
block (i.e., a basic block that is not part of the current function), we
used to throw an exception. However this is unnecessary since oftentimes
it is sufficient to call the `function_dispatcher` or even perform a
regular function call.

The most obvious example is the case of a direct tail call. In this
situation performing a function call to the corresponding isolated
function is the most appopriate thing to do.
2018-12-15 08:34:36 +01:00
Alessandro Di Federico 2003b5c79f Being a callee is more important than being read
We used to black list memory portions target of memory read, so that
they couldn't become function entry points. However, this led to false
positives, in particular with functions that are explicitly called.

This commit ensures that we black list those addresses only if they are
not targets of function calls.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico c5657f8116 Optimize support.c
We now optimize `support.c`. We didn't do that since we were optimizing
everything after linking anyway, however, without `-O2`, functions in
`support.c` were getting an `optnone` attribute which inhibited any
optimization. In particular `newpc` and analogous functions were not
inlined. Resolving this issue led to a gigantic improvement in terms of
performance of the output program.
2018-12-13 18:03:11 +01:00
Andrea Gussoni af6f963d77 Improve exception handling
When optimizing a module to which function isolation has been applied the
`prune-eh` pass lead to several issues, specifically:

* `support.c` is now compiled with support for exceptions, to prevent
  `raise_exception_helper` from being marked `nounwind` during the
  link phase.
* Added a fake `ret` at the end of the `catchblock` to avoid promotion
  of `invoke`s to regular `call`s.
* Marked the `invoke` instructions as `noinline`.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 0010b6c704 Import revcc
`revcc` is a simple script that forwards its arguments to a specified
compiler, except in the case in which the compiler is asked to link the
final program. In such case, the compiler is invoked as appropriate, but
the resulting binary is then translated using rev.ng and replaced by the
translated version.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico a292542d06 Fix include paths order
We used to include `.` and `include/`, but the former is no longer
necessary and the latter has to have the highest priority to avoid that
installed headers take higher precedence, leading to a build employing
outdated headers.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 9d13ce343d OSRA: handle computations on constants
This commit fixes an issue in OSRA with computations on constants. If a
constant was added to another constant, a new constant bounded value
would be created. However, such bounded value wouldn't get propagated
further. This commit fixes the problem by creating an OSRA relative to
the original constant plus an offset.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico cb425c6a7a FCI: use previously detected fallthrough addresses
When going through basic blocks, FCI ignores basic blocks that have
already been identified as function calls. However, this lead to exclude
their fallthrough addresses from the list of fallthrough addresses.

This commit fixes this situation.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico d4b8fe847d GCBI: use getBlockType in isTranslated 2018-12-13 18:03:11 +01:00
Alessandro Di Federico a43fad370f GCBI: introduce the EntryPoint BlockType
`getType` didn't have a `BlockType` to represent the entry basic block
of the `root` function. Therefore, such basic block was erroneously
identified as a translated basic block.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 4f64816ac3 GCBI::getFunctionCall: skip markers
`GCBI::getFunctionCall` used to stop to the first marker function call,
instead of going through all of them looking for `function_call`.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico ecfb842073 Force FCI during basic block harvesting
This commit forces the function call identification analysis during
harvesting of new basic blocks. Additionally, the appropriate jump
target reasons are associated to the involved basic blocks.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 0c9945c2d0 Introduce QuickMetadata::get() 2018-12-13 18:03:11 +01:00
Alessandro Di Federico bba5bdf4fb Use std::iterator_traits in IteratorWrapper
Using `std::iterator_traits` allows `IteratorWrapper` to be employed on
pointers too.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 371c38d6b8 Add nodce to the list of marker functions 2018-12-13 18:03:11 +01:00
Alessandro Di Federico 2669d78206 Add some dump methods 2018-12-13 18:03:11 +01:00
Alessandro Di Federico 787b45630d Fix assertion messages
Assertion used to erroneously print part of the message on `stdout`.
2018-12-13 18:03:11 +01:00
Alessandro Di Federico 4c446a38fe Check for include guards starting with _ 2018-12-13 18:03:11 +01:00
Alessandro Di Federico 655f25fdff Factor out code for generating modules in tests 2018-12-13 18:03:11 +01:00
Alessandro Di Federico 5cc504e117 Whitespace and other minor changes 2018-12-13 18:03:11 +01:00
Alessandro Di Federico a1120e4caf SA: precompute CSV indices
The stack analysis identifies CSV as `CPU+x` where `x` is an index that
uniquely identifies a CSV. We used to compute this index multiple times,
going through the list of global variables.

After we switched from metadata to global variables for strings
representing disassembled instructions, such process became very slow to
the point of being a bottleneck due to the large amount of global
variables.

This commit precomputes, once and for all, the unique identifier of each
CSV and saves it in a `std::set`.
2018-12-13 18:03:07 +01:00
Alessandro Di Federico f2dd01cea2 Handle [p_filesz, p_memsz] segment portion
`BinaryFile::readRawValue` scans the segment list to identify which
segment contains a certain address. However, it was failing if the
target address was in `.bss`, i.e., the portion of a segment after
`p_filesz` but `before `p_memsz`.

This commit lets `BinaryFile::readRawValue` return 0 in that situation.
2018-11-30 17:47:03 +01:00
Alessandro Di Federico 823f277d2d Do not assert on calls targeting multiple symbols 2018-11-30 17:47:03 +01:00
Alessandro Di Federico 90d2df3cca Mark dynamic function calls in isolated code too 2018-11-30 17:42:33 +01:00
Andrea Gussoni ffa035fc99 Detect invalid fallthrough after helper
Fix for a situation where the fallthrough basic block of an instruction
calling a helper function is not in an executable segment and therefore
not created.
2018-11-29 16:02:10 +01:00
Andrea Gussoni ce22b9c496 Fix SET interval overflow
Quick fix to detect overflow in SET interval computation.
2018-11-29 16:02:10 +01:00
Alessandro Di Federico be7ac56f07 Purge orphan basic blocks only when harvesting
This commit fixes a huge performance issue due to performing a orphan
basic block cleanup every time `JumpTargetManager::peek` was called
instead of only when actual harvesting was required.
2018-11-29 16:02:10 +01:00
Pietro Fezzardi 451177bae9 Fix check-conventions.sh to use ! not not 2018-11-29 16:02:10 +01:00
Andrea Gussoni 3663f574e8 Use new module when isolating functions
Now using the `root` function of the cloned module as a starting point
for the isolation process.

In this way we can ignore the old module, and in particular we can
drop the `ModuleCloningVMap`, a giant map that was used to keep the
match between old and new global objects and was used in the instruction
cloning phase.

Also changed the creation of the trampoline for the isolated function,
using a new basic block and later purging all the unreachable basic
blocks in the `root` function.
2018-11-29 16:02:10 +01:00
Andrea Gussoni 039896fb41 Fix OBJ and CSV variables in translate script
Moved the definition of `OBJ` before its first use.

Moved the definition of `CSV` outside the lifting scope, to avoid
erroneous behaviors when invoking the script with the `-s` option.
2018-11-29 11:25:01 +01:00
Alessandro Di Federico e2fdee1597 Merge branch 'feature/mipsel-support' 2018-11-15 16:05:11 +01:00
Alessandro Di Federico e21eed118c Tag function_call targeting external symbols
This commit uses SET, information about canonical values and labels to
detect if an indirect function call is targeting an external symbol.

The strings used for the name of external symbols are uniqued global
variables. This commit also uses this approach for the disassembly of
original instructions, which used to be metadata.
2018-11-15 16:03:09 +01:00
Alessandro Di Federico abb47bb964 Minor changes 2018-11-15 08:48:26 +01:00
Alessandro Di Federico cc4dfbce4c Introduce labels, relocation and canonical values
So far we've been tracking only base-relative relocations in an ad-hoc
fashion. This commit introduces a data structure that can describe the
most common relocations, including those for `.got`, `.got.plt`,
base-relative and `R_*_COPY`.

A label describes a range of the binary. A label can be generated from a
symbol (basically assigning a name to range of the binary) or from a
relocation, describing the content of a certain range.

This commit generates labels from symbols and relocations, including
MIPS implicit relocations.

This commit also introduces canonical values.

A register can have a canonical value, i.e., a value that register will
assume when the analyzed module is being run. This is typically useful
for the value of the global pointer, which is different from one module
to another but, within a module, is stable.

This commit registers the canonical value of `gp` (in MIPS), if
available.
2018-11-15 08:48:26 +01:00
Alessandro Di Federico 6748032643 Extend FCI interface to identify function calls 2018-11-14 14:41:25 +01:00
Alessandro Di Federico fc72f95f70 Ignore non-executable segments in segments_count
`segments_count` provides a way for the runtime to know how many
executable segments the original program had. This is used to implement
the `is_executable` function.

While the `segment_boundaries` contained only the executable segments,
`segments_count` included non-executable segments too, leading to an
out-of-bound read which sometimes led to a spurious `Unknown PC` error.
2018-11-14 09:34:49 +01:00
Alessandro Di Federico 979111aa65 Improve handling of undef in OSRA 2018-11-14 09:34:49 +01:00
Alessandro Di Federico 3a4d994d16 Fix disassembly (for delay slots and other stuff) 2018-11-14 09:34:49 +01:00
Alessandro Di Federico abce8cea14 Backport to QMD: add 64 bits ints 2018-11-14 09:34:49 +01:00
Alessandro Di Federico 37b4917ea5 delay slots are no longer relevant 2018-11-14 09:34:49 +01:00
Alessandro Di Federico 9606c8df35 QMD: add 64 bits ints 2018-11-14 09:34:49 +01:00
Alessandro Di Federico 3ccc0d666d Do not fail upon meeting a ToPurge basic block
While translating the code, it might happen that a basic block needs to
be splitted and the second part to be revisited. In such cases, the
second part is register for being "purged" at the next iteration.

Translation failed if we met such a basic block before purging. This
commit correctly handles such situations.
2018-11-14 09:34:49 +01:00