v3d: add new flag dirty TMU cache at v3d_compiler
[mesa.git] / bin / symbols-check.py
1 #!/usr/bin/env python
2
3 import argparse
4 import os
5 import platform
6 import subprocess
7
8 # This list contains symbols that _might_ be exported for some platforms
9 PLATFORM_SYMBOLS = [
10 '__bss_end__',
11 '__bss_start__',
12 '__bss_start',
13 '__end__',
14 '_bss_end__',
15 '_edata',
16 '_end',
17 '_fini',
18 '_init',
19 ]
20
21
22 def get_symbols(nm, lib):
23 '''
24 List all the (non platform-specific) symbols exported by the library
25 '''
26 symbols = []
27 platform_name = platform.system()
28 output = subprocess.check_output([nm, '-gP', lib],
29 stderr=open(os.devnull, 'w')).decode("ascii")
30 for line in output.splitlines():
31 fields = line.split()
32 if len(fields) == 2 or fields[1] == 'U':
33 continue
34 symbol_name = fields[0]
35 if platform_name == 'Linux':
36 if symbol_name in PLATFORM_SYMBOLS:
37 continue
38 elif platform_name == 'Darwin':
39 assert symbol_name[0] == '_'
40 symbol_name = symbol_name[1:]
41 symbols.append(symbol_name)
42
43 return symbols
44
45
46 def main():
47 parser = argparse.ArgumentParser()
48 parser.add_argument('--symbols-file',
49 action='store',
50 required=True,
51 help='path to file containing symbols')
52 parser.add_argument('--lib',
53 action='store',
54 required=True,
55 help='path to library')
56 parser.add_argument('--nm',
57 action='store',
58 required=True,
59 help='path to binary (or name in $PATH)')
60 args = parser.parse_args()
61
62 try:
63 lib_symbols = get_symbols(args.nm, args.lib)
64 except:
65 # We can't run this test, but we haven't technically failed it either
66 # Return the GNU "skip" error code
67 exit(77)
68 mandatory_symbols = []
69 optional_symbols = []
70 with open(args.symbols_file) as symbols_file:
71 qualifier_optional = '(optional)'
72 for line in symbols_file.readlines():
73
74 # Strip comments
75 line = line.split('#')[0]
76 line = line.strip()
77 if not line:
78 continue
79
80 # Line format:
81 # [qualifier] symbol
82 qualifier = None
83 symbol = None
84
85 fields = line.split()
86 if len(fields) == 1:
87 symbol = fields[0]
88 elif len(fields) == 2:
89 qualifier = fields[0]
90 symbol = fields[1]
91 else:
92 print(args.symbols_file + ': invalid format: ' + line)
93 exit(1)
94
95 # The only supported qualifier is 'optional', which means the
96 # symbol doesn't have to be exported by the library
97 if qualifier and not qualifier == qualifier_optional:
98 print(args.symbols_file + ': invalid qualifier: ' + qualifier)
99 exit(1)
100
101 if qualifier == qualifier_optional:
102 optional_symbols.append(symbol)
103 else:
104 mandatory_symbols.append(symbol)
105
106 unknown_symbols = []
107 for symbol in lib_symbols:
108 if symbol in mandatory_symbols:
109 continue
110 if symbol in optional_symbols:
111 continue
112 if symbol[:2] == '_Z':
113 # Ignore random C++ symbols
114 #TODO: figure out if there's any way to avoid exporting them in the first place
115 continue
116 unknown_symbols.append(symbol)
117
118 missing_symbols = [
119 sym for sym in mandatory_symbols if sym not in lib_symbols
120 ]
121
122 for symbol in unknown_symbols:
123 print(args.lib + ': unknown symbol exported: ' + symbol)
124
125 for symbol in missing_symbols:
126 print(args.lib + ': missing symbol: ' + symbol)
127
128 if unknown_symbols or missing_symbols:
129 exit(1)
130 exit(0)
131
132
133 if __name__ == '__main__':
134 main()