makesyscalls.sh revision 1.145.4.1 1 # $NetBSD: makesyscalls.sh,v 1.145.4.1 2015/04/06 15:18:20 skrll Exp $
2 #
3 # Copyright (c) 1994, 1996, 2000 Christopher G. Demetriou
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # 3. All advertising materials mentioning features or use of this software
15 # must display the following acknowledgement:
16 # This product includes software developed for the NetBSD Project
17 # by Christopher G. Demetriou.
18 # 4. The name of the author may not be used to endorse or promote products
19 # derived from this software without specific prior written permission
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 # @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93
33
34 set -e
35
36 case $# in
37 2) ;;
38 *) echo "Usage: $0 config-file input-file" 1>&2
39 exit 1
40 ;;
41 esac
42
43 # the config file sets the following variables:
44 # sysalign check for alignment of off_t/dev_t/time_t
45 # sysnames the syscall names file
46 # sysnumhdr the syscall numbers file
47 # syssw the syscall switch file
48 # sysarghdr the syscall argument struct definitions
49 # compatopts those syscall types that are for 'compat' syscalls
50 # switchname the name for the 'struct sysent' we define
51 # namesname the name for the 'const char *[]' we define
52 # constprefix the prefix for the system call constants
53 # registertype the type for register_t
54 # nsysent the size of the sysent table
55 # sys_nosys [optional] name of function called for unsupported
56 # syscalls, if not sys_nosys()
57 # maxsysargs [optiona] the maximum number or arguments
58 #
59 # NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'SYSLIBCOMPAT'.
60
61 # source the config file.
62 sys_nosys="sys_nosys" # default is sys_nosys(), if not specified otherwise
63 maxsysargs=8 # default limit is 8 (32bit) arguments
64 systrace="/dev/null"
65 rumpcalls="/dev/null"
66 rumpcallshdr="/dev/null"
67 rumpsysmap="/dev/null"
68 rumpsysent="rumpsysent.tmp"
69 rumpnoflags="\n\t\t.sy_flags = SYCALL_NOSYS,"
70 rumpnosys="(sy_call_t *)rumpns_enosys"
71 rumpnomodule="(sy_call_t *)rumpns_sys_nomodule"
72
73 case $1 in
74 /*) . $1;;
75 *) . ./$1;;
76 esac
77
78 # tmp files:
79 sysdcl="sysent.dcl"
80 sysprotos="sys.protos"
81 syscompat_pref="sysent."
82 sysent="sysent.switch"
83 sysnamesbottom="sysnames.bottom"
84 rumptypes="rumphdr.types"
85 rumpprotos="rumphdr.protos"
86 systracetmp="systrace.$$"
87 systraceret="systraceret.$$"
88
89 trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom $rumpsysent $rumptypes $rumpprotos $systracetmp $systraceret" 0
90
91 # Awk program (must support nawk extensions)
92 # Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
93 awk=${AWK:-awk}
94
95 # Does this awk have a "toupper" function?
96 have_toupper="$($awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null)"
97
98 # If this awk does not define "toupper" then define our own.
99 if [ "$have_toupper" = TRUE ] ; then
100 # Used awk (GNU awk or nawk) provides it
101 toupper=
102 else
103 # Provide our own toupper()
104 toupper='
105 function toupper(str) {
106 _toupper_cmd = "echo "str" |tr a-z A-Z"
107 _toupper_cmd | getline _toupper_str;
108 close(_toupper_cmd);
109 return _toupper_str;
110 }'
111 fi
112
113 # before handing it off to awk, make a few adjustments:
114 # (1) insert spaces around {, }, (, ), *, and commas.
115 # (2) get rid of any and all dollar signs (so that rcs id use safe)
116 #
117 # The awk script will deal with blank lines and lines that
118 # start with the comment character (';').
119
120 sed -e '
121 s/\$//g
122 :join
123 /\\$/{a\
124
125 N
126 s/\\\n//
127 b join
128 }
129 2,${
130 /^#/!s/\([{}()*,|]\)/ \1 /g
131 }
132 ' < $2 | $awk "
133 $toupper
134 BEGIN {
135 # Create a NetBSD tag that does not get expanded when checking
136 # this script out of CVS. (This part of the awk script is in a
137 # shell double-quoted string, so the backslashes are eaten by
138 # the shell.)
139 tag = \"\$\" \"NetBSD\" \"\$\"
140
141 # to allow nested #if/#else/#endif sets
142 savedepth = 0
143 # to track already processed syscalls
144
145 sysnames = \"$sysnames\"
146 sysprotos = \"$sysprotos\"
147 sysnumhdr = \"$sysnumhdr\"
148 sysarghdr = \"$sysarghdr\"
149 sysarghdrextra = \"$sysarghdrextra\"
150 systrace = \"$systrace\"
151 systracetmp = \"$systracetmp\"
152 systraceret = \"$systraceret\"
153 rumpcalls = \"$rumpcalls\"
154 rumpcallshdr = \"$rumpcallshdr\"
155 rumpsysent = \"$rumpsysent\"
156 rumpsysmap = \"$rumpsysmap\"
157 switchname = \"$switchname\"
158 namesname = \"$namesname\"
159 constprefix = \"$constprefix\"
160 registertype = \"$registertype\"
161 sysalign=\"$sysalign\"
162 if (!registertype) {
163 registertype = \"register_t\"
164 }
165 nsysent = \"$nsysent\"
166
167 sysdcl = \"$sysdcl\"
168 syscompat_pref = \"$syscompat_pref\"
169 sysent = \"$sysent\"
170 sysnamesbottom = \"$sysnamesbottom\"
171 rumpprotos = \"$rumpprotos\"
172 rumptypes = \"$rumptypes\"
173 sys_nosys = \"$sys_nosys\"
174 maxsysargs = \"$maxsysargs\"
175 rumpnoflags=\"$rumpnoflags\"
176 rumpnosys=\"$rumpnosys\"
177 rumpnomodule=\"$rumpnomodule\"
178 infile = \"$2\"
179
180 compatopts = \"$compatopts\"
181 "'
182
183 if (rumpcalls != "/dev/null")
184 haverumpcalls = 1
185
186 printf "/* %s */\n\n", tag > sysdcl
187 printf "/*\n * System call switch table.\n *\n" > sysdcl
188 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
189
190 ncompat = split(compatopts,compat)
191 for (i = 1; i <= ncompat; i++) {
192 compat_upper[i] = toupper(compat[i])
193
194 printf "\n#ifdef %s\n", compat_upper[i] > sysent
195 printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
196 compat[i] > sysent
197 printf "#else\n" > sysent
198 printf "#define %s(func) %s\n", compat[i], sys_nosys > sysent
199 printf "#endif\n" > sysent
200 }
201
202 printf "\n#define\ts(type)\tsizeof(type)\n" > sysent
203 printf "#define\tn(type)\t(sizeof(type)/sizeof (%s))\n", registertype > sysent
204 printf "#define\tns(type)\t.sy_narg = n(type), .sy_argsize = s(type)\n\n", registertype > sysent
205 printf "struct sysent %s[] = {\n",switchname > sysent
206
207 printf "/* %s */\n\n", tag > sysnames
208 printf "/*\n * System call names.\n *\n" > sysnames
209 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
210
211 printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
212 if (haverumpcalls)
213 printf("#ifndef RUMP_CLIENT\n") > sysprotos
214
215 printf "/* %s */\n\n", tag > sysnumhdr
216 printf "/*\n * System call numbers.\n *\n" > sysnumhdr
217 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
218
219 printf "/* %s */\n\n", tag > sysarghdr
220 printf "/*\n * System call argument lists.\n *\n" > sysarghdr
221 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
222
223 printf "/* %s */\n\n", tag > rumpcalls
224 printf "/*\n * System call vector and marshalling for rump.\n *\n" > rumpcalls
225 printf " * DO NOT EDIT-- this file is automatically generated.\n" > rumpcalls
226
227 printf "/* %s */\n\n", tag > rumpcallshdr
228 printf "/*\n * System call protos in rump namespace.\n *\n" > rumpcallshdr
229 printf " * DO NOT EDIT-- this file is automatically generated.\n" > rumpcallshdr
230
231 printf "/* %s */\n\n", tag > systrace
232 printf "/*\n * System call argument to DTrace register array converstion.\n *\n" > systrace
233 printf " * DO NOT EDIT-- this file is automatically generated.\n" > systrace
234 }
235 NR == 1 {
236 sub(/ $/, "")
237 printf " * created from%s\n */\n\n", $0 > sysdcl
238 printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > sysdcl
239
240 printf " * created from%s\n */\n\n", $0 > sysnames
241 printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > sysnames
242
243 printf " * created from%s\n */\n\n", $0 > rumpcalls
244 printf "#ifdef RUMP_CLIENT\n" > rumpcalls
245 printf "#include <rump/rumpuser_port.h>\n" > rumpcalls
246 printf "#endif /* RUMP_CLIENT */\n\n" > rumpcalls
247 printf "#include <sys/param.h>\n\n" > rumpcalls
248 printf "#ifdef __NetBSD__\n" > rumpcalls
249 printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > rumpcalls
250
251 printf "#include <sys/fstypes.h>\n" > rumpcalls
252 printf "#include <sys/proc.h>\n" > rumpcalls
253 printf "#endif /* __NetBSD__ */\n\n" > rumpcalls
254 printf "#ifdef RUMP_CLIENT\n" > rumpcalls
255 printf "#include <errno.h>\n" > rumpcalls
256 printf "#include <stdint.h>\n" > rumpcalls
257 printf "#include <stdlib.h>\n" > rumpcalls
258 printf "#include <string.h>\n\n" > rumpcalls
259 printf "#include <srcsys/syscall.h>\n" > rumpcalls
260 printf "#include <srcsys/syscallargs.h>\n\n" > rumpcalls
261 printf "#include <rump/rumpclient.h>\n\n" > rumpcalls
262 printf "#define rsys_syscall(num, data, dlen, retval)\t\\\n" > rumpcalls
263 printf " rumpclient_syscall(num, data, dlen, retval)\n" > rumpcalls
264 printf "#define rsys_seterrno(error) errno = error\n" > rumpcalls
265 printf "#else\n" > rumpcalls
266 printf "#include <sys/syscall.h>\n" > rumpcalls
267 printf "#include <sys/syscallargs.h>\n\n" > rumpcalls
268 printf "#include <sys/syscallvar.h>\n\n" > rumpcalls
269 printf "#include <rump/rumpuser.h>\n" > rumpcalls
270 printf "#include \"rump_private.h\"\n\n" > rumpcalls
271 printf "#define rsys_syscall(num, data, dlen, retval)\t\\\n" > rumpcalls
272 printf " rump_syscall(num, data, dlen, retval)\n\n" > rumpcalls
273 printf "#define rsys_seterrno(error) rumpuser_seterrno(error)\n" \
274 > rumpcalls
275 printf "#endif\n\n" > rumpcalls
276
277 printf "#ifndef RUMP_KERNEL_IS_LIBC\n" > rumpcalls
278 printf "#define RUMP_SYS_COMPAT\n" > rumpcalls
279 printf "#endif\n\n" > rumpcalls
280
281 printf "#if\tBYTE_ORDER == BIG_ENDIAN\n" > rumpcalls
282 printf "#define SPARG(p,k)\t((p)->k.be.datum)\n" > rumpcalls
283 printf "#else /* LITTLE_ENDIAN, I hope dearly */\n" > rumpcalls
284 printf "#define SPARG(p,k)\t((p)->k.le.datum)\n" > rumpcalls
285 printf "#endif\n\n" > rumpcalls
286 printf "\nvoid rumpns_sys_nomodule(void);\n" > rumpcalls
287
288 printf "\n#ifndef RUMP_CLIENT\n" > rumpsysent
289 printf "int rumpns_enosys(void);\n" > rumpsysent
290 printf "#define\ts(type)\tsizeof(type)\n" > rumpsysent
291 printf "#define\tn(type)\t(sizeof(type)/sizeof (%s))\n", registertype > rumpsysent
292 printf "#define\tns(type)\tn(type), s(type)\n\n", registertype > rumpsysent
293 printf "struct sysent rump_sysent[] = {\n" > rumpsysent
294
295 # System call names are included by userland (kdump(1)), so
296 # hide the include files from it.
297 printf "#if defined(_KERNEL_OPT)\n" > sysnames
298
299 printf "#endif /* _KERNEL_OPT */\n\n" > sysnamesbottom
300 printf "const char *const %s[] = {\n",namesname > sysnamesbottom
301
302 printf " * created from%s\n */\n\n", $0 > sysnumhdr
303 printf "#ifndef _" constprefix "SYSCALL_H_\n" > sysnumhdr
304 printf "#define _" constprefix "SYSCALL_H_\n\n" > sysnumhdr
305
306 printf " * created from%s\n */\n\n", $0 > sysarghdr
307 printf "#ifndef _" constprefix "SYSCALLARGS_H_\n" > sysarghdr
308 printf "#define _" constprefix "SYSCALLARGS_H_\n\n" > sysarghdr
309
310 printf " * created from%s\n */\n\n", $0 > rumpcallshdr
311 printf "#ifndef _RUMP_RUMP_SYSCALLS_H_\n" > rumpcallshdr
312 printf "#define _RUMP_RUMP_SYSCALLS_H_\n\n" > rumpcallshdr
313 printf "#ifdef _KERNEL\n" > rumpcallshdr
314 printf "#error Interface not supported inside kernel\n" > rumpcallshdr
315 printf "#endif /* _KERNEL */\n\n" > rumpcallshdr
316 printf "#include <rump/rump_syscalls_compat.h>\n\n" > rumpcallshdr
317
318 printf "%s", sysarghdrextra > sysarghdr
319 # Write max number of system call arguments to both headers
320 printf("#define\t%sMAXSYSARGS\t%d\n\n", constprefix, maxsysargs) \
321 > sysnumhdr
322 printf("#define\t%sMAXSYSARGS\t%d\n\n", constprefix, maxsysargs) \
323 > sysarghdr
324 printf "#undef\tsyscallarg\n" > sysarghdr
325 printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr
326 printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr
327 printf "\t\t%s pad;\t\t\t\t\t\t\\\n", registertype > sysarghdr
328 printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr
329 printf "\t\tstruct { /* LINTED zero array dimension */\t\t\\\n" \
330 > sysarghdr
331 printf "\t\t\tint8_t pad[ /* CONSTCOND */\t\t\t\\\n" > sysarghdr
332 printf "\t\t\t\t(sizeof (%s) < sizeof (x))\t\\\n", \
333 registertype > sysarghdr
334 printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr
335 printf "\t\t\t\t: sizeof (%s) - sizeof (x)];\t\\\n", \
336 registertype > sysarghdr
337 printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr
338 printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr
339 printf "\t}\n" > sysarghdr
340 printf("\n#undef check_syscall_args\n") >sysarghdr
341 printf("#define check_syscall_args(call) /*LINTED*/ \\\n" \
342 "\ttypedef char call##_check_args" \
343 "[sizeof (struct call##_args) \\\n" \
344 "\t\t<= %sMAXSYSARGS * sizeof (%s) ? 1 : -1];\n", \
345 constprefix, registertype) >sysarghdr
346
347 printf " * This file is part of the DTrace syscall provider.\n */\n\n" > systrace
348 printf "static void\nsystrace_args(register_t sysnum, const void *params, uintptr_t *uarg, size_t *n_args)\n{\n" > systrace
349 printf "\tintptr_t *iarg = (intptr_t *)uarg;\n" > systrace
350 printf "\tswitch (sysnum) {\n" > systrace
351
352 printf "static void\nsystrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)\n{\n\tconst char *p = NULL;\n" > systracetmp
353 printf "\tswitch (sysnum) {\n" > systracetmp
354
355 printf "static void\nsystrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)\n{\n\tconst char *p = NULL;\n" > systraceret
356 printf "\tswitch (sysnum) {\n" > systraceret
357
358 # compat types from syscalls.master. this is slightly ugly,
359 # but given that we have so few compats from over 17 years,
360 # a more complicated solution is not currently warranted.
361 uncompattypes["struct timeval50"] = "struct timeval";
362 uncompattypes["struct timespec50"] = "struct timespec";
363 uncompattypes["struct stat30"] = "struct stat";
364
365 next
366 }
367 NF == 0 || $1 ~ /^;/ {
368 next
369 }
370 $0 ~ /^%%$/ {
371 intable = 1
372 next
373 }
374 $1 ~ /^#[ ]*include/ {
375 print > sysdcl
376 print > sysnames
377 next
378 }
379 $1 ~ /^#/ && !intable {
380 print > sysdcl
381 print > sysnames
382 next
383 }
384 $1 ~ /^#/ && intable {
385 if ($1 ~ /^#[ ]*if/) {
386 savedepth++
387 savesyscall[savedepth] = syscall
388 }
389 if ($1 ~ /^#[ ]*else/) {
390 if (savedepth <= 0) {
391 printf("%s: line %d: unbalanced #else\n", \
392 infile, NR)
393 exit 1
394 }
395 syscall = savesyscall[savedepth]
396 }
397 if ($1 ~ /^#[ ]*endif/) {
398 if (savedepth <= 0) {
399 printf("%s: line %d: unbalanced #endif\n", \
400 infile, NR)
401 exit 1
402 }
403 savedepth--
404 }
405 print > sysent
406 print > sysarghdr
407 print > sysnumhdr
408 print > sysprotos
409 print > sysnamesbottom
410 print > systrace
411 print > systracetmp
412 print > systraceret
413
414 # XXX: technically we do not want to have conditionals in rump,
415 # but it is easier to just let the cpp handle them than try to
416 # figure out what we want here in this script
417 print > rumpsysent
418 next
419 }
420 syscall != $1 {
421 printf "%s: line %d: syscall number out of sync at %d\n", \
422 infile, NR, syscall
423 printf "line is:\n"
424 print
425 exit 1
426 }
427 function parserr(was, wanted) {
428 printf "%s: line %d: unexpected %s (expected <%s>)\n", \
429 infile, NR, was, wanted
430 printf "line is:\n"
431 print
432 exit 1
433 }
434 function fillerpsysent(syscall, flags, name, comment) {
435 return sprintf("\t{%s\n\t\t.sy_call = %s,\n\t},\t\t/* %d = filler */",\
436 flags, name, syscall, comment);
437 }
438 function parseline() {
439 f=3 # toss number and type
440 if ($2 == "INDIR")
441 sycall_flags="SYCALL_INDIRECT"
442 else
443 sycall_flags="0"
444 if ($NF != "}") {
445 funcalias=$NF
446 end=NF-1
447 } else {
448 funcalias=""
449 end=NF
450 }
451 if ($f == "INDIR") { # allow for "NOARG INDIR"
452 sycall_flags = "SYCALL_INDIRECT | " sycall_flags
453 f++
454 }
455 if ($f == "MODULAR") { # registered at runtime
456 modular = 1
457 f++
458 } else {
459 modular = 0;
460 }
461 if ($f == "RUMP") {
462 rumpable = 1
463 f++
464 } else {
465 rumpable = 0
466 }
467 if ($f ~ /^[a-z0-9_]*$/) { # allow syscall alias
468 funcalias=$f
469 f++
470 }
471 if ($f != "{")
472 parserr($f, "{")
473 f++
474 if ($end != "}")
475 parserr($end, "}")
476 end--
477 if ($end != ";")
478 parserr($end, ";")
479 end--
480 if ($end != ")")
481 parserr($end, ")")
482 end--
483
484 returntype = oldf = "";
485 do {
486 if (returntype != "" && oldf != "*")
487 returntype = returntype" ";
488 returntype = returntype$f;
489 oldf = $f;
490 f++
491 } while ($f != "|" && f < (end-1))
492 if (f == (end - 1)) {
493 parserr($f, "function argument definition (maybe \"|\"?)");
494 }
495 f++
496
497 fprefix=$f
498 f++
499 if ($f != "|") {
500 parserr($f, "function compat delimiter (maybe \"|\"?)");
501 }
502 f++
503
504 fcompat=""
505 if ($f != "|") {
506 fcompat=$f
507 f++
508 }
509
510 if ($f != "|") {
511 parserr($f, "function name delimiter (maybe \"|\"?)");
512 }
513 f++
514 fbase=$f
515
516 # pipe is special in how to returns its values.
517 # So just generate it manually if present.
518 if (rumpable == 1 && fbase == "pipe") {
519 rumpable = 0;
520 rumphaspipe = 1;
521 }
522
523 if (fcompat != "") {
524 funcname=fprefix "___" fbase "" fcompat
525 } else {
526 funcname=fprefix "_" fbase
527 }
528 if (returntype == "quad_t" || returntype == "off_t") {
529 if (sycall_flags == "0")
530 sycall_flags = "SYCALL_RET_64";
531 else
532 sycall_flags = "SYCALL_RET_64 | " sycall_flags;
533 }
534
535 if (funcalias == "") {
536 funcalias=funcname
537 sub(/^([^_]+_)*sys_/, "", funcalias)
538 realname=fbase
539 } else {
540 realname=funcalias
541 }
542 rumpfname=realname "" fcompat
543 f++
544
545 if ($f != "(")
546 parserr($f, "(")
547 f++
548
549 argc=0;
550 argalign=0;
551 if (f == end) {
552 if ($f != "void")
553 parserr($f, "argument definition")
554 isvarargs = 0;
555 varargc = 0;
556 argtype[0]="void";
557 return
558 }
559
560 # some system calls (open() and fcntl()) can accept a variable
561 # number of arguments. If syscalls accept a variable number of
562 # arguments, they must still have arguments specified for
563 # the remaining argument "positions," because of the way the
564 # kernel system call argument handling works.
565 #
566 # Indirect system calls, e.g. syscall(), are exceptions to this
567 # rule, since they are handled entirely by machine-dependent code
568 # and do not need argument structures built.
569
570 isvarargs = 0;
571 args64 = 0;
572 ptr = 0;
573 while (f <= end) {
574 if ($f == "...") {
575 f++;
576 isvarargs = 1;
577 varargc = argc;
578 continue;
579 }
580 argc++
581 argtype[argc]=""
582 oldf=""
583 while (f < end && $(f+1) != ",") {
584 if (argtype[argc] != "" && oldf != "*")
585 argtype[argc] = argtype[argc]" ";
586 argtype[argc] = argtype[argc]$f;
587 oldf = $f;
588 f++
589 }
590 if (argtype[argc] == "")
591 parserr($f, "argument definition")
592 if (argtype[argc] == "off_t" \
593 || argtype[argc] == "dev_t" \
594 || argtype[argc] == "time_t") {
595 if ((argalign % 2) != 0 && sysalign &&
596 funcname != "sys_posix_fadvise") # XXX for now
597 parserr($f, "a padding argument")
598 } else {
599 argalign++;
600 }
601 if (argtype[argc] == "quad_t" || argtype[argc] == "off_t" \
602 || argtype[argc] == "dev_t" || argtype[argc] == "time_t") {
603 if (sycall_flags == "0")
604 sycall_flags = "SYCALL_ARG"argc-1"_64";
605 else
606 sycall_flags = "SYCALL_ARG"argc-1"_64 | " sycall_flags;
607 args64++;
608 }
609 if (index(argtype[argc], "*") != 0 && ptr == 0) {
610 if (sycall_flags == "0")
611 sycall_flags = "SYCALL_ARG_PTR";
612 else
613 sycall_flags = "SYCALL_ARG_PTR | " sycall_flags;
614 ptr = 1;
615 }
616 argname[argc]=$f;
617 f += 2; # skip name, and any comma
618 }
619 if (args64 > 0)
620 sycall_flags = "SYCALL_NARGS64_VAL("args64") | " sycall_flags;
621 # must see another argument after varargs notice.
622 if (isvarargs) {
623 if (argc == varargc)
624 parserr($f, "argument definition")
625 } else
626 varargc = argc;
627 }
628
629 function printproto(wrap) {
630 printf("/* syscall: \"%s%s\" ret: \"%s\" args:", wrap, funcalias,
631 returntype) > sysnumhdr
632 for (i = 1; i <= varargc; i++)
633 printf(" \"%s\"", argtype[i]) > sysnumhdr
634 if (isvarargs)
635 printf(" \"...\"") > sysnumhdr
636 printf(" */\n") > sysnumhdr
637 printf("#define\t%s%s%s\t%d\n\n", constprefix, wrap, funcalias,
638 syscall) > sysnumhdr
639
640 # rumpalooza
641 if (!rumpable)
642 return
643
644 # accumulate fbases we have seen. we want the last
645 # occurence for the default __RENAME()
646 seen = funcseen[fbase]
647 funcseen[fbase] = rumpfname
648 # special case for mknod as type of last argument changed from
649 # uint32_t to dev_t
650 if ((seen && fbase != "mknod") || (!seen && fbase == "mknod"))
651 return
652
653 printf("%s rump_sys_%s(", returntype, realname) > rumpprotos
654
655 for (i = 1; i < varargc; i++)
656 if (argname[i] != "PAD")
657 printf("%s, ", uncompattype(argtype[i])) > rumpprotos
658
659 if (isvarargs)
660 printf("%s, ...)", uncompattype(argtype[varargc]))>rumpprotos
661 else
662 printf("%s)", uncompattype(argtype[argc])) > rumpprotos
663
664 printf(" __RENAME(RUMP_SYS_RENAME_%s)", toupper(fbase))> rumpprotos
665 printf(";\n") > rumpprotos
666
667 # generate forward-declares for types, apart from the
668 # braindead typedef jungle we cannot easily handle here
669 for (i = 1; i <= varargc; i++) {
670 type=uncompattype(argtype[i])
671 sub("const ", "", type)
672 ntype=type
673 sub(" *\\*.*", "", ntype);
674 if (!typeseen[ntype] && \
675 match(type, "struct") && match(type, "\\*")) {
676 typeseen[ntype] = 1
677 printf("%s;\n", ntype) > rumptypes
678 }
679 }
680 }
681
682 function printrumpsysent(insysent, compatwrap) {
683 if (modular) {
684 fn = rumpnomodule
685 flags = rumpnoflags
686 } else {
687 fn = rumpnosys
688 flags = ""
689 }
690 if (!insysent) {
691 printf("\t{%s\n\t\t.sy_call = %s,\n},\t\t/* %d = %s */\n", \
692 flags, fn, syscall, funcalias) > rumpsysent
693 return
694 }
695
696 printf("\t{") > rumpsysent
697 if (argc != 0) {
698 printf("\n\t\tns(struct %ssys_%s_args),", compatwrap_, funcalias) > rumpsysent
699 }
700
701 printf("\n\t\t.sy_call = %s,\n\t},", fn) > rumpsysent
702 printf("\t\t/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > rumpsysent
703 }
704
705 function iscompattype(type) {
706 for (var in uncompattypes) {
707 if (match(type, var)) {
708 return 1
709 }
710 }
711
712 return 0
713 }
714
715 function uncompattype(type) {
716 for (var in uncompattypes) {
717 if (match(type, var)) {
718 sub(var, uncompattypes[var], type)
719 return type
720 }
721 }
722
723 return type
724 }
725
726 function printrumpsysmap(syscall, wfn, funcalias, rumpentry) {
727 printf("%-4d %-22s %-18s %s\n",
728 syscall, wfn, funcalias, rumpentry) > rumpsysmap
729 }
730
731 function putsystrace(type, compatwrap_) {
732 printf("\t/* %s */\n\tcase %d: {\n", funcname, syscall) > systrace
733 printf("\t/* %s */\n\tcase %d:\n", funcname, syscall) > systracetmp
734 printf("\t/* %s */\n\tcase %d:\n", funcname, syscall) > systraceret
735 if (argc > 0) {
736 printf("\t\tswitch(ndx) {\n") > systracetmp
737 printf("\t\tstruct %s%s_args *p = params;\n", compatwrap_, funcname) > systrace
738 for (i = 1; i <= argc; i++) {
739 arg = argtype[i]
740 sub("__restrict$", "", arg)
741 printf("\t\tcase %d:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n", i - 1, arg) > systracetmp
742 if (arg ~ /.*p_t$/ || arg ~ /.*p$/ || arg ~ /.*_t_p$/ ||
743 arg ~ /.*_pointer_t$/)
744 printf("\t\tuarg[%d] = (intptr_t) SCARG(p, %s).i32; /* %s */\n", \
745 i - 1, \
746 argname[i], arg) > systrace
747 else if (index(arg, "*") > 0 || arg == "caddr_t")
748 printf("\t\tuarg[%d] = (intptr_t) SCARG(p, %s); /* %s */\n", \
749 i - 1, \
750 argname[i], arg) > systrace
751 else if (substr(arg, 1, 1) == "u" || arg == "size_t")
752 printf("\t\tuarg[%d] = SCARG(p, %s); /* %s */\n", \
753 i - 1, \
754 argname[i], arg) > systrace
755 else
756 printf("\t\tiarg[%d] = SCARG(p, %s); /* %s */\n", \
757 i - 1, \
758 argname[i], arg) > systrace
759 }
760 printf("\t\tdefault:\n\t\t\tbreak;\n\t\t};\n") > systracetmp
761
762 printf("\t\tif (ndx == 0 || ndx == 1)\n") > systraceret
763 printf("\t\t\tp = \"%s\";\n", returntype) > systraceret
764 printf("\t\tbreak;\n") > systraceret
765 }
766 printf("\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", argc) > systrace
767 printf("\t\tbreak;\n") > systracetmp
768 }
769
770 function putent(type, compatwrap) {
771 # output syscall declaration for switch table.
772 if (compatwrap == "")
773 compatwrap_ = ""
774 else
775 compatwrap_ = compatwrap "_"
776 if (argc == 0)
777 arg_type = "void";
778 else {
779 arg_type = "struct " compatwrap_ funcname "_args";
780 }
781 putsystrace(type, compatwrap_)
782 proto = "int\t" compatwrap_ funcname "(struct lwp *, const " \
783 arg_type " *, register_t *);\n"
784 if (sysmap[proto] != 1) {
785 sysmap[proto] = 1;
786 print proto > sysprotos;
787 }
788
789 # output syscall switch entry
790 printf("\t{") > sysent
791 if (argc != 0) {
792 printf("\n\t\tns(struct %s%s_args),", compatwrap_, funcname) > sysent
793 }
794 if (modular)
795 wfn = "sys_nomodule";
796 else if (compatwrap == "")
797 wfn = funcname;
798 else
799 wfn = compatwrap "(" funcname ")";
800 wfn_cast="(sy_call_t *)" wfn
801 if (sycall_flags != "0")
802 flags = "\n\t\t.sy_flags = " sycall_flags ","
803 else
804 flags = ""
805 printf("%s\n\t\t.sy_call = %s\n\t},", flags, wfn_cast) > sysent
806 printf("\t\t/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > sysent
807
808 # output syscall name for names table
809 printf("\t/* %3d */\t\"%s%s\",\n", syscall, compatwrap_, funcalias) \
810 > sysnamesbottom
811
812 # output syscall number of header, if appropriate
813 if (type == "STD" || type == "NOARGS" || type == "INDIR" || \
814 type == "NOERR") {
815 # output a prototype, to be used to generate lint stubs in
816 # libc.
817 printproto("")
818 } else if (type == "COMPAT" || type == "EXTERN") {
819 # Just define the syscall number with a comment. These
820 # may be used by compatibility stubs in libc.
821 printproto(compatwrap_)
822 }
823
824 # output syscall argument structure, if it has arguments
825 if (argc != 0) {
826 printf("\n") > sysarghdr
827 if (haverumpcalls && !rumpable)
828 printf("#ifndef RUMP_CLIENT\n") > sysarghdr
829 printf("struct %s%s_args", compatwrap_, funcname) > sysarghdr
830 if (type != "NOARGS") {
831 print " {" >sysarghdr;
832 for (i = 1; i <= argc; i++)
833 printf("\tsyscallarg(%s) %s;\n", argtype[i],
834 argname[i]) > sysarghdr
835 printf "}" >sysarghdr;
836 }
837 printf(";\n") > sysarghdr
838 if (type != "NOARGS" && type != "INDIR") {
839 printf("check_syscall_args(%s%s)\n", compatwrap_,
840 funcname) >sysarghdr
841 }
842 if (haverumpcalls && !rumpable)
843 printf("#endif /* !RUMP_CLIENT */\n") > sysarghdr
844 }
845
846 if (!rumpable) {
847 if (funcname == "sys_pipe" && rumphaspipe == 1) {
848 insysent = 1
849 printrumpsysmap(syscall,
850 funcname, funcalias, "rump_sys_pipe")
851 } else {
852 insysent = 0
853 }
854 } else {
855 insysent = 1
856 }
857 printrumpsysent(insysent, compatwrap)
858
859 # output rump marshalling code if necessary
860 if (!rumpable) {
861 return
862 }
863
864 printrumpsysmap(syscall, wfn, funcalias, "rump___sysimpl_" rumpfname)
865
866 printf("\n") > rumpcalls
867
868 if (compatwrap)
869 printf("#ifdef RUMP_SYS_COMPAT\n") > rumpcalls
870
871 # need a local prototype, we export the re-re-named one in .h
872 printf("%s rump___sysimpl_%s(", returntype, rumpfname) \
873 > rumpcalls
874 for (i = 1; i < argc; i++) {
875 if (argname[i] != "PAD")
876 printf("%s, ", uncompattype(argtype[i])) > rumpcalls
877 }
878 printf("%s);", uncompattype(argtype[argc])) > rumpcalls
879
880 printf("\n%s\nrump___sysimpl_%s(", returntype, rumpfname) > rumpcalls
881 for (i = 1; i < argc; i++) {
882 if (argname[i] != "PAD")
883 printf("%s %s, ", uncompattype(argtype[i]), \
884 argname[i]) > rumpcalls
885 }
886 printf("%s %s)\n", uncompattype(argtype[argc]), argname[argc]) \
887 > rumpcalls
888 printf("{\n\tregister_t retval[2];\n") > rumpcalls
889 if (returntype != "void") {
890 if (type != "NOERR") {
891 printf("\tint error = 0;\n") > rumpcalls
892 }
893 # assume rumpcalls return only integral types
894 printf("\t%s rv = -1;\n", returntype) > rumpcalls
895 }
896
897 argarg = "NULL"
898 argsize = 0;
899 if (argc) {
900 argarg = "&callarg"
901 argsize = "sizeof(callarg)"
902 printf("\tstruct %s%s_args callarg;\n\n",compatwrap_,funcname) \
903 > rumpcalls
904 printf "\tmemset(&callarg, 0, sizeof(callarg));\n" > rumpcalls
905 for (i = 1; i <= argc; i++) {
906 if (argname[i] == "PAD") {
907 printf("\tSPARG(&callarg, %s) = 0;\n", \
908 argname[i]) > rumpcalls
909 } else {
910 if (iscompattype(argtype[i])) {
911 printf("\tSPARG(&callarg, %s) = " \
912 "(%s)%s;\n", argname[i], argtype[i], \
913 argname[i]) > rumpcalls
914 } else {
915 printf("\tSPARG(&callarg, %s) = %s;\n",\
916 argname[i], argname[i]) > rumpcalls
917 }
918 }
919 }
920 printf("\n") > rumpcalls
921 } else {
922 printf("\n") > rumpcalls
923 }
924 printf("\t") > rumpcalls
925 if (returntype != "void" && type != "NOERR")
926 printf("error = ") > rumpcalls
927 printf("rsys_syscall(%s%s%s, " \
928 "%s, %s, retval);\n", constprefix, compatwrap_, funcalias, \
929 argarg, argsize) > rumpcalls
930 if (type != "NOERR") {
931 printf("\trsys_seterrno(error);\n") > rumpcalls
932 printf("\tif (error == 0) {\n") > rumpcalls
933 indent="\t\t"
934 ending="\t}\n"
935 } else {
936 indent="\t"
937 ending=""
938 }
939 if (returntype != "void") {
940 printf("%sif (sizeof(%s) > sizeof(register_t))\n", \
941 indent, returntype) > rumpcalls
942 printf("%s\trv = *(%s *)retval;\n", \
943 indent, returntype) > rumpcalls
944 printf("%selse\n", indent, indent) > rumpcalls
945 printf("%s\trv = *retval;\n", indent, returntype) > rumpcalls
946 printf("%s", ending) > rumpcalls
947 printf("\treturn rv;\n") > rumpcalls
948 }
949 printf("}\n") > rumpcalls
950
951 printf("#ifdef RUMP_KERNEL_IS_LIBC\n") > rumpcalls
952
953 # create the bog-standard, non-renamed public name.
954 # this way we get e.g. select instead of just __select50
955 if (fcompat)
956 printf("__weak_alias(%s,rump___sysimpl_%s);\n", \
957 fbase, rumpfname) > rumpcalls
958
959 printf("__weak_alias(%s,rump___sysimpl_%s);\n", \
960 funcalias, rumpfname) > rumpcalls
961 printf("__weak_alias(_%s,rump___sysimpl_%s);\n", \
962 funcalias, rumpfname) > rumpcalls
963 printf("__strong_alias(_sys_%s,rump___sysimpl_%s);\n", \
964 funcalias, rumpfname) >rumpcalls
965
966 printf("#endif /* RUMP_KERNEL_IS_LIBC */\n") > rumpcalls
967
968 if (compatwrap)
969 printf("#endif /* RUMP_SYS_COMPAT */\n") > rumpcalls
970
971 }
972 $2 == "STD" || $2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" \
973 || $2 == "NOERR" {
974 parseline()
975 putent($2, "")
976 syscall++
977 next
978 }
979 $2 == "OBSOL" || $2 == "UNIMPL" || $2 == "EXCL" || $2 == "IGNORED" {
980 if ($2 == "OBSOL")
981 comment="obsolete"
982 else if ($2 == "EXCL")
983 comment="excluded"
984 else if ($2 == "IGNORED")
985 comment="ignored"
986 else
987 comment="unimplemented"
988 for (i = 3; i <= NF; i++)
989 comment=comment " " $i
990
991 if ($2 == "IGNORED")
992 sys_stub = "(sy_call_t *)nullop";
993 else
994 sys_stub = sys_nosys;
995
996 print fillerpsysent(syscall, "", sys_stub, comment) > sysent
997 print fillerpsysent(syscall, rumpnoflags, rumpnosys, comment) > rumpsysent
998 printf("\t/* %3d */\t\"#%d (%s)\",\n", syscall, syscall, comment) \
999 > sysnamesbottom
1000 if ($2 != "UNIMPL")
1001 printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
1002 syscall++
1003 next
1004 }
1005 $2 == "EXTERN" {
1006 parseline()
1007 putent("EXTERN", "")
1008 syscall++
1009 next
1010 }
1011 {
1012 for (i = 1; i <= ncompat; i++) {
1013 if ($2 == compat_upper[i]) {
1014 parseline();
1015 putent("COMPAT", compat[i])
1016 syscall++
1017 next
1018 }
1019 }
1020 printf("%s: line %d: unrecognized keyword %s\n", infile, NR, $2)
1021 exit 1
1022 }
1023 END {
1024 # output pipe() syscall with its special retval[2] handling
1025 if (rumphaspipe) {
1026 printf("int rump_sys_pipe(int *);\n") > rumpprotos
1027 printf("\nint rump_sys_pipe(int *);\n") > rumpcalls
1028 printf("int\nrump_sys_pipe(int *fd)\n{\n") > rumpcalls
1029 printf("\tregister_t retval[2];\n") > rumpcalls
1030 printf("\tint error = 0;\n") > rumpcalls
1031 printf("\n\terror = rsys_syscall(SYS_pipe, ") > rumpcalls
1032 printf("NULL, 0, retval);\n") > rumpcalls
1033 printf("\tif (error) {\n") > rumpcalls
1034 printf("\t\trsys_seterrno(error);\n") > rumpcalls
1035 printf("\t} else {\n\t\tfd[0] = retval[0];\n") > rumpcalls
1036 printf("\t\tfd[1] = retval[1];\n\t}\n") > rumpcalls
1037 printf("\treturn error ? -1 : 0;\n}\n") > rumpcalls
1038 printf("#ifdef RUMP_KERNEL_IS_LIBC\n") > rumpcalls
1039 printf("__weak_alias(pipe,rump_sys_pipe);\n") > rumpcalls
1040 printf("__weak_alias(_pipe,rump_sys_pipe);\n") > rumpcalls
1041 printf("__strong_alias(_sys_pipe,rump_sys_pipe);\n") > rumpcalls
1042 printf("#endif\n") > rumpcalls
1043 }
1044
1045 # print default rump syscall interfaces
1046 for (var in funcseen) {
1047 printf("#ifndef RUMP_SYS_RENAME_%s\n", \
1048 toupper(var)) > rumpcallshdr
1049 printf("#define RUMP_SYS_RENAME_%s rump___sysimpl_%s\n", \
1050 toupper(var), funcseen[var]) > rumpcallshdr
1051 printf("#endif\n\n") > rumpcallshdr
1052 }
1053
1054 maxsyscall = syscall
1055 if (nsysent) {
1056 if (syscall > nsysent) {
1057 printf("%s: line %d: too many syscalls [%d > %d]\n", infile, NR, syscall, nsysent)
1058 exit 1
1059 }
1060 while (syscall < nsysent) {
1061 print fillerpsysent(syscall, "", sys_nosys, "filler") > sysent
1062 print fillerpsysent(syscall, rumpnoflags, rumpnosys, "filler") > rumpsysent
1063 printf("\t/* %3d */\t\"# filler\",\n", syscall) \
1064 > sysnamesbottom
1065 syscall++
1066 }
1067 }
1068 printf("};\n") > sysent
1069 printf("};\n") > rumpsysent
1070 printf("CTASSERT(__arraycount(rump_sysent) == SYS_NSYSENT);\n") > rumpsysent
1071 printf("__strong_alias(rumpns_sysent,rump_sysent);\n") > rumpsysent
1072 printf("#endif /* RUMP_CLIENT */\n") > rumpsysent
1073 if (haverumpcalls)
1074 printf("#endif /* !RUMP_CLIENT */\n") > sysprotos
1075 printf("};\n") > sysnamesbottom
1076 printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, maxsyscall) > sysnumhdr
1077 if (nsysent)
1078 printf("#define\t%sNSYSENT\t%d\n", constprefix, nsysent) > sysnumhdr
1079 printf "\tdefault:\n\t\t*n_args = 0;\n\t\tbreak;\n\t};\n}\n" > systrace
1080 printf "\tdefault:\n\t\tbreak;\n\t};\n\tif (p != NULL)\n\t\tstrlcpy(desc, p, descsz);\n}\n" > systracetmp
1081 printf "\tdefault:\n\t\tbreak;\n\t};\n\tif (p != NULL)\n\t\tstrlcpy(desc, p, descsz);\n}\n" > systraceret
1082 } '
1083
1084 cat $sysprotos >> $sysarghdr
1085 echo "#endif /* _${constprefix}SYSCALL_H_ */" >> $sysnumhdr
1086 echo "#endif /* _${constprefix}SYSCALLARGS_H_ */" >> $sysarghdr
1087 printf "\n#endif /* _RUMP_RUMP_SYSCALLS_H_ */\n" >> $rumpprotos
1088 cat $sysdcl $sysent > $syssw
1089 cat $sysnamesbottom >> $sysnames
1090 cat $rumpsysent >> $rumpcalls
1091
1092 touch $rumptypes
1093 cat $rumptypes >> $rumpcallshdr
1094 echo >> $rumpcallshdr
1095 cat $rumpprotos >> $rumpcallshdr
1096
1097 #chmod 444 $sysnames $sysnumhdr $syssw
1098
1099 cat $systracetmp >> $systrace
1100 cat $systraceret >> $systrace
1101
1102 echo Generated following files:
1103 echo $sysarghdr $sysnumhdr $syssw $sysnames $systrace $rumpcalls $rumpcallshdr $rumpsysmap
1104