3 from __future__
import absolute_import
, division
, print_function
12 disassembler
= "objdump"
16 """Returns true for lines that should be compared in the disassembly
18 return "file format" not in line
21 def disassemble(objfile
):
22 """Disassemble object to a file."""
24 [disassembler
, "-d", objfile
], stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
26 (out
, err
) = p
.communicate()
27 if p
.returncode
or err
:
28 print("Disassemble failed: {}".format(objfile
))
30 return [line
for line
in out
.split(os
.linesep
) if keep_line(line
)]
33 def dump_debug(objfile
):
34 """Dump all of the debug info from a file."""
36 [disassembler
, "-WliaprmfsoRt", objfile
],
37 stdout
=subprocess
.PIPE
,
38 stderr
=subprocess
.PIPE
,
40 (out
, err
) = p
.communicate()
41 if p
.returncode
or err
:
42 print("Dump debug failed: {}".format(objfile
))
44 return [line
for line
in out
.split(os
.linesep
) if keep_line(line
)]
47 def first_diff(a
, b
, fromfile
, tofile
):
48 """Returns the first few lines of a difference, if there is one. Python
49 diff can be very slow with large objects and the most interesting changes
50 are the first ones. Truncate data before sending to difflib. Returns None
51 is there is no difference."""
55 for idx
, val
in enumerate(a
):
60 if first_diff_idx
== None:
64 # Diff to first line of diff plus some lines
66 diff
= difflib
.unified_diff(
67 a
[: first_diff_idx
+ context
], b
[: first_diff_idx
+ context
], fromfile
, tofile
69 difference
= "\n".join(diff
)
70 if first_diff_idx
+ context
< len(a
):
71 difference
+= "\n*** Diff truncated ***"
75 def compare_object_files(objfilea
, objfileb
):
76 """Compare disassembly of two different files.
77 Allowing unavoidable differences, such as filenames.
78 Return the first difference if the disassembly differs, or None.
80 disa
= disassemble(objfilea
)
81 disb
= disassemble(objfileb
)
82 return first_diff(disa
, disb
, objfilea
, objfileb
)
85 def compare_debug_info(objfilea
, objfileb
):
86 """Compare debug info of two different files.
87 Allowing unavoidable differences, such as filenames.
88 Return the first difference if the debug info differs, or None.
89 If there are differences in the code, there will almost certainly be differences in the debug info too.
91 dbga
= dump_debug(objfilea
)
92 dbgb
= dump_debug(objfileb
)
93 return first_diff(dbga
, dbgb
, objfilea
, objfileb
)
96 def compare_exact(objfilea
, objfileb
):
97 """Byte for byte comparison between object files.
98 Returns True if equal, False otherwise.
100 return filecmp
.cmp(objfilea
, objfileb
)
103 if __name__
== "__main__":
104 parser
= argparse
.ArgumentParser()
105 parser
.add_argument("objfilea", nargs
=1)
106 parser
.add_argument("objfileb", nargs
=1)
107 parser
.add_argument("-v", "--verbose", action
="store_true")
108 args
= parser
.parse_args()
109 diff
= compare_object_files(args
.objfilea
[0], args
.objfileb
[0])
111 print("Difference detected")