make-syscalls.sh 9.5 KB

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