On Thu, 3 Aug 2023 18:43:21 -0700
Andrew Hewus Fresh <and...@afresh1.com> wrote:

> Here's a new version, I think I addressed all of the feedback I got,
> although may have missed something.

ok gkoehler@

You sent this new version 2 weeks ago, but I didn't build it until
yesterday.  syscall_emulator.t passes on macppc and powerpc64.

> 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"
> +);

Reply via email to