1#!/usr/bin/env python 2 3import glob 4import os 5import re 6import string 7import subprocess 8import sys 9 10toolchain = os.environ['ANDROID_TOOLCHAIN'] 11arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) 12 13sys.stderr.write('Checking symbols for arch "%s"...\n' % arch) 14 15def GetSymbols(library, functions_or_variables): 16 global api 17 global arch 18 19 api = '9' 20 if library == 'libm' and arch == 'arm': 21 api = '3' 22 23 # There were no 64-bit ABIs before API level 21. 24 if '64' in arch: 25 api = '21' 26 27 # What GCC calls aarch64, Android calls arm64. 28 if arch == 'aarch64': 29 arch = 'arm64' 30 31 path = '%s/development/ndk/platforms/android-%s/arch-%s/symbols/%s.so.%s.txt' % (os.environ['ANDROID_BUILD_TOP'], api, arch, library, functions_or_variables) 32 symbols = set() 33 for line in open(path, 'r'): 34 symbols.add(line.rstrip()) 35 #sys.stdout.write('%d %s in %s for %s\n' % (len(symbols), functions_or_variables, library, arch)) 36 return symbols 37 38def CheckSymbols(library, functions_or_variables): 39 expected_symbols = GetSymbols(library, functions_or_variables) 40 41 lib_dir = 'lib' 42 if '64' in arch: 43 lib_dir = 'lib64' 44 45 so_file = '%s/system/%s/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], lib_dir, library) 46 47 # Example readelf output: 48 # 264: 0001623c 4 FUNC GLOBAL DEFAULT 8 cabsf 49 # 266: 00016244 4 FUNC GLOBAL DEFAULT 8 dremf 50 # 267: 00019018 4 OBJECT GLOBAL DEFAULT 11 __fe_dfl_env 51 # 268: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_dcmplt 52 53 54 r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)') 55 56 actual_symbols = set() 57 for line in subprocess.check_output(['readelf', '-W', '--dyn-syms', so_file]).split('\n'): 58 m = r.match(line) 59 if m: 60 symbol = string.split(m.group(2), '@')[0] 61 if m.group(1) == 'FUNC' and functions_or_variables == 'functions': 62 actual_symbols.add(symbol) 63 elif m.group(1) == 'OBJECT' and functions_or_variables == 'variables': 64 actual_symbols.add(symbol) 65 #else: 66 #print 'ignoring: ' % line 67 68 missing = expected_symbols - actual_symbols 69 if len(missing) > 0: 70 sys.stderr.write('%d missing %s in %s for %s:\n' % (len(missing), functions_or_variables, library, arch)) 71 for miss in sorted(missing): 72 sys.stderr.write(' %s\n' % miss) 73 74 extra = actual_symbols - expected_symbols 75 if len(extra) > 0: 76 sys.stderr.write('%d extra %s in %s for %s:\n' % (len(extra), functions_or_variables, library, arch)) 77 for s in sorted(extra): 78 sys.stderr.write(' %s\n' % s) 79 80 return len(missing) == 0 81 82CheckSymbols("libc", "functions") 83CheckSymbols("libc", "variables") 84CheckSymbols("libm", "functions") 85CheckSymbols("libm", "variables") 86 87sys.exit(0) 88