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