]>
Commit | Line | Data |
---|---|---|
48d0341c | 1 | #!/bin/sh |
aeb72b16 | 2 | |
795fbc9a | 3 | # Usage: make-syscalls.sh ../sysdeps/unix/common |
aeb72b16 RM |
4 | # Expects $sysdirs in environment. |
5 | ||
34173b51 | 6 | ############################################################################## |
105ce2ce CD |
7 | # |
8 | # This script is used to process the syscall data encoded in the various | |
9 | # syscalls.list files to produce thin assembly syscall wrappers around the | |
d5627550 | 10 | # appropriate OS syscall. See syscall-template.S for more details on the |
105ce2ce CD |
11 | # actual wrapper. |
12 | # | |
13 | # Syscall Signature Prefixes: | |
14 | # | |
105ce2ce CD |
15 | # E: errno and return value are not set by the call |
16 | # V: errno is not set, but errno or zero (success) is returned from the call | |
17 | # | |
18 | # Syscall Signature Key Letters: | |
34173b51 GM |
19 | # |
20 | # a: unchecked address (e.g., 1st arg to mmap) | |
4d928e8d | 21 | # b: non-NULL buffer (e.g., 2nd arg to read; return value from mmap) |
34173b51 GM |
22 | # B: optionally-NULL buffer (e.g., 4th arg to getsockopt) |
23 | # f: buffer of 2 ints (e.g., 4th arg to socketpair) | |
4d928e8d | 24 | # F: 3rd arg to fcntl |
34173b51 | 25 | # i: scalar (any signedness & size: int, long, long long, enum, whatever) |
4d928e8d | 26 | # I: 3rd arg to ioctl |
34173b51 GM |
27 | # n: scalar buffer length (e.g., 3rd arg to read) |
28 | # N: pointer to value/return scalar buffer length (e.g., 6th arg to recvfrom) | |
4d928e8d GM |
29 | # p: non-NULL pointer to typed object (e.g., any non-void* arg) |
30 | # P: optionally-NULL pointer to typed object (e.g., 2nd argument to gettimeofday) | |
31 | # s: non-NULL string (e.g., 1st arg to open) | |
32 | # S: optionally-NULL string (e.g., 1st arg to acct) | |
34173b51 | 33 | # v: vararg scalar (e.g., optional 3rd arg to open) |
e694422d | 34 | # V: byte-per-page vector (3rd arg to mincore) |
4d928e8d | 35 | # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4) |
105ce2ce | 36 | # |
34173b51 | 37 | |
34173b51 GM |
38 | ############################################################################## |
39 | ||
aeb72b16 RM |
40 | thisdir=$1; shift |
41 | ||
ab95290c UD |
42 | echo '' |
43 | echo \#### DIRECTORY = $thisdir | |
aeb72b16 RM |
44 | # Check each sysdep dir with higher priority than this one, |
45 | # and remove from $calls all the functions found in other dirs. | |
ab95290c UD |
46 | # Punt when we reach the directory defining these syscalls. |
47 | sysdirs=`for dir in $sysdirs; do | |
48 | test $dir = $thisdir && break; echo $dir; done` | |
49 | echo \#### SYSDIRS = $sysdirs | |
aeb72b16 | 50 | |
ab95290c UD |
51 | # Get the list of system calls for this directory. |
52 | calls=`sed 's/#.*$// | |
53 | /^[ ]*$/d' $thisdir/syscalls.list` | |
aeb72b16 | 54 | |
ab95290c UD |
55 | calls=`echo "$calls" | |
56 | while read file caller rest; do | |
aeb72b16 RM |
57 | # Remove each syscall that is implemented by a file in $dir. |
58 | # If a syscall specified a "caller", then only compile that syscall | |
59 | # if the caller function is also implemented in this directory. | |
ab95290c UD |
60 | srcfile=-; |
61 | for dir in $sysdirs; do | |
62 | { test -f $dir/$file.c && srcfile=$dir/$file.c; } || | |
63 | { test -f $dir/$file.S && srcfile=$dir/$file.S; } || | |
ab95290c UD |
64 | { test x$caller != x- && |
65 | { { test -f $dir/$caller.c && srcfile=$dir/$caller.c; } || | |
46259bec | 66 | { test -f $dir/$caller.S && srcfile=$dir/$caller.S; }; }; } && break; |
ab95290c UD |
67 | done; |
68 | echo $file $srcfile $caller $rest; | |
69 | done` | |
aeb72b16 RM |
70 | |
71 | # Any calls left? | |
72 | test -n "$calls" || exit 0 | |
73 | ||
09c0ee5f | 74 | # This uses variables $weak, $strong, and $any_versioned. |
c1487492 RM |
75 | emit_weak_aliases() |
76 | { | |
77 | # A shortcoming in the current gas is that it will only allow one | |
78 | # version-alias per symbol. So we create new strong aliases as needed. | |
79 | vcount="" | |
80 | ||
09c0ee5f RM |
81 | # We use the <shlib-compat.h> macros to generate the versioned aliases |
82 | # so that the version sets can be mapped to the configuration's | |
eed3e1eb JM |
83 | # minimum version set as per shlib-versions DEFAULT lines. If an |
84 | # entry point is specified in the form NAME@VERSION:OBSOLETED, a | |
85 | # SHLIB_COMPAT conditional is generated. | |
09c0ee5f RM |
86 | if [ $any_versioned = t ]; then |
87 | echo " echo '#include <shlib-compat.h>'; \\" | |
88 | fi | |
89 | ||
c1487492 RM |
90 | for name in $weak; do |
91 | case $name in | |
92 | *@@*) | |
93 | base=`echo $name | sed 's/@@.*//'` | |
09c0ee5f | 94 | ver=`echo $name | sed 's/.*@@//;s/\./_/g'` |
4f41c682 | 95 | echo " echo '#if IS_IN (libc)'; \\" |
c1487492 RM |
96 | if test -z "$vcount" ; then |
97 | source=$strong | |
98 | vcount=1 | |
99 | else | |
100 | source="${strong}_${vcount}" | |
101 | vcount=`expr $vcount + 1` | |
102 | echo " echo 'strong_alias ($strong, $source)'; \\" | |
103 | fi | |
09c0ee5f | 104 | echo " echo 'versioned_symbol (libc, $source, $base, $ver)'; \\" |
8d8f2279 | 105 | echo " echo '#else'; \\" |
5c5c0dd7 | 106 | echo " echo 'weak_alias ($strong, $base)'; \\" |
8d8f2279 | 107 | echo " echo '#endif'; \\" |
c1487492 RM |
108 | ;; |
109 | *@*) | |
110 | base=`echo $name | sed 's/@.*//'` | |
09c0ee5f | 111 | ver=`echo $name | sed 's/.*@//;s/\./_/g'` |
eed3e1eb JM |
112 | case $ver in |
113 | *:*) | |
114 | compat_ver=${ver#*:} | |
115 | ver=${ver%%:*} | |
116 | compat_cond=" && SHLIB_COMPAT (libc, $ver, $compat_ver)" | |
117 | ;; | |
118 | *) | |
119 | compat_cond= | |
120 | ;; | |
121 | esac | |
122 | echo " echo '#if defined SHARED && IS_IN (libc)$compat_cond'; \\" | |
c1487492 RM |
123 | if test -z "$vcount" ; then |
124 | source=$strong | |
125 | vcount=1 | |
126 | else | |
127 | source="${strong}_${vcount}" | |
128 | vcount=`expr $vcount + 1` | |
129 | echo " echo 'strong_alias ($strong, $source)'; \\" | |
130 | fi | |
09c0ee5f | 131 | echo " echo 'compat_symbol (libc, $source, $base, $ver)'; \\" |
8d8f2279 | 132 | echo " echo '#endif'; \\" |
c1487492 RM |
133 | ;; |
134 | !*) | |
135 | name=`echo $name | sed 's/.//'` | |
136 | echo " echo 'strong_alias ($strong, $name)'; \\" | |
c21d37de | 137 | echo " echo 'hidden_def ($name)'; \\" |
c1487492 RM |
138 | ;; |
139 | *) | |
140 | echo " echo 'weak_alias ($strong, $name)'; \\" | |
c21d37de | 141 | echo " echo 'hidden_weak ($name)'; \\" |
c1487492 RM |
142 | ;; |
143 | esac | |
144 | done | |
145 | } | |
146 | ||
147 | ||
aeb72b16 | 148 | # Emit rules to compile the syscalls remaining in $calls. |
34173b51 GM |
149 | echo "$calls" | |
150 | while read file srcfile caller syscall args strong weak; do | |
ab95290c | 151 | |
c1487492 RM |
152 | vdso_syscall= |
153 | case x"$syscall" in | |
154 | *:*@*) | |
155 | vdso_syscall="${syscall#*:}" | |
156 | syscall="${syscall%:*}" | |
157 | ;; | |
158 | esac | |
159 | ||
7944bd34 RM |
160 | case x"$syscall" in |
161 | x-) callnum=_ ;; | |
162 | *) | |
34173b51 GM |
163 | # Figure out if $syscall is defined with a number in syscall.h. |
164 | callnum=- | |
165 | eval `{ echo "#include <sysdep.h>"; | |
ab95290c | 166 | echo "callnum=SYS_ify ($syscall)"; } | |
7aba050d UD |
167 | $asm_CPP -D__OPTIMIZE__ - | |
168 | sed -n -e "/^callnum=.*$syscall/d" \ | |
169 | -e "/^\(callnum=\)[ ]*\(.*\)/s//\1'\2'/p"` | |
7944bd34 RM |
170 | ;; |
171 | esac | |
ab95290c | 172 | |
036e46b6 RM |
173 | noerrno=0 |
174 | errval=0 | |
86b2dc40 | 175 | case $args in |
036e46b6 RM |
176 | E*) noerrno=1; args=`echo $args | sed 's/E:\?//'`;; |
177 | V*) errval=1; args=`echo $args | sed 's/V:\?//'`;; | |
86b2dc40 UD |
178 | esac |
179 | ||
ab95290c UD |
180 | # Derive the number of arguments from the argument signature |
181 | case $args in | |
182 | [0-9]) nargs=$args;; | |
183 | ?:) nargs=0;; | |
184 | ?:?) nargs=1;; | |
185 | ?:??) nargs=2;; | |
186 | ?:???) nargs=3;; | |
187 | ?:????) nargs=4;; | |
188 | ?:?????) nargs=5;; | |
189 | ?:??????) nargs=6;; | |
5785c39f GM |
190 | ?:???????) nargs=7;; |
191 | ?:????????) nargs=8;; | |
192 | ?:?????????) nargs=9;; | |
ab95290c | 193 | esac |
aeb72b16 | 194 | |
ab95290c UD |
195 | # Make sure only the first syscall rule is used, if multiple dirs |
196 | # define the same syscall. | |
34173b51 GM |
197 | echo '' |
198 | echo "#### CALL=$file NUMBER=$callnum ARGS=$args SOURCE=$srcfile" | |
199 | ||
6fef930c AS |
200 | # If there are versioned aliases the entry is only generated for the |
201 | # shared library, unless it is a default version. | |
09c0ee5f | 202 | any_versioned=f |
6fef930c AS |
203 | shared_only=f |
204 | case $weak in | |
09c0ee5f RM |
205 | *@@*) any_versioned=t ;; |
206 | *@*) any_versioned=t shared_only=t ;; | |
6fef930c AS |
207 | esac |
208 | ||
f5361098 | 209 | case x$srcfile"$callnum" in |
d8e94af6 RM |
210 | x--) |
211 | # Undefined callnum for an extra syscall. | |
212 | if [ x$caller != x- ]; then | |
036e46b6 | 213 | if [ $noerrno != 0 ]; then |
d8e94af6 RM |
214 | echo >&2 "$0: no number for $fileno, no-error syscall ($strong $weak)" |
215 | exit 2 | |
216 | fi | |
217 | echo "unix-stub-syscalls += $strong $weak" | |
218 | fi | |
219 | ;; | |
ab95290c UD |
220 | x*-) ;; ### Do nothing for undefined callnum |
221 | x-*) | |
222 | echo "ifeq (,\$(filter $file,\$(unix-syscalls)))" | |
aeb72b16 | 223 | |
6fef930c | 224 | if test $shared_only = t; then |
ef030f7f UD |
225 | # The versioned symbols are only in the shared library. |
226 | echo "ifneq (,\$(filter .os,\$(object-suffixes)))" | |
6fef930c | 227 | fi |
aeb72b16 RM |
228 | # Accumulate the list of syscall files for this directory. |
229 | echo "unix-syscalls += $file" | |
230 | test x$caller = x- || echo "unix-extra-syscalls += $file" | |
231 | ||
232 | # Emit a compilation rule for this syscall. | |
6fef930c | 233 | if test $shared_only = t; then |
ef030f7f | 234 | # The versioned symbols are only in the shared library. |
c1487492 RM |
235 | echo "shared-only-routines += $file" |
236 | test -n "$vdso_syscall" || echo "\$(objpfx)${file}.os: \\" | |
6fef930c | 237 | else |
c1487492 RM |
238 | object_suffixes='$(object-suffixes)' |
239 | test -z "$vdso_syscall" || object_suffixes='$(object-suffixes-noshared)' | |
ef030f7f | 240 | echo "\ |
363a641b | 241 | \$(foreach p,\$(sysd-rules-targets),\ |
c1487492 | 242 | \$(foreach o,${object_suffixes},\$(objpfx)\$(patsubst %,\$p,$file)\$o)): \\" |
6fef930c | 243 | fi |
7944bd34 | 244 | |
036e46b6 | 245 | echo " \$(..)sysdeps/unix/make-syscalls.sh" |
7944bd34 RM |
246 | case x"$callnum" in |
247 | x_) | |
248 | echo "\ | |
3d855f75 | 249 | \$(make-target-directory) |
7944bd34 RM |
250 | (echo '/* Dummy module requested by syscalls.list */'; \\" |
251 | ;; | |
252 | x*) | |
253 | echo "\ | |
adee0e1f | 254 | \$(make-target-directory) |
036e46b6 RM |
255 | (echo '#define SYSCALL_NAME $syscall'; \\ |
256 | echo '#define SYSCALL_NARGS $nargs'; \\ | |
96a15749 | 257 | echo '#define SYSCALL_SYMBOL $strong'; \\ |
96a15749 RM |
258 | echo '#define SYSCALL_NOERRNO $noerrno'; \\ |
259 | echo '#define SYSCALL_ERRVAL $errval'; \\ | |
036e46b6 | 260 | echo '#include <syscall-template.S>'; \\" |
7944bd34 RM |
261 | ;; |
262 | esac | |
aeb72b16 | 263 | |
da2d1bc5 | 264 | # Append any weak aliases or versions defined for this syscall function. |
c1487492 | 265 | emit_weak_aliases |
aeb72b16 RM |
266 | |
267 | # And finally, pipe this all into the compiler. | |
363a641b RM |
268 | echo ' ) | $(compile-syscall) '"\ |
269 | \$(foreach p,\$(patsubst %$file,%,\$(basename \$(@F))),\$(\$(p)CPPFLAGS))" | |
aeb72b16 | 270 | |
c1487492 RM |
271 | if test -n "$vdso_syscall"; then |
272 | # In the shared library, we're going to emit an IFUNC using a vDSO function. | |
273 | # $vdso_syscall looks like "name@KERNEL_X.Y" where "name" is the symbol | |
274 | # name in the vDSO and KERNEL_X.Y is its symbol version. | |
275 | vdso_symbol="${vdso_syscall%@*}" | |
276 | vdso_symver="${vdso_syscall#*@}" | |
0a834dde | 277 | vdso_symver=`echo "$vdso_symver" | sed 's/\./_/g'` |
95b07fbc AZ |
278 | cat <<EOF |
279 | ||
c1487492 | 280 | \$(foreach p,\$(sysd-rules-targets),\$(objpfx)\$(patsubst %,\$p,$file).os): \\ |
d9efd775 | 281 | \$(..)sysdeps/unix/make-syscalls.sh |
c1487492 | 282 | \$(make-target-directory) |
bfb0deb3 JM |
283 | (echo '#define ${strong} __redirect_${strong}'; \\ |
284 | echo '#include <dl-vdso.h>'; \\ | |
285 | echo '#undef ${strong}'; \\ | |
286 | echo '#define vdso_ifunc_init() \\'; \\ | |
287 | echo ' PREPARE_VERSION_KNOWN (symver, ${vdso_symver})'; \\ | |
288 | echo '__ifunc (__redirect_${strong}, ${strong},'; \\ | |
289 | echo ' _dl_vdso_vsym ("${vdso_symbol}", &symver), void,'; \\ | |
290 | echo ' vdso_ifunc_init)'; \\ | |
95b07fbc | 291 | EOF |
c21d37de | 292 | # This is doing "hidden_def (${strong})", but the compiler |
c1487492 RM |
293 | # doesn't know that we've defined ${strong} in the same file, so |
294 | # we can't do it the normal way. | |
95b07fbc AZ |
295 | cat <<EOF |
296 | echo 'asm (".globl __GI_${strong}");'; \\ | |
297 | echo 'asm ("__GI_${strong} = ${strong}");'; \\ | |
298 | EOF | |
c1487492 | 299 | emit_weak_aliases |
95b07fbc AZ |
300 | cat <<EOF |
301 | ) | \$(compile-stdin.c) \ | |
302 | \$(foreach p,\$(patsubst %$file,%,\$(basename \$(@F))),\$(\$(p)CPPFLAGS)) | |
303 | EOF | |
c1487492 RM |
304 | fi |
305 | ||
6fef930c | 306 | if test $shared_only = t; then |
ef030f7f UD |
307 | # The versioned symbols are only in the shared library. |
308 | echo endif | |
6fef930c | 309 | fi |
ef030f7f | 310 | |
ab95290c UD |
311 | echo endif |
312 | ;; | |
313 | esac | |
314 | ||
aeb72b16 | 315 | done |