1 #!/usr/bin/env python2.7
3 from __future__ import print_function
11 disassembler = 'objdump'
14 """Returns true for lines that should be compared in the disassembly
16 return "file format" not in line
18 def disassemble(objfile):
19 """Disassemble object to a file."""
20 p = subprocess.Popen([disassembler, '-d', objfile],
21 stdout=subprocess.PIPE,
22 stderr=subprocess.PIPE)
23 (out, err) = p.communicate()
24 if p.returncode or err:
25 print("Disassemble failed: {}".format(objfile))
27 return filter(keep_line, out.split(os.linesep))
29 def first_diff(a, b, fromfile, tofile):
30 """Returns the first few lines of a difference, if there is one. Python
31 diff can be very slow with large objects and the most interesting changes
32 are the first ones. Truncate data before sending to difflib. Returns None
33 is there is no difference."""
37 for idx, val in enumerate(a):
42 if first_diff_idx == None:
46 # Diff to first line of diff plus some lines
48 diff = difflib.unified_diff(a[:first_diff_idx+context],
49 b[:first_diff_idx+context],
52 difference = "\n".join(diff)
53 if first_diff_idx + context < len(a):
54 difference += "\n*** Diff truncated ***"
57 def compare_object_files(objfilea, objfileb):
58 """Compare disassembly of two different files.
59 Allowing unavoidable differences, such as filenames.
60 Return the first difference if the disassembly differs, or None.
62 disa = disassemble(objfilea)
63 disb = disassemble(objfileb)
64 return first_diff(disa, disb, objfilea, objfileb)
66 if __name__ == '__main__':
67 parser = argparse.ArgumentParser()
68 parser.add_argument('objfilea', nargs=1)
69 parser.add_argument('objfileb', nargs=1)
70 parser.add_argument('-v', '--verbose', action='store_true')
71 args = parser.parse_args()
72 diff = compare_object_files(args.objfilea[0], args.objfileb[0])
74 print("Difference detected")