On Sun, Jul 09, 2023 at 01:29:58PM -0700, Andrew Hewus Fresh wrote: > Here is a patch to replace perl(1)'s use of syscall(2) with a dispatcher > that will call the libc function instead. > > I have to do some work on style before this is ready to commit, but it > should be ready for some testing. > > I don't currently plan on committing syscall_emulator.c because we need > to regenerate it each time as I'm not sure how to tie it into sys/kern's > `make syscalls` to only do it when things change. > > Looking for tests from folks who use syscall from perl as well as style > suggestions (like how do I correctly sort headers?) and maybe even > ways to enable additional syscalls.
Here's a new version, I think I addressed all of the feedback I got, although may have missed something. Hopefully it is easier to test with sthen@'s fix. Thanks miod@, espie@, sthen@, and especially gkoehler@ for a lot of excellent feedback. I'm sure there's still stuff missing and obvious problems that don't stand out to someone who writes a lot of perl. Starting Saturday I'm traveling for work for the week, so will probably be even less responsive than usual until I'm back. Index: gnu/usr.bin/perl/MANIFEST =================================================================== RCS file: /home/afresh1/OpenBSD-perl/OP/cvs/src/gnu/usr.bin/perl/MANIFEST,v retrieving revision 1.67 diff -u -p -a -u -p -r1.67 MANIFEST --- gnu/usr.bin/perl/MANIFEST 8 Jul 2023 14:18:35 -0000 1.67 +++ gnu/usr.bin/perl/MANIFEST 3 Aug 2023 04:34:38 -0000 @@ -6605,6 +6605,7 @@ t/op/svleak.pl Test file for svleak.t t/op/svleak.t See if stuff leaks SVs t/op/switch.t See if switches (given/when) work t/op/symbolcache.t See if undef/delete works on stashes with functions +t/op/syscall_emulator.t Tests that syscall works via the emulator t/op/sysio.t See if sysread and syswrite work t/op/taint.t See if tainting works t/op/threads.t Misc. tests for perl features with threads Index: gnu/usr.bin/perl/Makefile.SH =================================================================== RCS file: /home/afresh1/OpenBSD-perl/OP/cvs/src/gnu/usr.bin/perl/Makefile.SH,v retrieving revision 1.60 diff -u -p -a -u -p -r1.60 Makefile.SH --- gnu/usr.bin/perl/Makefile.SH 8 Jul 2023 14:18:35 -0000 1.60 +++ gnu/usr.bin/perl/Makefile.SH 3 Aug 2023 04:34:38 -0000 @@ -541,7 +541,7 @@ c1 = av.c scope.c op.c doop.c doio.c dum c2 = perly.c pp.c pp_hot.c pp_ctl.c pp_sys.c regcomp.c regexec.c utf8.c sv.c c3 = taint.c toke.c util.c deb.c run.c builtin.c universal.c pad.c globals.c keywords.c c4 = perlio.c numeric.c mathoms.c locale.c pp_pack.c pp_sort.c caretx.c dquote.c time64.c -c5 = $(mallocsrc) +c5 = $(mallocsrc) syscall_emulator.c !NO!SUBS! @@ -557,7 +557,7 @@ c = $(c1) $(c2) $(c3) $(c4) $(c5) minipe obj1 = $(mallocobj) gv$(OBJ_EXT) toke$(OBJ_EXT) perly$(OBJ_EXT) pad$(OBJ_EXT) regcomp$(OBJ_EXT) dump$(OBJ_EXT) util$(OBJ_EXT) mg$(OBJ_EXT) reentr$(OBJ_EXT) mro_core$(OBJ_EXT) keywords$(OBJ_EXT) builtin$(OBJ_EXT) obj2 = hv$(OBJ_EXT) av$(OBJ_EXT) run$(OBJ_EXT) pp_hot$(OBJ_EXT) sv$(OBJ_EXT) pp$(OBJ_EXT) scope$(OBJ_EXT) pp_ctl$(OBJ_EXT) pp_sys$(OBJ_EXT) -obj3 = doop$(OBJ_EXT) doio$(OBJ_EXT) regexec$(OBJ_EXT) utf8$(OBJ_EXT) taint$(OBJ_EXT) deb$(OBJ_EXT) globals$(OBJ_EXT) perlio$(OBJ_EXT) numeric$(OBJ_EXT) mathoms$(OBJ_EXT) locale$(OBJ_EXT) pp_pack$(OBJ_EXT) pp_sort$(OBJ_EXT) caretx$(OBJ_EXT) dquote$(OBJ_EXT) time64$(OBJ_EXT) +obj3 = doop$(OBJ_EXT) doio$(OBJ_EXT) regexec$(OBJ_EXT) utf8$(OBJ_EXT) taint$(OBJ_EXT) deb$(OBJ_EXT) globals$(OBJ_EXT) perlio$(OBJ_EXT) numeric$(OBJ_EXT) mathoms$(OBJ_EXT) locale$(OBJ_EXT) pp_pack$(OBJ_EXT) pp_sort$(OBJ_EXT) caretx$(OBJ_EXT) dquote$(OBJ_EXT) time64$(OBJ_EXT) syscall_emulator$(OBJ_EXT) # split the objects into 3 exclusive sets: those used by both miniperl and # perl, and those used by just one or the other. Doesn't include the Index: gnu/usr.bin/perl/Makefile.bsd-wrapper =================================================================== RCS file: /home/afresh1/OpenBSD-perl/OP/cvs/src/gnu/usr.bin/perl/Makefile.bsd-wrapper,v retrieving revision 1.113 diff -u -p -a -u -p -r1.113 Makefile.bsd-wrapper --- gnu/usr.bin/perl/Makefile.bsd-wrapper 15 Feb 2023 01:38:20 -0000 1.113 +++ gnu/usr.bin/perl/Makefile.bsd-wrapper 3 Aug 2023 04:34:38 -0000 @@ -39,11 +39,18 @@ cleandir: fi cd ${.CURDIR} && ${MAKE} -f Makefile.bsd-wrapper1 cleandir -all: config.sh +all: syscall_emulator.c config.sh cd ${.CURDIR} && exec ${MAKE} -f Makefile.bsd-wrapper1 perl.build cd ${.CURDIR} && exec ${MAKE} -f Makefile.bsd-wrapper1 mansrc.build install: cd ${.CURDIR} && exec ${MAKE} -f Makefile.bsd-wrapper1 install + + +syscall_emulator.c: gen_syscall_emulator.pl syscall_emulator.h /usr/include/sys/syscall.h /usr/include/sys/syscallargs.h + /usr/bin/perl $(.CURDIR)/gen_syscall_emulator.pl > $@ + +syscall_emulator.h: + ln -sf $(.CURDIR)/$@ $@ .include <bsd.obj.mk> Index: gnu/usr.bin/perl/config.over =================================================================== RCS file: /home/afresh1/OpenBSD-perl/OP/cvs/src/gnu/usr.bin/perl/config.over,v retrieving revision 1.22 diff -u -p -a -u -p -r1.22 config.over --- gnu/usr.bin/perl/config.over 5 Feb 2017 00:33:38 -0000 1.22 +++ gnu/usr.bin/perl/config.over 3 Aug 2023 04:34:38 -0000 @@ -64,3 +64,9 @@ myuname='openbsd' # force to use ranlib ranlib='ranlib' + +# Enable the syscall emulator, +# enabling syscall even if we don't have it +d_syscall=define +d_syscallproto=define + Index: gnu/usr.bin/perl/gen_syscall_emulator.pl =================================================================== RCS file: gnu/usr.bin/perl/gen_syscall_emulator.pl diff -N gnu/usr.bin/perl/gen_syscall_emulator.pl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/usr.bin/perl/gen_syscall_emulator.pl 3 Aug 2023 04:34:41 -0000 @@ -0,0 +1,360 @@ +#!/usr/bin/perl +# $OpenBSD$ # +use v5.36; +use autodie; + +# Copyright (c) 2023 Andrew Hewus Fresh <afre...@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +my $includes = '/usr/include'; + +# Because perl uses a long for every syscall argument, +# if we are building a syscall_emulator for use by perl, +# taking that into account make things work more consistently +# across different OpenBSD architectures. +# Unfortunately there doesn't appear to be an easy way +# to make everything work "the way it was". +use constant PERL_LONG_ARGS => 1; + +# See also /usr/src/sys/kern/syscalls.master +my %syscalls = parse_syscalls( + "$includes/sys/syscall.h", + "$includes/sys/syscallargs.h", +)->%*; +delete $syscalls{MAXSYSCALL}; # not an actual function + +# The ordered list of all the headers we need +my @headers = qw< + sys/syscall.h + stdarg.h + errno.h + + sys/socket.h + sys/event.h + sys/futex.h + sys/ioctl.h + sys/ktrace.h + sys/mman.h + sys/mount.h + sys/msg.h + sys/poll.h + sys/ptrace.h + sys/resource.h + sys/select.h + sys/sem.h + sys/shm.h + sys/stat.h + sys/sysctl.h + sys/time.h + sys/uio.h + sys/wait.h + + dirent.h + fcntl.h + sched.h + signal.h + stdlib.h + stdio.h + syslog.h + tib.h + time.h + unistd.h +>; + +foreach my $header (@headers) { + my $filename = "$includes/$header"; + open my $fh, '<', $filename; + my $content = do { local $/; readline $fh }; + close $fh; + + foreach my $name (sort keys %syscalls) { + my $s = $syscalls{$name}; + my $func_sig = find_func_sig($content, $name, $s); + + if (ref $func_sig) { + die "Multiple defs for $name <$header> <$s->{header}>" + if $s->{header}; + $s->{func} = $func_sig; + $s->{header} = $header; + } elsif ($func_sig) { + $s->{mismatched_sig} = "$func_sig <$header>"; + } + } +} + +say "/*\n * Generated from gen_syscall_emulator.pl\n */"; +say "#include <$_>" for @headers; +print <<"EOL"; +#include "syscall_emulator.h" + +long +syscall_emulator(int syscall, ...) +{ + long ret = 0; + va_list args; + va_start(args, syscall); + + switch(syscall) { +EOL + +foreach my $name ( + sort { $syscalls{$a}{id} <=> $syscalls{$b}{id} } keys %syscalls + ) { + my %s = %{ $syscalls{$name} }; + + # Some syscalls we can't emulate, so we comment those out. + $s{skip} //= "Indirect syscalls not supported" + if !$s{argtypes} && ($s{args}[-1] || '') eq '...'; + $s{skip} //= "Mismatched func: $s{mismatched_sig}" + if $s{mismatched_sig} and not $s{func}; + $s{skip} //= "No signature found in headers" + unless $s{header}; + + my $ret = $s{ret} eq 'void' ? '' : 'ret = '; + $ret .= '(long)' if $s{ret} eq 'void *'; + + my (@args, @defines); + my $argname = ''; + if ($s{argtypes}) { + if (@{ $s{argtypes} } > 1) { + @defines = map { + my $t = $_->{type}; + my $n = $_->{name}; + $n = "_$n" if $n eq $name; # link :-/ + push @args, $n; + PERL_LONG_ARGS + ? "$t $n = ($t)va_arg(args, long);" + : "$t $n = va_arg(args, $t);" + } @{ $s{argtypes} }; + } else { + if (@{ $s{argtypes} }) { + $argname = " // " . join ', ', + map { $_->{name} } + @{ $s{argtypes} }; + } + @args = map { "va_arg(args, $_->{type})" } + @{ $s{argtypes} }; + } + } else { + @args = @{ $s{args} }; + + # If we didn't find args in syscallargs.h but have args + # we don't know how to write our function. + $s{skip} //= "Not found in sys/syscallargs.h" + if @args; + } + + #my $header = $s{header} ? " <$s{header}>" : ''; + + my $indent = "\t"; + say "$indent/* $s{skip}" if $s{skip}; + + $indent .= ' *' if $s{skip}; + say "${indent} $s{signature} <sys/syscall.h>" + if $s{skip} && $s{skip} =~ /Mismatch/; + + my $brace = @defines ? " {" : ""; + say "${indent}case $s{define}:$brace"; # // $s{id}"; + say "${indent}\t$_" for @defines; + #say "${indent}\t// $s{signature}$header"; + say "${indent}\t$ret$name(" . join(', ', @args) . ");$argname"; + say "${indent}\tbreak;"; + say "${indent}}" if $brace; + + say "\t */" if $s{skip}; +} + +print <<"EOL"; + default: + ret = -1; + errno = ENOSYS; + } + va_end(args); + + return ret; +} +EOL + + +sub parse_syscalls($syscall, $args) +{ + my %s = parse_syscall_h($syscall)->%*; + + my %a = parse_syscallargs_h($args)->%*; + $s{$_}{argtypes} = $a{$_} for grep { $a{$_} } keys %s; + + return \%s; +} + +sub parse_syscall_h($filename) +{ + my %s; + open my $fh, '<', $filename; + while (readline $fh) { + if (m{^/\* + \s+ syscall: \s+ "(?<name>[^"]+)" + \s+ ret: \s+ "(?<ret> [^"]+)" + \s+ args: \s+ (?<args>.*?) + \s* \*/ + | + ^\#define \s+ (?<define>SYS_(?<name>\S+)) \s+ (?<id>\d+) + }x) + { + my $name = $+{name}; + $s{$name}{$_} = $+{$_} for keys %+; + $s{$name}{args} = [ $+{args} =~ /"(.*?)"/g ] + if exists $+{args}; + } + } + close $fh; + + foreach my $name (keys %s) { + my %d = %{ $s{$name} }; + next unless $d{ret}; # the MAXSYSCALL + + my $ret = $d{ret}; + my @args = @{ $d{args} || [] }; + @args = 'void' unless @args; + + if ($args[-1] ne '...') { + my @a; + for (@args) { + push @a, $_; + last if $_ eq '...'; + } + @args = @a; + } + + my $args = join ", ", @args; + $s{$name}{signature} = "$ret\t$name($args);" =~ s/\s+/ /gr; + #print " $s{$name}{signature}\n"; + } + + return \%s; +} + +sub parse_syscallargs_h($filename) +{ + my %args; + + open my $fh, '<', $filename; + while (readline $fh) { + if (my ($syscall) = /^struct \s+ sys_(\w+)_args \s+ \{/x) { + $args{$syscall} = []; + while (readline $fh) { + last if /^\s*\};\s*$/; + if (/syscallarg + \( (?<type> [^)]+ ) \) + \s+ (?<name> \w+ ) \s* ; + /x) { + push @{$args{$syscall}}, {%+}; + } + } + } + } + close $fh; + + return \%args; +} + +sub find_func_sig($content, $name, $s) +{ + my $re = $s->{re} //= qr{^ + (?<ret> \S+ (?: [^\S\n]+ \S+)? ) [^\S\n]* \n? + \b \Q$name\E \( (?<args> [^)]* ) \) + [^;]*; + }xms; + + $content =~ /$re/ || return !!0; + my $ret = $+{ret}; + my $args = $+{args}; + + for ($ret, $args) { + s/^\s+//; + s/\s+$//; + s/\s+/ /g; + } + + # The actual functions may have this extra annotation + $args =~ s/\*\s*__restrict/*/g; + + my %func_sig = ( ret => $ret, args => [ split /\s*,\s*/, $args ] ); + + return "$ret $name($args);" =~ s/\s+/ /gr + unless sigs_match($s, \%func_sig); + + return \%func_sig; +} + +# Tests whether two types are equivalent. +# Sometimes there are two ways to represent the same thing +# and it seems the functions and the syscalls +# differ a fair amount. +sub types_match($l, $r) +{ + state %m = ( + caddr_t => 'char *', + idtype_t => 'int', + nfds_t => 'u_int', + __off_t => 'off_t', + pid_t => 'int', + __size_t => 'u_long', + size_t => 'u_long', + 'unsigned int' => 'u_int', + 'unsigned long' => 'u_long', + ); + + $l //= '__undef__'; + $r //= '__undef__'; + + s/\b volatile \s+//x for $l, $r; + s/\b const \s+//x for $l, $r; + s/\s* \[\d*\] $/ \*/x for $l, $r; + + my ($f, $s) = sort { length($a) <=> length($b) } $l, $r; + if (index($s, $f) == 0) { + $s =~ s/^\Q$f\E\s*//; + if ( $s && $s =~ /^\w+$/ ) { + #warn "prefix ['$f', '$s']\n"; + s/\s*\Q$s\E$// for $l, $r; + } + } + + $l = $m{$l} //= $l; + $r = $m{$r} //= $r; + + return $l eq $r; +} + + +# Tests whether two function signatures match, +# expected to be left from syscall.h, right from the appopriate header. +sub sigs_match($l, $r) +{ + return !!0 unless types_match( $l->{ret}, $l->{ret} ); + + my @l_args = @{ $l->{args} || [] }; + my @r_args = @{ $r->{args} || [] }; + + for (\@l_args, \@r_args) { + @{$_} = 'void' unless @{$_}; + } + + for my $i ( 0 .. $#l_args ) { + return !!0 unless types_match($l_args[$i], $r_args[$i]); + last if $l_args[$i] eq '...'; + } + + return !!1; +} Index: gnu/usr.bin/perl/pp_sys.c =================================================================== RCS file: /home/afresh1/OpenBSD-perl/OP/cvs/src/gnu/usr.bin/perl/pp_sys.c,v retrieving revision 1.24 diff -u -p -a -u -p -r1.24 pp_sys.c --- gnu/usr.bin/perl/pp_sys.c 15 Feb 2023 01:36:13 -0000 1.24 +++ gnu/usr.bin/perl/pp_sys.c 3 Aug 2023 04:34:42 -0000 @@ -30,6 +30,8 @@ #define PERL_IN_PP_SYS_C #include "perl.h" #include "time64.h" +#include "syscall_emulator.h" +#define syscall syscall_emulator #ifdef I_SHADOW /* Shadow password support for solaris - p...@cs.umd.edu Index: gnu/usr.bin/perl/syscall_emulator.c =================================================================== RCS file: gnu/usr.bin/perl/syscall_emulator.c diff -N gnu/usr.bin/perl/syscall_emulator.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/usr.bin/perl/syscall_emulator.c 3 Aug 2023 04:34:43 -0000 @@ -0,0 +1,1420 @@ +/* + * Generated from gen_syscall_emulator.pl + */ +#include <sys/syscall.h> +#include <stdarg.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/event.h> +#include <sys/futex.h> +#include <sys/ioctl.h> +#include <sys/ktrace.h> +#include <sys/mman.h> +#include <sys/mount.h> +#include <sys/msg.h> +#include <sys/poll.h> +#include <sys/ptrace.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <fcntl.h> +#include <sched.h> +#include <signal.h> +#include <stdlib.h> +#include <stdio.h> +#include <syslog.h> +#include <tib.h> +#include <time.h> +#include <unistd.h> +#include "syscall_emulator.h" + +long +syscall_emulator(int syscall, ...) +{ + long ret = 0; + va_list args; + va_start(args, syscall); + + switch(syscall) { + /* Indirect syscalls not supported + *case SYS_syscall: + * ret = syscall(int, ...); + * break; + */ + case SYS_exit: + exit(va_arg(args, int)); // rval + break; + case SYS_fork: + ret = fork(); + break; + case SYS_read: { + int fd = (int)va_arg(args, long); + void * buf = (void *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + ret = read(fd, buf, nbyte); + break; + } + case SYS_write: { + int fd = (int)va_arg(args, long); + const void * buf = (const void *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + ret = write(fd, buf, nbyte); + break; + } + case SYS_open: { + const char * path = (const char *)va_arg(args, long); + int flags = (int)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = open(path, flags, mode); + break; + } + case SYS_close: + ret = close(va_arg(args, int)); // fd + break; + case SYS_getentropy: { + void * buf = (void *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + ret = getentropy(buf, nbyte); + break; + } + /* No signature found in headers + *case SYS___tfork: { + * const struct __tfork * param = (const struct __tfork *)va_arg(args, long); + * size_t psize = (size_t)va_arg(args, long); + * ret = __tfork(param, psize); + * break; + *} + */ + case SYS_link: { + const char * path = (const char *)va_arg(args, long); + const char * _link = (const char *)va_arg(args, long); + ret = link(path, _link); + break; + } + case SYS_unlink: + ret = unlink(va_arg(args, const char *)); // path + break; + case SYS_wait4: { + pid_t pid = (pid_t)va_arg(args, long); + int * status = (int *)va_arg(args, long); + int options = (int)va_arg(args, long); + struct rusage * rusage = (struct rusage *)va_arg(args, long); + ret = wait4(pid, status, options, rusage); + break; + } + case SYS_chdir: + ret = chdir(va_arg(args, const char *)); // path + break; + case SYS_fchdir: + ret = fchdir(va_arg(args, int)); // fd + break; + case SYS_mknod: { + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + dev_t dev = (dev_t)va_arg(args, long); + ret = mknod(path, mode, dev); + break; + } + case SYS_chmod: { + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = chmod(path, mode); + break; + } + case SYS_chown: { + const char * path = (const char *)va_arg(args, long); + uid_t uid = (uid_t)va_arg(args, long); + gid_t gid = (gid_t)va_arg(args, long); + ret = chown(path, uid, gid); + break; + } + /* No signature found in headers + *case SYS_break: + * ret = break(char *); + * break; + */ + case SYS_getdtablecount: + ret = getdtablecount(); + break; + case SYS_getrusage: { + int who = (int)va_arg(args, long); + struct rusage * rusage = (struct rusage *)va_arg(args, long); + ret = getrusage(who, rusage); + break; + } + case SYS_getpid: + ret = getpid(); + break; + case SYS_mount: { + const char * type = (const char *)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + int flags = (int)va_arg(args, long); + void * data = (void *)va_arg(args, long); + ret = mount(type, path, flags, data); + break; + } + case SYS_unmount: { + const char * path = (const char *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = unmount(path, flags); + break; + } + case SYS_setuid: + ret = setuid(va_arg(args, uid_t)); // uid + break; + case SYS_getuid: + ret = getuid(); + break; + case SYS_geteuid: + ret = geteuid(); + break; + case SYS_ptrace: { + int req = (int)va_arg(args, long); + pid_t pid = (pid_t)va_arg(args, long); + caddr_t addr = (caddr_t)va_arg(args, long); + int data = (int)va_arg(args, long); + ret = ptrace(req, pid, addr, data); + break; + } + case SYS_recvmsg: { + int s = (int)va_arg(args, long); + struct msghdr * msg = (struct msghdr *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = recvmsg(s, msg, flags); + break; + } + case SYS_sendmsg: { + int s = (int)va_arg(args, long); + const struct msghdr * msg = (const struct msghdr *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = sendmsg(s, msg, flags); + break; + } + case SYS_recvfrom: { + int s = (int)va_arg(args, long); + void * buf = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int flags = (int)va_arg(args, long); + struct sockaddr * from = (struct sockaddr *)va_arg(args, long); + socklen_t * fromlenaddr = (socklen_t *)va_arg(args, long); + ret = recvfrom(s, buf, len, flags, from, fromlenaddr); + break; + } + case SYS_accept: { + int s = (int)va_arg(args, long); + struct sockaddr * name = (struct sockaddr *)va_arg(args, long); + socklen_t * anamelen = (socklen_t *)va_arg(args, long); + ret = accept(s, name, anamelen); + break; + } + case SYS_getpeername: { + int fdes = (int)va_arg(args, long); + struct sockaddr * asa = (struct sockaddr *)va_arg(args, long); + socklen_t * alen = (socklen_t *)va_arg(args, long); + ret = getpeername(fdes, asa, alen); + break; + } + case SYS_getsockname: { + int fdes = (int)va_arg(args, long); + struct sockaddr * asa = (struct sockaddr *)va_arg(args, long); + socklen_t * alen = (socklen_t *)va_arg(args, long); + ret = getsockname(fdes, asa, alen); + break; + } + case SYS_access: { + const char * path = (const char *)va_arg(args, long); + int amode = (int)va_arg(args, long); + ret = access(path, amode); + break; + } + case SYS_chflags: { + const char * path = (const char *)va_arg(args, long); + u_int flags = (u_int)va_arg(args, long); + ret = chflags(path, flags); + break; + } + case SYS_fchflags: { + int fd = (int)va_arg(args, long); + u_int flags = (u_int)va_arg(args, long); + ret = fchflags(fd, flags); + break; + } + case SYS_sync: + sync(); + break; + /* No signature found in headers + *case SYS_msyscall: { + * void * addr = (void *)va_arg(args, long); + * size_t len = (size_t)va_arg(args, long); + * ret = msyscall(addr, len); + * break; + *} + */ + case SYS_stat: { + const char * path = (const char *)va_arg(args, long); + struct stat * ub = (struct stat *)va_arg(args, long); + ret = stat(path, ub); + break; + } + case SYS_getppid: + ret = getppid(); + break; + case SYS_lstat: { + const char * path = (const char *)va_arg(args, long); + struct stat * ub = (struct stat *)va_arg(args, long); + ret = lstat(path, ub); + break; + } + case SYS_dup: + ret = dup(va_arg(args, int)); // fd + break; + case SYS_fstatat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + struct stat * buf = (struct stat *)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = fstatat(fd, path, buf, flag); + break; + } + case SYS_getegid: + ret = getegid(); + break; + case SYS_profil: { + caddr_t samples = (caddr_t)va_arg(args, long); + size_t size = (size_t)va_arg(args, long); + u_long offset = (u_long)va_arg(args, long); + u_int scale = (u_int)va_arg(args, long); + ret = profil(samples, size, offset, scale); + break; + } + case SYS_ktrace: { + const char * fname = (const char *)va_arg(args, long); + int ops = (int)va_arg(args, long); + int facs = (int)va_arg(args, long); + pid_t pid = (pid_t)va_arg(args, long); + ret = ktrace(fname, ops, facs, pid); + break; + } + case SYS_sigaction: { + int signum = (int)va_arg(args, long); + const struct sigaction * nsa = (const struct sigaction *)va_arg(args, long); + struct sigaction * osa = (struct sigaction *)va_arg(args, long); + ret = sigaction(signum, nsa, osa); + break; + } + case SYS_getgid: + ret = getgid(); + break; + /* Mismatched func: int sigprocmask(int, const sigset_t *, sigset_t *); <signal.h> + * int sigprocmask(int, sigset_t); <sys/syscall.h> + *case SYS_sigprocmask: { + * int how = (int)va_arg(args, long); + * sigset_t mask = (sigset_t)va_arg(args, long); + * ret = sigprocmask(how, mask); + * break; + *} + */ + case SYS_mmap: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int prot = (int)va_arg(args, long); + int flags = (int)va_arg(args, long); + int fd = (int)va_arg(args, long); + off_t pos = (off_t)va_arg(args, long); + ret = (long)mmap(addr, len, prot, flags, fd, pos); + break; + } + case SYS_setlogin: + ret = setlogin(va_arg(args, const char *)); // namebuf + break; + case SYS_acct: + ret = acct(va_arg(args, const char *)); // path + break; + /* Mismatched func: int sigpending(sigset_t *); <signal.h> + * int sigpending(void); <sys/syscall.h> + *case SYS_sigpending: + * ret = sigpending(); + * break; + */ + case SYS_fstat: { + int fd = (int)va_arg(args, long); + struct stat * sb = (struct stat *)va_arg(args, long); + ret = fstat(fd, sb); + break; + } + case SYS_ioctl: { + int fd = (int)va_arg(args, long); + u_long com = (u_long)va_arg(args, long); + void * data = (void *)va_arg(args, long); + ret = ioctl(fd, com, data); + break; + } + case SYS_reboot: + ret = reboot(va_arg(args, int)); // opt + break; + case SYS_revoke: + ret = revoke(va_arg(args, const char *)); // path + break; + case SYS_symlink: { + const char * path = (const char *)va_arg(args, long); + const char * link = (const char *)va_arg(args, long); + ret = symlink(path, link); + break; + } + case SYS_readlink: { + const char * path = (const char *)va_arg(args, long); + char * buf = (char *)va_arg(args, long); + size_t count = (size_t)va_arg(args, long); + ret = readlink(path, buf, count); + break; + } + case SYS_execve: { + const char * path = (const char *)va_arg(args, long); + char *const * argp = (char *const *)va_arg(args, long); + char *const * envp = (char *const *)va_arg(args, long); + ret = execve(path, argp, envp); + break; + } + case SYS_umask: + ret = umask(va_arg(args, mode_t)); // newmask + break; + case SYS_chroot: + ret = chroot(va_arg(args, const char *)); // path + break; + case SYS_getfsstat: { + struct statfs * buf = (struct statfs *)va_arg(args, long); + size_t bufsize = (size_t)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = getfsstat(buf, bufsize, flags); + break; + } + case SYS_statfs: { + const char * path = (const char *)va_arg(args, long); + struct statfs * buf = (struct statfs *)va_arg(args, long); + ret = statfs(path, buf); + break; + } + case SYS_fstatfs: { + int fd = (int)va_arg(args, long); + struct statfs * buf = (struct statfs *)va_arg(args, long); + ret = fstatfs(fd, buf); + break; + } + case SYS_fhstatfs: { + const fhandle_t * fhp = (const fhandle_t *)va_arg(args, long); + struct statfs * buf = (struct statfs *)va_arg(args, long); + ret = fhstatfs(fhp, buf); + break; + } + case SYS_vfork: + ret = vfork(); + break; + case SYS_gettimeofday: { + struct timeval * tp = (struct timeval *)va_arg(args, long); + struct timezone * tzp = (struct timezone *)va_arg(args, long); + ret = gettimeofday(tp, tzp); + break; + } + case SYS_settimeofday: { + const struct timeval * tv = (const struct timeval *)va_arg(args, long); + const struct timezone * tzp = (const struct timezone *)va_arg(args, long); + ret = settimeofday(tv, tzp); + break; + } + case SYS_setitimer: { + int which = (int)va_arg(args, long); + const struct itimerval * itv = (const struct itimerval *)va_arg(args, long); + struct itimerval * oitv = (struct itimerval *)va_arg(args, long); + ret = setitimer(which, itv, oitv); + break; + } + case SYS_getitimer: { + int which = (int)va_arg(args, long); + struct itimerval * itv = (struct itimerval *)va_arg(args, long); + ret = getitimer(which, itv); + break; + } + case SYS_select: { + int nd = (int)va_arg(args, long); + fd_set * in = (fd_set *)va_arg(args, long); + fd_set * ou = (fd_set *)va_arg(args, long); + fd_set * ex = (fd_set *)va_arg(args, long); + struct timeval * tv = (struct timeval *)va_arg(args, long); + ret = select(nd, in, ou, ex, tv); + break; + } + case SYS_kevent: { + int fd = (int)va_arg(args, long); + const struct kevent * changelist = (const struct kevent *)va_arg(args, long); + int nchanges = (int)va_arg(args, long); + struct kevent * eventlist = (struct kevent *)va_arg(args, long); + int nevents = (int)va_arg(args, long); + const struct timespec * timeout = (const struct timespec *)va_arg(args, long); + ret = kevent(fd, changelist, nchanges, eventlist, nevents, timeout); + break; + } + case SYS_munmap: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = munmap(addr, len); + break; + } + case SYS_mprotect: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int prot = (int)va_arg(args, long); + ret = mprotect(addr, len, prot); + break; + } + case SYS_madvise: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int behav = (int)va_arg(args, long); + ret = madvise(addr, len, behav); + break; + } + case SYS_utimes: { + const char * path = (const char *)va_arg(args, long); + const struct timeval * tptr = (const struct timeval *)va_arg(args, long); + ret = utimes(path, tptr); + break; + } + case SYS_futimes: { + int fd = (int)va_arg(args, long); + const struct timeval * tptr = (const struct timeval *)va_arg(args, long); + ret = futimes(fd, tptr); + break; + } + case SYS_mquery: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int prot = (int)va_arg(args, long); + int flags = (int)va_arg(args, long); + int fd = (int)va_arg(args, long); + off_t pos = (off_t)va_arg(args, long); + ret = (long)mquery(addr, len, prot, flags, fd, pos); + break; + } + case SYS_getgroups: { + int gidsetsize = (int)va_arg(args, long); + gid_t * gidset = (gid_t *)va_arg(args, long); + ret = getgroups(gidsetsize, gidset); + break; + } + case SYS_setgroups: { + int gidsetsize = (int)va_arg(args, long); + const gid_t * gidset = (const gid_t *)va_arg(args, long); + ret = setgroups(gidsetsize, gidset); + break; + } + case SYS_getpgrp: + ret = getpgrp(); + break; + case SYS_setpgid: { + pid_t pid = (pid_t)va_arg(args, long); + pid_t pgid = (pid_t)va_arg(args, long); + ret = setpgid(pid, pgid); + break; + } + case SYS_futex: { + uint32_t * f = (uint32_t *)va_arg(args, long); + int op = (int)va_arg(args, long); + int val = (int)va_arg(args, long); + const struct timespec * timeout = (const struct timespec *)va_arg(args, long); + uint32_t * g = (uint32_t *)va_arg(args, long); + ret = futex(f, op, val, timeout, g); + break; + } + case SYS_utimensat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + const struct timespec * times = (const struct timespec *)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = utimensat(fd, path, times, flag); + break; + } + case SYS_futimens: { + int fd = (int)va_arg(args, long); + const struct timespec * times = (const struct timespec *)va_arg(args, long); + ret = futimens(fd, times); + break; + } + /* No signature found in headers + *case SYS_kbind: { + * const struct __kbind * param = (const struct __kbind *)va_arg(args, long); + * size_t psize = (size_t)va_arg(args, long); + * int64_t proc_cookie = (int64_t)va_arg(args, long); + * ret = kbind(param, psize, proc_cookie); + * break; + *} + */ + case SYS_clock_gettime: { + clockid_t clock_id = (clockid_t)va_arg(args, long); + struct timespec * tp = (struct timespec *)va_arg(args, long); + ret = clock_gettime(clock_id, tp); + break; + } + case SYS_clock_settime: { + clockid_t clock_id = (clockid_t)va_arg(args, long); + const struct timespec * tp = (const struct timespec *)va_arg(args, long); + ret = clock_settime(clock_id, tp); + break; + } + case SYS_clock_getres: { + clockid_t clock_id = (clockid_t)va_arg(args, long); + struct timespec * tp = (struct timespec *)va_arg(args, long); + ret = clock_getres(clock_id, tp); + break; + } + case SYS_dup2: { + int from = (int)va_arg(args, long); + int to = (int)va_arg(args, long); + ret = dup2(from, to); + break; + } + case SYS_nanosleep: { + const struct timespec * rqtp = (const struct timespec *)va_arg(args, long); + struct timespec * rmtp = (struct timespec *)va_arg(args, long); + ret = nanosleep(rqtp, rmtp); + break; + } + case SYS_fcntl: { + int fd = (int)va_arg(args, long); + int cmd = (int)va_arg(args, long); + void * arg = (void *)va_arg(args, long); + ret = fcntl(fd, cmd, arg); + break; + } + case SYS_accept4: { + int s = (int)va_arg(args, long); + struct sockaddr * name = (struct sockaddr *)va_arg(args, long); + socklen_t * anamelen = (socklen_t *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = accept4(s, name, anamelen, flags); + break; + } + /* No signature found in headers + *case SYS___thrsleep: { + * const volatile void * ident = (const volatile void *)va_arg(args, long); + * clockid_t clock_id = (clockid_t)va_arg(args, long); + * const struct timespec * tp = (const struct timespec *)va_arg(args, long); + * void * lock = (void *)va_arg(args, long); + * const int * abort = (const int *)va_arg(args, long); + * ret = __thrsleep(ident, clock_id, tp, lock, abort); + * break; + *} + */ + case SYS_fsync: + ret = fsync(va_arg(args, int)); // fd + break; + case SYS_setpriority: { + int which = (int)va_arg(args, long); + id_t who = (id_t)va_arg(args, long); + int prio = (int)va_arg(args, long); + ret = setpriority(which, who, prio); + break; + } + case SYS_socket: { + int domain = (int)va_arg(args, long); + int type = (int)va_arg(args, long); + int protocol = (int)va_arg(args, long); + ret = socket(domain, type, protocol); + break; + } + case SYS_connect: { + int s = (int)va_arg(args, long); + const struct sockaddr * name = (const struct sockaddr *)va_arg(args, long); + socklen_t namelen = (socklen_t)va_arg(args, long); + ret = connect(s, name, namelen); + break; + } + case SYS_getdents: { + int fd = (int)va_arg(args, long); + void * buf = (void *)va_arg(args, long); + size_t buflen = (size_t)va_arg(args, long); + ret = getdents(fd, buf, buflen); + break; + } + case SYS_getpriority: { + int which = (int)va_arg(args, long); + id_t who = (id_t)va_arg(args, long); + ret = getpriority(which, who); + break; + } + case SYS_pipe2: { + int * fdp = (int *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = pipe2(fdp, flags); + break; + } + case SYS_dup3: { + int from = (int)va_arg(args, long); + int to = (int)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = dup3(from, to, flags); + break; + } + /* No signature found in headers + *case SYS_sigreturn: + * ret = sigreturn(va_arg(args, struct sigcontext *)); // sigcntxp + * break; + */ + case SYS_bind: { + int s = (int)va_arg(args, long); + const struct sockaddr * name = (const struct sockaddr *)va_arg(args, long); + socklen_t namelen = (socklen_t)va_arg(args, long); + ret = bind(s, name, namelen); + break; + } + case SYS_setsockopt: { + int s = (int)va_arg(args, long); + int level = (int)va_arg(args, long); + int name = (int)va_arg(args, long); + const void * val = (const void *)va_arg(args, long); + socklen_t valsize = (socklen_t)va_arg(args, long); + ret = setsockopt(s, level, name, val, valsize); + break; + } + case SYS_listen: { + int s = (int)va_arg(args, long); + int backlog = (int)va_arg(args, long); + ret = listen(s, backlog); + break; + } + case SYS_chflagsat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + u_int flags = (u_int)va_arg(args, long); + int atflags = (int)va_arg(args, long); + ret = chflagsat(fd, path, flags, atflags); + break; + } + case SYS_pledge: { + const char * promises = (const char *)va_arg(args, long); + const char * execpromises = (const char *)va_arg(args, long); + ret = pledge(promises, execpromises); + break; + } + case SYS_ppoll: { + struct pollfd * fds = (struct pollfd *)va_arg(args, long); + u_int nfds = (u_int)va_arg(args, long); + const struct timespec * ts = (const struct timespec *)va_arg(args, long); + const sigset_t * mask = (const sigset_t *)va_arg(args, long); + ret = ppoll(fds, nfds, ts, mask); + break; + } + case SYS_pselect: { + int nd = (int)va_arg(args, long); + fd_set * in = (fd_set *)va_arg(args, long); + fd_set * ou = (fd_set *)va_arg(args, long); + fd_set * ex = (fd_set *)va_arg(args, long); + const struct timespec * ts = (const struct timespec *)va_arg(args, long); + const sigset_t * mask = (const sigset_t *)va_arg(args, long); + ret = pselect(nd, in, ou, ex, ts, mask); + break; + } + /* Mismatched func: int sigsuspend(const sigset_t *); <signal.h> + * int sigsuspend(int); <sys/syscall.h> + *case SYS_sigsuspend: + * ret = sigsuspend(va_arg(args, int)); // mask + * break; + */ + case SYS_sendsyslog: { + const char * buf = (const char *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = sendsyslog(buf, nbyte, flags); + break; + } + case SYS_unveil: { + const char * path = (const char *)va_arg(args, long); + const char * permissions = (const char *)va_arg(args, long); + ret = unveil(path, permissions); + break; + } + /* No signature found in headers + *case SYS___realpath: { + * const char * pathname = (const char *)va_arg(args, long); + * char * resolved = (char *)va_arg(args, long); + * ret = __realpath(pathname, resolved); + * break; + *} + */ + case SYS_recvmmsg: { + int s = (int)va_arg(args, long); + struct mmsghdr * mmsg = (struct mmsghdr *)va_arg(args, long); + unsigned int vlen = (unsigned int)va_arg(args, long); + int flags = (int)va_arg(args, long); + struct timespec * timeout = (struct timespec *)va_arg(args, long); + ret = recvmmsg(s, mmsg, vlen, flags, timeout); + break; + } + case SYS_sendmmsg: { + int s = (int)va_arg(args, long); + struct mmsghdr * mmsg = (struct mmsghdr *)va_arg(args, long); + unsigned int vlen = (unsigned int)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = sendmmsg(s, mmsg, vlen, flags); + break; + } + case SYS_getsockopt: { + int s = (int)va_arg(args, long); + int level = (int)va_arg(args, long); + int name = (int)va_arg(args, long); + void * val = (void *)va_arg(args, long); + socklen_t * avalsize = (socklen_t *)va_arg(args, long); + ret = getsockopt(s, level, name, val, avalsize); + break; + } + case SYS_thrkill: { + pid_t tid = (pid_t)va_arg(args, long); + int signum = (int)va_arg(args, long); + void * tcb = (void *)va_arg(args, long); + ret = thrkill(tid, signum, tcb); + break; + } + case SYS_readv: { + int fd = (int)va_arg(args, long); + const struct iovec * iovp = (const struct iovec *)va_arg(args, long); + int iovcnt = (int)va_arg(args, long); + ret = readv(fd, iovp, iovcnt); + break; + } + case SYS_writev: { + int fd = (int)va_arg(args, long); + const struct iovec * iovp = (const struct iovec *)va_arg(args, long); + int iovcnt = (int)va_arg(args, long); + ret = writev(fd, iovp, iovcnt); + break; + } + case SYS_kill: { + int pid = (int)va_arg(args, long); + int signum = (int)va_arg(args, long); + ret = kill(pid, signum); + break; + } + case SYS_fchown: { + int fd = (int)va_arg(args, long); + uid_t uid = (uid_t)va_arg(args, long); + gid_t gid = (gid_t)va_arg(args, long); + ret = fchown(fd, uid, gid); + break; + } + case SYS_fchmod: { + int fd = (int)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = fchmod(fd, mode); + break; + } + case SYS_setreuid: { + uid_t ruid = (uid_t)va_arg(args, long); + uid_t euid = (uid_t)va_arg(args, long); + ret = setreuid(ruid, euid); + break; + } + case SYS_setregid: { + gid_t rgid = (gid_t)va_arg(args, long); + gid_t egid = (gid_t)va_arg(args, long); + ret = setregid(rgid, egid); + break; + } + case SYS_rename: { + const char * from = (const char *)va_arg(args, long); + const char * to = (const char *)va_arg(args, long); + ret = rename(from, to); + break; + } + case SYS_flock: { + int fd = (int)va_arg(args, long); + int how = (int)va_arg(args, long); + ret = flock(fd, how); + break; + } + case SYS_mkfifo: { + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = mkfifo(path, mode); + break; + } + case SYS_sendto: { + int s = (int)va_arg(args, long); + const void * buf = (const void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int flags = (int)va_arg(args, long); + const struct sockaddr * to = (const struct sockaddr *)va_arg(args, long); + socklen_t tolen = (socklen_t)va_arg(args, long); + ret = sendto(s, buf, len, flags, to, tolen); + break; + } + case SYS_shutdown: { + int s = (int)va_arg(args, long); + int how = (int)va_arg(args, long); + ret = shutdown(s, how); + break; + } + case SYS_socketpair: { + int domain = (int)va_arg(args, long); + int type = (int)va_arg(args, long); + int protocol = (int)va_arg(args, long); + int * rsv = (int *)va_arg(args, long); + ret = socketpair(domain, type, protocol, rsv); + break; + } + case SYS_mkdir: { + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = mkdir(path, mode); + break; + } + case SYS_rmdir: + ret = rmdir(va_arg(args, const char *)); // path + break; + case SYS_adjtime: { + const struct timeval * delta = (const struct timeval *)va_arg(args, long); + struct timeval * olddelta = (struct timeval *)va_arg(args, long); + ret = adjtime(delta, olddelta); + break; + } + /* Mismatched func: int getlogin_r(char *, size_t); <unistd.h> + * int getlogin_r(char *, u_int); <sys/syscall.h> + *case SYS_getlogin_r: { + * char * namebuf = (char *)va_arg(args, long); + * u_int namelen = (u_int)va_arg(args, long); + * ret = getlogin_r(namebuf, namelen); + * break; + *} + */ + case SYS_getthrname: { + pid_t tid = (pid_t)va_arg(args, long); + char * name = (char *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = getthrname(tid, name, len); + break; + } + case SYS_setthrname: { + pid_t tid = (pid_t)va_arg(args, long); + const char * name = (const char *)va_arg(args, long); + ret = setthrname(tid, name); + break; + } + /* No signature found in headers + *case SYS_pinsyscall: { + * int syscall = (int)va_arg(args, long); + * void * addr = (void *)va_arg(args, long); + * size_t len = (size_t)va_arg(args, long); + * ret = pinsyscall(syscall, addr, len); + * break; + *} + */ + case SYS_setsid: + ret = setsid(); + break; + case SYS_quotactl: { + const char * path = (const char *)va_arg(args, long); + int cmd = (int)va_arg(args, long); + int uid = (int)va_arg(args, long); + char * arg = (char *)va_arg(args, long); + ret = quotactl(path, cmd, uid, arg); + break; + } + /* No signature found in headers + *case SYS_ypconnect: + * ret = ypconnect(va_arg(args, int)); // type + * break; + */ + case SYS_nfssvc: { + int flag = (int)va_arg(args, long); + void * argp = (void *)va_arg(args, long); + ret = nfssvc(flag, argp); + break; + } + case SYS_mimmutable: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = mimmutable(addr, len); + break; + } + case SYS_waitid: { + int idtype = (int)va_arg(args, long); + id_t id = (id_t)va_arg(args, long); + siginfo_t * info = (siginfo_t *)va_arg(args, long); + int options = (int)va_arg(args, long); + ret = waitid(idtype, id, info, options); + break; + } + case SYS_getfh: { + const char * fname = (const char *)va_arg(args, long); + fhandle_t * fhp = (fhandle_t *)va_arg(args, long); + ret = getfh(fname, fhp); + break; + } + /* No signature found in headers + *case SYS___tmpfd: + * ret = __tmpfd(va_arg(args, int)); // flags + * break; + */ + /* No signature found in headers + *case SYS_sysarch: { + * int op = (int)va_arg(args, long); + * void * parms = (void *)va_arg(args, long); + * ret = sysarch(op, parms); + * break; + *} + */ + case SYS_lseek: { + int fd = (int)va_arg(args, long); + off_t offset = (off_t)va_arg(args, long); + int whence = (int)va_arg(args, long); + ret = lseek(fd, offset, whence); + break; + } + case SYS_truncate: { + const char * path = (const char *)va_arg(args, long); + off_t length = (off_t)va_arg(args, long); + ret = truncate(path, length); + break; + } + case SYS_ftruncate: { + int fd = (int)va_arg(args, long); + off_t length = (off_t)va_arg(args, long); + ret = ftruncate(fd, length); + break; + } + case SYS_pread: { + int fd = (int)va_arg(args, long); + void * buf = (void *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + off_t offset = (off_t)va_arg(args, long); + ret = pread(fd, buf, nbyte, offset); + break; + } + case SYS_pwrite: { + int fd = (int)va_arg(args, long); + const void * buf = (const void *)va_arg(args, long); + size_t nbyte = (size_t)va_arg(args, long); + off_t offset = (off_t)va_arg(args, long); + ret = pwrite(fd, buf, nbyte, offset); + break; + } + case SYS_preadv: { + int fd = (int)va_arg(args, long); + const struct iovec * iovp = (const struct iovec *)va_arg(args, long); + int iovcnt = (int)va_arg(args, long); + off_t offset = (off_t)va_arg(args, long); + ret = preadv(fd, iovp, iovcnt, offset); + break; + } + case SYS_pwritev: { + int fd = (int)va_arg(args, long); + const struct iovec * iovp = (const struct iovec *)va_arg(args, long); + int iovcnt = (int)va_arg(args, long); + off_t offset = (off_t)va_arg(args, long); + ret = pwritev(fd, iovp, iovcnt, offset); + break; + } + case SYS_setgid: + ret = setgid(va_arg(args, gid_t)); // gid + break; + case SYS_setegid: + ret = setegid(va_arg(args, gid_t)); // egid + break; + case SYS_seteuid: + ret = seteuid(va_arg(args, uid_t)); // euid + break; + case SYS_pathconf: { + const char * path = (const char *)va_arg(args, long); + int name = (int)va_arg(args, long); + ret = pathconf(path, name); + break; + } + case SYS_fpathconf: { + int fd = (int)va_arg(args, long); + int name = (int)va_arg(args, long); + ret = fpathconf(fd, name); + break; + } + case SYS_swapctl: { + int cmd = (int)va_arg(args, long); + const void * arg = (const void *)va_arg(args, long); + int misc = (int)va_arg(args, long); + ret = swapctl(cmd, arg, misc); + break; + } + case SYS_getrlimit: { + int which = (int)va_arg(args, long); + struct rlimit * rlp = (struct rlimit *)va_arg(args, long); + ret = getrlimit(which, rlp); + break; + } + case SYS_setrlimit: { + int which = (int)va_arg(args, long); + const struct rlimit * rlp = (const struct rlimit *)va_arg(args, long); + ret = setrlimit(which, rlp); + break; + } + case SYS_sysctl: { + const int * name = (const int *)va_arg(args, long); + u_int namelen = (u_int)va_arg(args, long); + void * old = (void *)va_arg(args, long); + size_t * oldlenp = (size_t *)va_arg(args, long); + void * new = (void *)va_arg(args, long); + size_t newlen = (size_t)va_arg(args, long); + ret = sysctl(name, namelen, old, oldlenp, new, newlen); + break; + } + case SYS_mlock: { + const void * addr = (const void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = mlock(addr, len); + break; + } + case SYS_munlock: { + const void * addr = (const void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = munlock(addr, len); + break; + } + case SYS_getpgid: + ret = getpgid(va_arg(args, pid_t)); // pid + break; + case SYS_utrace: { + const char * label = (const char *)va_arg(args, long); + const void * addr = (const void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + ret = utrace(label, addr, len); + break; + } + case SYS_semget: { + key_t key = (key_t)va_arg(args, long); + int nsems = (int)va_arg(args, long); + int semflg = (int)va_arg(args, long); + ret = semget(key, nsems, semflg); + break; + } + case SYS_msgget: { + key_t key = (key_t)va_arg(args, long); + int msgflg = (int)va_arg(args, long); + ret = msgget(key, msgflg); + break; + } + case SYS_msgsnd: { + int msqid = (int)va_arg(args, long); + const void * msgp = (const void *)va_arg(args, long); + size_t msgsz = (size_t)va_arg(args, long); + int msgflg = (int)va_arg(args, long); + ret = msgsnd(msqid, msgp, msgsz, msgflg); + break; + } + case SYS_msgrcv: { + int msqid = (int)va_arg(args, long); + void * msgp = (void *)va_arg(args, long); + size_t msgsz = (size_t)va_arg(args, long); + long msgtyp = (long)va_arg(args, long); + int msgflg = (int)va_arg(args, long); + ret = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); + break; + } + case SYS_shmat: { + int shmid = (int)va_arg(args, long); + const void * shmaddr = (const void *)va_arg(args, long); + int shmflg = (int)va_arg(args, long); + ret = (long)shmat(shmid, shmaddr, shmflg); + break; + } + case SYS_shmdt: + ret = shmdt(va_arg(args, const void *)); // shmaddr + break; + case SYS_minherit: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int inherit = (int)va_arg(args, long); + ret = minherit(addr, len, inherit); + break; + } + case SYS_poll: { + struct pollfd * fds = (struct pollfd *)va_arg(args, long); + u_int nfds = (u_int)va_arg(args, long); + int timeout = (int)va_arg(args, long); + ret = poll(fds, nfds, timeout); + break; + } + case SYS_issetugid: + ret = issetugid(); + break; + case SYS_lchown: { + const char * path = (const char *)va_arg(args, long); + uid_t uid = (uid_t)va_arg(args, long); + gid_t gid = (gid_t)va_arg(args, long); + ret = lchown(path, uid, gid); + break; + } + case SYS_getsid: + ret = getsid(va_arg(args, pid_t)); // pid + break; + case SYS_msync: { + void * addr = (void *)va_arg(args, long); + size_t len = (size_t)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = msync(addr, len, flags); + break; + } + case SYS_pipe: + ret = pipe(va_arg(args, int *)); // fdp + break; + case SYS_fhopen: { + const fhandle_t * fhp = (const fhandle_t *)va_arg(args, long); + int flags = (int)va_arg(args, long); + ret = fhopen(fhp, flags); + break; + } + case SYS_kqueue: + ret = kqueue(); + break; + case SYS_mlockall: + ret = mlockall(va_arg(args, int)); // flags + break; + case SYS_munlockall: + ret = munlockall(); + break; + case SYS_getresuid: { + uid_t * ruid = (uid_t *)va_arg(args, long); + uid_t * euid = (uid_t *)va_arg(args, long); + uid_t * suid = (uid_t *)va_arg(args, long); + ret = getresuid(ruid, euid, suid); + break; + } + case SYS_setresuid: { + uid_t ruid = (uid_t)va_arg(args, long); + uid_t euid = (uid_t)va_arg(args, long); + uid_t suid = (uid_t)va_arg(args, long); + ret = setresuid(ruid, euid, suid); + break; + } + case SYS_getresgid: { + gid_t * rgid = (gid_t *)va_arg(args, long); + gid_t * egid = (gid_t *)va_arg(args, long); + gid_t * sgid = (gid_t *)va_arg(args, long); + ret = getresgid(rgid, egid, sgid); + break; + } + case SYS_setresgid: { + gid_t rgid = (gid_t)va_arg(args, long); + gid_t egid = (gid_t)va_arg(args, long); + gid_t sgid = (gid_t)va_arg(args, long); + ret = setresgid(rgid, egid, sgid); + break; + } + case SYS_closefrom: + ret = closefrom(va_arg(args, int)); // fd + break; + case SYS_sigaltstack: { + const struct sigaltstack * nss = (const struct sigaltstack *)va_arg(args, long); + struct sigaltstack * oss = (struct sigaltstack *)va_arg(args, long); + ret = sigaltstack(nss, oss); + break; + } + case SYS_shmget: { + key_t key = (key_t)va_arg(args, long); + size_t size = (size_t)va_arg(args, long); + int shmflg = (int)va_arg(args, long); + ret = shmget(key, size, shmflg); + break; + } + case SYS_semop: { + int semid = (int)va_arg(args, long); + struct sembuf * sops = (struct sembuf *)va_arg(args, long); + size_t nsops = (size_t)va_arg(args, long); + ret = semop(semid, sops, nsops); + break; + } + case SYS_fhstat: { + const fhandle_t * fhp = (const fhandle_t *)va_arg(args, long); + struct stat * sb = (struct stat *)va_arg(args, long); + ret = fhstat(fhp, sb); + break; + } + case SYS___semctl: { + int semid = (int)va_arg(args, long); + int semnum = (int)va_arg(args, long); + int cmd = (int)va_arg(args, long); + union semun * arg = (union semun *)va_arg(args, long); + ret = __semctl(semid, semnum, cmd, arg); + break; + } + case SYS_shmctl: { + int shmid = (int)va_arg(args, long); + int cmd = (int)va_arg(args, long); + struct shmid_ds * buf = (struct shmid_ds *)va_arg(args, long); + ret = shmctl(shmid, cmd, buf); + break; + } + case SYS_msgctl: { + int msqid = (int)va_arg(args, long); + int cmd = (int)va_arg(args, long); + struct msqid_ds * buf = (struct msqid_ds *)va_arg(args, long); + ret = msgctl(msqid, cmd, buf); + break; + } + case SYS_sched_yield: + ret = sched_yield(); + break; + case SYS_getthrid: + ret = getthrid(); + break; + /* No signature found in headers + *case SYS___thrwakeup: { + * const volatile void * ident = (const volatile void *)va_arg(args, long); + * int n = (int)va_arg(args, long); + * ret = __thrwakeup(ident, n); + * break; + *} + */ + /* No signature found in headers + *case SYS___threxit: + * __threxit(va_arg(args, pid_t *)); // notdead + * break; + */ + /* No signature found in headers + *case SYS___thrsigdivert: { + * sigset_t sigmask = (sigset_t)va_arg(args, long); + * siginfo_t * info = (siginfo_t *)va_arg(args, long); + * const struct timespec * timeout = (const struct timespec *)va_arg(args, long); + * ret = __thrsigdivert(sigmask, info, timeout); + * break; + *} + */ + /* No signature found in headers + *case SYS___getcwd: { + * char * buf = (char *)va_arg(args, long); + * size_t len = (size_t)va_arg(args, long); + * ret = __getcwd(buf, len); + * break; + *} + */ + case SYS_adjfreq: { + const int64_t * freq = (const int64_t *)va_arg(args, long); + int64_t * oldfreq = (int64_t *)va_arg(args, long); + ret = adjfreq(freq, oldfreq); + break; + } + case SYS_setrtable: + ret = setrtable(va_arg(args, int)); // rtableid + break; + case SYS_getrtable: + ret = getrtable(); + break; + case SYS_faccessat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + int amode = (int)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = faccessat(fd, path, amode, flag); + break; + } + case SYS_fchmodat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = fchmodat(fd, path, mode, flag); + break; + } + case SYS_fchownat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + uid_t uid = (uid_t)va_arg(args, long); + gid_t gid = (gid_t)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = fchownat(fd, path, uid, gid, flag); + break; + } + case SYS_linkat: { + int fd1 = (int)va_arg(args, long); + const char * path1 = (const char *)va_arg(args, long); + int fd2 = (int)va_arg(args, long); + const char * path2 = (const char *)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = linkat(fd1, path1, fd2, path2, flag); + break; + } + case SYS_mkdirat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = mkdirat(fd, path, mode); + break; + } + case SYS_mkfifoat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = mkfifoat(fd, path, mode); + break; + } + case SYS_mknodat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + dev_t dev = (dev_t)va_arg(args, long); + ret = mknodat(fd, path, mode, dev); + break; + } + case SYS_openat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + int flags = (int)va_arg(args, long); + mode_t mode = (mode_t)va_arg(args, long); + ret = openat(fd, path, flags, mode); + break; + } + case SYS_readlinkat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + char * buf = (char *)va_arg(args, long); + size_t count = (size_t)va_arg(args, long); + ret = readlinkat(fd, path, buf, count); + break; + } + case SYS_renameat: { + int fromfd = (int)va_arg(args, long); + const char * from = (const char *)va_arg(args, long); + int tofd = (int)va_arg(args, long); + const char * to = (const char *)va_arg(args, long); + ret = renameat(fromfd, from, tofd, to); + break; + } + case SYS_symlinkat: { + const char * path = (const char *)va_arg(args, long); + int fd = (int)va_arg(args, long); + const char * link = (const char *)va_arg(args, long); + ret = symlinkat(path, fd, link); + break; + } + case SYS_unlinkat: { + int fd = (int)va_arg(args, long); + const char * path = (const char *)va_arg(args, long); + int flag = (int)va_arg(args, long); + ret = unlinkat(fd, path, flag); + break; + } + case SYS___set_tcb: + __set_tcb(va_arg(args, void *)); // tcb + break; + case SYS___get_tcb: + ret = (long)__get_tcb(); + break; + default: + ret = -1; + errno = ENOSYS; + } + va_end(args); + + return ret; +} Index: gnu/usr.bin/perl/syscall_emulator.h =================================================================== RCS file: gnu/usr.bin/perl/syscall_emulator.h diff -N gnu/usr.bin/perl/syscall_emulator.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/usr.bin/perl/syscall_emulator.h 3 Aug 2023 04:34:43 -0000 @@ -0,0 +1 @@ +long syscall_emulator(int, ...); Index: gnu/usr.bin/perl/t/op/syscall_emulator.t =================================================================== RCS file: gnu/usr.bin/perl/t/op/syscall_emulator.t diff -N gnu/usr.bin/perl/t/op/syscall_emulator.t --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/usr.bin/perl/t/op/syscall_emulator.t 3 Aug 2023 04:34:43 -0000 @@ -0,0 +1,146 @@ +#!/usr/bin/perl +# $OpenBSD$ # + +# Copyright (c) 2023 Andrew Hewus Fresh <afre...@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +BEGIN { + chdir 't' if -d 't'; + require "./test.pl"; + set_up_inc( qw(. ../lib lib ../dist/base/lib) ); +} + +use v5.36; + +use File::Temp; +use POSIX qw< S_IRUSR S_IWUSR S_IRGRP S_IROTH O_CREAT O_WRONLY O_RDONLY >; + +use constant { + PROT_READ => 0x01, + MAP_PRIVATE => 0x0002, + MAP_FAILED => -1, +}; + +my $dir = File::Temp->newdir("syscall_emulator-XXXXXXXXX"); +{ + local $ENV{PERL5LIB} = join ':', @INC; + system($^X, "../utils/h2ph", '-d', $dir, + "/usr/include/sys/syscall.h"); + local @INC = ("$dir/usr/include", "$dir"); + require 'sys/syscall.ph'; +} + +my $filename = "test.txt"; +my $file = "$dir/$filename"; +my $fd; +my $out = "Hello World\n"; +my $in = "\0" x 32; +my ($in_p, $in_v); +my $sb = "\0" x 4096; +my $st_mode; + +my $perms = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; + +plan tests => 17; + +ok(! + (($fd = syscall(SYS_open(), $file, O_CREAT|O_WRONLY, $perms)) < 0), + "Opened $filename for write/create" +); +ok(! + (syscall(SYS_write(), $fd, $out, length $out) <= 0), + "Wrote out to $filename" +); +ok(! + (syscall(SYS_close(), $fd) != 0), + "closed $filename" +); + + +ok(! + (syscall(SYS_stat(), $file, $sb) != 0), + "stat $filename" +); + +# fortunately st_mode is the first unsigned long in stat struct +$st_mode = unpack "L", $sb; + +ok( ($st_mode & 0777) == ($perms & 0777), + sprintf "new file %s has correct permissions (%o)", + $filename, $st_mode & 0777 +); + +ok(! + (($fd = syscall(SYS_open(), $file, O_RDONLY)) < 0), + "Opened $filename for read" +); +ok(! + (syscall(SYS_read(), $fd, $in, length $in) <= 0), + "read from $filename" +); + +$in = unpack 'Z*', $in; + +ok( length($in) == length($out) && ($in eq $out), + "Read written content from $filename" +); + +ok(! + (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), + "lseek on fd" +); + +ok(! + (syscall(SYS_pread(), $fd, $in = "\0" x 32, 5, 3) < 0), + "pread on fd" +); + +$in = unpack 'Z*', $in; + +ok( length($in) == 5 && ($in eq substr $out, 3, 5), + "Read written content from $filename ($in)" +); + +ok(! + (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), + "lseek on fd" +); + +ok(! + (syscall(SYS_lseek(), $fd, 0, SEEK_SET) < 0), + "lseek on fd" +); + +ok(! + (($in_p = syscall(SYS_mmap(), undef, length($out), PROT_READ, MAP_PRIVATE, + $fd, 0)) == MAP_FAILED), + "mmap fd" +); + +# From ingy's Pointer module +$in_v = unpack "p*", pack "L!", $in_p; + +ok( length($in_v) == length($out) && ($in_v eq $out), + "Read written content from $filename" +); + +ok(! + (syscall(SYS_munmap(), $in_p, length($out)) != 0), + "munmap fd" +); + +ok(! + (syscall(SYS_close(), $fd) != 0), + "closed $filename" +); -- andrew Beta. Software undergoes beta testing shortly before it's released. Beta is Latin for "still doesn't work."