Commit Graph

36 Commits

Author SHA1 Message Date
Alessandro Di Federico a997a0525a Use opcode names in basic block statistics 2016-08-20 03:10:46 +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 4dd3638a46 Fix overflow when we check membership to a segment
Checking if a range of addresses belong to a segment should be
implemented by checking if the start and end address belong to the
address, the `Start <= Address && Address + Size < End` approach leads
to subtle errors when `Address` is close to the maximum representable
value due to an overflow.
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 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 670ca9d990 Remove the specila handling of null-jumps 2016-04-14 16:10:13 +02:00
Alessandro Di Federico 1ca682e3d1 Implement "unvisit" logic for SET 2016-04-14 16:10:13 +02:00
Alessandro Di Federico b74f09cad4 support.c: introduce unknownPC plus fixes
`unknownPC` is an extern function we expect to be linked to the output
which is called when we have to crash due to an unexpected jump target.

* Remove unused references to register variables, now only need the
  stack pointer
* Fix bug in how the auxiliary values were pushed on the stack.
* Push 0 HW_CAPs
* Implement some glib's functions
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 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 224fd3d93c Handle the PC += arg case
Some hand crafted assembly code perform a PC-relative jump of an
non-statically known amount. This patch introduces a simple hack to
handle such a situation by simply detecting it and marking as potential
jump targets all the instructions to come until the next jump.

This is implemented by the `JumpTargetManager::handleSumJump` and
`isSumJump` functions.

This commit also introduces a new implementation of `getNextPC` not
requiring the dominator tree.
2016-01-30 11:14:15 +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 e5c037e6f6 Introduce global data harvesting for code pointers
The `JumpTargetManager` constructor now collects everything looks like a
code pointer in read-only and writeable data.
2016-01-12 19:44:01 +01:00
Alessandro Di Federico ef98afc1e3 Insert an unreachable after exit_tb
Introduce an unreachable instruction after each emitted call to
`exit_tb` to terminate properly basic blocks. This patch also removes it
when appropropriate (i.e. in `TranslateDirectBranchesPass` and
`JumpTargetManager::translateIndirectJumps`).
2016-01-12 19:41:37 +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
Alessandro Di Federico 3420b0f85f Filter instructions while inspecting immediates
In `JumpTargetsFromConstantsPass` ignore calls to `newpc` and stores to
the PC, since they are harmful or simply don't carry any useful
information.
2016-01-12 18:47:15 +01:00
Alessandro Di Federico e6b0ce7ad5 Don't assert for write-to-PC-less exit_tb
`JumpTargetManager::getPrevPCWrite` used to assert in case a write to the
PC is not immediately found before an `exit_tb`. Relax this constraint.
In the future we might re-introduce it if we handle a couple of common
cases.
2016-01-12 18:15:28 +01:00
Alessandro Di Federico fa475803dd Handle double translations due to VLE
In variable-length encoding architectures, sometimes you might have one
instruction containing another one. This is not a problem until you get
the next one, which would be translated twice, in fact, it's not at the
beginning of a basic block and the current mechanism to detect already
translated code does not handle it.

This patch makes `JumpTargetManager::newPC` check the whole map of the
translated instructions. This might have to be improved in the future.
2016-01-12 18:14:52 +01:00
Alessandro Di Federico 14c86619ca Let getBlockAt callers handle non-executable PCs 2016-01-12 18:13:45 +01:00
Alessandro Di Federico 7dab9b0bf0 Simplify getBlockAt splitting logic
Thanks to the presence of calls to `newpc` the splitting logic in
`JumpTargetManager::newPC` can be simplified.
2016-01-12 18:09:18 +01:00
Alessandro Di Federico 77fdb38903 Abort on jump to an unknown addresses 2016-01-12 18:07:04 +01:00
Alessandro Di Federico 432e89895b Harvest possible code pointers from code constants
* Introduce the `JumpTargetsFromConstantsPass` pass, which goes through
  all the unvisited basic blocks looking for constants and trying to feed
  them to `JumpTargetManager`, which will decide if they are code
  pointers or not.
* To make life of `JumpTargetsFromConstantsPass` easier run
  `EarlyCSEPass` before it, which is particularly useful to make explicit
  constants that some architectures materialize in two steps (high and
  low part).
* Remove the fake fallthrough workaround in `TranslateDirectBranchesPass`
  which was used to register for exploration basic blocks after a direct
  jump, which was necessary due to the fact that return instructions are
  indirect jumps and were losing the basic blocks after function calls.
  This is no longer necessary thanks to `JumpTargetsFromConstantsPass`.
2016-01-09 11:25:17 +01:00
Alessandro Di Federico 81a4f6f048 Disallow translation of non-executable data
Now, in `JumpTargetManager::getBlockAt`, before registering a new PC for
translation we check that the corresponding address was actually
contained in a segment marked as executable in the original binary. This
prevents translation of data, which is a problem in particular when we
will start to harvest possible code pointers from global data or
constants found in the code

* Register in `CodeGenerator::ExecutableRanges` address ranges which
  contained executable code in the input ELF.
* In `JumpTargetManager::getBlockAt` check if the given PC was actually
  in an executable memory area, and assert or return `nullptr` depending
  on the `Try` parameter.
2016-01-09 11:25:06 +01:00
Alessandro Di Federico 186435d456 Switch to incremental creation of the dispatcher
Before this patch the dispatcher area was created all at once at a final
stage, however it's useful also while translating, since it keeps all the
code reachable, which is particularly important to be able to build a
exhaustive dominator tree.

* Create the dispatcher area when a new instance of `JumpTargetManager`
  is created.
* Create a fake conditional branch to the dispatcher at the beginning of
  the `root` function.
* Incrementally build the dispatcher's switch case in
  `JumpTargetManager::getBlockAt`.
2016-01-09 11:25:06 +01:00
Alessandro Di Federico 5882aaff95 Give useful names to created basic blocks 2016-01-09 11:25:02 +01:00
Alessandro Di Federico 5c2111db5b Rename JumpTargetManager.peek{JumpTarget,} 2016-01-09 11:07:38 +01:00
Alessandro Di Federico 641915f465 Bug: first read value, then erase from vector
Fixed a bug which lead to remove from the list of unexplored basic
blocks the wrong one while calling `JumpTargetManager::newPC` from
`InstructionTranslator::newInstruction`. This bug was due to the fact
that we were reading the address of the basic block associated with a PC
*after* erasing it from the `std::vector`.
2016-01-09 10:29:12 +01:00
Alessandro Di Federico 8e3268c9c0 Handle post-helper indirect jumps
In certain cases we have a call to `exitTB` right after an helper, in
particular in x86, after a syscall. We cannot know what the target
address will be, so we have to handle this as an indirect jump.

* `JumpTargetManager::getPrevPCWrite`: clean up.
* `JumpTargetManager::getPrevPCWrite`: while searching for stores to the
  PC, also check for call instructions. If one is met, return nullptr.
* `TranslateDirectBranchesPass::runOnFunction` and
  `JumpTargetManager::translateIndirectJumps`: insert new code before
  `exitTB`, not the write to the PC.
2016-01-04 21:29:03 +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 9fd83ea336 Implement the exit_tb PTC instruction
* Emit a call to an helper function (ExitTB) corresponding to each
  exit_tb PTC instruction.
* Update TranslateDirectBranchesPass and
  JumpTargetManager::translateIndirectJumps to look for the last write
  to the PC before calls to ExitTB.
* Exposing the PC with JumpTargetManager::PC is not needed anymore. Users
  from outside should only be interested in finding the the previous
  write to the PC (using JumpTargetManager::getPrevPCWrite).
2015-12-03 18:02:52 +01:00
Alessandro Di Federico 4e326f5799 Factorize LLVM-related helper functions 2015-12-03 17:59:32 +01:00
Alessandro Di Federico 9bf830c8ed Add a terminator before splitting a basic block 2015-12-03 17:57:23 +01:00
Alessandro Di Federico 5d130b7072 Split ptctollvmir.cpp into multiple files 2015-11-24 15:21:17 +01:00