X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..cb3231590a3c94ab4375e2228bd5e86b0cf1ad7e:/libsyscall/xcodescripts/create-syscalls.pl diff --git a/libsyscall/xcodescripts/create-syscalls.pl b/libsyscall/xcodescripts/create-syscalls.pl index ca2700866..6bf15db90 100755 --- a/libsyscall/xcodescripts/create-syscalls.pl +++ b/libsyscall/xcodescripts/create-syscalls.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (c) 2006-2012 Apple Inc. All rights reserved. +# Copyright (c) 2006-2014 Apple Inc. All rights reserved. # # @APPLE_OSREFERENCE_LICENSE_HEADER_START@ # @@ -61,9 +61,9 @@ my $OutDir; # size in bytes of known types (only used for i386) my %TypeBytes = ( 'au_asid_t' => 4, - 'associd_t' => 4, + 'sae_associd_t' => 4, 'caddr_t' => 4, - 'connid_t' => 4, + 'sae_connid_t' => 4, 'gid_t' => 4, 'id_t' => 4, 'idtype_t' => 4, @@ -94,29 +94,20 @@ my %TypeBytes = ( '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", @@ -126,6 +117,7 @@ my %Symbols = ( nargs => 0, bytes => 0, aliases => {}, + mismatch_args => {}, # Arguments that might need to be zero/sign-extended }, ); @@ -135,17 +127,18 @@ my @Cancelable = qw/ accept access aio_suspend close connect connectx disconnectx - fcntl fdatasync fpathconf fstat fsync + faccessat fcntl fdatasync fpathconf fstat fstatat fsync getlogin ioctl - link lseek lstat + link linkat lseek lstat msgrcv msgsnd msync - open - pathconf peeloff poll posix_spawn pread pwrite - read readv recvfrom recvmsg rename + 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 sync - unlink + select sem_wait semop sendmsg sendto sigsuspend stat symlink symlinkat sync + unlink unlinkat wait4 waitid write writev /; @@ -157,8 +150,10 @@ sub usage { # 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). @@ -193,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 { @@ -211,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} = { @@ -222,6 +227,7 @@ sub readMaster { nargs => $nargs, bytes => $argbytes, aliases => {}, + mismatch_args => \%mismatch_args, # Arguments that might need to be zero/sign-extended except => [], }; } @@ -240,6 +246,8 @@ sub checkForCustomStubs { if (!$$sym{is_private}) { foreach my $subarch (@Architectures) { (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}); } @@ -261,6 +269,8 @@ sub readAliases { my @a = (); for my $arch (@Architectures) { (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; } @@ -316,21 +326,47 @@ sub writeStubForSymbol { my ($f, $symbol) = @_; my @conditions; + my $has_arm64 = 0; for my $subarch (@Architectures) { (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 }; - + 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"); + 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 "__SYSCALL2(%s, %s, %d, %s)\n", $$symbol{asm_sym}, $$symbol{syscall}, $$symbol{nargs}, $nc; if (!$$symbol{is_private} && (scalar(@conditions) < scalar(@Architectures))) { @@ -342,6 +378,10 @@ sub writeStubForSymbol { # 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 { @@ -349,6 +389,8 @@ sub writeAliasesForSymbol { foreach my $subarch (@Architectures) { (my $arch = $subarch) =~ s/arm(v.*)/arm/; + $arch =~ s/x86_64(.*)/x86_64/; + $arch =~ s/arm64(.*)/arm64/; next unless scalar($$symbol{aliases}{$arch});