Simplest: change workflow
This commit is contained in:
parent
aec0ab59ad
commit
9f09dec677
|
@ -173,11 +173,12 @@ let interpret_var_expr c_var offset expr = BStd.Bil.(
|
||||||
| _ -> None
|
| _ -> None
|
||||||
)
|
)
|
||||||
|
|
||||||
let process_def def (cur_offset: memory_offset)
|
let process_def def (cur_cfa: cfa_pos)
|
||||||
: ((cfa_pos * memory_offset) option) =
|
: (cfa_pos option) =
|
||||||
let lose_track = Some (CfaLostTrack, Int64.zero) in
|
let lose_track = Some (CfaLostTrack) in
|
||||||
(match Regs.X86_64.of_var (BStd.Def.lhs def) with
|
|
||||||
| Some reg when reg = Regs.X86_64.rsp ->
|
(match cur_cfa, Regs.X86_64.of_var (BStd.Def.lhs def) with
|
||||||
|
| RspOffset(cur_offset), Some reg when reg = Regs.X86_64.rsp ->
|
||||||
let exp = BStd.Def.rhs def in
|
let exp = BStd.Def.rhs def in
|
||||||
let free_vars = BStd.Exp.free_vars exp in
|
let free_vars = BStd.Exp.free_vars exp in
|
||||||
let free_x86_regs = Regs.X86_64.map_varset free_vars in
|
let free_x86_regs = Regs.X86_64.map_varset free_vars in
|
||||||
|
@ -193,7 +194,7 @@ let process_def def (cur_offset: memory_offset)
|
||||||
(match interpreted with
|
(match interpreted with
|
||||||
| None -> lose_track
|
| None -> lose_track
|
||||||
| Some new_offset ->
|
| Some new_offset ->
|
||||||
Some (RspOffset(new_offset), new_offset)
|
Some (RspOffset(new_offset))
|
||||||
)
|
)
|
||||||
| _ -> lose_track
|
| _ -> lose_track
|
||||||
)
|
)
|
||||||
|
@ -201,11 +202,14 @@ let process_def def (cur_offset: memory_offset)
|
||||||
)
|
)
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
|
|
||||||
let process_jmp jmp (cur_offset: memory_offset)
|
let process_jmp jmp (cur_cfa: cfa_pos)
|
||||||
: ((cfa_pos * memory_offset) option) =
|
: (cfa_pos option) =
|
||||||
let gen_change off =
|
let gen_change = match cur_cfa with
|
||||||
let new_offset = Int64.add cur_offset (Int64.of_int off) in
|
| RspOffset cur_offset -> (fun off ->
|
||||||
Some (RspOffset(new_offset), new_offset)
|
let new_offset = Int64.add cur_offset (Int64.of_int off) in
|
||||||
|
Some (RspOffset(new_offset))
|
||||||
|
)
|
||||||
|
| _ -> (fun _ -> None)
|
||||||
in
|
in
|
||||||
|
|
||||||
match (BStd.Jmp.kind jmp) with
|
match (BStd.Jmp.kind jmp) with
|
||||||
|
@ -213,14 +217,13 @@ let process_jmp jmp (cur_offset: memory_offset)
|
||||||
| BStd.Ret ret -> gen_change (8)
|
| BStd.Ret ret -> gen_change (8)
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
let sym_of_blk next_instr_graph blk : cfa_changes_fde =
|
let process_blk
|
||||||
(** Extracts the symbolic CFA changes of a block. These changes assume that
|
next_instr_graph (block_init: cfa_pos) blk : (cfa_changes_fde * cfa_pos) =
|
||||||
at the beginning of the block, CFA = RspOffset(0) and will be offset
|
(** Extracts the CFA changes of a block. *)
|
||||||
after *)
|
|
||||||
|
|
||||||
let apply_offset cur_addr_opt ((accu:cfa_change list), cur_offset) = function
|
let apply_offset cur_addr_opt ((accu:cfa_change list), cur_cfa) = function
|
||||||
| None -> (accu, cur_offset)
|
| None -> (accu, cur_cfa)
|
||||||
| Some (pos, n_offset) ->
|
| Some pos ->
|
||||||
let cur_addr = (match cur_addr_opt with
|
let cur_addr = (match cur_addr_opt with
|
||||||
| None -> assert false
|
| None -> assert false
|
||||||
| Some x -> to_int64_addr x) in
|
| Some x -> to_int64_addr x) in
|
||||||
|
@ -229,55 +232,27 @@ let sym_of_blk next_instr_graph blk : cfa_changes_fde =
|
||||||
(change :: cur_accu))
|
(change :: cur_accu))
|
||||||
(AddrMap.find cur_addr next_instr_graph)
|
(AddrMap.find cur_addr next_instr_graph)
|
||||||
accu),
|
accu),
|
||||||
n_offset
|
pos
|
||||||
in
|
in
|
||||||
|
|
||||||
let fold_elt (accu, cur_offset) elt = match elt with
|
let fold_elt (accu, cur_cfa) elt = match elt with
|
||||||
| `Def(def) ->
|
| `Def(def) ->
|
||||||
apply_offset
|
apply_offset
|
||||||
(opt_addr_of def) (accu, cur_offset) @@ process_def def cur_offset
|
(opt_addr_of def) (accu, cur_cfa) @@ process_def def cur_cfa
|
||||||
| `Jmp(jmp) ->
|
| `Jmp(jmp) ->
|
||||||
apply_offset
|
apply_offset
|
||||||
(opt_addr_of jmp) (accu, cur_offset) @@ process_jmp jmp cur_offset
|
(opt_addr_of jmp) (accu, cur_cfa) @@ process_jmp jmp cur_cfa
|
||||||
| _ -> (accu, cur_offset)
|
| _ -> (accu, cur_cfa)
|
||||||
in
|
in
|
||||||
|
|
||||||
let elts_seq = BStd.Blk.elts blk in
|
let elts_seq = BStd.Blk.elts blk in
|
||||||
let out, end_offset = BStd.Seq.fold elts_seq
|
let out, end_cfa = BStd.Seq.fold elts_seq
|
||||||
~init:([], Int64.zero)
|
~init:([], block_init)
|
||||||
~f:fold_elt in
|
~f:fold_elt in
|
||||||
out
|
out, end_cfa
|
||||||
|
|
||||||
let end_offset (changelist: cfa_changes_fde): memory_offset option =
|
|
||||||
match changelist with
|
|
||||||
| CfaChange(_, RspOffset(x)) :: _ -> Some x
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
exception Inconsistent of BStd.tid
|
exception Inconsistent of BStd.tid
|
||||||
|
|
||||||
let rec dfs_propagate changemap propagated parent_val node graph =
|
|
||||||
let c_tid = BStd.Term.tid @@ CFG.Node.label node in
|
|
||||||
match TIdMap.find_opt c_tid propagated with
|
|
||||||
| Some x ->
|
|
||||||
if x = parent_val then
|
|
||||||
(* Already propagated and consistent, all fine *)
|
|
||||||
propagated
|
|
||||||
else
|
|
||||||
(* Already propagated with a different value: inconsistency *)
|
|
||||||
raise (Inconsistent c_tid)
|
|
||||||
| None ->
|
|
||||||
let n_propagated = TIdMap.add c_tid parent_val propagated in
|
|
||||||
let outwards = CFG.Node.outputs node graph in
|
|
||||||
let self_entry = TIdMap.find c_tid changemap in
|
|
||||||
let offset = (match end_offset self_entry with
|
|
||||||
Some x -> x
|
|
||||||
| None -> Int64.zero) in
|
|
||||||
let cur_val = Int64.add parent_val offset in
|
|
||||||
BStd.Seq.fold outwards
|
|
||||||
~init:n_propagated
|
|
||||||
~f:(fun accu edge ->
|
|
||||||
dfs_propagate changemap accu cur_val (CFG.Edge.dst edge) graph)
|
|
||||||
|
|
||||||
let get_entry_blk graph =
|
let get_entry_blk graph =
|
||||||
let entry = BStd.Seq.min_elt (CFG.nodes graph) ~cmp:(fun x y ->
|
let entry = BStd.Seq.min_elt (CFG.nodes graph) ~cmp:(fun x y ->
|
||||||
let ax = opt_addr_of @@ CFG.Node.label x
|
let ax = opt_addr_of @@ CFG.Node.label x
|
||||||
|
@ -292,14 +267,7 @@ let get_entry_blk graph =
|
||||||
| None -> assert false
|
| None -> assert false
|
||||||
| Some x -> x
|
| Some x -> x
|
||||||
|
|
||||||
let same_keys map1 map2 =
|
let process_sub sub : cfa_changes_fde =
|
||||||
let exists_in_other other key _ =
|
|
||||||
TIdMap.mem key other in
|
|
||||||
|
|
||||||
TIdMap.for_all (exists_in_other map2) map1
|
|
||||||
&& TIdMap.for_all (exists_in_other map1) map2
|
|
||||||
|
|
||||||
let of_sub sub : cfa_changes_fde =
|
|
||||||
(** Extracts the `cfa_changes_fde` of a subroutine *)
|
(** Extracts the `cfa_changes_fde` of a subroutine *)
|
||||||
|
|
||||||
Format.eprintf "Sub %s...@." @@ BStd.Sub.name sub ;
|
Format.eprintf "Sub %s...@." @@ BStd.Sub.name sub ;
|
||||||
|
@ -308,77 +276,48 @@ let of_sub sub : cfa_changes_fde =
|
||||||
let next_instr_graph = build_next_instr cfg in
|
let next_instr_graph = build_next_instr cfg in
|
||||||
|
|
||||||
let initial_cfa_rsp_offset = Int64.of_int 8 in
|
let initial_cfa_rsp_offset = Int64.of_int 8 in
|
||||||
let store_sym accu blk =
|
|
||||||
let blk = CFG.Node.label blk in
|
|
||||||
let res = sym_of_blk next_instr_graph blk in
|
|
||||||
TIdMap.add (BStd.Term.tid blk) res accu
|
|
||||||
in
|
|
||||||
|
|
||||||
let node_addr nd = opt_addr_of @@ CFG.Node.label nd in
|
let rec dfs_process
|
||||||
|
(sub_changes: (cfa_changes_fde * cfa_pos) TIdMap.t) node entry_offset =
|
||||||
|
(** Processes one block *)
|
||||||
|
|
||||||
let merge_corrected blk_tid changes offset = match (changes, offset) with
|
let cur_blk = CFG.Node.label node in
|
||||||
| Some changes, Some offset ->
|
let tid = BStd.Term.tid @@ cur_blk in
|
||||||
Some (
|
|
||||||
List.map (fun (CfaChange(addr, pos)) -> match pos with
|
|
||||||
RspOffset(off) -> CfaChange(addr,
|
|
||||||
RspOffset(Int64.add off offset))
|
|
||||||
| RbpOffset(off) -> CfaChange(addr, RbpOffset(off))
|
|
||||||
| CfaLostTrack -> CfaChange(addr, CfaLostTrack)
|
|
||||||
)
|
|
||||||
changes
|
|
||||||
)
|
|
||||||
| _ -> None
|
|
||||||
in
|
|
||||||
|
|
||||||
let tid_match = BStd.Seq.fold (CFG.nodes cfg)
|
match (TIdMap.find_opt tid sub_changes) with
|
||||||
~init:TIdMap.empty
|
| None ->
|
||||||
~f:(fun accu node ->
|
(* Not yet visited: compute the changes *)
|
||||||
let tid = BStd.Term.tid @@ CFG.Node.label node in
|
let cur_blk_changes, end_cfa =
|
||||||
TIdMap.add tid node accu)
|
process_blk next_instr_graph entry_offset cur_blk in
|
||||||
in
|
let n_sub_changes =
|
||||||
|
TIdMap.add tid (cur_blk_changes, entry_offset) sub_changes in
|
||||||
let blk_sym = BStd.Seq.fold
|
BStd.Seq.fold (CFG.Node.succs node cfg)
|
||||||
~init:TIdMap.empty
|
~f:(fun accu child -> dfs_process accu child end_cfa)
|
||||||
~f:store_sym
|
~init:n_sub_changes
|
||||||
@@ CFG.nodes cfg
|
| Some (_, former_entry_offset) ->
|
||||||
|
(* Already visited: check that entry values are matching *)
|
||||||
|
if entry_offset <> former_entry_offset then
|
||||||
|
raise (Inconsistent tid)
|
||||||
|
else
|
||||||
|
sub_changes
|
||||||
in
|
in
|
||||||
|
|
||||||
let entry_blk = get_entry_blk cfg in
|
let entry_blk = get_entry_blk cfg in
|
||||||
let offset_map = dfs_propagate
|
let initial_offset = (RspOffset initial_cfa_rsp_offset) in
|
||||||
blk_sym (TIdMap.empty) initial_cfa_rsp_offset entry_blk cfg in
|
let changes_map = dfs_process TIdMap.empty entry_blk initial_offset in
|
||||||
|
|
||||||
let corrected = TIdMap.merge merge_corrected blk_sym offset_map in
|
let merged_changes = TIdMap.fold
|
||||||
|
(fun _ (cfa_changes, _) accu -> cfa_changes @ accu)
|
||||||
|
changes_map
|
||||||
|
[CfaChange(int64_addr_of sub, initial_offset)] in
|
||||||
|
|
||||||
let is_connex = same_keys tid_match corrected in
|
let sorted_changes = List.sort
|
||||||
if not is_connex then
|
(fun (CfaChange (addr1, _)) (CfaChange (addr2, _)) ->
|
||||||
raise InvalidSub ;
|
compare addr1 addr2)
|
||||||
|
merged_changes
|
||||||
let tid_list = TIdMap.bindings tid_match in
|
|
||||||
let sorted_blk = List.sort (fun (tid1, bl1) (tid2, bl2) ->
|
|
||||||
let res = match (node_addr bl1, node_addr bl2) with
|
|
||||||
| Some addr1, Some addr2 -> compare addr1 addr2
|
|
||||||
| Some _, None -> 1
|
|
||||||
| None, Some _ -> -1
|
|
||||||
| None, None -> compare tid1 tid2
|
|
||||||
in
|
in
|
||||||
-res)
|
|
||||||
tid_list
|
|
||||||
in
|
|
||||||
|
|
||||||
let out = List.fold_left
|
sorted_changes
|
||||||
(fun accu blk ->
|
|
||||||
let changes = TIdMap.find blk corrected in
|
|
||||||
List.fold_left (fun accu chg -> chg::accu)
|
|
||||||
accu
|
|
||||||
changes
|
|
||||||
)
|
|
||||||
[]
|
|
||||||
(List.map (fun (x, y) -> x) sorted_blk) in
|
|
||||||
|
|
||||||
let init = [
|
|
||||||
CfaChange(int64_addr_of sub, RspOffset(initial_cfa_rsp_offset))
|
|
||||||
] in
|
|
||||||
init @ out
|
|
||||||
|
|
||||||
let cleanup_fde (fde_changes: cfa_changes_fde) : cfa_changes_fde =
|
let cleanup_fde (fde_changes: cfa_changes_fde) : cfa_changes_fde =
|
||||||
(** Cleanup the result of `of_sub`.
|
(** Cleanup the result of `of_sub`.
|
||||||
|
@ -429,7 +368,7 @@ let of_prog prog : cfa_changes =
|
||||||
(** Extracts the `cfa_changes` of a program *)
|
(** Extracts the `cfa_changes` of a program *)
|
||||||
let fold_step accu sub =
|
let fold_step accu sub =
|
||||||
(try
|
(try
|
||||||
let res = cleanup_fde @@ of_sub sub in
|
let res = cleanup_fde @@ process_sub sub in
|
||||||
StrMap.add (BStd.Sub.name sub) res accu
|
StrMap.add (BStd.Sub.name sub) res accu
|
||||||
with InvalidSub -> accu)
|
with InvalidSub -> accu)
|
||||||
in
|
in
|
||||||
|
|
Loading…
Reference in a new issue