Fix rbp pop heuristic
Add criterion to rbp pop detection: iii) that are the last references to %rbp in a `Def` in the subroutine's CFG (cf (ii)).
This commit is contained in:
parent
4d6187ac21
commit
db32807dd0
1 changed files with 31 additions and 12 deletions
|
@ -264,6 +264,11 @@ let build_next_instr sub_ranges (disasm: BStd.disasm): AddrSet.t AddrMap.t =
|
||||||
~init:AddrMap.empty
|
~init:AddrMap.empty
|
||||||
~f:build_of_block
|
~f:build_of_block
|
||||||
|
|
||||||
|
type rbp_pop_state =
|
||||||
|
| SomePop of BStd.tid
|
||||||
|
| SomeRbpUse
|
||||||
|
| NoPop
|
||||||
|
|
||||||
let find_rbp_pop_set cfg entry =
|
let find_rbp_pop_set cfg entry =
|
||||||
(** Returns a BStd.Tid.Set.t of the terms actually "popping" %rbp, that is,
|
(** Returns a BStd.Tid.Set.t of the terms actually "popping" %rbp, that is,
|
||||||
the terms that should trigger a change to RbpUndef of the %rbp register.
|
the terms that should trigger a change to RbpUndef of the %rbp register.
|
||||||
|
@ -273,6 +278,8 @@ let find_rbp_pop_set cfg entry =
|
||||||
ii) that are the last of this kind in the subroutine's CFG (ie. such that
|
ii) that are the last of this kind in the subroutine's CFG (ie. such that
|
||||||
there is not another instruction matching (i) that is reachable through
|
there is not another instruction matching (i) that is reachable through
|
||||||
the CFG from the current instruction).
|
the CFG from the current instruction).
|
||||||
|
iii) that are the last references to %rbp in a `Def` in the subroutine's
|
||||||
|
CFG (cf (ii)).
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let def_is_rbp_pop def =
|
let def_is_rbp_pop def =
|
||||||
|
@ -302,20 +309,30 @@ let find_rbp_pop_set cfg entry =
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
let def_uses_rbp def =
|
||||||
|
let def_vars = BStd.Var.Set.add
|
||||||
|
(BStd.Def.free_vars def)
|
||||||
|
(BStd.Def.lhs def) in
|
||||||
|
BStd.Var.Set.exists def_vars (fun var -> match Regs.X86_64.of_var var with
|
||||||
|
| Some x when x = Regs.X86_64.rbp -> true
|
||||||
|
| _ -> false)
|
||||||
|
in
|
||||||
|
|
||||||
let block_find_rbp_pop block =
|
let block_find_rbp_pop block =
|
||||||
let fold_elt = function
|
let fold_elt = function
|
||||||
| `Def(def) when (def_is_rbp_pop def) -> Some (BStd.Term.tid def)
|
| `Def(def) when (def_is_rbp_pop def) -> SomePop (BStd.Term.tid def)
|
||||||
| _ -> None
|
| `Def(def) when (def_uses_rbp def) -> SomeRbpUse
|
||||||
|
| _ -> NoPop
|
||||||
in
|
in
|
||||||
|
|
||||||
let elts_seq = BStd.Blk.elts block in
|
let elts_seq = BStd.Blk.elts block in
|
||||||
let last_pop = BStd.Seq.fold elts_seq
|
let last_pop = BStd.Seq.fold elts_seq
|
||||||
~init:None
|
~init:NoPop
|
||||||
~f:(fun accu elt ->
|
~f:(fun accu elt ->
|
||||||
(match fold_elt elt with
|
(match fold_elt elt with
|
||||||
| None -> accu
|
| NoPop -> accu
|
||||||
| Some tid -> Some tid))
|
| SomeRbpUse -> SomeRbpUse
|
||||||
|
| SomePop tid -> SomePop tid))
|
||||||
in
|
in
|
||||||
last_pop
|
last_pop
|
||||||
in
|
in
|
||||||
|
@ -330,7 +347,7 @@ let find_rbp_pop_set cfg entry =
|
||||||
BStd.Tid.Set.empty, true, visited
|
BStd.Tid.Set.empty, true, visited
|
||||||
| false ->
|
| false ->
|
||||||
let visited = BStd.Blk.Set.add visited block in
|
let visited = BStd.Blk.Set.add visited block in
|
||||||
let pop_set, has_pop, visited =
|
let pop_set, eligible, visited =
|
||||||
BStd.Seq.fold (CFG.Node.succs node cfg)
|
BStd.Seq.fold (CFG.Node.succs node cfg)
|
||||||
~f:(fun (pre_pop_set, pre_has_pop, visited) child ->
|
~f:(fun (pre_pop_set, pre_has_pop, visited) child ->
|
||||||
let cur_pop_set, cur_has_pop, visited =
|
let cur_pop_set, cur_has_pop, visited =
|
||||||
|
@ -341,14 +358,15 @@ let find_rbp_pop_set cfg entry =
|
||||||
)
|
)
|
||||||
~init:(BStd.Tid.Set.empty, false, visited)
|
~init:(BStd.Tid.Set.empty, false, visited)
|
||||||
in
|
in
|
||||||
let pop_set, has_pop = (match has_pop with
|
let pop_set, eligible = (match eligible with
|
||||||
| false -> (* No rbp pop below, we seek rbp pops in this block *)
|
| false -> (* No rbp pop below, we seek rbp pops in this block *)
|
||||||
(match block_find_rbp_pop block with
|
(match block_find_rbp_pop block with
|
||||||
| None -> pop_set, false
|
| NoPop -> pop_set, false
|
||||||
| Some tid -> BStd.Tid.Set.add pop_set tid, true
|
| SomeRbpUse -> pop_set, true
|
||||||
|
| SomePop tid -> BStd.Tid.Set.add pop_set tid, true
|
||||||
)
|
)
|
||||||
| true -> pop_set, has_pop) in
|
| true -> pop_set, eligible) in
|
||||||
pop_set, has_pop, visited
|
pop_set, eligible, visited
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -739,8 +757,9 @@ let process_sub sub next_instr_graph : subroutine_cfa_data =
|
||||||
(* Already visited: check that entry values are matching *)
|
(* Already visited: check that entry values are matching *)
|
||||||
if entry_offset <> former_entry_offset then (
|
if entry_offset <> former_entry_offset then (
|
||||||
if allow_rbp then
|
if allow_rbp then
|
||||||
Format.eprintf "Found inconsistency (0x%Lx): %a -- %a@."
|
Format.eprintf "Found inconsistency (0x%Lx <%a>): %a -- %a@."
|
||||||
(int64_addr_of cur_blk)
|
(int64_addr_of cur_blk)
|
||||||
|
BStd.Tid.pp tid
|
||||||
pp_reg_pos entry_offset pp_reg_pos former_entry_offset ;
|
pp_reg_pos entry_offset pp_reg_pos former_entry_offset ;
|
||||||
raise (Inconsistent tid)
|
raise (Inconsistent tid)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue