Fix folding insert feeding extract
[platform/upstream/SPIRV-Tools.git] / utils / check_symbol_exports.py
1 #!/usr/bin/env python
2 # Copyright (c) 2017 Google Inc.
3
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Checks names of global exports from a library."""
16
17 from __future__ import print_function
18
19 import os.path
20 import re
21 import subprocess
22 import sys
23
24
25 PROG = 'check_symbol_exports'
26
27
28 def command_output(cmd, directory):
29     """Runs a command in a directory and returns its standard output stream.
30
31     Captures the standard error stream.
32
33     Raises a RuntimeError if the command fails to launch or otherwise fails.
34     """
35     p = subprocess.Popen(cmd,
36                          cwd=directory,
37                          stdout=subprocess.PIPE,
38                          stderr=subprocess.PIPE)
39     (stdout, _) = p.communicate()
40     if p.returncode != 0:
41         raise RuntimeError('Failed to run %s in %s' % (cmd, directory))
42     return stdout
43
44
45 def check_library(library):
46     """Scans the given library file for global exports.  If all such
47     exports are namespaced or begin with spv (in either C or C++ styles)
48     then return 0.  Otherwise emit a message and return 1."""
49
50     # The pattern for a global symbol record
51     symbol_pattern = re.compile(r'^[0-aA-Fa-f]+ g *F \.text.*[0-9A-Fa-f]+ +(.*)')
52
53     # Ok patterns are as follows, assuming Itanium name mangling:
54     #   spv[A-Z]          :  extern "C" symbol starting with spv
55     #   _ZN               :  something in a namespace
56     #   _Z[0-9]+spv[A-Z_] :  C++ symbol starting with spv[A-Z_]
57     symbol_ok_pattern = re.compile(r'^(spv[A-Z]|_ZN|_Z[0-9]+spv[A-Z_])')
58     seen = set()
59     result = 0
60     for line in command_output(['objdump', '-t', library], '.').split('\n'):
61         match = symbol_pattern.search(line)
62         if match:
63             symbol = match.group(1)
64             if symbol not in seen:
65                 seen.add(symbol)
66                 #print("look at '{}'".format(symbol))
67                 if not symbol_ok_pattern.match(symbol):
68                     print('{}: error: Unescaped exported symbol: {}'.format(PROG, symbol))
69                     result = 1
70     return result
71
72
73 def main():
74     import argparse
75     parser = argparse.ArgumentParser(description='Check global names exported from a library')
76     parser.add_argument('library', help='The static library to examine')
77     args = parser.parse_args()
78
79     if not os.path.isfile(args.library):
80         print('{}: error: {} does not exist'.format(PROG, args.library))
81         sys.exit(1)
82
83     if os.name is 'posix':
84         status = check_library(args.library)
85         sys.exit(status)
86     else:
87         print('Passing test since not on Posix')
88         sys.exit(0)
89
90
91 if __name__ == '__main__':
92     main()