1 (**************************************************************************)
2 (* *)
3 (* OCaml *)
4 (* *)
5 (* Xavier Leroy, projet Gallium, INRIA Paris *)
6 (* *)
7 (* Copyright 2015 Institut National de Recherche en Informatique et *)
8 (* en Automatique. *)
9 (* *)
10 (* All rights reserved. This file is distributed under the terms of *)
11 (* the GNU Lesser General Public License version 2.1, with the *)
12 (* special exception on linking described in the file LICENSE. *)
13 (* *)
14 (**************************************************************************)
15
16 (* Compare two bytecode executables for equality.
17 Ignore loader prefix and debug infos. *)
18
19 open Printf
20
21 let readtoc ic =
22 Bytesections.read_toc ic;
23 (Bytesections.toc(), Bytesections.pos_first_section ic)
24
25 type cmpresult = Same | Differ of int
26
27 let rec cmpbytes ic1 ic2 len ofs =
28 if len <= 0 then Same else begin
29 let c1 = input_char ic1 and c2 = input_char ic2 in
30 if c1 = c2 then cmpbytes ic1 ic2 (len - 1) (ofs + 1) else Differ ofs
31 end
32
33 let skip_section name =
34 name = "DBUG"
35
36 let cmpbyt file1 file2 =
37 let ic1 = open_in_bin file1 in
38 let (toc1, pos1) = readtoc ic1 in
39 let ic2 = open_in_bin file2 in
40 let (toc2, pos2) = readtoc ic2 in
41 seek_in ic1 pos1;
42 seek_in ic2 pos2;
43 let rec cmpsections t1 t2 =
44 match t1, t2 with
45 | [], [] ->
46 true
47 | (name1, len1) :: t1, t2 when skip_section name1 ->
48 seek_in ic1 (pos_in ic1 + len1);
49 cmpsections t1 t2
50 | t1, (name2, len2) :: t2 when skip_section name2 ->
51 seek_in ic2 (pos_in ic2 + len2);
52 cmpsections t1 t2
53 | [], _ ->
54 eprintf "%s has more sections than %s\n" file2 file1;
55 false
56 | _, [] ->
57 eprintf "%s has more sections than %s\n" file1 file2;
58 false
59 | (name1, len1) :: t1, (name2, len2) :: t2 ->
60 if name1 <> name2 then begin
61 eprintf "Section mismatch: %s (in %s) / %s (in %s)\n"
62 name1 file1 name2 file2;
63 false
64 end else if len1 <> len2 then begin
65 eprintf "Length of section %s differ: %d (in %s) / %d (in %s)\n"
66 name1 len1 file1 len2 file2;
67 false
68 end else begin
69 match cmpbytes ic1 ic2 len1 0 with
70 | Differ ofs ->
71 eprintf "Files %s and %s differ: section %s, offset %d\n"
72 file1 file2 name1 ofs;
73 false
74 | Same ->
75 cmpsections t1 t2
76 end
77 in
78 let res = cmpsections toc1 toc2 in
79 close_in ic1; close_in ic2;
80 res
81
82 let _ =
83 if Array.length Sys.argv <> 3 then begin
84 eprintf "Usage: cmpbyt <file 1> <file 2>\n";
85 exit 2
86 end;
87 if cmpbyt Sys.argv.(1) Sys.argv.(2) then exit 0 else exit 1
88