Permalink
Browse files

improves relocations handling (#768)

* added a relocatabale reconstructor

* work in progress

* it's working!!

* refactored relocator

* refactoring

* added Bap_relocator

Technicaly, we may add this module to plugin,
but will also have to update api pligin dependencies
in register_pass function, since api should be applied
after all relocations resolving

* work in progress

* it's working!

* made the relocatable bracnher the default one!

* lot's of debug code in Rel_reconstructor.

Last commit for him

* removed rel_reconstructor, rel_fact

* refactoring bap_relocator

* refactoring

* removed wrong dependency

* adds a cfg to IR lifting function

We still have a problem, that bil doesn't reflect
jump instruction destinations in case of relocations
presence. This leads to wrong IR program.

One of possible solutions is to add a whole program cfg
into sema lift functions for destinations search.

Once we did it, we don't need to think about local relocations
at all - only about external symbols

* added cfg again

* renamed Bap_relocator to Bap_inject_externals

* added to symtab `find_call` and `add_call`

* refactoring

* identation

* fixed bug with calls discovering

* resolved jump as calls with no return

* just fix doc

* moved everything toa plugin

* removed unused + refactored

* refactoring

* removed unused

* lot's of changes

Added to Symtab functions `add_callee` and `find_callee`.
It became possible to add a name of callee side in Reconstructor.
It's useful for detection of external calls while lifting to IR.

* wip

* made it workable

added to sema_lift a lookup of callees of
indirect calls

* updated testsuite

* review accepted

* just remove unnecessary changes

* edited typo

* fixed docs again

* refactored brancher

* updated testsuite

* fixed a bug with cross section call

let's harden a resolving of external functions and
check indirect calls against addresses in symtab too:
if address is in symtab, then such call can't be external

* refactoring

* updated documentation

* fixed predicate for resolving jumps
  • Loading branch information...
gitoleg authored and ivg committed Sep 7, 2018
1 parent 9d3c263 commit 9c7444eecdf3c9d56fe003fbf4fce002e1cafd94
View
@@ -242,17 +242,6 @@ let union_memory m1 m2 =
Memmap.to_sequence m2 |> Seq.fold ~init:m1 ~f:(fun m1 (mem,v) ->
Memmap.add m1 mem v)
let symbolize_synthetic prog insns spec =
if MVar.is_updated spec then
match MVar.read spec with
| None -> prog
| Some spec ->
let p =
Bap_synthetic_symbolizer.resolve spec insns prog in
Signal.send Info.got_program p;
p
else prog
let create_exn
?disassembler:backend
?brancher
@@ -270,7 +259,6 @@ let create_exn
let cfg = MVar.create ~compare:Cfg.compare Cfg.empty in
let symtab = MVar.create ~compare:Symtab.compare Symtab.empty in
let program = MVar.create ~compare:Program.compare (Program.create ()) in
let spec = MVar.from_source (Stream.map ~f:(fun s -> Ok s) Info.spec) in
let task = "loading" in
report_progress ~task ~stage:0 ~total:5 ~note:"reading" ();
let {Input.arch; data; code; file; finish} = read () in
@@ -329,8 +317,6 @@ let create_exn
else
let disasm = Disasm.create g in
let program = MVar.read program in
let program =
symbolize_synthetic program (Disasm.insns disasm) spec in
report_progress ~task ~stage:4 ~note:"finishing" ();
finish {
disasm;
@@ -512,7 +498,7 @@ module Pass = struct
type error =
| Unsat_dep of pass * string
| Runtime_error of pass * exn
[@@deriving variants, sexp_of]
[@@deriving variants, sexp_of]
let find name : pass option =
DList.find passes ~f:(fun p -> p.name = name)
@@ -570,7 +556,8 @@ end
let register x =
let module S = (val x : S) in
let stream =
Stream.map Info.img ~f:(fun img -> Ok (S.of_image img)) in
Stream.map Info.img ~f:(fun img ->
Or_error.try_with (fun () -> S.of_image img)) in
S.Factory.register "internal" stream
let () =

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -1,11 +1,12 @@
open Core_kernel.Std
open Bap_types.Std
open Bap_image_std
open Monads.Std
module Source = Bap_disasm_source
module Targets = Bap_disasm_target_factory
module Dis = Bap_disasm_basic
module Insn = Bap_disasm_insn
type edge = Bap_disasm_block.edge [@@deriving sexp]
type dest = addr option * edge [@@deriving sexp]
@@ -15,6 +16,79 @@ type full_insn = Bap_disasm_basic.full_insn
type t = Brancher of (mem -> full_insn -> dests)
type brancher = t
module Rel_info = struct
type t = {
rels : addr Addr.Map.t;
exts : Addr.Set.t;
}
module Fact = Ogre.Make(Monad.Ident)
module Request = struct
open Image.Scheme
open Fact.Syntax
let of_aseq s =
Seq.fold s ~init:Addr.Map.empty ~f:(fun m (key,data) ->
Map.add m ~key ~data)
let arch_width =
Fact.require arch >>= fun a ->
match Arch.of_string a with
| Some a -> Fact.return (Arch.addr_size a |> Size.in_bits)
| None -> Fact.failf "unknown/unsupported architecture" ()
let relocations =
arch_width >>= fun width ->
Fact.collect Ogre.Query.(select (from relocation)) >>= fun s ->
Fact.return
(of_aseq @@ Seq.map s ~f:(fun (addr, data) ->
Addr.of_int64 ~width addr, Addr.of_int64 ~width data))
let external_symbols =
arch_width >>= fun width ->
Fact.collect Ogre.Query.(
select (from external_reference)) >>= fun s ->
Fact.return
(Seq.fold s ~init:Addr.Set.empty ~f:(fun addrs (addr, _) ->
Set.add addrs (Addr.of_int64 ~width addr)))
end
let relocations = Fact.eval Request.relocations
let external_symbols = Fact.eval Request.external_symbols
let empty = {rels = Addr.Map.empty; exts = Addr.Set.empty}
let of_spec spec =
match relocations spec, external_symbols spec with
| Ok rels, Ok exts -> {rels; exts}
| Error e, _ | _, Error e -> Error.raise e
let span mem =
let start = Memory.min_addr mem in
let len = Memory.length mem in
Seq.init len ~f:(Addr.nsucc start)
let is_external {exts} mem =
Seq.exists ~f:(Set.mem exts) (span mem)
let find_internal {rels} mem =
Seq.find_map ~f:(Map.find rels) (span mem)
end
let fixup rel_info mem target =
match Rel_info.find_internal rel_info mem with
| Some _ as a -> a
| None ->
if Rel_info.is_external rel_info mem then None
else Some target
let resolve_jumps rel_info mem dests =
List.map ~f:(function
| Some addr, `Jump -> fixup rel_info mem addr, `Jump
| x -> x) dests
let create f = Brancher f
let resolve (Brancher f) = f
@@ -32,6 +106,13 @@ let kind_of_branches t f =
| `Fall,`Fall -> `Fall
| _ -> `Cond
let has_jumps =
Bil.exists
(object
inherit [unit] Stmt.finder
method! enter_jmp _ r = r.return (Some ())
end)
let rec dests_of_bil bil : dests =
List.concat_map ~f:dests_of_stmt bil
and dests_of_stmt = function
@@ -45,13 +126,16 @@ and merge_branches yes no =
let kind = kind_of_branches x y in
List.(rev_append x y >>| fun (a,_) -> a,kind)
let dests_of_bil arch =
let dests_of_bil ?(rel_info=Rel_info.empty) arch =
let module Target = (val Targets.target_of_arch arch) in
fun mem insn ->
let next = Addr.succ (Memory.max_addr mem) in
let dests = match Target.lift mem insn with
| Error _ -> []
| Ok bil -> dests_of_bil bil in
| Ok bil ->
if has_jumps bil then
resolve_jumps rel_info mem (dests_of_bil bil)
else [] in
let is = Dis.Insn.is insn in
let fall = Some next, `Fall in
match kind_of_dests dests with
@@ -60,8 +144,10 @@ let dests_of_bil arch =
| `Cond | `Fall -> fall :: dests
| _ -> dests
let of_bil arch = create (dests_of_bil arch)
let of_image img = Image.arch img |> of_bil
let of_image img =
let rel_info = Rel_info.of_spec (Image.spec img) in
create (dests_of_bil ~rel_info (Image.arch img))
module Factory = Source.Factory.Make(struct type nonrec t = t end)
@@ -255,27 +255,12 @@ let next dis s =
let stop_on = [`Valid]
let relocate brancher lift mem insn =
let find_jump dsts =
List.find_map dsts ~f:(function
| Some addr, `Jump -> Some addr
| _ -> None) in
let replace_jump bil addr =
List.map bil ~f:(function
| Bil.Jmp (Bil.Int _) -> Bil.Jmp (Bil.Int addr)
| s -> s) in
lift mem insn >>= fun bil ->
match find_jump (brancher mem insn) with
| None -> return bil
| Some addr -> return (replace_jump bil addr)
let stage1 ?(rooter=Rooter.empty) lift brancher disasm base =
let roots =
Rooter.roots rooter |> Seq.filter ~f:(Memory.contains base) in
let addr,roots = match Seq.to_list roots with
| r :: rs -> r,rs
| [] -> Memory.min_addr base, [] in
let lift = relocate brancher lift in
let init = {base; addr; visited = Span.empty;
roots; inits = Addr.Set.of_list roots; valid = Addr.Set.empty;
dests = Addr.Table.create (); errors = []; lift} in
Oops, something went wrong.

0 comments on commit 9c7444e

Please sign in to comment.