1#!/bin/sh
2#
3# Copyright (C) 2011 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17# gen-system-symbols.sh
18#
19# This tool is used to read the shared library from a source directory
20# (SRC) and extract the list of functions and variables.
21#
22# Then, for each library, it will generate in (DST) two text files
23# named <library>.functions.txt and <library>.variables.txt
24#
25
26# Only runs on Linux because it requires the "readelf" utility
27#
28
29. `dirname $0`/prebuilt-common.sh
30
31VERBOSE=no
32
33PROGRAM_PARAMETERS="<src-dir> <dst-dir>"
34PROGRAM_DESCRIPTION=\
35"This program is used to parse all shared libraries in <src-dir>
36and extract, for each one of them, the list of functions and variables
37that it exports.
38
39For some of these libraries, it will remove symbols that are not meant
40to be imported (unless you use --no-symbol-filtering)
41
42These lists will then be saved into two files:
43
44  <dst-dir>/<libname>.functions.txt
45  <dst-dir>/<libname>.variables.txt
46"
47
48NO_FILTERING=
49register_var_option "--no-symbol-filtering" NO_FILTERING "Disable symbol filtering"
50
51extract_parameters "$@"
52
53parse_params ()
54{
55    SRCDIR=$1
56    DSTDIR=$2
57
58    if [ -z "$SRCDIR" ]; then
59        dump "ERROR: Missing first parameter (source directory path), see --help"
60        exit 1
61    fi
62
63    if [ -z "$DSTDIR" ]; then
64        dump "ERROR: Missing second parameter (destination directory path), see --help"
65        exit 1
66    fi
67
68    if [ ! -d "$SRCDIR" ]; then
69        dump "ERROR: Not a source directory: $SRCDIR"
70        exit 1
71    fi
72
73    mkdir -p $DSTDIR
74    fail_panic "Could not create destination directory: $DSTDIR"
75}
76
77parse_params $PARAMETERS
78
79READELF=readelf
80
81# $1: shared library path
82get_library_functions ()
83{
84    $READELF -s -D -W $1 | awk '$5 ~ /FUNC/ && $6 ~ /GLOBAL|WEAK/ && $8 !~ /UND/ { print $9; }' | sort -u
85}
86
87# $1: shared library path
88get_library_variables ()
89{
90    $READELF -s -D -W $1 | awk '$5 ~ /OBJECT/ && $6 ~ /GLOBAL|WEAK/ && $8 !~ /UND/ { print $9; }' | sort -u
91}
92
93# Temp file used to list shared library symbol exclusions
94# See set_symbol_excludes and extract_shared_library_xxxx functions below
95SYMBOL_EXCLUDES=$TMPDIR/ndk-symbol-excludes.txt
96
97# Temp file used to list shared library symbol inclusions, these
98# are essentially overrides to the content of SYMBOL_EXCLUDES
99SYMBOL_INCLUDES=$TMPDIR/ndk-symbol-includes.txt
100
101# Temp file used to filter symbols
102SYMBOL_TMPFILE=$TMPDIR/ndk-symbols-list.txt
103
104# Reset the symbol exclusion list to its default
105reset_symbol_excludes ()
106{
107    # By default, do not export C++ mangled symbol, which all start with _Z
108    echo '^_Z' > $SYMBOL_EXCLUDES
109
110    # __INIT_ARRAY__, __FINI_ARRAY__ and _GLOBAL_OFFSET_TABLE_ are special symbols
111    # that should normally be hidden.
112    echo "^__INIT_ARRAY__" >> $SYMBOL_EXCLUDES
113    echo "^__FINI_ARRAY__" >> $SYMBOL_EXCLUDES
114    echo "^_GLOBAL_OFFSET_TABLE_" >> $SYMBOL_EXCLUDES
115    > $SYMBOL_INCLUDES
116}
117
118# Add new exclusion patterns to SYMBOL_EXCLUDES
119set_symbol_excludes ()
120{
121    (echo "$@" | tr ' ' '\n') >> $SYMBOL_EXCLUDES
122}
123
124# Add new inclusion patterns to SYMBOL_INCLUDES
125set_symbol_includes ()
126{
127    (echo "$@" | tr ' ' '\n') >> $SYMBOL_INCLUDES
128}
129
130# Clear symbol exclusion/inclusion files
131clear_symbol_excludes ()
132{
133    rm -f $SYMBOL_EXCLUDES $SYMBOL_INCLUDES
134}
135
136# Filter the list of symbols from a file
137# $1: path to symbol list file
138filter_symbols ()
139{
140    (grep -v -f $SYMBOL_EXCLUDES $1 ; grep -f $SYMBOL_INCLUDES $1) | sort -u
141}
142
143# $1: Library name
144# $2+: List of symbols (functions or variables)
145# Out: sorted list of filtered symbols, based on library name
146filter_library_symbols ()
147{
148    local LIB=$1
149    shift
150    local SYMBOLS="$@"
151    (echo "$SYMBOLS" | tr ' ' '\n' | sort -u) > $SYMBOL_TMPFILE
152
153    reset_symbol_excludes
154
155    case $LIB in
156        libc.so)
157            # Remove a few internal symbols that should not be exposed
158            # from the C library (we plan to clean that up soon by using the
159            # "hidden" visibility attribute in the near future).
160            #
161            set_symbol_excludes \
162                '^the_' '^dns_' 'load_domain_search_list' 'res_get_dns_changed' \
163                '^_resolv_cache' '^_dns_getht' '^_thread_atexit' \
164                '^free_malloc_leak_info' 'fake_gmtime_r' 'fake_localtime_r' \
165                '^gAllocationsMutex' '^gHashTable' '^gMallocLeakZygoteChild'
166            # libc.so now absort libstdc++ use to have, thus contains C++ symbols from now on
167            set_symbol_includes '^_Z.*'
168            ;;
169        libstdc++.so)
170            # This used to be the only library that is allowed to export C++ symbols for now.
171            set_symbol_includes '^_Z.*'
172            ;;
173        liblog.so)
174            set_symbol_excludes '^.*'         # exclude everything
175            set_symbol_includes '^__android_' # except __android_xxxx functions
176            ;;
177        libOpenSLES.so)
178            set_symbol_excludes '^_' '^MPH_' # remove MPH_to_xxx definitions
179            ;;
180        libGLESv*.so)
181            # Exclude non-OES extension entry points
182            set_symbol_excludes 'EXT$'
183            set_symbol_excludes 'AMD$'
184            set_symbol_excludes 'ANGLE$'
185            set_symbol_excludes 'APPLE$'
186            set_symbol_excludes 'IMG$'
187            set_symbol_excludes 'NV$'
188            set_symbol_excludes 'QCOM$'
189            ;;
190    esac
191    filter_symbols "$SYMBOL_TMPFILE"
192}
193
194for LIB in $(cd $SRCDIR && ls lib*.so); do
195    SRCLIB=$SRCDIR/$LIB
196    log "Extracting symbols from $LIB"
197    FUNCS=$(get_library_functions $SRCLIB)
198    VARS=$(get_library_variables $SRCLIB)
199    if [ -z "$NO_FILTERING" ]; then
200        FUNCS=$(filter_library_symbols $LIB $FUNCS)
201        VARS=$(filter_library_symbols $LIB $VARS)
202    fi
203    NUMFUNCS=$(echo $FUNCS | wc -w)
204    NUMVARS=$(echo $VARS | wc -w)
205    log "    Found $NUMFUNCS functions and $NUMVARS variables"
206    (echo "$FUNCS" | tr ' ' '\n') > $DSTDIR/$LIB.functions.txt
207    (echo "$VARS" | tr ' ' '\n') > $DSTDIR/$LIB.variables.txt
208done
209