]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - utils/check_cfc/obj_diff.py
Vendor import of clang trunk r238337:
[FreeBSD/FreeBSD.git] / utils / check_cfc / obj_diff.py
1 #!/usr/bin/env python2.7
2
3 from __future__ import print_function
4
5 import argparse
6 import difflib
7 import os
8 import subprocess
9 import sys
10
11 disassembler = 'objdump'
12
13 def keep_line(line):
14     """Returns true for lines that should be compared in the disassembly
15     output."""
16     return "file format" not in line
17
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))
26         sys.exit(1)
27     return filter(keep_line, out.split(os.linesep))
28
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."""
34
35     # Find first diff
36     first_diff_idx = None
37     for idx, val in enumerate(a):
38         if val != b[idx]:
39             first_diff_idx = idx
40             break
41
42     if first_diff_idx == None:
43         # No difference
44         return None
45
46     # Diff to first line of diff plus some lines
47     context = 3
48     diff = difflib.unified_diff(a[:first_diff_idx+context],
49                                 b[:first_diff_idx+context],
50                                 fromfile,
51                                 tofile)
52     difference = "\n".join(diff)
53     if first_diff_idx + context < len(a):
54         difference += "\n*** Diff truncated ***"
55     return difference
56
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.
61     """
62     disa = disassemble(objfilea)
63     disb = disassemble(objfileb)
64     return first_diff(disa, disb, objfilea, objfileb)
65
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])
73     if diff:
74         print("Difference detected")
75         if args.verbose:
76             print(diff)
77         sys.exit(1)
78     else:
79         print("The same")