mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 20:20:06 +00:00
878b3b400b
subprocess.Popen returns byte data by default. Python2 was happy to try to execute string operations on such data and hope for the best, but python3 is more persnickety. Luckily, there's a simple way to indicate to the Popen class that text data is wanted that benefits the script. Just specifying universal_newlines will cause the returned data to be text and also convert any system-specific newlines to '\n' which the script relies on anyway. Enabled on Mac as an incidental change after confirming that the script works there just as well as it does on Linux. It probably works on FreeBSD too, but I retired my BSD system years ago. So I have no way to check. Don't run it on Windows. - It didn't work after all. It was just detecting non-posix and returning success.
94 lines
3.1 KiB
Python
Executable File
94 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright (c) 2017 Google Inc.
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""Checks names of global exports from a library."""
|
|
|
|
from __future__ import print_function
|
|
|
|
import os.path
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
PROG = 'check_symbol_exports'
|
|
|
|
|
|
def command_output(cmd, directory):
|
|
"""Runs a command in a directory and returns its standard output stream.
|
|
|
|
Captures the standard error stream.
|
|
|
|
Raises a RuntimeError if the command fails to launch or otherwise fails.
|
|
"""
|
|
p = subprocess.Popen(cmd,
|
|
cwd=directory,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
universal_newlines=True)
|
|
(stdout, _) = p.communicate()
|
|
if p.returncode != 0:
|
|
raise RuntimeError('Failed to run %s in %s' % (cmd, directory))
|
|
return stdout
|
|
|
|
|
|
def check_library(library):
|
|
"""Scans the given library file for global exports. If all such
|
|
exports are namespaced or begin with spv (in either C or C++ styles)
|
|
then return 0. Otherwise emit a message and return 1."""
|
|
|
|
# The pattern for a global symbol record
|
|
symbol_pattern = re.compile(r'^[0-aA-Fa-f]+ g *F \.text.*[0-9A-Fa-f]+ +(.*)')
|
|
|
|
# Ok patterns are as follows, assuming Itanium name mangling:
|
|
# spv[A-Z] : extern "C" symbol starting with spv
|
|
# _ZN : something in a namespace
|
|
# _Z[0-9]+spv[A-Z_] : C++ symbol starting with spv[A-Z_]
|
|
symbol_ok_pattern = re.compile(r'^(spv[A-Z]|_ZN|_Z[0-9]+spv[A-Z_])')
|
|
seen = set()
|
|
result = 0
|
|
for line in command_output(['objdump', '-t', library], '.').split('\n'):
|
|
match = symbol_pattern.search(line)
|
|
if match:
|
|
symbol = match.group(1)
|
|
if symbol not in seen:
|
|
seen.add(symbol)
|
|
#print("look at '{}'".format(symbol))
|
|
if not symbol_ok_pattern.match(symbol):
|
|
print('{}: error: Unescaped exported symbol: {}'.format(PROG, symbol))
|
|
result = 1
|
|
return result
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description='Check global names exported from a library')
|
|
parser.add_argument('library', help='The static library to examine')
|
|
args = parser.parse_args()
|
|
|
|
if not os.path.isfile(args.library):
|
|
print('{}: error: {} does not exist'.format(PROG, args.library))
|
|
sys.exit(1)
|
|
|
|
if os.name is 'posix':
|
|
status = check_library(args.library)
|
|
sys.exit(status)
|
|
else:
|
|
print('Passing test since not on Posix')
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|