Commit Graph

73 Commits

Author SHA1 Message Date
Alessandro Di Federico 451a321bfc Let the entry point go through the dispatcher
We used to jump directly to the program entry point (typically
`_start`), without initializing the program counter. We now initialize
the program counter and the let the program start with the dispatcher,
since it seems a safer solution.
2017-02-20 12:24:49 +01:00
Alessandro Di Federico 1a3950a3ea Force root function's name 2017-02-20 12:13:11 +01:00
Alessandro Di Federico 6b91aeb9a2 Register manual entry point as jump target
This commit fixes a bug triggered by specifying the `--entry` switch:
the entry point would not be registered as a jump target, instead the
code would try to get the basic block associated to that address,
resulting in an assertion.

The manually specified entry point is now registered as a jump target
coming from global data.
2017-01-23 22:06:55 +01:00
Alessandro Di Federico 75d38a71cd Cleanup final IR from temporary functions 2017-01-11 15:57:32 +01:00
Alessandro Di Federico 4501dad2c0 Introduce the --no-link option
Introduce an option to prevent `revamb` from linking in all the QEMU
helpers. This is useful if the output doesn't need to be compiled, but
just analyzed.
2017-01-11 15:25:53 +01:00
Alessandro Di Federico 5c619ab063 Introduce the GCBI and FCI passes
This commit introduces two new passes:

* `GeneratedCodeBasicInfo`: recovers from the IR some basic information
  like the size of delay slots in the input architecture, the name of
  the program counter and so on. It can also identify the type of a
  basic block (e.g., dispatcher, jump target...).  *
* `FunctionCallIdentification`: identifies function calls and injects a
  marker before the associated terminator instruction.

The idea of these two passes is to try to progressively move information
we used to keep in `JumpTargetManager` into the IR, so that it is more
easily accessible and passes do not need a reference to `JTM`.

In particular by having markers for function calls available during jump
target discovery we don't have to have duplicated and suboptimal
implementation of `isCall`.

This commit also introduce some additional helper functions and an
helper class to quickly.
2016-12-08 21:56:11 +01:00
Alessandro Di Federico d7c2ca7f7e General improvements on debugging information
* Don't dump entry point addres, not very interesting
* Handle `nullptr` in `getName`
2016-12-04 00:28:57 +01:00
Alessandro Di Federico b649681c21 CpuLoopExitPass: fix bug using a possible nullptr
Do not call `purgeNoReturn` on the `CpuLoopExit` function before
checking if the function has ever been created.
2016-12-04 00:28:57 +01:00
Alessandro Di Federico c069700bc5 Keep the CFG simple: do not jump to the dispatcher
Every time we don't know where an indirect jump can go, we used to emit
a jump to the dispatcher, however this complicates our analyses, in
particular the computed dominator tree provides less useful information
than it could.

This commit transforms all the jumps to the dispatcher into jumps to a
"anypc" basic block which during analysis just contains an unreachable
instruction, but during finalization this instruction is replaced with a
jump to the dispatcher. A similar (temporary) situation is for the
"unexpectepc" case.

This commit also makes the `visit(Sucessors|Predecessors)` functions
more idiomatic by employing a trait for black lists.
2016-12-04 00:28:56 +01:00
Alessandro Di Federico bc6a732ad7 Don't compute function boundaries by default 2016-12-03 08:46:12 +01:00
Alessandro Di Federico 83ea2caacd Isolate ELF code and remove architecture parameter
This commit removes all the ELF-specific code from the `CodeGenerator`
class by creating a new class, `BinaryFile` which contains all the
information about the program that might be needed in an image format
independent way. However, `BinaryFile` has some fields which are
specific to ELF, we might want to address this when additional file
formats are supported.

A key benefit of isolating this code is that we can anticipate the
parsing of the input file, so that we have its architecture available
earlier than when `CodeGenerator` is instantiated, therefore we can drop
the `--architecture` parameter.
2016-12-03 08:46:12 +01:00
Alessandro Di Federico c50dcc5c5d Use symbols to produce meaningful names
This commit introduces the usage of symbols, if they are available. We
employ them to produce meaningful names for basic block names.

* Collect the symbols from `.symtab`/`.dynsym`
* Box the `Segments` into a new data structure (`BinaryInfo`) which also
  handles symbols.
* `JumpTargetManager::nameForAddress`: produce a meaningful name using
  symbols, if possible.
* Spread some `const`-ness
2016-09-28 00:03:13 +02:00
Alessandro Di Federico 95cf77d3b3 Downgrade from C++14 to C++11 2016-09-21 04:50:17 +02:00
Alessandro Di Federico d01ee1f437 Copyright notices, license and credits 2016-09-21 01:45:26 +02:00
Alessandro Di Federico cc87ad607d Introduce NoreturnAnalysis
This commit introduces the `noreturn` analysis, whose aim is to detect
all the basic blocks the are doomed to lead to a `noreturn` syscall such
as `execve` or `exit`.

* Implement `NoreturnAnalysis`.
* Include and initialize in the `Architecture` data structure all the
  necessary information to detect `noreturn` syscalls. Specifically, the
  name of the QEMU helper for syscalls, the name of the register holding
  the syscall number and the syscall numbers representing `noreturn`
  syscalls.
* `ReachingDefinitionsPass`: make reaching definitions available both in
  reaching definitions mode and reached loads mode. This part needs
  further cleanup. We also might be willing to implement this with a
  `Boost.Bimap`.
* Use `SET` to collect information useful for the
  `NoreturnAnalysis`. Also restructure how the `OperationsStack` works
  to be more streamlined and keep track of multiple information about
  the instruction currently being tracked.
2016-09-17 15:33:57 +02:00
Alessandro Di Federico 37de0a0002 Introduce FunctionBoundariesDetectionPass
`FunctionBoundariesDetectionPass` implements our function detection
system.
2016-09-17 15:33:57 +02:00
Alessandro Di Federico 7859f9de78 Keep track of how jump targets have been met
This commit registers for each jump target how we met it, as a flag. It
also keeps track of which pointers in global data have been involved in
materialization performed by SET: those who are not are of special
interest for us, since they are likely function pointers, and are
therefore marked with a specific flag.
2016-09-17 15:33:55 +02:00
Alessandro Di Federico 27b4e46525 Draft tracking of reasons for registering JTs 2016-09-17 15:33:54 +02:00
Alessandro Di Federico 1d87dced75 Drop the concept of "reliable" jump target 2016-09-17 15:33:54 +02:00
Alessandro Di Federico 6c5c0ad8f7 Add support for using section information 2016-09-17 15:33:54 +02:00
Alessandro Di Federico 041ea8726d Introduce predecessors and successors 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 1a5fc0f519 Introduce collection of basic block statistics
Let revamb produce a CSV file containing statistics about the translated
input basic blocks for further analysis (e.g., identify false
positives).
2016-08-20 03:10:46 +02:00
Alessandro Di Federico dbb462a9a5 Fix issues in release builds
Mainly fixes due to the absence of asserts.
2016-08-20 03:10:46 +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 329fcb3707 Introduce tracing support 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 0d035a93e1 Introduce clang support: fixes and cleanup 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 57721ff851 Isolate SET
* Rename `JumpTargetsFromConstantsPass` to `SET`
* Move `SET` to set.{cpp,h}
* Remove some useless includes
2016-08-20 03:10:45 +02:00
Alessandro Di Federico fbca5bba2e Import OSRA and update SET
* Import OSRA
* Improve the SET (aka `JumpTargetFromConstants`) by introducing the
  `OperationsStack` class.
* Review `harvest` logic
* Allow to disable OSRA (along with the sumjump heuristic)
* Take the core of `getNextPC` out of it and move it to `getPC`, a
  function returning both the current and the next PC. Also, fix a bug
  when reaching the beginning of a basic block.
* Detect "reliable" jump targets: a "reliable" jump target is a jump
  target obtained from a store to a PC but it's not a fallthrough jump.
2016-08-20 03:10:39 +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 938057c4d8 Handle basic blocks with no terminator 2016-04-14 16:10:13 +02:00
Alessandro Di Federico 0f255102cd Handle helpers that might change the PC
If before a call to an heper the PC is saved, it means that the helper
can change the PC, therefore we need to go the dispatcher on return. In
this case, we also have to force the PC after the call to be a jump
target.
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 3eb8caed40 Introduce instruction alignment information 2016-04-14 16:10:13 +02:00
Alessandro Di Federico bbab7763ce At the end, remove all dead blocks 2016-04-14 16:10:13 +02:00
Alessandro Di Federico 6814f0c595 Compute explicitly the next PC while translating
When we meet a new PC from the PTC input, find immediately the next PC.
This makes the information available early and removes the necessity for
`closeLastInstruction`.
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 4d9e5684e9 Update --entry parameter
Give a new, useful, meaning to the `--entry` parameter: it's new purpose
is to be able to easily try to translate the code at a certain address.
In this sense, prevent global data harvesting if `--entry` is specified.
The handling of GVN options has also been improved.
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 298915ac6d Remove noreturn attribute from helpers 2016-04-14 16:10:13 +02:00
Alessandro Di Federico 6837959a16 Fix emission of program header address 2016-04-14 16:10:13 +02:00
Alessandro Di Federico c94fad95e4 Produce coverage CSV
Implement producing a CSV file containing information about the which
PCs have been translated. For each PC it is specified whether its a jump
target or not.
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 04a2374ef5 Make support variable external and named
Assigning support variables (such as those for original segments and the
ELF header helper) external linkage and giving them a name prevents the
optimizer from dropping them.
2016-02-02 16:03:34 +01:00
Alessandro Di Federico 32b756510f Prepare stack for the translated program
* Create 3 constant global variables (`phdr_address`, `e_phentsize` and
  `e_phnum`) in the IR which will be used to populate the auxiliary
  vectors at run-time.
* Update compile options for `support.c` to ignore useless warnings and
  enable debug information
* Implement in `support.c` some functions required by QEMU run-time and
  other cleanups to make it compatible with programs translated from
  `_start`, not `root`
* Implement in `support.c` the `prepare_stack` function, which
  initializes the base of the stack with environment variables,
  arguments and auxiliary vectors
* Improve syscall support
2016-01-30 11:15:04 +01:00
Alessandro Di Federico e2e7593fa6 Coverage: explore PC after syscall 2016-01-30 11:03:36 +01:00
Alessandro Di Federico cb7096b076 Start execution from the specified virtual address 2016-01-30 11:03:09 +01:00
Alessandro Di Federico de2621165f Abort if helper module's loading fails 2016-01-30 11:02:24 +01:00
Alessandro Di Federico 475adf963c Update VariableManager's DataLayout after linking 2016-01-30 11:02:07 +01:00
Alessandro Di Federico c3138d5db6 Force the linker to import non-static functions 2016-01-30 11:00:52 +01:00
Alessandro Di Federico 3746bcbd78 Move harvesting of code pointers in JTM
The logic to implement harvesting of new code pointers when we're out of
them during translation, has been moved to `JumpTargetManager`. Its
interface has also been reduced and some logging has been introduced.

At the current stage, if there's nothing to `peek`, we first give a shot
of `SROA` and `TranslateDirectBranchesPass`, and then, if nothing came
out, we go for `EarlyCSE` and `JumpTargetsFromConstantsPass`.
2016-01-12 23:28:23 +01:00
Alessandro Di Federico 8c381090a7 Move TranslateDirectBranchesPass to JTM 2016-01-12 23:05:29 +01:00
Alessandro Di Federico 0d58bc3cf7 Introduce logging framework 2016-01-12 22:43:04 +01:00
Alessandro Di Federico f8dcd566ae Collect information about ELF segments
Instead of taking note of the executable ranges exclusively, keep track
of all the segments in `CodeGenerator`. `JumpTargetManager` instead will
keep track of executable areas only.

* Introduce the `SegmentInfo` struct, which simply holds essential
  information about the segment such as start and end address,
  permissions and a reference to the global variable holding its content.
* Update `CodeGenerator` to keep a vector of `SegmentInfo`.
* `JumpTargetManager`: polish the constructor and make it take the vector
  of `SegmentInfo`, from which the executable ranges are then extracted.
2016-01-12 18:47:15 +01:00