1#
2# Copyright (C) 2015 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the 'License');
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an 'AS IS' BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import glob
17import os
18import re
19import subprocess
20
21
22def GetFromTxt(txt_file):
23    symbols = set()
24    f = open(txt_file, 'r')
25    for line in f.read().splitlines():
26        symbols.add(line)
27    f.close()
28    return symbols
29
30
31def GetFromElf(elf_file, sym_type='--dyn-syms'):
32    # pylint: disable=line-too-long
33    # Example readelf output:
34    #     264: 0001623c         4 FUNC        GLOBAL DEFAULT        8 cabsf
35    #     266: 00016244         4 FUNC        GLOBAL DEFAULT        8 dremf
36    #     267: 00019018         4 OBJECT    GLOBAL DEFAULT     11 __fe_dfl_env
37    #     268: 00000000         0 FUNC        GLOBAL DEFAULT    UND __aeabi_dcmplt
38
39    r = re.compile(
40        r' +\d+: [0-9a-f]+ +\d+ (I?FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
41
42    symbols = set()
43
44    output = subprocess.check_output(['readelf', sym_type, '-W', elf_file],
45            text=True)
46    for line in output.split('\n'):
47        if ' HIDDEN ' in line or ' UND ' in line:
48            continue
49        m = r.match(line)
50        if m:
51            symbol = m.group(2)
52            symbol = re.sub('@.*', '', symbol)
53            symbols.add(symbol)
54
55    return symbols
56
57
58def GetFromAndroidStaticLib(files):
59    out_dir = os.environ['ANDROID_PRODUCT_OUT']
60    lib_dir = os.path.join(out_dir, 'obj')
61
62    results = set()
63    for f in files:
64        static_lib_dir = os.path.join(
65            lib_dir,
66            'STATIC_LIBRARIES',
67            '{}_intermediates'.format(os.path.splitext(f)[0]))
68        results |= GetFromElf(
69            os.path.join(static_lib_dir, f),
70            sym_type='--syms')
71    return results
72
73
74def GetFromAndroidSo(files):
75    out_dir = os.environ['ANDROID_PRODUCT_OUT']
76    lib_dir = os.path.join(out_dir, 'system/lib64')
77    if not os.path.isdir(lib_dir):
78        lib_dir = os.path.join(out_dir, 'system/lib')
79
80    lib_dir = os.path.join(out_dir, 'apex/com.android.runtime/lib64/bionic/')
81    if not os.path.isdir(lib_dir):
82        lib_dir = os.path.join(out_dir, 'apex/com.android.runtime/lib/bionic/')
83
84    results = set()
85    for f in files:
86        results |= GetFromElf(os.path.join(lib_dir, f))
87    return results
88
89
90def GetFromSystemSo(files):
91    lib_dir = '/lib/x86_64-linux-gnu'
92    results = set()
93    for f in files:
94        results |= GetFromElf(glob.glob(os.path.join(lib_dir, f))[-1])
95    return results
96