1#!/bin/sh 2#===- lib/sanitizer_common/scripts/gen_dynamic_list.sh ---------------------===# 3# 4# The LLVM Compiler Infrastructure 5# 6# This file is distributed under the University of Illinois Open Source 7# License. See LICENSE.TXT for details. 8# 9#===------------------------------------------------------------------------===# 10# 11# Generates the list of functions that should be exported from sanitizer 12# runtimes. The output format is recognized by --dynamic-list linker option. 13# Usage: 14# gen_dynamic_list.sh libclang_rt.*san*.a [ files ... ] 15# 16#===------------------------------------------------------------------------===# 17 18usage() { 19 echo "usage: gen_dynamic_list.py [-h] [--version-list] [--extra EXTRA]" 20 echo " libraries [libraries ...]" 21} 22 23get_global_functions() { 24 # On PowerPC, nm prints function descriptors from .data section. 25 $my_file $1 | grep -q "PowerPC" 26 if [ $? -eq 0 ]; then 27 export func_symbols="T|W|D" 28 else 29 export func_symbols="T|W" 30 fi 31 32 $my_nm $1 > $tmpfile1 33 if [ $? -ne 0 ]; then 34 printf 'Error calling: %s %s... bailing out\n' "$my_nm" "$1" 35 exit 1 36 fi 37 38 $my_awk '{if(NF == 3 && $2 ~ ENVIRON["func_symbols"]){print $3}}' \ 39 $tmpfile1 >> $tmpfile2 40} 41 42version_list= 43extra= 44 45tmpfile1=`mktemp /tmp/${0##*/}.XXXXXX` || exit 1 46tmpfile2=`mktemp /tmp/${0##*/}.XXXXXX` || exit 1 47 48trap "rm -f $tmpfile1 $tmpfile2" EXIT 49 50my_nm=${NM:-nm} 51my_awk=${AWK:-awk} 52my_file=${FILE:-file} 53 54while :; do 55 case $1 in 56 -h|--help) 57 usage 58 exit 59 ;; 60 --extra) 61 if [ "x$2" = "x" ]; then 62 usage 63 printf 'Error missing argument for the option\n' 64 else 65 extra=$2 66 shift 67 fi 68 ;; 69 --extra=?*) 70 extra=${1#*=} 71 ;; 72 --extra=) 73 usage 74 printf 'Error missing argument: %s\n' "$1" 75 ;; 76 --version-list) 77 version_list=1 78 ;; 79 --) 80 shift 81 break 82 ;; 83 -?*) 84 usage 85 printf 'Error parsing argument: %s\n' "$1" 86 ;; 87 *) 88 if [ "x$1" = "x" ]; then 89 break 90 else 91 get_global_functions "$1" 92 fi 93 ;; 94 esac 95 shift 96done 97 98export version_list 99 100cat $tmpfile2 > /tmp/A 101 102$my_awk " 103BEGIN { 104 # operator new[](unsigned long) 105 new_delete[\"_Znam\"] = 1 106 new_delete[\"_ZnamRKSt9nothrow_t\"] = 1 107 # operator new(unsigned long) 108 new_delete[\"_Znwm\"] = 1 109 new_delete[\"_ZnwmRKSt9nothrow_t\"] = 1 110 # operator new[](unsigned int) 111 new_delete[\"_Znaj\"] = 1 112 new_delete[\"_ZnajRKSt9nothrow_t\"] = 1 113 # operator new(unsigned int) 114 new_delete[\"_Znwj\"] = 1 115 new_delete[\"_ZnwjRKSt9nothrow_t\"] = 1 116 # operator new(unsigned long, std::align_val_t) 117 new_delete[\"_ZnwmSt11align_val_t\"] = 1 118 new_delete[\"_ZnwmSt11align_val_tRKSt9nothrow_t\"] = 1 119 # operator new(unsigned int, std::align_val_t) 120 new_delete[\"_ZnwjSt11align_val_t\"] = 1 121 new_delete[\"_ZnwjSt11align_val_tRKSt9nothrow_t\"] = 1 122 # operator new[](unsigned long, std::align_val_t) 123 new_delete[\"_ZnamSt11align_val_t\"] = 1 124 new_delete[\"_ZnamSt11align_val_tRKSt9nothrow_t\"] = 1 125 # operator new[](unsigned int, std::align_val_t) 126 new_delete[\"_ZnajSt11align_val_t\"] = 1 127 new_delete[\"_ZnajSt11align_val_tRKSt9nothrow_t\"] = 1 128 # operator delete[](void *) 129 new_delete[\"_ZdaPv\"] = 1 130 new_delete[\"_ZdaPvRKSt9nothrow_t\"] = 1 131 # operator delete(void *) 132 new_delete[\"_ZdlPv\"] = 1 133 new_delete[\"_ZdlPvRKSt9nothrow_t\"] = 1 134 # operator delete[](void*, unsigned long) 135 new_delete[\"_ZdaPvm\"] = 1 136 # operator delete(void*, unsigned long) 137 new_delete[\"_ZdlPvm\"] = 1 138 # operator delete[](void*, unsigned int) 139 new_delete[\"_ZdaPvj\"] = 1 140 # operator delete(void*, unsigned int) 141 new_delete[\"_ZdlPvj\"] = 1 142 # operator delete(void*, std::align_val_t) 143 new_delete[\"_ZdlPvSt11align_val_t\"] = 1 144 new_delete[\"_ZdlPvSt11align_val_tRKSt9nothrow_t\"] = 1 145 # operator delete[](void*, std::align_val_t) 146 new_delete[\"_ZdaPvSt11align_val_t\"] = 1 147 new_delete[\"_ZdaPvSt11align_val_tRKSt9nothrow_t\"] = 1 148 # operator delete(void*, unsigned long, std::align_val_t) 149 new_delete[\"_ZdlPvmSt11align_val_t\"] = 1 150 # operator delete[](void*, unsigned long, std::align_val_t) 151 new_delete[\"_ZdaPvmSt11align_val_t\"] = 1 152 # operator delete(void*, unsigned int, std::align_val_t) 153 new_delete[\"_ZdlPvjSt11align_val_t\"] = 1 154 # operator delete[](void*, unsigned int, std::align_val_t) 155 new_delete[\"_ZdaPvjSt11align_val_t\"] = 1 156 157 versioned_functions[\"memcpy\"] = 1 158 versioned_functions[\"pthread_attr_getaffinity_np\"] = 1 159 versioned_functions[\"pthread_cond_broadcast\"] = 1 160 versioned_functions[\"pthread_cond_destroy\"] = 1 161 versioned_functions[\"pthread_cond_init\"] = 1 162 versioned_functions[\"pthread_cond_signal\"] = 1 163 versioned_functions[\"pthread_cond_timedwait\"] = 1 164 versioned_functions[\"pthread_cond_wait\"] = 1 165 versioned_functions[\"realpath\"] = 1 166 versioned_functions[\"sched_getaffinity\"] = 1 167 168 len = 0 169} 170NR==FNR { 171 function_set[\$0] = 1 172 next 173} 174{ 175 if (\$0 in new_delete) { 176 result[len++] = \$0 177 next 178 } 179 if (substr(\$0, 1, 14) == \"__interceptor_\") { 180 result[len++] = \$0 181 # We have to avoid exporting the interceptors for versioned library 182 # functions due to gold internal error. 183 orig_name = substr(\$0, 15) 184 if ((orig_name in function_set) && 185 (ENVIRON["version_list"] == "1" || 186 !(orig_name in versioned_functions))) { 187 result[len++] = orig_name 188 } 189 next 190 } 191 if (substr(\$0, 1, 12) == \"__sanitizer_\") { 192 result[len++] = \$0 193 next 194 } 195} 196END { 197 for (i in result) { 198 print result[i] 199 } 200} 201" $tmpfile2 $tmpfile2 > $tmpfile1 202 203if [ "x$extra" != "x" ]; then 204 cat $extra >> $tmpfile1 205fi 206 207sort $tmpfile1 -o $tmpfile2 208 209echo "{" 210if [ "x$version_list" != "x" ]; then 211 echo "global:" 212fi 213$my_awk '{print " " $0 ";"}' $tmpfile2 214if [ "x$version_list" != "x" ]; then 215 echo "local:" 216 echo " *;" 217fi 218echo "};" 219