| Stephen Crane | 77bb564 | 2017-08-31 15:08:26 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 2 |  | 
|  | 3 | import glob | 
|  | 4 | import os | 
|  | 5 | import re | 
|  | 6 | import string | 
|  | 7 | import subprocess | 
|  | 8 | import sys | 
|  | 9 |  | 
|  | 10 | toolchain = os.environ['ANDROID_TOOLCHAIN'] | 
|  | 11 | arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain) | 
|  | 12 |  | 
|  | 13 | sys.stderr.write('Checking symbols for arch "%s"...\n' % arch) | 
|  | 14 |  | 
|  | 15 | def GetSymbols(library, functions_or_variables): | 
| Elliott Hughes | ec738d9 | 2015-05-11 12:10:40 -0700 | [diff] [blame] | 16 | global api | 
|  | 17 | global arch | 
|  | 18 |  | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 19 | api = '9' | 
|  | 20 | if library == 'libm' and arch == 'arm': | 
|  | 21 | api = '3' | 
| Elliott Hughes | ec738d9 | 2015-05-11 12:10:40 -0700 | [diff] [blame] | 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 |  | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 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 |  | 
|  | 38 | def CheckSymbols(library, functions_or_variables): | 
|  | 39 | expected_symbols = GetSymbols(library, functions_or_variables) | 
|  | 40 |  | 
| Elliott Hughes | ec738d9 | 2015-05-11 12:10:40 -0700 | [diff] [blame] | 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) | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 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() | 
| Elliott Hughes | ec738d9 | 2015-05-11 12:10:40 -0700 | [diff] [blame] | 57 | for line in subprocess.check_output(['readelf', '-W', '--dyn-syms', so_file]).split('\n'): | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 58 | m = r.match(line) | 
|  | 59 | if m: | 
| Dmitriy Ivanov | 6cda074 | 2015-06-04 10:12:37 -0700 | [diff] [blame] | 60 | symbol = string.split(m.group(2), '@')[0] | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 61 | if m.group(1) == 'FUNC' and functions_or_variables == 'functions': | 
| Dmitriy Ivanov | 6cda074 | 2015-06-04 10:12:37 -0700 | [diff] [blame] | 62 | actual_symbols.add(symbol) | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 63 | elif m.group(1) == 'OBJECT' and functions_or_variables == 'variables': | 
| Dmitriy Ivanov | 6cda074 | 2015-06-04 10:12:37 -0700 | [diff] [blame] | 64 | actual_symbols.add(symbol) | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 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 |  | 
| Elliott Hughes | ec738d9 | 2015-05-11 12:10:40 -0700 | [diff] [blame] | 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 |  | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 80 | return len(missing) == 0 | 
|  | 81 |  | 
|  | 82 | CheckSymbols("libc", "functions") | 
|  | 83 | CheckSymbols("libc", "variables") | 
|  | 84 | CheckSymbols("libm", "functions") | 
|  | 85 | CheckSymbols("libm", "variables") | 
|  | 86 |  | 
|  | 87 | sys.exit(0) |