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