From 5ecd56a134980e836178564fe5210d25ec639e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Tue, 20 Nov 2018 16:55:56 +0100 Subject: [PATCH] Simplest: compute first and last address of sub --- DwarfSynth/Frontend.ml | 22 +++++---- DwarfSynth/Simplest.ml | 106 +++++++++++++++++++++++++++++++---------- 2 files changed, 94 insertions(+), 34 deletions(-) diff --git a/DwarfSynth/Frontend.ml b/DwarfSynth/Frontend.ml index 5dee48f..42fb03a 100644 --- a/DwarfSynth/Frontend.ml +++ b/DwarfSynth/Frontend.ml @@ -31,12 +31,16 @@ let pp_cfa_change ppx addr pos = Simplest.( Format.fprintf ppx "%a u u@." pp_int64_hex addr ) -let pp_pre_dwarf_readelf ppx pre_dwarf = - Simplest.StrMap.iter (fun fde_name entry -> - Format.fprintf ppx "FDE %s@." fde_name ; - if not (Simplest.AddrMap.is_empty entry) then ( - Format.fprintf ppx " LOC CFA ra@." ; - Simplest.AddrMap.iter (pp_cfa_change ppx) entry ; - Format.fprintf ppx "@.") - ) - pre_dwarf +let pp_pre_dwarf_readelf ppx (pre_dwarf: Simplest.subroutine_cfa_map) = + Simplest.( + Simplest.StrMap.iter (fun fde_name entry -> + Format.fprintf ppx "FDE %s pc=%a..%a@." + fde_name pp_int64_hex entry.beg_pos pp_int64_hex entry.end_pos; + let cfa_entry = entry.cfa_changes_fde in + if not (Simplest.AddrMap.is_empty cfa_entry) then ( + Format.fprintf ppx " LOC CFA ra@." ; + Simplest.AddrMap.iter (pp_cfa_change ppx) cfa_entry ; + Format.fprintf ppx "@.") + ) + pre_dwarf + ) diff --git a/DwarfSynth/Simplest.ml b/DwarfSynth/Simplest.ml index 5d84b34..b041496 100644 --- a/DwarfSynth/Simplest.ml +++ b/DwarfSynth/Simplest.ml @@ -14,8 +14,14 @@ type cfa_pos = type cfa_changes_fde = cfa_pos AddrMap.t +type subroutine_cfa_data = { + cfa_changes_fde: cfa_changes_fde; + beg_pos: memory_address; + end_pos: memory_address; +} + module StrMap = Map.Make(String) -type cfa_changes = cfa_changes_fde StrMap.t +type subroutine_cfa_map = subroutine_cfa_data StrMap.t module TIdMap = Map.Make(BStd.Tid) @@ -310,7 +316,66 @@ let get_entry_blk graph = | None -> assert false | Some x -> x -let process_sub sub : cfa_changes_fde = +let find_last_addr sub = + (** Finds the maximal instruction address in a subroutine *) + + let map_opt fl fr merge l r = match l, r with + | None, None -> None + | Some x, None -> Some (fl x) + | None, Some y -> Some (fr y) + | Some x, Some y -> Some (merge (fl x) (fr y)) + in + let max_opt_addr_word = map_opt + (fun x -> x) + (fun y -> to_int64_addr y) + max + in + let max_opt_addr = map_opt + (fun x -> x) + (fun y -> y) + max + in + let max_def cur_max def = + max_opt_addr_word cur_max (opt_addr_of def) + in + + let fold_res = + BStd.Seq.fold (BStd.Term.enum BStd.blk_t sub) + ~init:None + ~f:(fun cur_max blk -> + max_opt_addr + (BStd.Seq.fold (BStd.Term.enum BStd.def_t blk) + ~init:cur_max + ~f:max_def) + (BStd.Seq.fold (BStd.Term.enum BStd.jmp_t blk) + ~init:cur_max + ~f:max_def) + ) + in + match fold_res with + | None -> Int64.zero + | Some x -> x + +let cleanup_fde (fde_changes: cfa_changes_fde) : cfa_changes_fde = + (** Cleanup the result of `of_sub`. + + Merges entries at the same address, propagates track lost *) + + let fold_one addr cfa_change (accu, last_change, lost_track) = + match cfa_change, last_change, lost_track with + | _, _, true -> (accu, None, lost_track) + | CfaLostTrack, _, false -> + (AddrMap.add addr cfa_change accu, None, true) + | cfa_change, Some prev_change, false when cfa_change = prev_change -> + (accu, last_change, false) + | cfa_change, _, false -> + (AddrMap.add addr cfa_change accu, Some cfa_change, false) + in + + match AddrMap.fold fold_one fde_changes (AddrMap.empty, None, false) with + | out, _, _ -> out + +let process_sub sub : subroutine_cfa_data = (** Extracts the `cfa_changes_fde` of a subroutine *) Format.eprintf "Sub %s...@." @@ BStd.Sub.name sub ; @@ -318,6 +383,9 @@ let process_sub sub : cfa_changes_fde = let cfg = BStd.Sub.to_cfg sub in let next_instr_graph = build_next_instr cfg in + let first_addr = int64_addr_of sub in + let last_addr = find_last_addr sub in + let initial_cfa_rsp_offset = Int64.of_int 8 in let rec dfs_process @@ -359,34 +427,22 @@ let process_sub sub : cfa_changes_fde = changes_map AddrMap.empty in - merged_changes + let cfa_changes = cleanup_fde merged_changes in -let cleanup_fde (fde_changes: cfa_changes_fde) : cfa_changes_fde = - (** Cleanup the result of `of_sub`. + let output = { + cfa_changes_fde = cfa_changes ; + beg_pos = first_addr ; + end_pos = last_addr ; + } in - Merges entries at the same address, propagates track lost *) + output - let fold_one addr cfa_change (accu, last_change, lost_track) = - match cfa_change, last_change, lost_track with - | _, _, true -> (accu, None, lost_track) - | CfaLostTrack, _, false -> - (AddrMap.add addr cfa_change accu, None, true) - | cfa_change, Some prev_change, false when cfa_change = prev_change -> - (accu, last_change, false) - | cfa_change, _, false -> - (AddrMap.add addr cfa_change accu, Some cfa_change, false) - in - - match AddrMap.fold fold_one fde_changes (AddrMap.empty, None, false) with - | out, _, _ -> out - - -let of_prog prog : cfa_changes = +let of_prog prog : subroutine_cfa_map = (** Extracts the `cfa_changes` of a program *) let fold_step accu sub = (try - let res = cleanup_fde @@ process_sub sub in - StrMap.add (BStd.Sub.name sub) res accu + let subroutine_data = process_sub sub in + StrMap.add (BStd.Sub.name sub) subroutine_data accu with | InvalidSub -> accu | Inconsistent tid -> @@ -400,7 +456,7 @@ let of_prog prog : cfa_changes = ~init:StrMap.empty ~f:fold_step -let of_proj proj : cfa_changes = +let of_proj proj : subroutine_cfa_map = (** Extracts the `cfa_changes` of a project *) let prog = BStd.Project.program proj in of_prog prog