From 3ab947ce345e9d18ddcda57d8f88b2a9b8f5d267 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Mon, 12 Oct 2015 11:48:36 +0200 Subject: Removal of cchecklink, superseded by AbsInt's Valex tool. --- checklink/Check.ml | 3216 ---------------------------------------------------- 1 file changed, 3216 deletions(-) delete mode 100644 checklink/Check.ml (limited to 'checklink/Check.ml') diff --git a/checklink/Check.ml b/checklink/Check.ml deleted file mode 100644 index 0e69ab72..00000000 --- a/checklink/Check.ml +++ /dev/null @@ -1,3216 +0,0 @@ -open Asm -open Asm_printers -open AST -open Bitstring_utils -open C2C -open Camlcoq -open ELF_parsers -open ELF_printers -open ELF_types -open ELF_utils -open Frameworks -open Lens -open Library -open PPC_parsers -open PPC_printers -open PPC_types -open PPC_utils -open Sections - -(** Enables immediate printing of log information to stdout. - Warning: will print out everything even when backtracking. -*) -let debug = ref false - -(** Whether to print the ELF map. *) -let print_elfmap = ref false - -(** Whether to dump the ELF map. *) -let dump_elfmap = ref false - -(** Whether to check that all ELF function/data symbols have been matched - against CompCert idents. *) -let exhaustivity = ref true - -(** Whether to print the list of all symbols (function and data) that were not - found in .sdump files. *) -let list_missing = ref false - -(** CompCert Asm *) -type ccode = Asm.coq_function - -let print_debug s = - if !debug then print_endline (string_of_log_entry true (DEBUG(s))) - -(** Adds a log entry into the framework. *) -let add_log (entry: log_entry) (efw: e_framework): e_framework = - if !debug then print_endline ("--DEBUG-- " ^ string_of_log_entry true entry); - {efw with log = entry :: efw.log} - -(** [flag] should have only one bit set. *) -let is_set_flag (flag: int32) (bitset: int32): bool = - Int32.logand bitset flag <> 0l - -(** Checks that [atom]'s binding matches [sym]'s. *) -let check_st_bind atom (sym: elf32_sym): s_framework -> s_framework = - let static = atom.a_storage = C.Storage_static || atom.a_inline in - match static, sym.st_bind with - | true, STB_LOCAL -> id - | false, STB_GLOBAL -> id - | _ -> ( - sf_ef ^%= - add_log (ERROR( - "Symbol: " ^ sym.st_name ^ " has a wrong binding (local vs. global)" - )) - ) - -(** Adapted from CompCert *) -let name_of_section_Linux: section_name -> string = function -| Section_text -> ".text" -| Section_data i -> if i then ".data" else "COMM" -| Section_small_data i -> if i then ".sdata" else ".sbss" -| Section_const i -> if i then ".rodata" else "COMM" -| Section_small_const i -> if i then ".sdata2" else "COMM" -| Section_string -> ".rodata" -| Section_literal -> ".rodata.cst8" -| Section_jumptable -> ".text" -| Section_user(s, wr, ex) -> s -| Section_debug_info -> ".debug_info" -| Section_debug_abbrev -> ".debug_abbrev" - -(** Adapted from CompCert *) -let name_of_section_Diab: section_name -> string = function -| Section_text -> ".text" -| Section_data i -> if i then ".data" else "COMM" -| Section_small_data i -> if i then ".sdata" else ".sbss" -| Section_const _ -> ".text" -| Section_small_const _ -> ".sdata2" -| Section_string -> ".text" -| Section_literal -> ".text" -| Section_jumptable -> ".text" -| Section_user(s, wr, ex) -> s -| Section_debug_info -> ".debug_info" -| Section_debug_abbrev -> ".debug_abbrev" - -(** Taken from CompCert *) -let name_of_section: section_name -> string = - begin match Configuration.system with - | "linux" -> name_of_section_Linux - | "diab" -> name_of_section_Diab - | _ -> fatal "Unsupported CompCert configuration" - end - -(** Compares a CompCert section name with an ELF section name. *) -let match_sections_name - (c_section: section_name) (e_name: string) (sfw: s_framework): - s_framework - = - let c_name = name_of_section c_section in - try - let (value, conflicts) = StringMap.find c_name sfw.ef.section_map in - let expected = from_inferrable value in - if e_name = expected - then sfw - else ( - sfw - >>> (sf_ef |-- section_map) ^%= - StringMap.add c_name (value, StringSet.add e_name conflicts) - ) - with Not_found -> ( - sfw - >>> (sf_ef |-- section_map) ^%= - StringMap.add c_name (Inferred(e_name), StringSet.empty) - ) - -(** Checks the symbol table entry of the function symbol number [sym_ndx], - according to CompCert's [ident]. -*) -let check_fun_symtab - (ident: ident) (sym_ndx: int) (sfw: s_framework): - s_framework - = - let elf = sfw.ef.elf in - let symtab_sndx = from_some (section_ndx_by_name elf ".symtab") in - let symtab_ent_start = - Int32.(add - elf.e_shdra.(symtab_sndx).sh_offset - (Safe32.of_int (16 * sym_ndx))) in - let sym = sfw.ef.elf.e_symtab.(sym_ndx) in - let atom = Hashtbl.find sfw.atoms ident in - let section = - match atom.a_sections with - | [t; _; _] -> t - | _ -> Section_text - in - sfw - >>> check_st_bind atom sym - >>> ( - if sym.st_type = STT_FUNC - then id - else (sf_ef ^%= - add_log (ERROR("Symbol should have type STT_FUNC")) - ) - ) - >>> ( - if sym.st_other = 0 - then id - else (sf_ef ^%= - add_log (ERROR("Symbol should have st_other set to 0")) - ) - ) - >>> match_sections_name section elf.e_shdra.(sym.st_shndx).sh_name - >>> sf_ef ^%= - add_range symtab_ent_start 16l 4 (Symtab_function(sym)) - -(** Checks that the offset [ofs] is well aligned with regards to [al], expressed - in bytes. *) -let is_well_aligned (ofs: int32) (al: int): bool = - al = 0 || Int32.rem ofs (Safe32.of_int al) = 0l - -(** Adds a function symbol to the set of covered symbols. *) -let mark_covered_fun_sym_ndx (ndx: int) ffw: f_framework = - let elf = ffw.sf.ef.elf in - let sym = elf.e_symtab.(ndx) in - let sym_sndx = sym.st_shndx in - let sym_size = sym.st_size in - let sym_shdr = elf.e_shdra.(sym_sndx) in - let sym_vaddr = sym.st_value in - let sym_ofs_local = Int32.sub sym_vaddr sym_shdr.sh_addr in - let sxn_ofs = sym_shdr.sh_offset in - let sym_begin = Int32.add sxn_ofs sym_ofs_local in - let atom = Hashtbl.find ffw.sf.atoms ffw.this_ident in - let align = - match atom.a_alignment with - | Some(a) -> a - | None -> 0 - in - ffw.sf.ef.chkd_fun_syms.(ndx) <- true; - ffw - >>> (ff_ef ^%= add_range sym_begin sym_size align (Function_symbol(sym))) - >>> (ff_sf ^%= - if not (is_well_aligned sym_ofs_local align) - then ( - sf_ef ^%= - add_log (ERROR("Symbol not correctly aligned in the ELF file")) - ) - else id - ) - >>> (ff_sf ^%= check_fun_symtab ffw.this_ident ndx) - -(** Tries to refine the mapping for key [k] in [ident_to_sym_ndx] so that it is - mapped to [vaddr]. Fails if no symbol in [k]'s mapping has that virtual - address. Otherwise, it filters out all symbols whose virtual - address does not match [vaddr]. -*) -let idmap_unify (k: P.t) (vaddr: int32) (sfw: s_framework) - : s_framework or_err = - try ( - (* get the list of possible symbols for ident [k] *) - let id_ndxes = PosMap.find k sfw.ident_to_sym_ndx in - (* consider only the ones at the correct virtual address *) - match List.filter - (fun ndx -> sfw.ef.elf.e_symtab.(ndx).st_value = vaddr) - id_ndxes - with - | [] -> - (* no symbol has that virtual address *) - ERR( - Printf.sprintf - "Incoherent constraints for ident %s with value %s and candidates [%s]" - (Hashtbl.find sfw.ident_to_name k) - (string_of_int32 vaddr) - (string_of_list - (fun ndx -> string_of_int32 sfw.ef.elf.e_symtab.(ndx).st_value) - ", " id_ndxes - ) - ) - | ndxes -> - if id_ndxes = ndxes - then OK(sfw) - else OK((ident_to_sym_ndx ^%= (PosMap.add k ndxes)) sfw) - ) - with - | Not_found -> - ERR( - Printf.sprintf - "Missing ident: %s should be at vaddr: %s" - (Hashtbl.find sfw.ident_to_name k) - (string_of_int32 vaddr) - ) - -(** Checks whether the label [k] points to [v] in [label_to_vaddr]. If it points - to another virtual address, this returns an ERR. If it points to nothing, - the mapping [k] -> [v] is added. Thus, the first time a label is - encountered determines the expected virtual address of its destination. - Subsequent references to the label will have to conform. -*) -let lblmap_unify (k: label) (v: int32) (ffw: f_framework) - : f_framework or_err = - try ( - let v' = PosMap.find k ffw.label_to_vaddr in - if v = v' - then OK ffw - else ( - ERR( - "Incoherent constraints for label " ^ - string_of_positive k ^ " with values " ^ - string_of_int32 v ^ " and " ^ string_of_int32 v' - ) - ) - ) - with - | Not_found -> - OK { - ffw with - label_to_vaddr = PosMap.add k v ffw.label_to_vaddr - } - -let ireg_arr: ireg array = - [| - GPR0; GPR1; GPR2; GPR3; GPR4; GPR5; GPR6; GPR7; GPR8; GPR9; GPR10; GPR11; - GPR12; GPR13; GPR14; GPR15; GPR16; GPR17; GPR18; GPR19; GPR20; GPR21; GPR22; - GPR23; GPR24; GPR25; GPR26; GPR27; GPR28; GPR29; GPR30; GPR31 - |] - -let freg_arr: freg array = - [| - FPR0; FPR1; FPR2; FPR3; FPR4; FPR5; FPR6; FPR7; FPR8; FPR9; FPR10; FPR11; - FPR12; FPR13; FPR14; FPR15; FPR16; FPR17; FPR18; FPR19; FPR20; FPR21; FPR22; - FPR23; FPR24; FPR25; FPR26; FPR27; FPR28; FPR29; FPR30; FPR31 - |] - -let num_crbit = function - | CRbit_0 -> 0 - | CRbit_1 -> 1 - | CRbit_2 -> 2 - | CRbit_3 -> 3 - | CRbit_6 -> 6 - -type checker = f_framework -> f_framework or_err -let check (cond: bool) (msg: string): checker = - fun ffw -> if cond then OK(ffw) else ERR(msg) -let check_eq (msg: string) (a: 'a) (b: 'a): checker = - check (a = b) msg -let match_bools a b = - check_eq ( - Printf.sprintf "match_bools %s %s" (string_of_bool a) (string_of_bool b) - ) a b -let match_ints a b = - check_eq ( - Printf.sprintf "match_ints %s %s" (string_of_int a) (string_of_int b) - ) a b -let match_int32s a b: checker = - check_eq ( - Printf.sprintf "match_int32s %s %s" (string_of_int32 a) (string_of_int32 b) - ) a b -(** We compare floats by their bit representation, so that 0.0 and -0.0 are - different. *) -let match_floats (a: Floats.float) (b: int64): checker = - let a = camlint64_of_coqint (Floats.Float.to_bits a) in - check_eq ( - Printf.sprintf "match_floats %s %s" (string_of_int64 a) (string_of_int64 b) - ) a b -let match_floats32 (a: Floats.float32) (b: int32): checker = - let a = camlint_of_coqint (Floats.Float32.to_bits a) in - check_eq ( - Printf.sprintf "match_floats %s %s" (string_of_int32 a) (string_of_int32 b) - ) a b -let match_crbits cb eb = - let cb = num_crbit cb in - check_eq ( - Printf.sprintf "match_crbits %d %d" cb eb - ) cb eb -let match_iregs cr er = - let er = ireg_arr.(er) in - check_eq ( - Printf.sprintf "match_iregs %s %s" (string_of_ireg cr) (string_of_ireg er) - ) cr er -let match_fregs cr er = - let er = freg_arr.(er) in - check_eq ( - Printf.sprintf "match_fregs %s %s" (string_of_freg cr) (string_of_freg er) - ) cr er - -let name_of_ndx (efw: e_framework) (ndx: int): string = - let st = efw.elf.e_symtab.(ndx) in - st.st_name ^ " at address " ^ (string_of_int32 st.st_value) - -(** Filters the lower 16 bits of an int32. *) -let low: int32 -> int32 = Int32.logand 0x0000ffffl - -(** high_exts x is equal to: - - - the 16 high bits of x if its lower 16 bits form a positive 16 bit integer - - - the 16 high bits of x plus one otherwise - - This is so that: x == high_exts x + exts (low x) -*) -let high_exts (x: int32): int32 = Int32.( - if logand x 0x00008000l = 0l - then logand x 0xffff0000l - else add 0x00010000l (logand x 0xffff0000l) -) - -(** Matches a CompCert constant against an [int32]. *) -let match_csts (cc: constant) (ec: int32): checker = fun ffw -> - let sfw = ffw |. ff_sf in - let efw = ffw |. ff_ef in - match cc with - | Cint (i) -> - let i = z_int32_lax i in - let msg = - Printf.sprintf "match_csts Cint %s %s" - (string_of_int32 i) - (string_of_int32 ec) - in - check_eq msg ec i ffw - | Csymbol_low (ident, i) -> - let candidates = - try PosMap.find ident sfw.ident_to_sym_ndx - with Not_found -> [] - in - let vaddrs = - List.filter - (fun ndx -> - let ident_vaddr = efw.elf.e_symtab.(ndx).st_value in - Int32.(low (add ident_vaddr (z_int32_lax i)) = low ec) - ) - candidates - in - begin match vaddrs with - | [] -> - let sym_names = List.map (name_of_ndx efw) candidates in - ERR("Csymbol_low " ^ string_of_list id ", " sym_names) - | _ -> - if candidates = vaddrs - then OK(ffw) - else OK( - ffw - >>> ((ff_sf |-- ident_to_sym_ndx) ^%= (PosMap.add ident vaddrs)) - ) - end - | Csymbol_high (ident, i) -> - (* In this case, ec is 0x0000XXXX standing for XXXX0000 *) - let candidates = - try PosMap.find ident sfw.ident_to_sym_ndx - with Not_found -> [] - in - let vaddrs = - List.filter - (fun ndx -> - let ident_vaddr = efw.elf.e_symtab.(ndx).st_value in - Int32.(high_exts (add ident_vaddr (z_int32_lax i)) - = shift_left ec 16)) - candidates in - begin match vaddrs with - | [] -> - let sym_names = List.map (name_of_ndx efw) candidates in - ERR("Csymbol_high " ^ string_of_list id ", " sym_names) - | _ -> - if candidates = vaddrs - then OK(ffw) - else OK( - ffw - >>> ((ff_sf |-- ident_to_sym_ndx) ^%= (PosMap.add ident vaddrs)) - ) - end - | Csymbol_sda (ident, i) -> - (* sda should be handled separately in places it occurs *) - ERR("Incorrect reference to near-data symbol " - ^ Hashtbl.find ffw.sf.ident_to_name ident) - | Csymbol_rel_low (ident, i) | Csymbol_rel_high (ident, i) -> - (* should be handled separately in places it occurs *) - ERR("Incorrect reference to far-data symbol " - ^ Hashtbl.find ffw.sf.ident_to_name ident) - -let match_z_int32 (cz: Z.t) (ei: int32) = - let cz = z_int32 cz in - check_eq ( - Printf.sprintf "match_z_int32 %s %s" (string_of_int32 cz) (string_of_int32 ei) - ) cz ei - -let match_z_int (cz: Z.t) (ei: int) = - let cz = z_int32 cz in - let ei = Safe32.of_int ei in - check_eq ( - Printf.sprintf "match_z_int %s %s" (string_of_int32i cz) (string_of_int32i ei) - ) cz ei - -(* [m] is interpreted as a bitmask, and checked against [ei]. *) -let match_mask (m: Z.t) (ei: int32) = - let m = z_int32_lax m in - check_eq ( - Printf.sprintf "match_mask %s %s" - (string_of_int32 m) - (string_of_int32 ei) - ) m ei - -(** Checks that the special register referred to in [spr] is [r]. *) -let match_spr (str: string) (r: int) (spr: bitstring): checker = fun ffw -> - bitmatch spr with - | { v:5; 0:5 } when v = r -> OK(ffw) - | { _ } -> ERR(str) - -let match_xer = match_spr "match_xer" 1 -let match_lr = match_spr "match_lr" 8 -let match_ctr = match_spr "match_ctr" 9 - -(** Read a n-bits bitstring as a signed integer, two's complement representation - (n < 32). -*) -let exts (bs: bitstring): int32 = - let signif_bits = Bitstring.bitstring_length bs - 1 in - bitmatch bs with - | { sign : 1 ; - rest : signif_bits : int } -> - Int64.( - to_int32 ( - if sign - then logor rest (lognot (sub (shift_left one signif_bits) one)) - else rest - ) - ) - -(** Creates a bitmask from bits mb to me, according to the specification in - "4.2.1.4 Integer Rotate and Shift Instructions" of the PowerPC manual. -*) -let rec bitmask mb me = - assert (0 <= mb); assert (0 <= me); assert (mb < 32); assert (me < 32); - if (mb, me) = (0, 31) - then -1l (* this case does not compute correctly otherwise *) - else if mb <= me - (* 0 ... mb ... me ... 31 - 0 0 0 1 1 1 1 1 0 0 0 - *) - then Int32.(shift_left - (sub (shift_left 1l (me - mb + 1)) 1l) - (31 - me) - ) - (* - 0 ... me ... mb ... 31 - 1 1 1 1 0 0 0 1 1 1 1 - == - 1 1 1 1 1 1 1 1 1 1 1 -1l - - - 0 0 0 0 1 1 1 0 0 0 0 bitmask (me + 1) (mb - 1) - *) - else if mb = me + 1 - then (-1l) (* this needs special handling *) - else Int32.(sub (-1l) (bitmask (me + 1) (mb - 1))) - -(** Checks that a label did not occur twice in the same function. *) -let check_label_unicity ffw = - let rec check_label_unicity_aux l ffw = - match l with - | [] -> ffw - | h::t -> - ffw - >>> ( - if List.mem h t - then ( - ff_ef ^%= - (add_log (ERROR("Duplicate label: " ^ string_of_positive h))) - ) - else id - ) - >>> check_label_unicity_aux t - in - check_label_unicity_aux ffw.label_list ffw - -(** Checks that all the labels that have been referred to in instructions - actually appear in the code. *) -let check_label_existence ffw = - PosMap.fold - (fun k v -> - if List.mem k ffw.label_list - then id - else ( - ff_ef ^%= - (add_log (ERROR("Missing label: " ^ string_of_positive k))) - ) - ) - ffw.label_to_vaddr - ffw - -(** Matches the segment at virtual address [vaddr] with the jumptable expected - from label list [lbllist]. Then checks whether the matched chunk of the code - had the expected [size]. -*) -let rec match_jmptbl lbllist vaddr size ffw = - let rec match_jmptbl_aux lbllist bs ffw = - match lbllist with - | [] -> OK ffw - | lbl :: lbls -> ( - bitmatch bs with - | { vaddr : 32 : int; - rest : -1 : bitstring } -> - ffw - >>> lblmap_unify lbl vaddr - >>= match_jmptbl_aux lbls rest - | { _ } -> - ERR("Ill-formed jump table") - ) - in - let elf = ffw.sf.ef.elf in - begin match bitstring_at_vaddr elf vaddr size with - | None -> ERR("No section for the jumptable") - | Some(bs, pofs, psize) -> - ffw - >>> match_jmptbl_aux lbllist bs - >>^ (ff_ef ^%= - add_range pofs psize 0 Jumptable - ) - end - -let match_bo_bt_bool bo = - bitmatch bo with - | { false:1; true:1; true:1; false:1; false:1 } -> true - | { _ } -> false - -let match_bo_bf_bool bo = - bitmatch bo with - | { false:1; false:1; true:1; false:1; false:1 } -> true - | { _ } -> false - -let match_bo_bdnz_bool bo = - bitmatch bo with - | { true:1; false:1; false:1; false:1; false:1 } -> true - | { _ } -> false - -let match_bo_bt bo: checker = fun ffw -> - bitmatch bo with - | { false:1; true:1; true:1; false:1; false:1 } -> OK(ffw) - | { _ } -> ERR("match_bo_bt") - -let match_bo_bf bo: checker = fun ffw -> - if match_bo_bf_bool bo - then OK(ffw) - else ERR("match_bo_bf") - -let match_bo_ctr bo: checker = fun ffw -> - bitmatch bo with - | { true:1; false:1; true:1; false:1; false:1 } -> OK(ffw) - | { _ } -> ERR("match_bo_ctr") - -(** Checks whether it is feasible that the position at offset [ofs] from the - CompCert symbol [ident] is situated at a relative address [addr] from - the SDA register [r]. This means that the following equation must hold: - [r] + addr = @ident + ofs - This allows us to determine what address [r] has to contain. If it is the - first such guess or if it matches previous expectations, it's fine. - Otherwise, there is a conflict that is reported in sda_map. -*) -let check_sda ident ofs r addr ffw: f_framework or_err = - let ofs = z_int32 ofs in - let check_sda_aux ndx: (int * f_framework) or_err = - let elf = ffw.sf.ef.elf in - let sym = elf.e_symtab.(ndx) in - let expected_addr = Safe32.(sym.st_value + ofs - addr) in - try - let r_addr = from_inferrable (IntMap.find r ffw.sf.ef.sda_map) in - if r_addr = expected_addr - then OK(ndx, ffw) - else ERR( - Printf.sprintf - "SDA register %d is expected to point both at 0x%lx and 0x%lx" - r r_addr expected_addr - ) - with Not_found -> - OK(ndx, - ffw >>> (ff_ef |-- sda_map) ^%= IntMap.add r (Inferred(expected_addr)) - ) - in - (* We might not know yet what symbols is the one for that ident *) - let sym_list = PosMap.find ident ffw.sf.ident_to_sym_ndx in - (* So we test all the candidates *) - let res = List.map check_sda_aux sym_list in - (* For now, we hope at most one matches *) - match filter_ok res with - | [] -> ERR("No satisfying SDA mapping, errors were: " ^ - string_of_list id ", " (filter_err res)) - | [(ndx, ffw)] -> OK( - ffw - (* We instantiate the relationship for that ident to the matching symbol *) - >>> (ff_sf |-- ident_to_sym_ndx) ^%= PosMap.add ident [ndx] - ) - | _ -> fatal "Multiple possible SDA mappings, please report." - -(** Compares a whole CompCert function code against an ELF code, starting at - program counter [pc]. -*) -let rec compare_code ccode ecode pc: checker = fun fw -> - match ccode, ecode with - | [], [] -> OK(fw) - | [], e_rest -> - let rest_str = String.concat "\n" (List.map string_of_instr e_rest) in - ERR("CompCert code exhausted before the end of ELF code, remaining:\n" - ^ rest_str) - | c_rest, [] -> - let rest_str = String.concat "\n" (List.map string_of_instruction c_rest) in - ERR("ELF code exhausted before the end of CompCert code, remaining:\n" - ^ rest_str) - | c::cs, e::es -> - let recur_simpl = compare_code cs es (Int32.add 4l pc) in - let current_instr = - "[" ^ string_of_int32 pc ^ "] " ^ string_of_instruction c ^ " - " ^ string_of_instr e in - let error = ERR("Non-matching instructions: " ^ current_instr) in - let fw = - if !debug - then (ff_ef ^%= add_log (DEBUG(current_instr))) fw - else fw - in - match c with - | Padd(rd, r1, r2) -> - begin match ecode with - | ADDx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Paddc(rd, r1, r2) -> - begin match ecode with - | ADDCx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Padde(rd, r1, r2) -> - begin match ecode with - | ADDEx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Paddi(rd, r1, Csymbol_sda(ident, ofs)) -> - begin match ecode with - | ADDI(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= check_sda ident ofs rA (exts simm) - >>= recur_simpl - | _ -> error - end - | Paddi(rd, r1, cst) -> - begin match ecode with - | ADDI(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts simm) - >>= recur_simpl - | _ -> error - end - | Paddic(rd, r1, cst) -> - begin match ecode with - | ADDIC(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts simm) - >>= recur_simpl - | _ -> error - end - | Paddis(rd, r1, Csymbol_rel_high(id, ofs)) -> - begin match cs with - | Paddi(rd', r1', Csymbol_rel_low(id', ofs')) :: cs - when id' = id && ofs' = ofs -> - begin match ecode with - | ADDIS(rD, rA, simm) :: ADDI(rD', rA', simm') :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1' rA' - >>= match_iregs rd' rD' - >>= check_sda id ofs rA - Int32.(add (shift_left (of_int simm) 16) (exts simm')) - >>= compare_code cs es (Int32.add 8l pc) - | _ -> error - end - | _ -> error - end - | Paddis(rd, r1, cst) -> - begin match ecode with - | ADDIS(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (Safe32.of_int simm) - >>= recur_simpl - | _ -> error - end - | Paddze(rd, r1) -> - begin match ecode with - | ADDZEx(rD, rA, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pallocframe(sz, ofs) -> error - | Pandc(rd, r1, r2) -> - begin match ecode with - | ANDCx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pand_(rd, r1, r2) -> - begin match ecode with - | ANDx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools true rc - >>= recur_simpl - | _ -> error - end - | Pandis_(rd, r1, cst) -> - begin match ecode with - | ANDIS_(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - | Pandi_(rd, r1, cst) -> - begin match ecode with - | ANDI_(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - | Pannot(ef, args) -> - OK(fw) - >>= compare_code cs ecode pc - | Pb(lbl) -> - begin match ecode with - | Bx(li, aa, lk) :: es -> - let lblvaddr = Int32.(add pc (mul 4l (exts li))) in - OK(fw) - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa - >>= match_bools false lk - >>= recur_simpl - | _ -> error - end - | Pbctr sg -> - begin match ecode with - | BCCTRx(bo, bi, lk) :: es -> - OK(fw) - >>= match_bo_ctr bo - >>= match_ints 0 bi - >>= match_bools false lk - >>= recur_simpl - | _ -> error - end - | Pbctrl sg -> - begin match ecode with - | BCCTRx(bo, bi, lk) :: es -> - OK(fw) - >>= match_bo_ctr bo - >>= match_ints 0 bi - >>= match_bools true lk - >>= recur_simpl - | _ -> error - end - | Pbdnz(lbl) -> - begin match ecode with - | BCx (bo, bi, bd, aa, lk) :: es when match_bo_bdnz_bool bo -> - let lblvaddr = Int32.(add pc (mul 4l (exts bd))) in - OK(fw) - >>= match_ints 0 bi - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa - >>= match_bools false lk - >>= recur_simpl - | _ -> error - end - | Pbf(bit, lbl) -> - begin match ecode with - | BCx(bo, bi, bd, aa, lk) :: es when match_bo_bf_bool bo -> - let lblvaddr = Int32.(add pc (mul 4l (exts bd))) in - OK(fw) - (*>>= match_bo_bf bo already done in pattern match *) - >>= match_crbits bit bi - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa - >>= match_bools false lk - >>= recur_simpl - | BCx(bo0, bi0, bd0, aa0, lk0) :: - Bx (li1, aa1, lk1) :: es -> - let cnext = Int32.add pc 8l in - let enext = Int32.(add pc (mul 4l (exts bd0))) in - let lblvaddr = Int32.(add pc (mul 4l (exts bd0))) in - OK(fw) - >>= match_bo_bt bo0 - >>= match_crbits bit bi0 - >>= match_int32s cnext enext - >>= match_bools false aa0 - >>= match_bools false lk0 - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa1 - >>= match_bools false lk1 - >>= compare_code cs es (Int32.add 8l pc) - | _ -> error - end - | Pbl(ident, sg) -> - begin match ecode with - | Bx(li, aa, lk) :: es -> - let dest = Int32.(add pc (mul 4l (exts li))) in - OK(fw) - >>= (ff_sf ^%=? idmap_unify ident dest) - >>= match_bools false aa - >>= match_bools true lk - >>= recur_simpl - | _ -> error - end - | Pblr -> - begin match ecode with - | BCLRx(bo, bi, lk) :: es -> - OK(fw) - >>= match_bo_ctr bo - >>= match_ints 0 bi - >>= match_bools false lk - >>= recur_simpl - | _ -> error - end - | Pbs(ident, sg) -> - begin match ecode with - | Bx(li, aa, lk) :: es -> - let dest = Int32.(add pc (mul 4l (exts li))) in - OK(fw) - >>= match_bools false aa - >>= match_bools false lk - >>= (ff_sf ^%=? idmap_unify ident dest) - >>= recur_simpl - | _ -> error - end - | Pbt(bit, lbl) -> - begin match ecode with - | BCx(bo, bi, bd, aa, lk) :: es when match_bo_bt_bool bo -> - let lblvaddr = Int32.(add pc (mul 4l (exts bd))) in - OK(fw) - (*>>= match_bo_bt bo already done in pattern match *) - >>= match_crbits bit bi - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa - >>= match_bools false lk - >>= recur_simpl - | BCx(bo0, bi0, bd0, aa0, lk0) :: - Bx (li1, aa1, lk1) :: es -> - let cnext = Int32.add pc 8l in - let enext = Int32.(add pc (mul 4l (exts bd0))) in - let lblvaddr = Int32.(add pc (mul 4l (exts bd0))) in - OK(fw) - >>= match_bo_bf bo0 - >>= match_crbits bit bi0 - >>= match_int32s cnext enext - >>= match_bools false aa0 - >>= match_bools false lk0 - >>= lblmap_unify lbl lblvaddr - >>= match_bools false aa1 - >>= match_bools false lk1 - >>= compare_code cs es (Int32.add 8l pc) - | _ -> error - end - | Pbtbl(reg, table) -> - begin match ecode with - | RLWINMx(rS0, rA0, sh, mb, me, rc0) :: - ADDIS (rD1, rA1, simm1) :: - LWZ (rD2, rA2, d2) :: - MTSPR (rS3, spr3) :: - BCCTRx(bo4, bi4, rc4) :: es -> - let tblvaddr = Int32.( - add (shift_left (Safe32.of_int simm1) 16) (exts d2) - ) in - let tblsize = Safe32.of_int (4 * List.length table) in - OK(fw) - >>= match_iregs GPR12 rA0 - >>= match_iregs reg rS0 - >>= match_ints sh 2 - >>= match_ints mb 0 - >>= match_ints me 29 - >>= match_bools false rc0 - >>= match_iregs GPR12 rA1 - >>= match_iregs GPR12 rD1 - >>= match_iregs GPR12 rA2 - >>= match_iregs GPR12 rD2 - >>= match_iregs GPR12 rS3 - >>= match_ctr spr3 - >>= match_bo_ctr bo4 - >>= match_ints 0 bi4 - >>= match_bools false rc4 - >>= match_jmptbl table tblvaddr tblsize - >>= compare_code cs es (Int32.add 20l pc) - | _ -> error - end - | Pbuiltin(ef, args, res) -> - begin match ef with - | EF_inline_asm(_) -> fatal "Unsupported: inline asm statement." - | _ -> fatal "Unexpected Pbuiltin, please report." - end - | Pcfi_adjust _ | Pcfi_rel_offset _ -> - OK(fw) - >>= compare_code cs ecode pc - | Pcmplw(r1, r2) -> - begin match ecode with - | CMPL(crfD, l, rA, rB) :: es -> - OK(fw) - >>= match_crbits CRbit_0 crfD - >>= match_bools false l - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pcmplwi(r1, cst) -> - begin match ecode with - | CMPLI(crfD, l, rA, uimm) :: es -> - OK(fw) - >>= match_iregs r1 rA - >>= match_csts cst (Safe32.of_int uimm) - >>= match_crbits CRbit_0 crfD - >>= match_bools false l - >>= recur_simpl - | _ -> error - end - | Pcmpw(r1, r2) -> - begin match ecode with - | CMP(crfD, l, rA, rB) :: es -> - OK(fw) - >>= match_ints crfD 0 - >>= match_bools l false - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pcmpwi(r1, cst) -> - begin match ecode with - | CMPI(crfD, l, rA, simm) :: es -> - OK(fw) - >>= match_ints crfD 0 - >>= match_bools false l - >>= match_iregs r1 rA - >>= match_csts cst (exts simm) - >>= recur_simpl - | _ -> error - end - | Pcntlzw(r1, r2) -> - begin match ecode with - | CNTLZWx(rS, rA, rc) :: es -> - OK(fw) - >>= match_iregs r2 rS - >>= match_iregs r1 rA - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pcreqv(bd, b1, b2) -> - begin match ecode with - | CREQV(crbD, crbA, crbB) :: es -> - OK(fw) - >>= match_crbits bd crbD - >>= match_crbits b1 crbA - >>= match_crbits b2 crbB - >>= recur_simpl - | _ -> error - end - | Pcror(bd, b1, b2) -> - begin match ecode with - | CROR(crbD, crbA, crbB) :: es -> - OK(fw) - >>= match_crbits bd crbD - >>= match_crbits b1 crbA - >>= match_crbits b2 crbB - >>= recur_simpl - | _ -> error - end - | Pcrxor(bd, b1, b2) -> - begin match ecode with - | CRXOR(crbD, crbA, crbB) :: es -> - OK(fw) - >>= match_crbits bd crbD - >>= match_crbits b1 crbA - >>= match_crbits b2 crbB - >>= recur_simpl - | _ -> error - end - | Pdivw(rd, r1, r2) -> - begin match ecode with - | DIVWx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pdivwu(rd, r1, r2) -> - begin match ecode with - | DIVWUx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Peieio -> - begin match ecode with - | EIEIO :: es -> - OK(fw) - >>= recur_simpl - | _ -> error - end - | Peqv(rd, r1, r2) -> - begin match ecode with - | EQVx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pextsb(rd, r1) -> - begin match ecode with - | EXTSBx(rS, rA, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pextsh(rd, r1) -> - begin match ecode with - | EXTSHx(rS, rA, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfabs(rd, r1) | Pfabss(rd, r1) -> - begin match ecode with - | FABSx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfadd(rd, r1, r2) -> - begin match ecode with - | FADDx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfadds(rd, r1, r2) -> - begin match ecode with - | FADDSx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfcmpu(r1, r2) -> - begin match ecode with - | FCMPU(crfD, frA, frB) :: es -> - OK(fw) - >>= match_crbits CRbit_0 crfD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= recur_simpl - | _ -> error - end - | Pfcti(rd, r1) -> - error - | Pfctiw(rd, r1) -> - begin match ecode with - | FCTIWx(frD0, frB0, rc0) :: es -> - OK(fw) - >>= match_fregs rd frD0 - >>= match_fregs r1 frB0 - >>= match_bools false rc0 - >>= recur_simpl - | _ -> error - end - | Pfctiwz(rd, r1) -> - begin match ecode with - | FCTIWZx(frD0, frB0, rc0) :: es -> - OK(fw) - >>= match_fregs rd frD0 - >>= match_fregs r1 frB0 - >>= match_bools false rc0 - >>= recur_simpl - | _ -> error - end - | Pfdiv(rd, r1, r2) -> - begin match ecode with - | FDIVx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfdivs(rd, r1, r2) -> - begin match ecode with - | FDIVSx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfmake(rd, r1, r2) -> - error - | Pfmr(rd, r1) -> - begin match ecode with - | FMRx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfmul(rd, r1, r2) -> - begin match ecode with - | FMULx(frD, frA, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfmuls(rd, r1, r2) -> - begin match ecode with - | FMULSx(frD, frA, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfneg(rd, r1) | Pfnegs(rd, r1) -> - begin match ecode with - | FNEGx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfreeframe(sz, ofs) -> - error - | Pfrsp(rd, r1) -> - begin match ecode with - | FRSPx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfxdp(rd, r1) -> - error - | Pfsub(rd, r1, r2) -> - begin match ecode with - | FSUBx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfsubs(rd, r1, r2) -> - begin match ecode with - | FSUBSx(frD, frA, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r2 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfmadd(rd, r1, r2, r3) -> - begin match ecode with - | FMADDx(frD, frA, frB, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r3 frB - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfmsub(rd, r1, r2, r3) -> - begin match ecode with - | FMSUBx(frD, frA, frB, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r3 frB - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfnmadd(rd, r1, r2, r3) -> - begin match ecode with - | FNMADDx(frD, frA, frB, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r3 frB - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfnmsub(rd, r1, r2, r3) -> - begin match ecode with - | FNMSUBx(frD, frA, frB, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r3 frB - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfsqrt(rd, r1) -> - begin match ecode with - | FSQRTx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfrsqrte(rd, r1) -> - begin match ecode with - | FRSQRTEx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfres(rd, r1) -> - begin match ecode with - | FRESx(frD, frB, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pfsel(rd, r1, r2, r3) -> - begin match ecode with - | FSELx(frD, frA, frB, frC, rc) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_fregs r1 frA - >>= match_fregs r3 frB - >>= match_fregs r2 frC - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pisync -> - begin match ecode with - | ISYNC :: es -> - OK(fw) - >>= recur_simpl - | _ -> error - end - | Plabel(lbl) -> - OK(fw) - >>= lblmap_unify lbl pc - >>^ (fun fw -> {fw with label_list = lbl :: fw.label_list}) - >>= compare_code cs ecode pc - | Plbz(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LBZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plbz(rd, cst, r1) -> - begin match ecode with - | LBZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_csts cst (exts d) - >>= match_iregs r1 rA - >>= recur_simpl - | _ -> error - end - | Plbzx(rd, r1, r2) -> - begin match ecode with - | LBZX(rD, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plfd(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LFD(frD, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plfd(rd, cst, r1) | Plfd_a(rd, cst, r1) -> - begin match ecode with - | LFD(frD, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_csts cst (exts d) - >>= match_iregs r1 rA - >>= recur_simpl - | _ -> error - end - | Plfdx(rd, r1, r2) | Plfdx_a(rd, r1, r2) -> - begin match ecode with - | LFDX(frD, rA, rB) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plfi(r1, c) -> - begin match ecode with - | ADDIS(rD0, rA0, simm0) :: - LFD (frD1, rA1, d1) :: es -> - let vaddr = Int32.( - add (shift_left (Safe32.of_int simm0) 16) (exts d1) - ) in - if Int32.rem vaddr 8l <> 0l - then ERR("Float constants should be 8-byte aligned") - else - let elf = fw.sf.ef.elf in - let atom = Hashtbl.find fw.sf.atoms fw.this_ident in - let literal_section = - begin match atom.a_sections with - | [_; l; _] -> l - | _ -> Section_literal - end - in - let continue = compare_code cs es (Int32.add 8l pc) in - begin match bitstring_at_vaddr elf vaddr 8l with - | None -> - ERR("Floating point constant address is wrong") - | Some(bs, pofs, psize) -> - let f = - bitmatch bs with - | { f : 64 : int } -> f - in - OK(fw) - >>= (fun ffw -> - begin match section_at_vaddr elf vaddr with - | None -> ERR("No section at that virtual address") - | Some(sndx) -> - let section_name = elf.e_shdra.(sndx).sh_name in - OK( - ffw - >>> ( - ff_sf ^%= - match_sections_name literal_section section_name - ) - ) - end - ) - >>= match_iregs GPR12 rD0 - >>= match_iregs GPR0 rA0 - >>= match_fregs r1 frD1 - >>= match_floats c f - >>^ (ff_ef ^%= add_range pofs psize 8 (Float_literal(f))) - >>= match_iregs GPR12 rA1 - >>= continue - end - | _ -> error - end - | Plfis(r1, c) -> - begin match ecode with - | ADDIS(rD0, rA0, simm0) :: - LFS (frD1, rA1, d1) :: es -> - let vaddr = Int32.( - add (shift_left (Safe32.of_int simm0) 16) (exts d1) - ) in - if Int32.rem vaddr 4l <> 0l - then ERR("Float32 constants should be 4-byte aligned") - else - let elf = fw.sf.ef.elf in - let atom = Hashtbl.find fw.sf.atoms fw.this_ident in - let literal_section = - begin match atom.a_sections with - | [_; l; _] -> l - | _ -> Section_literal - end - in - let continue = compare_code cs es (Int32.add 8l pc) in - begin match bitstring_at_vaddr elf vaddr 4l with - | None -> - ERR("Floating point constant address is wrong") - | Some(bs, pofs, psize) -> - let f = - bitmatch bs with - | { f : 32 : int } -> f - in - OK(fw) - >>= (fun ffw -> - begin match section_at_vaddr elf vaddr with - | None -> ERR("No section at that virtual address") - | Some(sndx) -> - let section_name = elf.e_shdra.(sndx).sh_name in - OK( - ffw - >>> ( - ff_sf ^%= - match_sections_name literal_section section_name - ) - ) - end - ) - >>= match_iregs GPR12 rD0 - >>= match_iregs GPR0 rA0 - >>= match_fregs r1 frD1 - >>= match_floats32 c f - >>^ (ff_ef ^%= add_range pofs psize 4 (Float32_literal(f))) - >>= match_iregs GPR12 rA1 - >>= continue - end - | _ -> error - end - | Plfs(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LFS(frD, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plfs(rd, cst, r1) -> - begin match ecode with - | LFS(frD, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_csts cst (exts d) - >>= match_iregs r1 rA - >>= recur_simpl - | _ -> error - end - | Plfsx(rd, r1, r2) -> - begin match ecode with - | LFSX(frD, rA, rB) :: es -> - OK(fw) - >>= match_fregs rd frD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plha(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LHA(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plha(rd, cst, r1) -> - begin match ecode with - | LHA(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_csts cst (exts d) - >>= match_iregs r1 rA - >>= recur_simpl - | _ -> error - end - | Plhax(rd, r1, r2) -> - begin match ecode with - | LHAX(rD, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plhbrx(rd, r1, r2) -> - begin match ecode with - | LHBRX(rD, rA, rB):: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plhz(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LHZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plhz(rd, cst, r1) -> - begin match ecode with - | LHZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_csts cst (exts d) - >>= match_iregs r1 rA - >>= recur_simpl - | _ -> error - end - | Plhzx(rd, r1, r2) -> - begin match ecode with - | LHZX(rD, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plwarx(rd, r1, r2) -> - begin match ecode with - | LWARX(rD, rA, rB):: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plwbrx(rd, r1, r2) -> - begin match ecode with - | LWBRX(rD, rA, rB):: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Plwz(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | LWZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Plwz(rd, cst, r1) | Plwz_a(rd, cst, r1) -> - begin match ecode with - | LWZ(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Plwzu(rd, cst, r1) -> - begin match ecode with - | LWZU(rD, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Plwzx(rd, r1, r2) | Plwzx_a(rd, r1, r2) -> - begin match ecode with - | LWZX(rD, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pmfcr rd -> - begin match ecode with - | MFCR (rD0) :: es -> - OK(fw) - >>= match_iregs rd rD0 - >>= recur_simpl - | _ -> error - end - | Pmfcrbit(rd, bit) -> - error - | Pmflr(r) -> - begin match ecode with - | MFSPR(rD, spr) :: es -> - OK(fw) - >>= match_iregs r rD - >>= match_lr spr - >>= recur_simpl - | _ -> error - end - | Pmr(rd, r1) -> - begin match ecode with - | ORx(rS, rA, rB, rc) :: es when (rB = rS) -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pmtctr(r1) -> - begin match ecode with - | MTSPR(rS, spr) :: es -> - OK(fw) - >>= match_iregs r1 rS - >>= match_ctr spr - >>= recur_simpl - | _ -> error - end - | Pmtlr(r1) -> - begin match ecode with - | MTSPR(rS, spr) :: es -> - OK(fw) - >>= match_iregs r1 rS - >>= match_lr spr - >>= recur_simpl - | _ -> error - end - | Pmulli(rd, r1, cst) -> - begin match ecode with - | MULLI(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts simm) - >>= recur_simpl - | _ -> error - end - | Pmullw(rd, r1, r2) -> - begin match ecode with - | MULLWx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pmulhw(rd, r1, r2) -> - begin match ecode with - | MULHWx(rD, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pmulhwu(rd, r1, r2) -> - begin match ecode with - | MULHWUx(rD, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pnand(rd, r1, r2) -> - begin match ecode with - | NANDx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pnor(rd, r1, r2) -> - begin match ecode with - | NORx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Por(rd, r1, r2) -> - begin match ecode with - | ORx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Porc(rd, r1, r2) -> - begin match ecode with - | ORCx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pori(rd, r1, cst) -> - begin match ecode with - | ORI(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - | Poris(rd, r1, cst) -> - begin match ecode with - | ORIS(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - | Prlwimi(rd, r1, amount, mask) -> - begin match ecode with - | RLWIMIx(rS, rA, sh, mb, me, rc) :: es -> - OK(fw) - >>= match_iregs r1 rS - >>= match_iregs rd rA - >>= match_z_int amount sh - >>= match_mask mask (bitmask mb me) - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Prlwinm(rd, r1, amount, mask) -> - begin match ecode with - | RLWINMx(rS, rA, sh, mb, me, rc) :: es -> - OK(fw) - >>= match_iregs r1 rS - >>= match_iregs rd rA - >>= match_z_int amount sh - >>= match_mask mask (bitmask mb me) - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pslw(rd, r1, r2) -> - begin match ecode with - | SLWx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psraw(rd, r1, r2) -> - begin match ecode with - | SRAWx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psrawi(rd, r1, n) -> - begin match ecode with - | SRAWIx(rS, rA, sh, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_z_int n sh - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psrw(rd, r1, r2) -> - begin match ecode with - | SRWx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pstb(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | STB(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Pstb(rd, cst, r1) -> - begin match ecode with - | STB(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstbx(rd, r1, r2) -> - begin match ecode with - | STBX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstfd(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | STFD(frS, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Pstfd(rd, cst, r1) | Pstfd_a(rd, cst, r1) -> - begin match ecode with - | STFD(frS, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstfdu(rd, cst, r1) -> - begin match ecode with - | STFDU(frS, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstfdx(rd, r1, r2) | Pstfdx_a(rd, r1, r2) -> - begin match ecode with - | STFDX(frS, rA, rB) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstfs(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | STFS(frS, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Pstfs(rd, cst, r1) -> - begin match ecode with - | STFS(frS, rA, d) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstfsx(rd, r1, r2) -> - begin match ecode with - | STFSX(frS, rA, rB) :: es -> - OK(fw) - >>= match_fregs rd frS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Psth(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | STH(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Psth(rd, cst, r1) -> - begin match ecode with - | STH(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Psthx(rd, r1, r2) -> - begin match ecode with - | STHX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Psthbrx(rd, r1, r2) -> - begin match ecode with - | STHBRX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstw(rd, Csymbol_sda(ident, ofs), r1) -> - begin match ecode with - | STW(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= check_sda ident ofs rA (exts d) - >>= recur_simpl - | _ -> error - end - | Pstw(rd, cst, r1) | Pstw_a(rd, cst, r1) -> - begin match ecode with - | STW(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstwu(rd, cst, r1) -> - begin match ecode with - | STWU(rS, rA, d) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_csts cst (exts d) - >>= recur_simpl - | _ -> error - end - | Pstwx(rd, r1, r2) | Pstwx_a(rd, r1, r2) -> - begin match ecode with - | STWX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstwbrx(rd, r1, r2) -> - begin match ecode with - | STWBRX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstwcx_(rd, r1, r2) -> - begin match ecode with - | STWCX_(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Pstwux(rd, r1, r2) -> - begin match ecode with - | STWUX(rS, rA, rB) :: es -> - OK(fw) - >>= match_iregs rd rS - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= recur_simpl - | _ -> error - end - | Psubfc(rd, r1, r2) -> - begin match ecode with - | SUBFCx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psubfe(rd, r1, r2) -> - begin match ecode with - | SUBFEx(rD, rA, rB, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_iregs r2 rB - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psubfze(rd, r1) -> - begin match ecode with - | SUBFZEx(rD, rA, oe, rc) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_bools false oe - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Psubfic(rd, r1, cst) -> - begin match ecode with - | SUBFIC(rD, rA, simm) :: es -> - OK(fw) - >>= match_iregs rd rD - >>= match_iregs r1 rA - >>= match_csts cst (exts simm) - >>= recur_simpl - | _ -> error - end - | Psync -> - begin match ecode with - | SYNC :: es -> - OK(fw) - >>= recur_simpl - | _ -> error - end - | Ptrap -> - begin match ecode with - | TW(tO, rA, rB) :: es -> - OK(fw) - >>= (fun ffw -> - bitmatch tO with - | { 31 : 5 : int } -> OK(ffw) - | { _ } -> ERR("bitmatch") - ) - >>= match_iregs GPR0 rA - >>= match_iregs GPR0 rB - >>= recur_simpl - | _ -> error - end - | Pxor(rd, r1, r2) -> - begin match ecode with - | XORx(rS, rA, rB, rc) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_iregs r2 rB - >>= match_bools false rc - >>= recur_simpl - | _ -> error - end - | Pxori(rd, r1, cst) -> - begin match ecode with - | XORI(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - | Pxoris(rd, r1, cst) -> - begin match ecode with - | XORIS(rS, rA, uimm) :: es -> - OK(fw) - >>= match_iregs rd rA - >>= match_iregs r1 rS - >>= match_csts cst (Safe32.of_int uimm) - >>= recur_simpl - | _ -> error - end - -(** A work element is a triple giving a CompCert ident for the function to - analyze, its name as a string, and the actual code. It is not obvious how - to recover one of the three components given the other two. -*) -type worklist = (ident * string * ccode) list - -(** Pops a work element from the worklist, ensuring that fully-determined idents - (i.e. those for which the possible virtual address have been narrowed to one - candidate) are picked first. - When the first element is not fully-determined, the whole list is sorted so - that hopefully several fully-determined idents are brought at the beginning - at the same time. -*) -let worklist_pop fw wl = - match wl with - | [] -> None - | h::t -> - let (i, _, _) = h in - let candidates = - try PosMap.find i fw.ident_to_sym_ndx - with Not_found -> [] - in - match candidates with - | [] | [_] -> Some (h, t, candidates) - | _ -> - let wl = List.fast_sort - (fun (i1, _, _) (i2, _, _) -> - compare - (List.length (PosMap.find i1 fw.ident_to_sym_ndx)) - (List.length (PosMap.find i2 fw.ident_to_sym_ndx))) - wl in - let winner = List.hd wl in - let (i, _, _) = winner in - Some (winner, List.tl wl, PosMap.find i fw.ident_to_sym_ndx) - -(** Processes a worklist, threading in the framework. -*) -let rec worklist_process (wl: worklist) sfw: s_framework = - match worklist_pop sfw wl with - | None -> sfw (*done*) - | Some ((ident, name, ccode), wl, candidates) -> - let process_ndx ndx = ( - let elf = (sfw |. sf_ef).elf in - let pc = elf.e_symtab.(ndx).st_value in - match code_of_sym_ndx elf ndx with - | None -> ERR("Could not find symbol data for function symbol " ^ name) - | Some ecode -> - sfw - >>> sf_ef ^%= - add_log (DEBUG("Processing function: " ^ name)) - >>> (fun sfw -> - { - sf = sfw; - this_sym_ndx = ndx; - this_ident = ident; - label_to_vaddr = PosMap.empty; - label_list = []; - } - ) - >>> compare_code ccode.fn_code ecode pc - >>^ mark_covered_fun_sym_ndx ndx - ) in - begin match candidates with - | [] -> - sfw - >>> sf_ef ^%= - add_log (ERROR("Skipping missing symbol " ^ name)) - >>> worklist_process wl - | [ndx] -> - begin match process_ndx ndx with - | OK(ffw) -> - ffw - >>> check_label_existence - >>> check_label_unicity - >>> (fun ffw -> - worklist_process wl ffw.sf - ) - | ERR(s) -> - sfw - >>> sf_ef ^%= - add_log (ERROR( - Printf.sprintf - "Unique candidate for %s did not match: %s" - name - s - )) - >>> worklist_process wl - end - | ndxes -> - (* Multiple candidates for one symbol *) - let fws = filter_ok (List.map process_ndx ndxes) in - begin match fws with - | [] -> - sfw - >>> sf_ef ^%= - add_log (ERROR("No matching candidate for: " ^ name)) - >>> worklist_process wl - | [ffw] -> - worklist_process wl ffw.sf - | fws -> - sfw - >>> sf_ef ^%= - add_log (ERROR( - "Multiple matching candidates for: " ^ name - )) - >>> worklist_process wl - end - end - -(** Compares a data symbol with its expected contents. Returns the updated - framework as well as the size of the data matched. -**) -let compare_data (l: init_data list) (bs: bitstring) (sfw: s_framework) - : (s_framework * int) or_err = - let error = ERR("Reached end of data bitstring too soon") in - let rec compare_data_aux l bs s (sfw: s_framework): - (s_framework * int) or_err = - match l with - | [] -> OK(sfw, s) - | d::l -> - let sfw = - if !debug - then ( - (sf_ef ^%= add_log (DEBUG(" " ^ string_of_init_data d))) sfw - ) - else sfw - in - begin match d with - | Init_int8(i) -> ( - bitmatch bs with - | { j : 8 : int; bs : -1 : bitstring } -> - if (z_int_lax i) land 0xFF = j - then compare_data_aux l bs (s + 1) sfw - else ERR("Wrong int8") - | { _ } -> error - ) - | Init_int16(i) -> ( - bitmatch bs with - | { j : 16 : int; bs : -1 : bitstring } -> - if (z_int_lax i) land 0xFFFF = j - then compare_data_aux l bs (s + 2) sfw - else ERR("Wrong int16") - | { _ } -> error - ) - | Init_int32(i) -> ( - bitmatch bs with - | { j : 32 : int; bs : -1 : bitstring } -> - if z_int32_lax i = j - then compare_data_aux l bs (s + 4) sfw - else ERR("Wrong int32") - | { _ } -> error - ) - | Init_float32(f) -> ( - bitmatch bs with - | { j : 32 : int; bs : -1 : bitstring } -> - if camlint_of_coqint (Floats.Float32.to_bits f) = j - then compare_data_aux l bs (s + 4) sfw - else ERR("Wrong float32") - | { _ } -> error - ) - | Init_float64(f) -> ( - bitmatch bs with - | { j : 64 : int; bs : -1 : bitstring } -> - if camlint64_of_coqint (Floats.Float.to_bits f) = j - then compare_data_aux l bs (s + 8) sfw - else ERR("Wrong float64") - | { _ } -> error - ) - | Init_int64(i) -> ( - bitmatch bs with - | { j : 64 : int; bs : -1 : bitstring } -> - if z_int64 i = j - then compare_data_aux l bs (s + 8) sfw - else ERR("Wrong int64") - | { _ } -> error - ) - | Init_space(z) -> ( - let space_size = z_int z in - bitmatch bs with - | { space : space_size * 8 : bitstring; bs : -1 : bitstring } -> - if is_zeros space (space_size * 8) - then compare_data_aux l bs (s + space_size) sfw - else ERR("Wrong space " ^ - string_of_int (z_int z) ^ " " ^ - string_of_bitstring space) - | { _ } -> error - ) - | Init_addrof(ident, ofs) -> ( - bitmatch bs with - | { vaddr : 32 : int; bs : -1 : bitstring } -> - sfw - >>> idmap_unify ident (Int32.sub vaddr (z_int32 ofs)) - >>= compare_data_aux l bs (s + 4) - | { _ } -> error - ) - end - in - compare_data_aux l bs 0 sfw - -(** Checks the data symbol table. -*) -let check_data_symtab ident sym_ndx size sfw = - let elf = sfw.ef.elf in - let symtab_ent_start = Int32.( - add - elf.e_shdra.(elf.e_symtab_sndx).sh_offset - (Safe32.of_int (16 * sym_ndx)) - ) in - let sym = sfw.ef.elf.e_symtab.(sym_ndx) in - let atom = Hashtbl.find sfw.atoms ident in - let section = - match atom.a_sections with - | [s] -> s - | _ -> Section_data true - in - sfw - >>> ( - if sym.st_size = Safe32.of_int size - then id - else ( - sf_ef ^%= - add_log (ERROR( - "Incorrect symbol size (" ^ sym.st_name ^ - "): expected " ^ string_of_int32i sym.st_size ^ - ", counted: " ^ string_of_int size - )) - ) - ) - >>> check_st_bind atom sym - >>> ( - match sym.st_type with - | STT_OBJECT -> id - | STT_NOTYPE -> (sf_ef ^%= - add_log (WARNING("Missing type for symbol " ^ sym.st_name)) - ) - | _ -> (sf_ef ^%= - add_log (ERROR("Symbol should have type STT_OBJECT")) - ) - ) - >>> ( - if sym.st_other = 0 - then id - else (sf_ef ^%= - add_log (ERROR("Symbol should have st_other set to 0")) - ) - ) - >>> match_sections_name section elf.e_shdra.(sym.st_shndx).sh_name - >>> (sf_ef ^%= - add_range symtab_ent_start 16l 4 (Symtab_data(sym)) - ) - -(** Checks all the program variables. -*) -let check_data (pv: (ident * unit globvar) list) (sfw: s_framework) - : s_framework = - let process_ndx ident ldata sfw ndx = - let elf = sfw.ef.elf in - let sym = elf.e_symtab.(ndx) in - let sym_vaddr = sym.st_value in - begin match bitstring_at_vaddr_nosize elf sym_vaddr with - | None -> ERR("Could not find symbol data for data symbol " ^ sym.st_name) - | Some(sym_bs, pofs, psize) -> - let res = - sfw - >>> (sf_ef ^%= add_log (DEBUG("Processing data: " ^ sym.st_name))) - >>> compare_data ldata sym_bs - in - begin match res with - | ERR(s) -> ERR(s) - | OK(sfw, size) -> - let align = - begin match (Hashtbl.find sfw.atoms ident).a_alignment with - | None -> 0 - | Some(a) -> a - end - in - sfw.ef.chkd_data_syms.(ndx) <- true; - OK(sfw) - >>= (fun sfw -> - if size = 0 - then OK(sfw) (* These occupy no space, for now we just forget them *) - else OK( - sfw - >>> sf_ef ^%= - add_range pofs (Safe32.of_int size) align (Data_symbol(sym)) - ) - ) - >>= (fun sfw -> - if not (is_well_aligned sym_vaddr align) - then ERR("Symbol not correctly aligned in the ELF file") - else OK(sfw) - ) - >>^ check_data_symtab ident ndx size - end - end - in - let check_data_aux sfw ig = - let (ident, gv) = ig in - let init_data = gv.gvar_init in - let ident_ndxes = PosMap.find ident sfw.ident_to_sym_ndx in - (*print_endline ("Candidates: " ^ string_of_list id ", " - (List.map - (fun ndx -> fw.elf.e_symtab.(ndx).st_name) - ident_ndxes));*) - let results = List.map (process_ndx ident init_data sfw) ident_ndxes in - let successes = filter_ok results in - match successes with - | [] -> - sfw - >>> sf_ef ^%= - add_log (ERROR( - "No matching data segment among candidates [" ^ - (string_of_list - (fun ndx -> sfw.ef.elf.e_symtab.(ndx).st_name) - ", " - ident_ndxes - ) ^ - "], Errors: [" ^ - string_of_list - (function OK(_) -> "" | ERR(s) -> s) - ", " - (List.filter (function ERR(_) -> true | _ -> false) results) - ^ "]" - )) - | [sfw] -> sfw - | fws -> - sfw - >>> sf_ef ^%= add_log (ERROR("Multiple matching data segments!")) - in - List.fold_left check_data_aux sfw - (* Empty lists mean the symbol is external, no need for check *) - (List.filter (fun (_, gv) -> gv.gvar_init <> []) pv) - -(** Read a .sdump file *) - -let sdump_magic_number = "CompCertSDUMP" ^ Version.version - -let read_sdump file = - let ic = open_in_bin file in - try - let magic = String.create (String.length sdump_magic_number) in - really_input ic magic 0 (String.length sdump_magic_number); - if magic <> sdump_magic_number then fatal "Bad magic number"; - let prog = (input_value ic: Asm.program) in - let names = (input_value ic: (ident, string) Hashtbl.t) in - let atoms = (input_value ic: (ident, C2C.atom_info) Hashtbl.t) in - close_in ic; - (prog, names, atoms) - with - | End_of_file -> - close_in ic; Printf.eprintf "Truncated file %s\n" file; exit 2 - | Failure msg -> - close_in ic; Printf.eprintf "Corrupted file %s: %s\n" file msg; exit 2 - -(** Split program definitions into functions and variables *) - -let split_prog_defs p = - let rec split fns vars = function - | [] -> (List.rev fns, List.rev vars) - | (id, Gfun fd) :: defs -> split ((id, fd) :: fns) vars defs - | (id, Gvar vd) :: defs -> split fns ((id, vd) :: vars) defs - in split [] [] p.prog_defs - -(** Processes a .sdump file. -*) -let process_sdump efw sdump: e_framework = - print_debug ("Beginning reading " ^ sdump); - let (prog, names, atoms) = read_sdump sdump in - let (prog_funct, prog_vars) = split_prog_defs prog in - print_debug ("Constructing mapping from idents to symbol indices"); - let ident_to_sym_ndx = - Hashtbl.fold - (fun ident name m -> - match ndxes_of_sym_name efw.elf name with - | [] -> m (* skip if missing *) - | ndxes -> PosMap.add ident ndxes m - ) - names - PosMap.empty - in - print_debug("Constructing worklist"); - let worklist_fundefs = - List.filter - (fun f -> - match snd f with - | Internal _ -> true - | External _ -> false - ) - prog_funct - in - let wl = - List.map - (fun f -> - match f with - | ident, Internal ccode -> (ident, Hashtbl.find names ident, ccode) - | _, External _ -> fatal "IMPOSSIBRU!" - ) - worklist_fundefs - in - print_debug("Beginning processing of the worklist"); - efw - >>> (fun efw -> - { ef = efw - ; program = prog - ; ident_to_name = names - ; ident_to_sym_ndx = ident_to_sym_ndx - ; atoms = atoms - } - ) - >>> worklist_process wl - >>> (fun sfw -> - print_debug "Checking data"; - sfw - ) - >>> check_data prog_vars - >>> (fun sfw -> sfw.ef) - -(** Returns true if [a, b] intersects [ofs, ofs + size - 1]. *) -let intersect (a, b) ofs size: bool = - let within (a, b) x = (a <= x) && (x <= b) in - (within (a, b) ofs) || (within (ofs, Int32.(sub (add ofs size) 1l)) a) - -let string_of_range a b = "[0x" ^ Printf.sprintf "%08lx" a ^ " - 0x" ^ - Printf.sprintf "%08lx" b ^ "]" - -(** Checks that the bits from [start] to [stop] in [bs] are zeroed. *) -let is_padding bs start stop = - let bs_start = start * 8 in - let bs_length = (stop - start + 1) * 8 in - start <= stop && - is_zeros (Bitstring.subbitstring bs bs_start bs_length) bs_length - -(** This functions goes through the list of checked bytes, and tries to find - padding in it. That is, it takes pairs of chunks in order, and adds a - padding chunk in between if these conditions are met: - - - the second chunk needs to be aligned. - - - the difference between the two chunks is strictly less than the alignment. - - - the data in this space is zeroed. - - Otherwise, it fills holes with an Unknown chunk. - Returns a framework where [chkd_bytes_list] is sorted and full. -*) -let check_padding efw = - print_debug "Checking padding"; - let elf = efw.elf in - let sndxes = list_n elf.e_hdr.e_shnum in - let matching_sections x y = - string_of_list - id - ", " - (List.map - (fun ndx -> elf.e_shdra.(ndx).sh_name) - (List.filter - (fun ndx -> - let shdr = elf.e_shdra.(ndx) in - intersect (x, y) shdr.sh_offset shdr.sh_size - ) - sndxes - ) - ) - in - let matching_symbols x y = - string_of_list - id - ", " - (List.map - (fun sym -> sym.st_name) - (List.filter - (fun sym -> - if sym.st_shndx >= Array.length elf.e_shdra - then false (* special section *) - else - match physical_offset_of_vaddr elf sym.st_value with - | None -> false - | Some(ofs) -> intersect (x, y) ofs sym.st_size - ) - (Array.to_list elf.e_symtab) - ) - ) - in - let unknown x y = Unknown( - "\nSections: " ^ matching_sections x y ^ "\nSymbols: " ^ matching_symbols x y - ) - in - (* check_padding_aux assumes a sorted list *) - let rec check_padding_aux efw accu l = - match l with - | [] -> efw - (* if there is only one chunk left, we add an unknown space between it and - the end. *) - | [(_, e, _, _) as h] -> - let elf_size = - Safe32.of_int ((Bitstring.bitstring_length efw.elf.e_bitstring) / 8) in - let elf_end = Int32.sub elf_size 1l in - if e = elf_end - then { efw with - chkd_bytes_list = List.rev (h :: accu); - } - else ( - let start = Int32.add e 1l in - { efw with - chkd_bytes_list = List.rev - ((start, elf_end, 0, unknown start elf_end) :: h :: accu); - } - ) - | ((b1, e1, a1, n1) as h1) :: ((b2, e2, a2, n2) as h2) :: rest -> - let pad_start = Int32.add e1 1l in - let pad_stop = Int32.sub b2 1l in - if pad_start = b2 (* if they are directly consecutive *) - || Safe.(of_int32 b2 - of_int32 e1) > a2 (* or if they are too far away *) - || not (is_padding efw.elf.e_bitstring - (Safe32.to_int pad_start) (Safe32.to_int pad_stop)) - then (* not padding *) - if pad_start <= pad_stop - then - check_padding_aux efw - ((pad_start, pad_stop, 0, unknown pad_start pad_stop) :: h1 :: accu) - (h2 :: rest) - else - check_padding_aux efw (h1 :: accu) (h2 :: rest) - else ( (* this is padding! *) - check_padding_aux efw - ((pad_start, pad_stop, 0, Padding) :: h1 :: accu) - (h2 :: rest) - ) - in - let sorted_chkd_bytes_list = - List.fast_sort - (fun (a, _, _, _) (b, _, _, _) -> Int32.compare a b) - efw.chkd_bytes_list - in check_padding_aux efw [] sorted_chkd_bytes_list - -(** Checks a boolean. *) -let ef_checkb b msg = - if b then id else add_log(ERROR(msg)) - -let check_elf_identification efw = - let ei = efw.elf.e_hdr.e_ident in - efw - >>> ef_checkb (ei.ei_class = ELFCLASS32) "ELF class should be ELFCLASS32" - >>> ef_checkb (ei.ei_data = ELFDATA2MSB || ei.ei_data = ELFDATA2LSB) - "ELF should be MSB or LSB" - >>> ef_checkb (ei.ei_version = EV_CURRENT) - "ELF identification version should be EV_CURRENT" - -let check_elf_header efw: e_framework = - let eh = efw.elf.e_hdr in - efw - >>> check_elf_identification - >>> ef_checkb (eh.e_type = ET_EXEC) "ELF type should be ET_EXEC" - >>> ef_checkb (eh.e_machine = EM_PPC) "ELF machine should be PPC" - >>> ef_checkb (eh.e_version = EV_CURRENT) "ELF version should be EV_CURRENT" - >>> add_range 0l 52l 0 ELF_header (* Header is always 52-bytes long *) - -(** Checks the index 0 of the symbol table. This index is reserved to hold - special values. *) -let check_sym_tab_zero efw = - let elf = efw.elf in - let sym0 = efw.elf.e_symtab.(0) in - (* First, let's mark it checked as a data symbol, to avoid warnings *) - efw.chkd_data_syms.(0) <- true; - efw - >>> ( - if sym0.st_name = "" - then id - else add_log (ERROR("Symbol 0 should not have a name")) - ) - >>> ( - if sym0.st_value = 0l - then id - else add_log (ERROR("Symbol 0 should have st_value = 0")) - ) - >>> ( - if sym0.st_size = 0l - then id - else add_log (ERROR("Symbol 0 should have st_size = 0")) - ) - >>> ( - if sym0.st_bind = STB_LOCAL - then id - else add_log (ERROR("Symbol 0 should have STB_LOCAL binding")) - ) - >>> ( - if sym0.st_type = STT_NOTYPE - then id - else add_log (ERROR("Symbol 0 should have STT_NOTYPE type")) - ) - >>> ( - if sym0.st_other = 0 - then id - else add_log (ERROR("Symbol 0 should have st_other = 0")) - ) - >>> ( - if sym0.st_shndx = shn_UNDEF - then id - else add_log (ERROR("Symbol 0 should have st_shndx = SHN_UNDEF")) - ) - >>> add_range elf.e_shdra.(elf.e_symtab_sndx).sh_offset 16l 4 Zero_symbol - -(** If CompCert sections have been mapped to an ELF section whose name is - not the same, we warn the user. -*) -let warn_sections_remapping efw = - print_debug "Checking remapped sections"; - StringMap.fold - (fun c_name (e_name, conflicts) efw -> - if c_name = "COMM" then efw else - if StringSet.is_empty conflicts - then - match e_name with - | Provided(e_name) -> - efw - | Inferred(e_name) -> - if c_name = e_name - then efw - else - begin - efw - >>> add_log (WARNING( - Printf.sprintf - "Detected linker script remapping: section %S -> %S" - c_name e_name - )) - end - else (* conflicts not empty *) - match e_name with - | Provided(e_name) -> - efw - >>> add_log (ERROR( - Printf.sprintf " - Conflicting remappings for section %s: - Specified: %s - Expected: %s" - c_name e_name (string_of_list id ", " (StringSet.elements conflicts)) - )) - | Inferred(e_name) -> - efw - >>> add_log (ERROR( - Printf.sprintf " - Conflicting remappings for section %s: - %s" - c_name (string_of_list id ", " (e_name :: (StringSet.elements conflicts))) - )) - ) - efw.section_map - efw - -let warn_sda_mapping efw = - print_debug "Checking SDA mappings"; - if IntMap.is_empty efw.sda_map - then efw - else ( - IntMap.fold - (fun r vaddr efw -> - match vaddr with - | Provided(_) -> efw - | Inferred(vaddr) -> - efw >>> add_log (WARNING( - Printf.sprintf - "This SDA register mapping was inferred: register r%u = 0x%lX" - r vaddr - )) - ) - efw.sda_map - efw - ) - -let (>>=) li f = List.flatten (List.map f li) - -(** Returns the list of all strictly-ordered pairs of [[0; len - 1]] that don't - satisfy f. *) -let forall_sym (len: int) (f: 'a -> 'a -> bool): ('a * 'a) list = - (list_n len) >>= fun x -> - (list_ab (x + 1) (len - 1)) >>= fun y -> - (if f x y then [] else [(x, y)]) - -let check_overlaps efw = - let shdra = efw.elf.e_shdra in - let intersect a asize b bsize = - asize <> 0l && bsize <> 0l && - ( - let last x xsize = Int32.(sub (add x xsize) 1l) in - let alast = last a asize in - let blast = last b bsize in - let within (a, b) x = (a <= x) && (x <= b) in - (within (a, alast) b) || (within (b, blast) a) - ) - in - match - forall_sym (Array.length shdra) - (fun i j -> - let ai = shdra.(i) in - let aj = shdra.(j) in - (ai.sh_type = SHT_NOBITS) - || (aj.sh_type = SHT_NOBITS) - || (not (intersect ai.sh_offset ai.sh_size aj.sh_offset aj.sh_size)) - ) - with - | [] -> efw - | l -> - List.fold_left - (fun efw (i, j) -> - let msg = - Printf.sprintf "Sections %s and %s overlap" shdra.(i).sh_name shdra.(j).sh_name - in - add_log (ERROR(msg)) efw - ) - efw l - -let check_unknown_chunks efw = - if - List.exists - (function (_, _, _, Unknown(_)) -> true | _ -> false) - efw.chkd_bytes_list - then add_log (WARNING( - "Some parts of the ELF file are unknown." ^ - (if !print_elfmap then "" else " Use -print-elfmap to see what was covered.") - )) efw - else efw - -let check_missed_symbols efw = - if not !exhaustivity - then efw - else - let chkd_syms_a = - Array.init - (Array.length efw.elf.e_symtab) - ( - fun ndx -> - match efw.elf.e_symtab.(ndx).st_type with - (* we only care about function and data symbols *) - | STT_SECTION | STT_FILE -> true - | STT_OBJECT | STT_FUNC | STT_NOTYPE | STT_UNKNOWN -> - (* checked as either a function or a data symbol *) - efw.chkd_fun_syms.(ndx) - || efw.chkd_data_syms.(ndx) - (* or part of the symbols we know are mising *) - || StringSet.mem efw.elf.e_symtab.(ndx).st_name efw.missing_syms - ) - in - let missed_syms_l = list_false_indices chkd_syms_a in - match missed_syms_l with - | [] -> efw - | _ -> - let symtab = efw.elf.e_symtab in - let symlist_names = string_of_list (fun ndx -> symtab.(ndx).st_name) " " in - let missed_funs = - List.filter (fun ndx -> symtab.(ndx).st_type = STT_FUNC) missed_syms_l in - let missed_data = - List.filter (fun ndx -> symtab.(ndx).st_type = STT_OBJECT) missed_syms_l in - let missed_unknown = - List.filter (fun ndx -> - match symtab.(ndx).st_type with - | STT_NOTYPE | STT_UNKNOWN -> true - | _ -> false - ) missed_syms_l in - if !list_missing - then - efw - >>> add_log (WARNING( - Printf.sprintf - " - The following function symbol(s) do not appear in .sdump files: - %s - The following data symbols do not appear in .sdump files: - %s - The following unknown type symbols do not appear in .sdump files: - %s" - (symlist_names missed_funs) - (symlist_names missed_data) - (symlist_names missed_unknown) - )) - else - efw - >>> add_log (WARNING( - Printf.sprintf - "%u function symbol(s), %u data symbol(s) and %u unknown type symbol(s) do not appear in .sdump files. Add -list-missing to list them." - (List.length missed_funs) - (List.length missed_data) - (List.length missed_unknown) - )) - -let print_diagnosis efw = - let (nb_err, nb_warn) = List.fold_left - (fun (e, w) -> function - | DEBUG(_) -> (e, w) - | ERROR(_) -> (e + 1, w) - | INFO(_) -> (e, w) - | WARNING(_) -> (e, w + 1) - ) - (0, 0) - efw.log - in - if !debug - then Printf.printf "\n\nFINAL LOG:\n\n"; - List.(iter - (fun e -> - match string_of_log_entry false e with - | "" -> () - | s -> print_endline s - ) - (rev efw.log) - ); - let plural n = if n > 1 then "s" else "" in - Printf.printf " SUMMARY: %d error%s, %d warning%s\n" - nb_err (plural nb_err) nb_warn (plural nb_warn); - efw - -let conf_file = ref (None: string option) - -let parse_conf filename = - let section_map = ref StringMap.empty in - let sda_map = ref IntMap.empty in - let missing_syms = ref StringSet.empty in - let ic = open_in filename in - try - while true - do - let line = input_line ic in - (* Test different patterns one by one, until one of them works *) - let rec match_line = function - | [] -> failwith (Printf.sprintf "Couldn't read configuration line: %s" line) - | try_match::rest -> - try try_match () - with Scanf.Scan_failure(_) -> match_line rest - in - (* an empty line is ignored *) - if line <> "" - then - match_line - (* a comment *) - [ (fun () -> - Scanf.sscanf line - "#%s" - (fun _ -> ()) - ) - (* a section remapping *) - ; (fun () -> - Scanf.sscanf line - "section %S -> %S" - (fun sfrom sto -> - if StringMap.mem sfrom !section_map - then failwith ( - Printf.sprintf - "Your configuration file contains multiple mappings for section %s" - sfrom - ) - else - section_map := - StringMap.add sfrom (Provided(sto), StringSet.empty) !section_map - ) - ) - (* a SDA mapping *) - ; (fun () -> - Scanf.sscanf line - "register r%u = %li" - (fun r addr -> - if IntMap.mem r !sda_map - then failwith ( - Printf.sprintf - "Your configuration file contains multiple SDA mappings for register %u" - r - ) - else - sda_map := IntMap.add r (Provided(addr)) !sda_map) - ) - (* a list of symbols supposed to be missing from the .sdump files *) - ; (fun () -> - Scanf.sscanf line - "external %s@\n" - (fun sym_list_s -> - let sym_list = Str.split (Str.regexp "[ \t]+") sym_list_s in - List.iter - (fun sym -> missing_syms := StringSet.add sym !missing_syms) - sym_list - ) - ) - ] - done; raise End_of_file (* unreachable, just to please the typer *) - with - | End_of_file -> (!section_map, !sda_map, !missing_syms) - -(** Checks a whole ELF file according to a list of .sdump files. This never - dumps anything, so it can be safely used when fuzz-testing even if the - user accidentally enabled dumping options. *) -let check_elf_nodump elf sdumps = - let eh = elf.e_hdr in - let nb_syms = Array.length elf.e_symtab in - let section_strtab = elf.e_shdra.(eh.e_shstrndx) in - let symtab_shdr = elf.e_shdra.(elf.e_symtab_sndx) in - let symbol_strtab = elf.e_shdra.(Safe32.to_int symtab_shdr.sh_link) in - let (section_map, sda_map, missing_syms) = - match !conf_file with - | None -> (StringMap.empty, IntMap.empty, StringSet.empty) - | Some(filename) -> parse_conf filename - in - let efw = - { elf = elf - ; log = [] - ; chkd_bytes_list = [] - ; chkd_fun_syms = Array.make nb_syms false - ; chkd_data_syms = Array.make nb_syms false - ; section_map = section_map - ; sda_map = sda_map - ; missing_syms = missing_syms - } - >>> check_elf_header - >>> add_range - eh.e_phoff - Safe.(to_int32 (eh.e_phnum * eh.e_phentsize)) - 4 - ELF_progtab - >>> add_range - eh.e_shoff - Safe.(to_int32 (eh.e_shnum * eh.e_shentsize)) - 4 - ELF_shtab - >>> add_range - section_strtab.sh_offset - section_strtab.sh_size - 0 - ELF_section_strtab - >>> add_range - symbol_strtab.sh_offset - symbol_strtab.sh_size - 0 - ELF_symbol_strtab - >>> check_sym_tab_zero - in - print_debug "Done checking header, beginning processing of .sdumps"; - (* Thread the framework through the processing of all .sdump files *) - List.fold_left process_sdump efw sdumps - (* check the padding in between identified byte chunks *) - >>> check_padding - (* warn if some CompCert sections have been remapped by the linker script *) - >>> warn_sections_remapping - (* warn if there exists non-empty overlapping sections *) - >>> check_overlaps - (* warn about inferred SDA registers *) - >>> warn_sda_mapping - (* warn about regions of the ELF file that could not be identified *) - >>> check_unknown_chunks - >>> check_missed_symbols - >>> print_diagnosis - -(** Checks a whole ELF file according to .sdump files. - If requested, dump the calculated bytes mapping, so that it can be - reused by the fuzzer. *) -let check_elf_dump elffilename sdumps = - print_debug "Beginning ELF parsing"; - let elf = read_elf elffilename in - print_debug "Beginning ELF checking"; - let efw = check_elf_nodump elf sdumps in - (* print the elfmap if requested *) - if !print_elfmap - then - begin - Printf.printf "\n\n%s\n\n\n" - (string_of_list - (fun (a, b, align, r) -> string_of_range a b ^ " (" ^ - string_of_int align ^ ") " ^ string_of_byte_chunk_desc r) - "\n" - efw.chkd_bytes_list - ) - end; - (* dump the elfmap if requested *) - if !dump_elfmap - then - begin - let oc = open_out (elffilename ^ ".elfmap") in - output_value oc efw.chkd_bytes_list; - close_out oc - end -- cgit