X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..cb3231590a3c94ab4375e2228bd5e86b0cf1ad7e:/libsyscall/xcodescripts/create-syscalls.pl diff --git a/libsyscall/xcodescripts/create-syscalls.pl b/libsyscall/xcodescripts/create-syscalls.pl index 68366de86..6bf15db90 100755 --- a/libsyscall/xcodescripts/create-syscalls.pl +++ b/libsyscall/xcodescripts/create-syscalls.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (c) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (c) 2006-2014 Apple Inc. All rights reserved. # # @APPLE_OSREFERENCE_LICENSE_HEADER_START@ # @@ -23,7 +23,7 @@ # ########################################################################## # -# % create-syscalls.pl syscalls.master custom-directory out-directory +# % create-syscalls.pl syscalls.master custom-directory platforms-directory platform-name out-directory # # This script fills the the out-directory with a Makefile.inc and *.s # files to create the double-underbar syscall stubs. It reads the @@ -61,7 +61,9 @@ my $OutDir; # size in bytes of known types (only used for i386) my %TypeBytes = ( 'au_asid_t' => 4, + 'sae_associd_t' => 4, 'caddr_t' => 4, + 'sae_connid_t' => 4, 'gid_t' => 4, 'id_t' => 4, 'idtype_t' => 4, @@ -89,31 +91,23 @@ my %TypeBytes = ( 'user_size_t' => 4, 'user_ssize_t' => 4, 'user_ulong_t' => 4, + 'uuid_t' => 4, +); + +# Types that potentially have different sizes in user-space compared to +# kernel-space as well as whether the value should be sign/zero-extended when +# passing the user/kernel boundary. +my %UserKernelMismatchTypes = ( + 'long' => 'SIGN_EXTEND', + 'size_t' => 'ZERO_EXTEND', + 'u_long' => 'ZERO_EXTEND', + 'user_size_t' => 'ZERO_EXTEND', + 'user_ssize_t' => 'SIGN_EXTEND' ); # Moving towards storing all data in this hash, then we always know # if data is aliased or not, or promoted or not. my %Symbols = ( - "quota" => { - c_sym => "quota", - syscall => "quota", - asm_sym => "_quota", - is_private => undef, - is_custom => undef, - nargs => 4, - bytes => 0, - aliases => {}, - }, - "setquota" => { - c_sym => "setquota", - syscall => "setquota", - asm_sym => "_setquota", - is_private => undef, - is_custom => undef, - nargs => 2, - bytes => 0, - aliases => {}, - }, "syscall" => { c_sym => "syscall", syscall => "syscall", @@ -123,19 +117,43 @@ my %Symbols = ( nargs => 0, bytes => 0, aliases => {}, + mismatch_args => {}, # Arguments that might need to be zero/sign-extended }, ); +# An explicit list of cancelable syscalls. For creating stubs that call the +# cancellable version of cerror. +my @Cancelable = qw/ + accept access aio_suspend + close connect connectx + disconnectx + faccessat fcntl fdatasync fpathconf fstat fstatat fsync + getlogin + ioctl + link linkat lseek lstat + msgrcv msgsnd msync + open openat + pathconf peeloff poll posix_spawn pread pselect pwrite + read readv recvfrom recvmsg rename renameat + rename_ext + __semwait_signal __sigwait + select sem_wait semop sendmsg sendto sigsuspend stat symlink symlinkat sync + unlink unlinkat + wait4 waitid write writev +/; + sub usage { - die "Usage: $MyName syscalls.master custom-directory platforms-directory out-directory\n"; + die "Usage: $MyName syscalls.master custom-directory platforms-directory platform-name out-directory\n"; } ########################################################################## # Read the syscall.master file and collect the system call names and number # of arguments. It looks for the NO_SYSCALL_STUB quailifier following the # prototype to determine if no automatic stub should be created by Libsystem. -# System call name that are already prefixed with double-underbar are set as -# if the NO_SYSCALL_STUB qualifier were specified (whether it is or not). +# +# The `sys_` prefix is stripped from syscall names, and is only kept for +# the kernel symbol in order to avoid namespace clashes and identify +# syscalls more easily. # # For the #if lines in syscall.master, all macros are assumed to be defined, # except COMPAT_GETFSSTAT (assumed undefined). @@ -170,16 +188,20 @@ sub readMaster { my $no_syscall_stub = /\)\s*NO_SYSCALL_STUB\s*;/; my($name, $args) = /\s(\S+)\s*\(([^)]*)\)/; next if $name =~ /e?nosys/; + $name =~ s/^sys_//; $args =~ s/^\s+//; $args =~ s/\s+$//; my $argbytes = 0; my $nargs = 0; + my %mismatch_args; if($args ne '' && $args ne 'void') { my @a = split(',', $args); $nargs = scalar(@a); - # Calculate the size of all the arguments (only used for i386) + my $index = 0; for my $type (@a) { $type =~ s/\s*\w+$//; # remove the argument name + + # Calculate the size of all the arguments (only used for i386) if($type =~ /\*$/) { $argbytes += 4; # a pointer type } else { @@ -188,6 +210,12 @@ sub readMaster { die "$MyName: $name: unknown type '$type'\n" unless defined($b); $argbytes += $b; } + # Determine which arguments might need to be zero/sign-extended + if(exists $UserKernelMismatchTypes{$type}) { + $mismatch_args{$index} = $UserKernelMismatchTypes{$type}; + } + + $index++; } } $Symbols{$name} = { @@ -199,6 +227,7 @@ sub readMaster { nargs => $nargs, bytes => $argbytes, aliases => {}, + mismatch_args => \%mismatch_args, # Arguments that might need to be zero/sign-extended except => [], }; } @@ -216,7 +245,9 @@ sub checkForCustomStubs { $$sym{is_custom} = $source; if (!$$sym{is_private}) { foreach my $subarch (@Architectures) { - (my $arch = $subarch) =~ s/arm(.*)/arm/; + (my $arch = $subarch) =~ s/arm(v.*)/arm/; + $arch =~ s/x86_64(.*)/x86_64/; + $arch =~ s/arm64(.*)/arm64/; $$sym{aliases}{$arch} = [] unless $$sym{aliases}{$arch}; push(@{$$sym{aliases}{$arch}}, $$sym{asm_sym}); } @@ -237,7 +268,9 @@ sub readAliases { my @a = (); for my $arch (@Architectures) { - (my $new_arch = $arch) =~ s/arm(.*)/arm/g; + (my $new_arch = $arch) =~ s/arm(v.*)/arm/g; + $new_arch =~ s/x86_64(.*)/x86_64/g; + $new_arch =~ s/arm64(.*)/arm64/g; push(@a, $new_arch) unless grep { $_ eq $new_arch } @a; } @@ -293,32 +326,71 @@ sub writeStubForSymbol { my ($f, $symbol) = @_; my @conditions; + my $has_arm64 = 0; for my $subarch (@Architectures) { - (my $arch = $subarch) =~ s/arm(.*)/arm/; + (my $arch = $subarch) =~ s/arm(v.*)/arm/; + $arch =~ s/x86_64(.*)/x86_64/; + $arch =~ s/arm64(.*)/arm64/; push(@conditions, "defined(__${arch}__)") unless grep { $_ eq $arch } @{$$symbol{except}}; + + if($arch eq "arm64") { + $has_arm64 = 1 unless grep { $_ eq $arch } @{$$symbol{except}}; + } } - + + my %is_cancel; + for (@Cancelable) { $is_cancel{$_} = 1 }; + print $f "#define __SYSCALL_32BIT_ARG_BYTES $$symbol{bytes}\n"; print $f "#include \"SYS.h\"\n\n"; + + if (scalar(@conditions)) { + printf $f "#ifndef SYS_%s\n", $$symbol{syscall}; + printf $f "#error \"SYS_%s not defined. The header files libsyscall is building against do not match syscalls.master.\"\n", $$symbol{syscall}; + printf $f "#endif\n\n"; + } + + my $nc = ($is_cancel{$$symbol{syscall}} ? "cerror" : "cerror_nocancel"); + + if($has_arm64) { + printf $f "#if defined(__arm64__)\n"; + printf $f "MI_ENTRY_POINT(%s)\n", $$symbol{asm_sym}; + if(keys %{$$symbol{mismatch_args}}) { + while(my($argnum, $extend) = each %{$$symbol{mismatch_args}}) { + printf $f "%s(%d)\n", $extend, $argnum; + } + } + + printf $f "SYSCALL_NONAME(%s, %d, %s)\n", $$symbol{syscall}, $$symbol{nargs}, $nc; + printf $f "ret\n"; + printf $f "#else\n"; + } + if (scalar(@conditions)) { printf $f "#if " . join(" || ", @conditions) . "\n"; - printf $f "__SYSCALL(%s, %s, %d)\n", $$symbol{asm_sym}, $$symbol{syscall}, $$symbol{nargs}; + printf $f "__SYSCALL2(%s, %s, %d, %s)\n", $$symbol{asm_sym}, $$symbol{syscall}, $$symbol{nargs}, $nc; if (!$$symbol{is_private} && (scalar(@conditions) < scalar(@Architectures))) { printf $f "#else\n"; - printf $f "__SYSCALL(%s, %s, %d)\n", "__".$$symbol{asm_sym}, $$symbol{syscall}, $$symbol{nargs}; + printf $f "__SYSCALL2(%s, %s, %d, %s)\n", "__".$$symbol{asm_sym}, $$symbol{syscall}, $$symbol{nargs}, $nc; } printf $f "#endif\n\n"; } else { # actually this isnt an inconsistency. kernel can expose what it wants but if all our arches # override it we need to honour that. } + + if($has_arm64) { + printf $f "#endif\n\n"; + } } sub writeAliasesForSymbol { my ($f, $symbol) = @_; foreach my $subarch (@Architectures) { - (my $arch = $subarch) =~ s/arm(.*)/arm/; + (my $arch = $subarch) =~ s/arm(v.*)/arm/; + $arch =~ s/x86_64(.*)/x86_64/; + $arch =~ s/arm64(.*)/arm64/; next unless scalar($$symbol{aliases}{$arch});