annotate clang/utils/check_cfc/obj_diff.py @ 248:cfe92afade2b

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 16 Aug 2023 18:23:14 +0900
parents 1d019706d866
children 1f2b6ac9f198
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 #!/usr/bin/env python
anatofuz
parents:
diff changeset
2
anatofuz
parents:
diff changeset
3 from __future__ import absolute_import, division, print_function
anatofuz
parents:
diff changeset
4
anatofuz
parents:
diff changeset
5 import argparse
anatofuz
parents:
diff changeset
6 import difflib
anatofuz
parents:
diff changeset
7 import filecmp
anatofuz
parents:
diff changeset
8 import os
anatofuz
parents:
diff changeset
9 import subprocess
anatofuz
parents:
diff changeset
10 import sys
anatofuz
parents:
diff changeset
11
anatofuz
parents:
diff changeset
12 disassembler = 'objdump'
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 def keep_line(line):
anatofuz
parents:
diff changeset
15 """Returns true for lines that should be compared in the disassembly
anatofuz
parents:
diff changeset
16 output."""
anatofuz
parents:
diff changeset
17 return "file format" not in line
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 def disassemble(objfile):
anatofuz
parents:
diff changeset
20 """Disassemble object to a file."""
anatofuz
parents:
diff changeset
21 p = subprocess.Popen([disassembler, '-d', objfile],
anatofuz
parents:
diff changeset
22 stdout=subprocess.PIPE,
anatofuz
parents:
diff changeset
23 stderr=subprocess.PIPE)
anatofuz
parents:
diff changeset
24 (out, err) = p.communicate()
anatofuz
parents:
diff changeset
25 if p.returncode or err:
anatofuz
parents:
diff changeset
26 print("Disassemble failed: {}".format(objfile))
anatofuz
parents:
diff changeset
27 sys.exit(1)
anatofuz
parents:
diff changeset
28 return [line for line in out.split(os.linesep) if keep_line(line)]
anatofuz
parents:
diff changeset
29
anatofuz
parents:
diff changeset
30 def dump_debug(objfile):
anatofuz
parents:
diff changeset
31 """Dump all of the debug info from a file."""
anatofuz
parents:
diff changeset
32 p = subprocess.Popen([disassembler, '-WliaprmfsoRt', objfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
anatofuz
parents:
diff changeset
33 (out, err) = p.communicate()
anatofuz
parents:
diff changeset
34 if p.returncode or err:
anatofuz
parents:
diff changeset
35 print("Dump debug failed: {}".format(objfile))
anatofuz
parents:
diff changeset
36 sys.exit(1)
anatofuz
parents:
diff changeset
37 return [line for line in out.split(os.linesep) if keep_line(line)]
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 def first_diff(a, b, fromfile, tofile):
anatofuz
parents:
diff changeset
40 """Returns the first few lines of a difference, if there is one. Python
anatofuz
parents:
diff changeset
41 diff can be very slow with large objects and the most interesting changes
anatofuz
parents:
diff changeset
42 are the first ones. Truncate data before sending to difflib. Returns None
anatofuz
parents:
diff changeset
43 is there is no difference."""
anatofuz
parents:
diff changeset
44
anatofuz
parents:
diff changeset
45 # Find first diff
anatofuz
parents:
diff changeset
46 first_diff_idx = None
anatofuz
parents:
diff changeset
47 for idx, val in enumerate(a):
anatofuz
parents:
diff changeset
48 if val != b[idx]:
anatofuz
parents:
diff changeset
49 first_diff_idx = idx
anatofuz
parents:
diff changeset
50 break
anatofuz
parents:
diff changeset
51
anatofuz
parents:
diff changeset
52 if first_diff_idx == None:
anatofuz
parents:
diff changeset
53 # No difference
anatofuz
parents:
diff changeset
54 return None
anatofuz
parents:
diff changeset
55
anatofuz
parents:
diff changeset
56 # Diff to first line of diff plus some lines
anatofuz
parents:
diff changeset
57 context = 3
anatofuz
parents:
diff changeset
58 diff = difflib.unified_diff(a[:first_diff_idx+context],
anatofuz
parents:
diff changeset
59 b[:first_diff_idx+context],
anatofuz
parents:
diff changeset
60 fromfile,
anatofuz
parents:
diff changeset
61 tofile)
anatofuz
parents:
diff changeset
62 difference = "\n".join(diff)
anatofuz
parents:
diff changeset
63 if first_diff_idx + context < len(a):
anatofuz
parents:
diff changeset
64 difference += "\n*** Diff truncated ***"
anatofuz
parents:
diff changeset
65 return difference
anatofuz
parents:
diff changeset
66
anatofuz
parents:
diff changeset
67 def compare_object_files(objfilea, objfileb):
anatofuz
parents:
diff changeset
68 """Compare disassembly of two different files.
anatofuz
parents:
diff changeset
69 Allowing unavoidable differences, such as filenames.
anatofuz
parents:
diff changeset
70 Return the first difference if the disassembly differs, or None.
anatofuz
parents:
diff changeset
71 """
anatofuz
parents:
diff changeset
72 disa = disassemble(objfilea)
anatofuz
parents:
diff changeset
73 disb = disassemble(objfileb)
anatofuz
parents:
diff changeset
74 return first_diff(disa, disb, objfilea, objfileb)
anatofuz
parents:
diff changeset
75
anatofuz
parents:
diff changeset
76 def compare_debug_info(objfilea, objfileb):
anatofuz
parents:
diff changeset
77 """Compare debug info of two different files.
anatofuz
parents:
diff changeset
78 Allowing unavoidable differences, such as filenames.
anatofuz
parents:
diff changeset
79 Return the first difference if the debug info differs, or None.
anatofuz
parents:
diff changeset
80 If there are differences in the code, there will almost certainly be differences in the debug info too.
anatofuz
parents:
diff changeset
81 """
anatofuz
parents:
diff changeset
82 dbga = dump_debug(objfilea)
anatofuz
parents:
diff changeset
83 dbgb = dump_debug(objfileb)
anatofuz
parents:
diff changeset
84 return first_diff(dbga, dbgb, objfilea, objfileb)
anatofuz
parents:
diff changeset
85
anatofuz
parents:
diff changeset
86 def compare_exact(objfilea, objfileb):
anatofuz
parents:
diff changeset
87 """Byte for byte comparison between object files.
anatofuz
parents:
diff changeset
88 Returns True if equal, False otherwise.
anatofuz
parents:
diff changeset
89 """
anatofuz
parents:
diff changeset
90 return filecmp.cmp(objfilea, objfileb)
anatofuz
parents:
diff changeset
91
anatofuz
parents:
diff changeset
92 if __name__ == '__main__':
anatofuz
parents:
diff changeset
93 parser = argparse.ArgumentParser()
anatofuz
parents:
diff changeset
94 parser.add_argument('objfilea', nargs=1)
anatofuz
parents:
diff changeset
95 parser.add_argument('objfileb', nargs=1)
anatofuz
parents:
diff changeset
96 parser.add_argument('-v', '--verbose', action='store_true')
anatofuz
parents:
diff changeset
97 args = parser.parse_args()
anatofuz
parents:
diff changeset
98 diff = compare_object_files(args.objfilea[0], args.objfileb[0])
anatofuz
parents:
diff changeset
99 if diff:
anatofuz
parents:
diff changeset
100 print("Difference detected")
anatofuz
parents:
diff changeset
101 if args.verbose:
anatofuz
parents:
diff changeset
102 print(diff)
anatofuz
parents:
diff changeset
103 sys.exit(1)
anatofuz
parents:
diff changeset
104 else:
anatofuz
parents:
diff changeset
105 print("The same")