diff options
Diffstat (limited to 'utils/check_cfc/obj_diff.py')
-rwxr-xr-x | utils/check_cfc/obj_diff.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/utils/check_cfc/obj_diff.py b/utils/check_cfc/obj_diff.py new file mode 100755 index 0000000..6f932b3 --- /dev/null +++ b/utils/check_cfc/obj_diff.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python2.7 + +from __future__ import print_function + +import argparse +import difflib +import os +import subprocess +import sys + +disassembler = 'objdump' + +def keep_line(line): + """Returns true for lines that should be compared in the disassembly + output.""" + return "file format" not in line + +def disassemble(objfile): + """Disassemble object to a file.""" + p = subprocess.Popen([disassembler, '-d', objfile], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + if p.returncode or err: + print("Disassemble failed: {}".format(objfile)) + sys.exit(1) + return filter(keep_line, out.split(os.linesep)) + +def first_diff(a, b, fromfile, tofile): + """Returns the first few lines of a difference, if there is one. Python + diff can be very slow with large objects and the most interesting changes + are the first ones. Truncate data before sending to difflib. Returns None + is there is no difference.""" + + # Find first diff + first_diff_idx = None + for idx, val in enumerate(a): + if val != b[idx]: + first_diff_idx = idx + break + + if first_diff_idx == None: + # No difference + return None + + # Diff to first line of diff plus some lines + context = 3 + diff = difflib.unified_diff(a[:first_diff_idx+context], + b[:first_diff_idx+context], + fromfile, + tofile) + difference = "\n".join(diff) + if first_diff_idx + context < len(a): + difference += "\n*** Diff truncated ***" + return difference + +def compare_object_files(objfilea, objfileb): + """Compare disassembly of two different files. + Allowing unavoidable differences, such as filenames. + Return the first difference if the disassembly differs, or None. + """ + disa = disassemble(objfilea) + disb = disassemble(objfileb) + return first_diff(disa, disb, objfilea, objfileb) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('objfilea', nargs=1) + parser.add_argument('objfileb', nargs=1) + parser.add_argument('-v', '--verbose', action='store_true') + args = parser.parse_args() + diff = compare_object_files(args.objfilea[0], args.objfileb[0]) + if diff: + print("Difference detected") + if args.verbose: + print(diff) + sys.exit(1) + else: + print("The same") |