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