Commit Graph

6113 Commits

Author SHA1 Message Date
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 c8274af360 Let tests run from _start 2016-01-30 11:15:50 +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 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 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 25f540a8c6 Minor improvements to DebugHelper
* Ignore support functions (i.e. everything outside the `root` function)
* Update DWARF version to 4
* Update subrprogram creation interface to LLVM 3.8
2016-01-30 10:59:29 +01:00
Alessandro Di Federico f20c8e8839 Take initial values for CPU state from libtinycode 2016-01-30 10:59:00 +01:00
Alessandro Di Federico a0f89a4269 Delay Env + non-const failures to run-time 2016-01-30 10:57:57 +01:00
Alessandro Di Federico 71f919675e Speedup compilation by using llc -O0 2016-01-30 10:57: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 0d58bc3cf7 Introduce logging framework 2016-01-12 22:43:04 +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 0280d0fc98 Divert translation to a new block after exit_tb 2016-01-12 18:47:10 +01:00
Alessandro Di Federico e2e6a9cdb8 Introduce early detection of jump targets
Detect simplest cases of writes to the program counter while they're
being translated. This way, we avoid running expensive passes to collect
straightforward jump targets.

Note: if the PC-write value is the current PC, ignore it. Splitting the
basic block being created is problematic.
2016-01-12 18:38:24 +01:00
Alessandro Di Federico 21d7cce3bf Graceful handling of translation failure
* Let `InstructionTranslator::newInstruction` return also the PC.
* `InstructionTranslator::translate`: make it aware of the current PC,
  and make it abort in case of error and return a boolean to indicate
  whether the translation should proceed or not.
* Simplify the fetch of a new address to translate.
* Let `InstructionTranslator::translateOpcode` return an error condition
  in case of failure, instead of asserting.
2016-01-12 18:38:18 +01:00
Alessandro Di Federico ef2d8241f6 Rework the root function header
* Don't start exploration from `VirtualAddress` but just add it as a
  block to explore. Then start the translation with
  `JumpTargetManager::peek` as usual.
* Remove the unreachable instruction we were using as a delimiter to
  create new local variables, since it make the module invalid. Use the
  fake branch to the dispatcher instead.
2016-01-12 18:20:07 +01:00
Alessandro Di Federico e9e14881cb Fix: delay removal of calls in CpuLoopExitPass 2016-01-12 18:18:23 +01:00
Alessandro Di Federico 78bb20907c Relax -Werror for unused/uninitialized variables 2016-01-12 18:17:19 +01:00
Alessandro Di Federico 7fec929195 Fix typo in handling of op_{div,mul}u2_i{32,64} 2016-01-12 18:17:05 +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 cc7851d040 Abort upon an unhandled usage of the CPU state
When an unexpected instruction is met in `CorrectCPUStateUsagePass`,
propagate the error until a load or a store is performed, then emit an
`abort`.
2016-01-12 18:08:14 +01:00
Alessandro Di Federico 77fdb38903 Abort on jump to an unknown addresses 2016-01-12 18:07:04 +01:00
Alessandro Di Federico df0997ab04 Ensure existence of abort since the beginning 2016-01-12 18:07:04 +01:00
Alessandro Di Federico 0cffa717ed Use puts and itoa instead of printf in tests 2016-01-12 18:01:14 +01:00
Alessandro Di Federico ea61c896fb Introduce dependencies among tests 2016-01-12 18:00:51 +01:00
Alessandro Di Federico d510fea8c7 Simplify command line usage exploiting ELF info
* s/`importGlobalData`/`parseELF`/
* Save the entry point specified in the ELF header, which will be used
  if the user doesn't provide an address.
* Let parse `parseELF` take care of informing libtinycode about what
  has to be mmap'd and where.
* Remove some support scripts used during testing, now no longer
  necessary.
* Various cleanups
2016-01-09 13:37:03 +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 8b5c59ad13 Search new jump targets only if we're out of them 2016-01-09 11:09:00 +01:00
Alessandro Di Federico 5c2111db5b Rename JumpTargetManager.peek{JumpTarget,} 2016-01-09 11:07:38 +01:00
Alessandro Di Federico 39b9e69773 Bug: use a reverse iterator in getNextPC
In `TranslateDirectBranchesPass::getNextPC` we were using a normal
iterator backward with a faulty exit condition that lead us to skip the
first instruction in a basic block.
This patch implements a proper solution: use `reverse_iterator`.
2016-01-09 11:05:44 +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 51ca34634b global.c: a new test for access to global data 2016-01-07 14:17:39 +01:00
Alessandro Di Federico 93eb350073 Add support for source-target endianess mismatch 2016-01-07 14:17:15 +01:00
Alessandro Di Federico ac316cd758 Add support for ELF and import its global data
* Use `llvm::object` framework to obtain useful information from the ELF
  binary such as pointer size and endianess.
* Introduce `CodeGenerator::importGlobalData`: import global (read-only
  and writeable data) from the input binary directly into the generated
  module.
* Introduce the `--linking-info` parameter: path to a CSV file where
  sections containing global data extracted from the input binary are
  listed with their name, start and end address.
* Expand the `Architecture` class with constructors and support accessor
  methods.
2016-01-07 14:16:05 +01:00
Alessandro Di Federico 0f2ddd80a0 Remove -o parameter: use the second argument 2016-01-05 15:35:44 +01:00