10528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner#!/bin/sh 20528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 30528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Copyright (C) 2011 The Android Open Source Project 40528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 50528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Licensed under the Apache License, Version 2.0 (the "License"); 60528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# you may not use this file except in compliance with the License. 70528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# You may obtain a copy of the License at 80528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 90528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# http://www.apache.org/licenses/LICENSE-2.0 100528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 110528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Unless required by applicable law or agreed to in writing, software 120528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# distributed under the License is distributed on an "AS IS" BASIS, 130528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# See the License for the specific language governing permissions and 150528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# limitations under the License. 160528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 170528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# gen-system-symbols.sh 180528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 190528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# This tool is used to read the shared library from a source directory 200528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# (SRC) and extract the list of functions and variables. 210528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 220528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Then, for each library, it will generate in (DST) two text files 230528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# named <library>.functions.txt and <library>.variables.txt 240528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 250528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 260528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Only runs on Linux because it requires the "readelf" utility 270528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# 280528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 290528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner. `dirname $0`/prebuilt-common.sh 300528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 310528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerVERBOSE=no 320528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerVERBOSE2=no 330528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 340528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerPROGRAM_PARAMETERS="<src-dir> <dst-dir>" 350528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerPROGRAM_DESCRIPTION=\ 360528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner"This program is used to parse all shared libraries in <src-dir> 370528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerand extract, for each one of them, the list of functions and variables 380528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerthat it exports. 390528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 400528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerFor some of these libraries, it will remove symbols that are not meant 410528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerto be imported (unless you use --no-symbol-filtering) 420528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 430528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerThese lists will then be saved into two files: 440528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 450528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner <dst-dir>/<libname>.functions.txt 460528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner <dst-dir>/<libname>.variables.txt 470528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner" 480528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 490528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerNO_FILTERING= 500528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerregister_var_option "--no-symbol-filtering" NO_FILTERING "Disable symbol filtering" 510528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 520528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerextract_parameters "$@" 530528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 540528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerparse_params () 550528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 560528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner SRCDIR=$1 570528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner DSTDIR=$2 580528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 590528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner if [ -z "$SRCDIR" ]; then 600528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner dump "ERROR: Missing first parameter (source directory path), see --help" 610528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner exit 1 620528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner fi 630528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 640528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner if [ -z "$DSTDIR" ]; then 650528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner dump "ERROR: Missing second parameter (destination directory path), see --help" 660528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner exit 1 670528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner fi 680528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 690528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner if [ ! -d "$SRCDIR" ]; then 700528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner dump "ERROR: Not a source directory: $SRCDIR" 710528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner exit 1 720528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner fi 730528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 740528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner mkdir -p $DSTDIR 750528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner fail_panic "Could not create destination directory: $DSTDIR" 760528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 770528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 780528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerparse_params $PARAMETERS 790528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 800528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerREADELF=readelf 810528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 820528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# $1: shared library path 830528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerget_library_functions () 840528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 85e9f5fc93f45682793836b68b277b0c451b92f885David 'Digit' Turner $READELF -s -D -W $1 | awk '$5 ~ /FUNC/ && $6 ~ /GLOBAL|WEAK/ && $8 !~ /UND/ { print $9; }' | sort -u 860528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 870528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 880528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# $1: shared library path 890528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerget_library_variables () 900528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 91e9f5fc93f45682793836b68b277b0c451b92f885David 'Digit' Turner $READELF -s -D -W $1 | awk '$5 ~ /OBJECT/ && $6 ~ /GLOBAL|WEAK/ && $8 !~ /UND/ { print $9; }' | sort -u 920528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 930528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 940528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Temp file used to list shared library symbol exclusions 950528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# See set_symbol_excludes and extract_shared_library_xxxx functions below 960528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerSYMBOL_EXCLUDES=/tmp/ndk-$USER/ndk-symbol-excludes.txt 970528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 980528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Temp file used to list shared library symbol inclusions, these 990528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# are essentially overrides to the content of SYMBOL_EXCLUDES 1000528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerSYMBOL_INCLUDES=/tmp/ndk-$USER/ndk-symbol-includes.txt 1010528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1020528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Temp file used to filter symbols 1030528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' TurnerSYMBOL_TMPFILE=/tmp/ndk-$USER/ndk-symbols-list.txt 1040528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1050528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Reset the symbol exclusion list to its default 1060528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerreset_symbol_excludes () 1070528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1080528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # By default, do not export C++ mangled symbol, which all start with _Z 1090528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner echo '^_Z' > $SYMBOL_EXCLUDES 1100528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1110528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # __INIT_ARRAY__ and __FINI_ARRAY__ are special symbols that should 1120528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # normally be hidden. 1130528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner echo "^__INIT_ARRAY__" >> $SYMBOL_EXCLUDES 1140528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner echo "^__FINI_ARRAY__" >> $SYMBOL_EXCLUDES 1150528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner > $SYMBOL_INCLUDES 1160528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1170528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1180528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Add new exclusion patterns to SYMBOL_EXCLUDES 1190528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerset_symbol_excludes () 1200528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1210528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (echo "$@" | tr ' ' '\n') >> $SYMBOL_EXCLUDES 1220528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1230528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1240528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Add new inclusion patterns to SYMBOL_INCLUDES 1250528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerset_symbol_includes () 1260528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1270528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (echo "$@" | tr ' ' '\n') >> $SYMBOL_INCLUDES 1280528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1290528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1300528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Clear symbol exclusion/inclusion files 1310528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerclear_symbol_excludes () 1320528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1330528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner rm -f $SYMBOL_EXCLUDES $SYMBOL_INCLUDES 1340528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1350528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1360528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Filter the list of symbols from a file 1370528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# $1: path to symbol list file 1380528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerfilter_symbols () 1390528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1400528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (grep -v -f $SYMBOL_EXCLUDES $1 ; grep -f $SYMBOL_INCLUDES $1) | sort -u 1410528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1420528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1430528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# $1: Library name 1440528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# $2+: List of symbols (functions or variables) 1450528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner# Out: sorted list of filtered symbols, based on library name 1460528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerfilter_library_symbols () 1470528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner{ 1480528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner local LIB=$1 1490528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner shift 1500528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner local SYMBOLS="$@" 1510528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (echo "$SYMBOLS" | tr ' ' '\n' | sort -u) > $SYMBOL_TMPFILE 1520528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1530528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner reset_symbol_excludes 1540528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1550528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner case $LIB in 1560528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner libc.so) 1570528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # Remove a few internal symbols that should not be exposed 1580528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # from the C library (we plan to clean that up soon by using the 1590528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # "hidden" visibility attribute in the near future). 1600528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # 1610528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner set_symbol_excludes \ 1620528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner '^the_' '^dns_' 'load_domain_search_list' 'res_get_dns_changed' \ 1630528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner '^_resolv_cache' '^_dns_getht' '^_thread_atexit' \ 1640528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner '^free_malloc_leak_info' 'fake_gmtime_r' 'fake_localtime_r' \ 1650528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner '^gAllocationsMutex' '^gHashTable' '^gMallocLeakZygoteChild' 1660528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner ;; 1670528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner libstdc++.so) 1680528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner # This is the only library that is allowed to export C++ symbols for now. 1690528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner set_symbol_includes '^_Z.*' 1700528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner ;; 1710528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner liblog.so) 1720528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner set_symbol_excludes '^.*' # exclude everything 1730528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner set_symbol_includes '^__android_' # except __android_xxxx functions 1740528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner ;; 1750528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner libOpenSLES.so) 1760528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner set_symbol_excludes '^_' '^MPH_' # remove MPH_to_xxx definitions 1770528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner ;; 1780528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner esac 1790528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner filter_symbols "$SYMBOL_TMPFILE" 1800528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner} 1810528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner 1820528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerfor LIB in $(cd $SRCDIR && ls lib*.so); do 1830528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner SRCLIB=$SRCDIR/$LIB 1840528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner log "Extracting symbols from $LIB" 1850528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner FUNCS=$(get_library_functions $SRCLIB) 1860528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner VARS=$(get_library_variables $SRCLIB) 1870528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner if [ -z "$NO_FILTERING" ]; then 1880528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner FUNCS=$(filter_library_symbols $LIB $FUNCS) 1890528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner VARS=$(filter_library_symbols $LIB $VARS) 1900528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner fi 1910528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner NUMFUNCS=$(echo $FUNCS | wc -w) 1920528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner NUMVARS=$(echo $VARS | wc -w) 1930528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner log " Found $NUMFUNCS functions and $NUMVARS variables" 1940528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (echo "$FUNCS" | tr ' ' '\n') > $DSTDIR/$LIB.functions.txt 1950528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turner (echo "$VARS" | tr ' ' '\n') > $DSTDIR/$LIB.variables.txt 1960528f4d870022e4c3ee4e32714a7ef88908e310fDavid 'Digit' Turnerdone 197