Commit Graph

45 Commits

Author SHA1 Message Date
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
Alessandro Di Federico 0280d0fc98 Divert translation to a new block after exit_tb 2016-01-12 18:47:10 +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 14c86619ca Let getBlockAt callers handle non-executable PCs 2016-01-12 18:13:45 +01:00
Alessandro Di Federico df0997ab04 Ensure existence of abort since the beginning 2016-01-12 18:07:04 +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 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 3c0fce0ba0 Transform calls to cpu_loop_exit to cpu_loop
`cpu_loop_exit` is used by QEMU to get back control from the translated
code while running an helper. Here we complete the inversion of the
hierarchy by transforming calls to `cpu_loop_exit` into calls to our
customized `cpu_loop`, which will handle syscalls and the like.

Since originally `cpu_loop_exit` was a noreturn function, we also need to
ensure that the semantic of its usage is preserved. We do this by setting
a global variable (`cpu_loop_exiting`) right after the call to
`cpu_loop_exit` and forcing the whole call stack to return immediately
if it's true.

* Introduce `CpuLoopExitPass`: replace all the calls to
  `cpu_loop_exit` with a call to `cpu_loop`, a store true to
  `cpu_loop_exiting` and a return. Then take all the callers and make
  them return if `cpu_loop_exiting` is set. Once we get to the translated
  function just reset `cpu_loop_exiting` to false.
* Introduce `VariableManager::computeEnvAddress`: generate code to
  compute the offset of env . This computation is useful when
  reference to the CPU state must be arificially introduced. This code
  will be flattened by `CorrectCPUStateUsagePass` later.
2016-01-04 21:47:26 +01:00
Alessandro Di Federico dc23749e0e Transform cpu_loop according to our requirements
`cpu_loop` is the main program loop used by QEMU during emulation. Here
we are interested in transforming it in a simple handler of exceptions
(e.g. signals and syscalls).

* Introduce `CpuLoopFunctionPass`: remove the outermost backedge in
  `cpu_loop` and replace the call to cpu_*_exec with the exception index.
* Implement the support function `find_unique` which returns the only
  element in a range satisfying a predicate, or, otherwise, asserts.
2016-01-04 21:46:14 +01:00
Alessandro Di Federico 810e477e2d Improve linking for libtinycode's helpers support
* Expand the function to replace with no-op or abort
* Factor out the code to replace function bodies (replaceFunction and
  replaceFunctionWithRet)
* Replace functions before linking, directly in the helper module
2016-01-04 21:33:45 +01:00
Alessandro Di Federico d684ea7ab1 Sync with the updated libtinycode interface 2016-01-04 21:20:38 +01:00
Alessandro Di Federico c9221fe8a0 Handle termination of a basic block after a call 2016-01-04 21:20:18 +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 a8075fcf4f Remove code to ignore first few PTC instructions
libtinycode no more emits initialization and finalization code that we
don't need.
2015-12-03 18:01:02 +01:00
Alessandro Di Federico 4e326f5799 Factorize LLVM-related helper functions 2015-12-03 17:59:32 +01:00
Alessandro Di Federico 5d130b7072 Split ptctollvmir.cpp into multiple files 2015-11-24 15:21:17 +01:00