diff --git a/bsd/arm/_types.h b/bsd/arm/_types.h index 6b98f12..a7878d5 100644 --- a/bsd/arm/_types.h +++ b/bsd/arm/_types.h @@ -19,8 +19,10 @@ typedef short __int16_t; typedef unsigned short __uint16_t; typedef int __int32_t; typedef unsigned int __uint32_t; +#ifndef DARLING_LINUX_MIGCOM typedef long long __int64_t; typedef unsigned long long __uint64_t; +#endif typedef long __darwin_intptr_t; typedef unsigned int __darwin_natural_t; @@ -52,9 +54,14 @@ typedef int __darwin_ct_rune_t; /* ct_rune_t */ typedef union { char __mbstate8[128]; long long _mbstateL; /* for alignment */ +#ifndef DARLING_LINUX_MIGCOM } __mbstate_t; typedef __mbstate_t __darwin_mbstate_t; /* mbstate_t */ +#else +// Redefinition conflict +} __darwin_mbstate_t; +#endif #if defined(__PTRDIFF_TYPE__) typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ diff --git a/darling/src/libsystem_kernel/CMakeLists.txt b/darling/src/libsystem_kernel/CMakeLists.txt index 25a0f63..4456eb4 100644 --- a/darling/src/libsystem_kernel/CMakeLists.txt +++ b/darling/src/libsystem_kernel/CMakeLists.txt @@ -10,7 +10,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(emulation/linux) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3 -w -fblocks -ffreestanding") +if(TARGET_i386 OR TARGET_x86_64) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3") +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -fblocks -ffreestanding") # Why -bind_at_load is necessary: # I couldn't find something like -Bsymbolic in Apple's ld diff --git a/darling/src/libsystem_kernel/emulation/linux/base.c b/darling/src/libsystem_kernel/emulation/linux/base.c index ec866f7..7ef8f0f 100644 --- a/darling/src/libsystem_kernel/emulation/linux/base.c +++ b/darling/src/libsystem_kernel/emulation/linux/base.c @@ -18,11 +18,47 @@ long __unknown_syscall_machdep(int nr, ...) } VISIBLE -int __linux_syscall(int nr, long a1, long a2, long a3, long a4, long a5, long a6) +int __linux_syscall_6args(int nr, long a1, long a2, long a3, long a4, long a5, long a6) { return linux_syscall(a1, a2, a3, a4, a5, a6, nr); } +VISIBLE +int __linux_syscall_noargs(int nr) +{ + return __linux_syscall_6args(nr, 0, 0, 0, 0, 0, 0); +} + +VISIBLE +int __linux_syscall_1arg(int nr, long a1) +{ + return __linux_syscall_6args(nr, a1, 0, 0, 0, 0, 0); +} + +VISIBLE +int __linux_syscall_2args(int nr, long a1, long a2) +{ + return __linux_syscall_6args(nr, a1, a2, 0, 0, 0, 0); +} + +VISIBLE +int __linux_syscall_3args(int nr, long a1, long a2, long a3) +{ + return __linux_syscall_6args(nr, a1, a2, a3, 0, 0, 0); +} + +VISIBLE +int __linux_syscall_4args(int nr, long a1, long a2, long a3, long a4) +{ + return __linux_syscall_6args(nr, a1, a2, a3, a4, 0, 0); +} + +VISIBLE +int __linux_syscall_5args(int nr, long a1, long a2, long a3, long a4, long a5) +{ + return __linux_syscall_6args(nr, a1, a2, a3, a4, a5, 0); +} + #ifdef __TESTING void _start() { diff --git a/darling/src/libsystem_kernel/emulation/linux/base.h b/darling/src/libsystem_kernel/emulation/linux/base.h index fbde716..f8e959d 100644 --- a/darling/src/libsystem_kernel/emulation/linux/base.h +++ b/darling/src/libsystem_kernel/emulation/linux/base.h @@ -21,8 +21,13 @@ long linux_syscall(long a1, long a2, long a3, long a4, long a5, long a6, int nr) #ifndef BUILDING_BASE_C -VISIBLE -int __linux_syscall(int nr, ...); +VISIBLE int __linux_syscall_noargs(int); +VISIBLE int __linux_syscall_1arg(int,long); +VISIBLE int __linux_syscall_2args(int,long,long); +VISIBLE int __linux_syscall_3args(int,long,long,long); +VISIBLE int __linux_syscall_4args(int,long,long,long,long); +VISIBLE int __linux_syscall_5args(int,long,long,long,long,long); +VISIBLE int __linux_syscall_6args(int,long,long,long,long,long,long); #endif /* BUILDING_BASE_C */ diff --git a/darling/src/libsystem_kernel/emulation/linux/bsdthread/bsdthread_register.c b/darling/src/libsystem_kernel/emulation/linux/bsdthread/bsdthread_register.c index 6c0f32c..7f8040b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/bsdthread/bsdthread_register.c +++ b/darling/src/libsystem_kernel/emulation/linux/bsdthread/bsdthread_register.c @@ -81,6 +81,13 @@ void pthread_entry_point_wrapper(void* self, int thread_port, void* funptr, register void* arg4 asm("edx") = funarg; register unsigned long arg5 asm("edi") = stack_addr; register unsigned int arg6 asm("esi") = flags; +#elif __arm64__ + register void* arg1 asm("x0") = self; + register int arg2 asm("w1") = thread_port; + register void* arg3 asm("x2") = funptr; + register void* arg4 asm("x3") = funarg; + register unsigned long arg5 asm("x4") = stack_addr; + register unsigned int arg6 asm("w5") = flags; #endif #if __x86_64__ @@ -105,6 +112,14 @@ void pthread_entry_point_wrapper(void* self, int thread_port, void* funptr, "r"(arg1),"r"(arg2),"r"(arg3),"r"(arg4),"r"(arg5),"r"(arg6), [pthread_entry_point] "rmi"(pthread_entry_point) ); +#elif __arm64__ + __asm__ __volatile__ ( + "br %[pthread_entry_point]\n" + :: + // Arguments follow the usual arm64 calling conventions. + "r"(arg1),"r"(arg2),"r"(arg3),"r"(arg4),"r"(arg5),"r"(arg6), + [pthread_entry_point] "r"(pthread_entry_point) + ); #else #error "Missing assembly for architecture" // pthread_entry_point(self, thread_port, funptr, funarg, stack_addr, flags); @@ -146,6 +161,13 @@ void wqueue_entry_point_asm_jump(void* self, int thread_port, void* stackaddr, register void* arg4 asm("edx") = item; register int arg5 asm("edi") = reuse; register int arg6 asm("esi") = nevents; +#elif __arm64__ + register void* arg1 asm("x0") = self; + register int arg2 asm("w1") = thread_port; + register void* arg3 asm("x2") = stackaddr; + register void* arg4 asm("x3") = item; + register int arg5 asm("w4") = reuse; + register int arg6 asm("w5") = nevents; #endif #if __x86_64__ @@ -170,6 +192,14 @@ void wqueue_entry_point_asm_jump(void* self, int thread_port, void* stackaddr, "r"(arg1),"r"(arg2),"r"(arg3),"r"(arg4),"r"(arg5),"r"(arg6), [wqueue_entry_point] "rmi"(wqueue_entry_point) ); +#elif defined(__arm64__) + __asm__ __volatile__ ( + "br %[wqueue_entry_point]\n" + :: + // Arguments follow the usual arm64 calling conventions. + "r"(arg1),"r"(arg2),"r"(arg3),"r"(arg4),"r"(arg5),"r"(arg6), + [wqueue_entry_point] "r"(wqueue_entry_point) + ); #else #error "Missing assembly for architecture" // wqueue_entry_point(self, thread_port, stackaddr, item, reuse, nevents); diff --git a/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.c b/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.c index cab862d..a4c62fa 100644 --- a/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.c +++ b/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.c @@ -2,6 +2,7 @@ #include #include #include "simple.h" +#include "base.h" extern struct elf_calls* _elfcalls; @@ -92,6 +93,16 @@ void __dserver_close_socket(int socket) { return elfcalls()->dserver_close_socket(socket); }; +VISIBLE +void* __darling_thread_get_tsd() { + return elfcalls()->get_tsd(); +} + +VISIBLE +void __darling_thread_set_tsd(void* value) { + elfcalls()->set_tsd(value); +} + int __dserver_get_process_lifetime_pipe() { return elfcalls()->dserver_get_process_lifetime_pipe(); } diff --git a/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.h b/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.h index b120cad..c52d176 100644 --- a/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.h +++ b/darling/src/libsystem_kernel/emulation/linux/elfcalls_wrapper.h @@ -33,6 +33,9 @@ int __dserver_per_thread_socket(void); void __dserver_per_thread_socket_refresh(void); void __dserver_close_socket(int socket); +void* __darling_thread_get_tsd(); +void __darling_thread_set_tsd(void* value); + int __dserver_get_process_lifetime_pipe(void); int __dserver_process_lifetime_pipe_refresh(void); void __dserver_close_process_lifetime_pipe(int fd); diff --git a/darling/src/libsystem_kernel/emulation/linux/ext/epoll_create.c b/darling/src/libsystem_kernel/emulation/linux/ext/epoll_create.c index 6064942..b8045f7 100644 --- a/darling/src/libsystem_kernel/emulation/linux/ext/epoll_create.c +++ b/darling/src/libsystem_kernel/emulation/linux/ext/epoll_create.c @@ -6,22 +6,8 @@ extern long cerror(int __err); VISIBLE -int epoll_create (int __size) +int epoll_create (__unused int __size) { - #if defined(__NR_epoll_create) - int rv; - - rv = LINUX_SYSCALL(__NR_epoll_create, __size); - if (rv < 0) - { - cerror(errno_linux_to_bsd(-rv)); - return -1; - } - - return rv; - #else - // The size argument in __NR_epoll_create is ignored - return epoll_create1(0); - #endif + return epoll_create1(0); } diff --git a/darling/src/libsystem_kernel/emulation/linux/ext/sys/epoll.h b/darling/src/libsystem_kernel/emulation/linux/ext/sys/epoll.h index 31adee2..f31f092 100644 --- a/darling/src/libsystem_kernel/emulation/linux/ext/sys/epoll.h +++ b/darling/src/libsystem_kernel/emulation/linux/ext/sys/epoll.h @@ -2,12 +2,6 @@ #define LINUX_EPOLL_H #include -#define epoll_create __linux_epoll_create -#define epoll_create1 __linux_epoll_create1 -#define epoll_ctl __linux_epoll_ctl -#define epoll_wait __linux_epoll_wait -#define epoll_pwait __linux_epoll_pwait - #ifndef __THROW # define __THROW #endif @@ -34,6 +28,14 @@ enum EPOLL_EVENTS #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 +#if defined(__x86_64__) || defined(__i386__) +#define __EPOLL_PACKED __attribute__ ((__packed__)) +#elif defined(__arm64__) +#define __EPOLL_PACKED +#else +#error "Missing __EPOLL_PACKED definition for arch" +#endif + typedef union epoll_data { void *ptr; @@ -46,10 +48,12 @@ struct epoll_event { uint32_t events; epoll_data_t data; -} __attribute__((packed)); +} __EPOLL_PACKED; extern int epoll_create (int __size) __THROW; +extern int epoll_create1 (int __flags); + extern int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) __THROW; diff --git a/darling/src/libsystem_kernel/emulation/linux/fcntl/open.h b/darling/src/libsystem_kernel/emulation/linux/fcntl/open.h index b5164cd..546f22a 100644 --- a/darling/src/libsystem_kernel/emulation/linux/fcntl/open.h +++ b/darling/src/libsystem_kernel/emulation/linux/fcntl/open.h @@ -4,21 +4,77 @@ long sys_open(const char* filename, int flags, unsigned int mode); long sys_open_nocancel(const char* filename, int flags, unsigned int mode); + +#if defined(__arm64__) +#define LINUX_O_DIRECTORY 040000 +#define LINUX_O_NOFOLLOW 0100000 +#define LINUX_O_DIRECT 0200000 +#define LINUX_O_LARGEFILE 0400000 +#endif + +// Based on +#define LINUX_O_ACCMODE 0003 #define LINUX_O_RDONLY 00 #define LINUX_O_WRONLY 01 #define LINUX_O_RDWR 02 + +#ifndef LINUX_O_CREAT #define LINUX_O_CREAT 0100 +#endif +#ifndef LINUX_O_EXCL #define LINUX_O_EXCL 0200 +#endif +#ifndef LINUX_O_NOCTTY #define LINUX_O_NOCTTY 0400 +#endif +#ifndef LINUX_O_TRUNC #define LINUX_O_TRUNC 01000 +#endif +#ifndef LINUX_O_APPEND #define LINUX_O_APPEND 02000 +#endif +#ifndef LINUX_O_NONBLOCK #define LINUX_O_NONBLOCK 04000 +#endif +#ifndef LINUX_O_NDELAY +#define LINUX_O_NDELAY O_NONBLOCK +#endif +#ifndef LINUX_O_SYNC #define LINUX_O_SYNC 04010000 +#endif +#ifndef LINUX_O_ASYNC #define LINUX_O_ASYNC 020000 -#define LINUX_O_CLOEXEC 02000000 +#endif +#ifndef LINUX_O_LARGEFILE #define LINUX_O_LARGEFILE 0100000 -#define LINUX_O_NOFOLLOW 0400000 +#endif +#ifndef LINUX_O_DIRECTORY #define LINUX_O_DIRECTORY 0200000 +#endif +#ifndef LINUX_O_NOFOLLOW +#define LINUX_O_NOFOLLOW 0400000 +#endif +#ifndef LINUX_O_CLOEXEC +#define LINUX_O_CLOEXEC 02000000 +#endif +#ifndef LINUX_O_DIRECT +#define LINUX_O_DIRECT 040000 +#endif +#ifndef LINUX_O_NOATIME +#define LINUX_O_NOATIME 01000000 +#endif +#ifndef LINUX_O_PATH +#define LINUX_O_PATH 010000000 +#endif +#ifndef LINUX_O_DSYNC +#define LINUX_O_DSYNC 010000 +#endif +#ifndef LINUX_O_TMPFILE +#define LINUX_O_TMPFILE (020000000 | LINUX_O_DIRECTORY) +#endif + +#define LINUX_O_FSYNC LINUX_O_SYNC + #define BSD_O_RDONLY 0 #define BSD_O_WRONLY 1 diff --git a/darling/src/libsystem_kernel/emulation/linux/linux-syscall.S b/darling/src/libsystem_kernel/emulation/linux/linux-syscall.S index c79bbbf..4bd208f 100644 --- a/darling/src/libsystem_kernel/emulation/linux/linux-syscall.S +++ b/darling/src/libsystem_kernel/emulation/linux/linux-syscall.S @@ -2,6 +2,9 @@ .globl _linux_syscall .private_extern _linux_syscall +#if defined(__arm64__) +.balign 4 +#endif _linux_syscall: #if defined(__x86_64__) @@ -69,6 +72,11 @@ _linux_syscall: pop %ebp ret +#elif defined(__arm64__) + mov x8, x6 + svc #0 + ret + #else # error Missing assembly! diff --git a/darling/src/libsystem_kernel/emulation/linux/linux-syscalls/linux-generic.h b/darling/src/libsystem_kernel/emulation/linux/linux-syscalls/linux-generic.h index 7fbf18b..eda9ccf 100644 --- a/darling/src/libsystem_kernel/emulation/linux/linux-syscalls/linux-generic.h +++ b/darling/src/libsystem_kernel/emulation/linux/linux-syscalls/linux-generic.h @@ -38,12 +38,12 @@ __SYSCALL(__NR_io_destroy, sys_io_destroy) __SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit) #define __NR_io_cancel 3 __SYSCALL(__NR_io_cancel, sys_io_cancel) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_io_getevents 4 __SC_3264(__NR_io_getevents, sys_io_getevents_time32, sys_io_getevents) #endif -/* fs/xattr.c */ #define __NR_setxattr 5 __SYSCALL(__NR_setxattr, sys_setxattr) #define __NR_lsetxattr 6 @@ -68,58 +68,38 @@ __SYSCALL(__NR_removexattr, sys_removexattr) __SYSCALL(__NR_lremovexattr, sys_lremovexattr) #define __NR_fremovexattr 16 __SYSCALL(__NR_fremovexattr, sys_fremovexattr) - -/* fs/dcache.c */ #define __NR_getcwd 17 __SYSCALL(__NR_getcwd, sys_getcwd) - -/* fs/cookies.c */ #define __NR_lookup_dcookie 18 __SC_COMP(__NR_lookup_dcookie, sys_lookup_dcookie, compat_sys_lookup_dcookie) - -/* fs/eventfd.c */ #define __NR_eventfd2 19 __SYSCALL(__NR_eventfd2, sys_eventfd2) - -/* fs/eventpoll.c */ #define __NR_epoll_create1 20 __SYSCALL(__NR_epoll_create1, sys_epoll_create1) #define __NR_epoll_ctl 21 __SYSCALL(__NR_epoll_ctl, sys_epoll_ctl) #define __NR_epoll_pwait 22 __SC_COMP(__NR_epoll_pwait, sys_epoll_pwait, compat_sys_epoll_pwait) - -/* fs/fcntl.c */ #define __NR_dup 23 __SYSCALL(__NR_dup, sys_dup) #define __NR_dup3 24 __SYSCALL(__NR_dup3, sys_dup3) #define __NR3264_fcntl 25 __SC_COMP_3264(__NR3264_fcntl, sys_fcntl64, sys_fcntl, compat_sys_fcntl64) - -/* fs/inotify_user.c */ #define __NR_inotify_init1 26 __SYSCALL(__NR_inotify_init1, sys_inotify_init1) #define __NR_inotify_add_watch 27 __SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch) #define __NR_inotify_rm_watch 28 __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) - -/* fs/ioctl.c */ #define __NR_ioctl 29 __SC_COMP(__NR_ioctl, sys_ioctl, compat_sys_ioctl) - -/* fs/ioprio.c */ #define __NR_ioprio_set 30 __SYSCALL(__NR_ioprio_set, sys_ioprio_set) #define __NR_ioprio_get 31 __SYSCALL(__NR_ioprio_get, sys_ioprio_get) - -/* fs/locks.c */ #define __NR_flock 32 __SYSCALL(__NR_flock, sys_flock) - -/* fs/namei.c */ #define __NR_mknodat 33 __SYSCALL(__NR_mknodat, sys_mknodat) #define __NR_mkdirat 34 @@ -130,25 +110,21 @@ __SYSCALL(__NR_unlinkat, sys_unlinkat) __SYSCALL(__NR_symlinkat, sys_symlinkat) #define __NR_linkat 37 __SYSCALL(__NR_linkat, sys_linkat) + #ifdef __ARCH_WANT_RENAMEAT /* renameat is superseded with flags by renameat2 */ #define __NR_renameat 38 __SYSCALL(__NR_renameat, sys_renameat) #endif /* __ARCH_WANT_RENAMEAT */ -/* fs/namespace.c */ #define __NR_umount2 39 __SYSCALL(__NR_umount2, sys_umount) #define __NR_mount 40 -__SC_COMP(__NR_mount, sys_mount, compat_sys_mount) +__SYSCALL(__NR_mount, sys_mount) #define __NR_pivot_root 41 __SYSCALL(__NR_pivot_root, sys_pivot_root) - -/* fs/nfsctl.c */ #define __NR_nfsservctl 42 __SYSCALL(__NR_nfsservctl, sys_ni_syscall) - -/* fs/open.c */ #define __NR3264_statfs 43 __SC_COMP_3264(__NR3264_statfs, sys_statfs64, sys_statfs, \ compat_sys_statfs64) @@ -161,7 +137,6 @@ __SC_COMP_3264(__NR3264_truncate, sys_truncate64, sys_truncate, \ #define __NR3264_ftruncate 46 __SC_COMP_3264(__NR3264_ftruncate, sys_ftruncate64, sys_ftruncate, \ compat_sys_ftruncate64) - #define __NR_fallocate 47 __SC_COMP(__NR_fallocate, sys_fallocate, compat_sys_fallocate) #define __NR_faccessat 48 @@ -186,20 +161,12 @@ __SYSCALL(__NR_openat, sys_openat) __SYSCALL(__NR_close, sys_close) #define __NR_vhangup 58 __SYSCALL(__NR_vhangup, sys_vhangup) - -/* fs/pipe.c */ #define __NR_pipe2 59 __SYSCALL(__NR_pipe2, sys_pipe2) - -/* fs/quota.c */ #define __NR_quotactl 60 __SYSCALL(__NR_quotactl, sys_quotactl) - -/* fs/readdir.c */ #define __NR_getdents64 61 __SYSCALL(__NR_getdents64, sys_getdents64) - -/* fs/read_write.c */ #define __NR3264_lseek 62 __SC_3264(__NR3264_lseek, sys_llseek, sys_lseek) #define __NR_read 63 @@ -207,9 +174,9 @@ __SYSCALL(__NR_read, sys_read) #define __NR_write 64 __SYSCALL(__NR_write, sys_write) #define __NR_readv 65 -__SC_COMP(__NR_readv, sys_readv, compat_sys_readv) +__SC_COMP(__NR_readv, sys_readv, sys_readv) #define __NR_writev 66 -__SC_COMP(__NR_writev, sys_writev, compat_sys_writev) +__SC_COMP(__NR_writev, sys_writev, sys_writev) #define __NR_pread64 67 __SC_COMP(__NR_pread64, sys_pread64, compat_sys_pread64) #define __NR_pwrite64 68 @@ -218,12 +185,9 @@ __SC_COMP(__NR_pwrite64, sys_pwrite64, compat_sys_pwrite64) __SC_COMP(__NR_preadv, sys_preadv, compat_sys_preadv) #define __NR_pwritev 70 __SC_COMP(__NR_pwritev, sys_pwritev, compat_sys_pwritev) - -/* fs/sendfile.c */ #define __NR3264_sendfile 71 __SYSCALL(__NR3264_sendfile, sys_sendfile64) -/* fs/select.c */ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_pselect6 72 __SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_pselect6_time32) @@ -231,21 +195,17 @@ __SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_psel __SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32) #endif -/* fs/signalfd.c */ #define __NR_signalfd4 74 __SC_COMP(__NR_signalfd4, sys_signalfd4, compat_sys_signalfd4) - -/* fs/splice.c */ #define __NR_vmsplice 75 -__SC_COMP(__NR_vmsplice, sys_vmsplice, compat_sys_vmsplice) +__SYSCALL(__NR_vmsplice, sys_vmsplice) #define __NR_splice 76 __SYSCALL(__NR_splice, sys_splice) #define __NR_tee 77 __SYSCALL(__NR_tee, sys_tee) - -/* fs/stat.c */ #define __NR_readlinkat 78 __SYSCALL(__NR_readlinkat, sys_readlinkat) + #if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64) #define __NR3264_fstatat 79 __SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat) @@ -253,13 +213,13 @@ __SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat) __SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat) #endif -/* fs/sync.c */ #define __NR_sync 81 __SYSCALL(__NR_sync, sys_sync) #define __NR_fsync 82 __SYSCALL(__NR_fsync, sys_fsync) #define __NR_fdatasync 83 __SYSCALL(__NR_fdatasync, sys_fdatasync) + #ifdef __ARCH_WANT_SYNC_FILE_RANGE2 #define __NR_sync_file_range2 84 __SC_COMP(__NR_sync_file_range2, sys_sync_file_range2, \ @@ -270,9 +230,9 @@ __SC_COMP(__NR_sync_file_range, sys_sync_file_range, \ compat_sys_sync_file_range) #endif -/* fs/timerfd.c */ #define __NR_timerfd_create 85 __SYSCALL(__NR_timerfd_create, sys_timerfd_create) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_timerfd_settime 86 __SC_3264(__NR_timerfd_settime, sys_timerfd_settime32, \ @@ -282,45 +242,35 @@ __SC_3264(__NR_timerfd_gettime, sys_timerfd_gettime32, \ sys_timerfd_gettime) #endif -/* fs/utimes.c */ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_utimensat 88 __SC_3264(__NR_utimensat, sys_utimensat_time32, sys_utimensat) #endif -/* kernel/acct.c */ #define __NR_acct 89 __SYSCALL(__NR_acct, sys_acct) - -/* kernel/capability.c */ #define __NR_capget 90 __SYSCALL(__NR_capget, sys_capget) #define __NR_capset 91 __SYSCALL(__NR_capset, sys_capset) - -/* kernel/exec_domain.c */ #define __NR_personality 92 __SYSCALL(__NR_personality, sys_personality) - -/* kernel/exit.c */ #define __NR_exit 93 __SYSCALL(__NR_exit, sys_exit) #define __NR_exit_group 94 __SYSCALL(__NR_exit_group, sys_exit_group) #define __NR_waitid 95 __SC_COMP(__NR_waitid, sys_waitid, compat_sys_waitid) - -/* kernel/fork.c */ #define __NR_set_tid_address 96 __SYSCALL(__NR_set_tid_address, sys_set_tid_address) #define __NR_unshare 97 __SYSCALL(__NR_unshare, sys_unshare) -/* kernel/futex.c */ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_futex 98 __SC_3264(__NR_futex, sys_futex_time32, sys_futex) #endif + #define __NR_set_robust_list 99 __SC_COMP(__NR_set_robust_list, sys_set_robust_list, \ compat_sys_set_robust_list) @@ -328,43 +278,40 @@ __SC_COMP(__NR_set_robust_list, sys_set_robust_list, \ __SC_COMP(__NR_get_robust_list, sys_get_robust_list, \ compat_sys_get_robust_list) -/* kernel/hrtimer.c */ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_nanosleep 101 __SC_3264(__NR_nanosleep, sys_nanosleep_time32, sys_nanosleep) #endif -/* kernel/itimer.c */ #define __NR_getitimer 102 __SC_COMP(__NR_getitimer, sys_getitimer, compat_sys_getitimer) #define __NR_setitimer 103 __SC_COMP(__NR_setitimer, sys_setitimer, compat_sys_setitimer) - -/* kernel/kexec.c */ #define __NR_kexec_load 104 __SC_COMP(__NR_kexec_load, sys_kexec_load, compat_sys_kexec_load) - -/* kernel/module.c */ #define __NR_init_module 105 __SYSCALL(__NR_init_module, sys_init_module) #define __NR_delete_module 106 __SYSCALL(__NR_delete_module, sys_delete_module) - -/* kernel/posix-timers.c */ #define __NR_timer_create 107 __SC_COMP(__NR_timer_create, sys_timer_create, compat_sys_timer_create) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_timer_gettime 108 __SC_3264(__NR_timer_gettime, sys_timer_gettime32, sys_timer_gettime) #endif + #define __NR_timer_getoverrun 109 __SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_timer_settime 110 __SC_3264(__NR_timer_settime, sys_timer_settime32, sys_timer_settime) #endif + #define __NR_timer_delete 111 __SYSCALL(__NR_timer_delete, sys_timer_delete) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_clock_settime 112 __SC_3264(__NR_clock_settime, sys_clock_settime32, sys_clock_settime) @@ -377,15 +324,10 @@ __SC_3264(__NR_clock_nanosleep, sys_clock_nanosleep_time32, \ sys_clock_nanosleep) #endif -/* kernel/printk.c */ #define __NR_syslog 116 __SYSCALL(__NR_syslog, sys_syslog) - -/* kernel/ptrace.c */ #define __NR_ptrace 117 -__SYSCALL(__NR_ptrace, sys_ptrace) - -/* kernel/sched/core.c */ +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace) #define __NR_sched_setparam 118 __SYSCALL(__NR_sched_setparam, sys_sched_setparam) #define __NR_sched_setscheduler 119 @@ -406,13 +348,13 @@ __SYSCALL(__NR_sched_yield, sys_sched_yield) __SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) #define __NR_sched_get_priority_min 126 __SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_sched_rr_get_interval 127 __SC_3264(__NR_sched_rr_get_interval, sys_sched_rr_get_interval_time32, \ sys_sched_rr_get_interval) #endif -/* kernel/signal.c */ #define __NR_restart_syscall 128 __SYSCALL(__NR_restart_syscall, sys_restart_syscall) #define __NR_kill 129 @@ -431,18 +373,18 @@ __SC_COMP(__NR_rt_sigaction, sys_rt_sigaction, compat_sys_rt_sigaction) __SC_COMP(__NR_rt_sigprocmask, sys_rt_sigprocmask, compat_sys_rt_sigprocmask) #define __NR_rt_sigpending 136 __SC_COMP(__NR_rt_sigpending, sys_rt_sigpending, compat_sys_rt_sigpending) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_rt_sigtimedwait 137 __SC_COMP_3264(__NR_rt_sigtimedwait, sys_rt_sigtimedwait_time32, \ sys_rt_sigtimedwait, compat_sys_rt_sigtimedwait_time32) #endif + #define __NR_rt_sigqueueinfo 138 __SC_COMP(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo, \ compat_sys_rt_sigqueueinfo) #define __NR_rt_sigreturn 139 __SC_COMP(__NR_rt_sigreturn, sys_rt_sigreturn, compat_sys_rt_sigreturn) - -/* kernel/sys.c */ #define __NR_setpriority 140 __SYSCALL(__NR_setpriority, sys_setpriority) #define __NR_getpriority 141 @@ -507,7 +449,6 @@ __SYSCALL(__NR_prctl, sys_prctl) #define __NR_getcpu 168 __SYSCALL(__NR_getcpu, sys_getcpu) -/* kernel/time.c */ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_gettimeofday 169 __SC_COMP(__NR_gettimeofday, sys_gettimeofday, compat_sys_gettimeofday) @@ -517,7 +458,6 @@ __SC_COMP(__NR_settimeofday, sys_settimeofday, compat_sys_settimeofday) __SC_3264(__NR_adjtimex, sys_adjtimex_time32, sys_adjtimex) #endif -/* kernel/timer.c */ #define __NR_getpid 172 __SYSCALL(__NR_getpid, sys_getpid) #define __NR_getppid 173 @@ -534,12 +474,11 @@ __SYSCALL(__NR_getegid, sys_getegid) __SYSCALL(__NR_gettid, sys_gettid) #define __NR_sysinfo 179 __SC_COMP(__NR_sysinfo, sys_sysinfo, compat_sys_sysinfo) - -/* ipc/mqueue.c */ #define __NR_mq_open 180 __SC_COMP(__NR_mq_open, sys_mq_open, compat_sys_mq_open) #define __NR_mq_unlink 181 __SYSCALL(__NR_mq_unlink, sys_mq_unlink) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_mq_timedsend 182 __SC_3264(__NR_mq_timedsend, sys_mq_timedsend_time32, sys_mq_timedsend) @@ -547,12 +486,11 @@ __SC_3264(__NR_mq_timedsend, sys_mq_timedsend_time32, sys_mq_timedsend) __SC_3264(__NR_mq_timedreceive, sys_mq_timedreceive_time32, \ sys_mq_timedreceive) #endif + #define __NR_mq_notify 184 __SC_COMP(__NR_mq_notify, sys_mq_notify, compat_sys_mq_notify) #define __NR_mq_getsetattr 185 __SC_COMP(__NR_mq_getsetattr, sys_mq_getsetattr, compat_sys_mq_getsetattr) - -/* ipc/msg.c */ #define __NR_msgget 186 __SYSCALL(__NR_msgget, sys_msgget) #define __NR_msgctl 187 @@ -561,20 +499,18 @@ __SC_COMP(__NR_msgctl, sys_msgctl, compat_sys_msgctl) __SC_COMP(__NR_msgrcv, sys_msgrcv, compat_sys_msgrcv) #define __NR_msgsnd 189 __SC_COMP(__NR_msgsnd, sys_msgsnd, compat_sys_msgsnd) - -/* ipc/sem.c */ #define __NR_semget 190 __SYSCALL(__NR_semget, sys_semget) #define __NR_semctl 191 __SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_semtimedop 192 __SC_3264(__NR_semtimedop, sys_semtimedop_time32, sys_semtimedop) #endif + #define __NR_semop 193 __SYSCALL(__NR_semop, sys_semop) - -/* ipc/shm.c */ #define __NR_shmget 194 __SYSCALL(__NR_shmget, sys_shmget) #define __NR_shmctl 195 @@ -583,8 +519,6 @@ __SC_COMP(__NR_shmctl, sys_shmctl, compat_sys_shmctl) __SC_COMP(__NR_shmat, sys_shmat, compat_sys_shmat) #define __NR_shmdt 197 __SYSCALL(__NR_shmdt, sys_shmdt) - -/* net/socket.c */ #define __NR_socket 198 __SYSCALL(__NR_socket, sys_socket) #define __NR_socketpair 199 @@ -606,49 +540,39 @@ __SYSCALL(__NR_sendto, sys_sendto) #define __NR_recvfrom 207 __SC_COMP(__NR_recvfrom, sys_recvfrom, compat_sys_recvfrom) #define __NR_setsockopt 208 -__SC_COMP(__NR_setsockopt, sys_setsockopt, compat_sys_setsockopt) +__SC_COMP(__NR_setsockopt, sys_setsockopt, sys_setsockopt) #define __NR_getsockopt 209 -__SC_COMP(__NR_getsockopt, sys_getsockopt, compat_sys_getsockopt) +__SC_COMP(__NR_getsockopt, sys_getsockopt, sys_getsockopt) #define __NR_shutdown 210 __SYSCALL(__NR_shutdown, sys_shutdown) #define __NR_sendmsg 211 __SC_COMP(__NR_sendmsg, sys_sendmsg, compat_sys_sendmsg) #define __NR_recvmsg 212 __SC_COMP(__NR_recvmsg, sys_recvmsg, compat_sys_recvmsg) - -/* mm/filemap.c */ #define __NR_readahead 213 __SC_COMP(__NR_readahead, sys_readahead, compat_sys_readahead) - -/* mm/nommu.c, also with MMU */ #define __NR_brk 214 __SYSCALL(__NR_brk, sys_brk) #define __NR_munmap 215 __SYSCALL(__NR_munmap, sys_munmap) #define __NR_mremap 216 __SYSCALL(__NR_mremap, sys_mremap) - -/* security/keys/keyctl.c */ #define __NR_add_key 217 __SYSCALL(__NR_add_key, sys_add_key) #define __NR_request_key 218 __SYSCALL(__NR_request_key, sys_request_key) #define __NR_keyctl 219 __SC_COMP(__NR_keyctl, sys_keyctl, compat_sys_keyctl) - -/* arch/example/kernel/sys_example.c */ #define __NR_clone 220 __SYSCALL(__NR_clone, sys_clone) #define __NR_execve 221 __SC_COMP(__NR_execve, sys_execve, compat_sys_execve) - #define __NR3264_mmap 222 __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap) -/* mm/fadvise.c */ #define __NR3264_fadvise64 223 __SC_COMP(__NR3264_fadvise64, sys_fadvise64_64, compat_sys_fadvise64_64) -/* mm/, CONFIG_MMU only */ +/* CONFIG_MMU only */ #ifndef __ARCH_NOMMU #define __NR_swapon 224 __SYSCALL(__NR_swapon, sys_swapon) @@ -673,15 +597,15 @@ __SYSCALL(__NR_madvise, sys_madvise) #define __NR_remap_file_pages 234 __SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) #define __NR_mbind 235 -__SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind) +__SYSCALL(__NR_mbind, sys_mbind) #define __NR_get_mempolicy 236 -__SC_COMP(__NR_get_mempolicy, sys_get_mempolicy, compat_sys_get_mempolicy) +__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) #define __NR_set_mempolicy 237 -__SC_COMP(__NR_set_mempolicy, sys_set_mempolicy, compat_sys_set_mempolicy) +__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) #define __NR_migrate_pages 238 -__SC_COMP(__NR_migrate_pages, sys_migrate_pages, compat_sys_migrate_pages) +__SYSCALL(__NR_migrate_pages, sys_migrate_pages) #define __NR_move_pages 239 -__SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages) +__SYSCALL(__NR_move_pages, sys_move_pages) #endif #define __NR_rt_tgsigqueueinfo 240 @@ -691,6 +615,7 @@ __SC_COMP(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, \ __SYSCALL(__NR_perf_event_open, sys_perf_event_open) #define __NR_accept4 242 __SYSCALL(__NR_accept4, sys_accept4) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_recvmmsg 243 __SC_COMP_3264(__NR_recvmmsg, sys_recvmmsg_time32, sys_recvmmsg, compat_sys_recvmmsg_time32) @@ -706,6 +631,7 @@ __SC_COMP_3264(__NR_recvmmsg, sys_recvmmsg_time32, sys_recvmmsg, compat_sys_recv #define __NR_wait4 260 __SC_COMP(__NR_wait4, sys_wait4, compat_sys_wait4) #endif + #define __NR_prlimit64 261 __SYSCALL(__NR_prlimit64, sys_prlimit64) #define __NR_fanotify_init 262 @@ -716,10 +642,12 @@ __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) #define __NR_open_by_handle_at 265 __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_clock_adjtime 266 __SC_3264(__NR_clock_adjtime, sys_clock_adjtime32, sys_clock_adjtime) #endif + #define __NR_syncfs 267 __SYSCALL(__NR_syncfs, sys_syncfs) #define __NR_setns 268 @@ -727,11 +655,9 @@ __SYSCALL(__NR_setns, sys_setns) #define __NR_sendmmsg 269 __SC_COMP(__NR_sendmmsg, sys_sendmmsg, compat_sys_sendmmsg) #define __NR_process_vm_readv 270 -__SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \ - compat_sys_process_vm_readv) +__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv) #define __NR_process_vm_writev 271 -__SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ - compat_sys_process_vm_writev) +__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev) #define __NR_kcmp 272 __SYSCALL(__NR_kcmp, sys_kcmp) #define __NR_finit_module 273 @@ -772,16 +698,20 @@ __SYSCALL(__NR_pkey_alloc, sys_pkey_alloc) __SYSCALL(__NR_pkey_free, sys_pkey_free) #define __NR_statx 291 __SYSCALL(__NR_statx, sys_statx) + #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_io_pgetevents 292 __SC_COMP_3264(__NR_io_pgetevents, sys_io_pgetevents_time32, sys_io_pgetevents, compat_sys_io_pgetevents) #endif + #define __NR_rseq 293 __SYSCALL(__NR_rseq, sys_rseq) #define __NR_kexec_file_load 294 __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load) + /* 295 through 402 are unassigned to sync up with generic numbers, don't use */ -#if __BITS_PER_LONG == 32 + +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32 #define __NR_clock_gettime64 403 __SYSCALL(__NR_clock_gettime64, sys_clock_gettime) #define __NR_clock_settime64 404 @@ -846,13 +776,52 @@ __SYSCALL(__NR_fsmount, sys_fsmount) __SYSCALL(__NR_fspick, sys_fspick) #define __NR_pidfd_open 434 __SYSCALL(__NR_pidfd_open, sys_pidfd_open) + #ifdef __ARCH_WANT_SYS_CLONE3 #define __NR_clone3 435 __SYSCALL(__NR_clone3, sys_clone3) #endif +#define __NR_close_range 436 +__SYSCALL(__NR_close_range, sys_close_range) +#define __NR_openat2 437 +__SYSCALL(__NR_openat2, sys_openat2) +#define __NR_pidfd_getfd 438 +__SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) +#define __NR_faccessat2 439 +__SYSCALL(__NR_faccessat2, sys_faccessat2) +#define __NR_process_madvise 440 +__SYSCALL(__NR_process_madvise, sys_process_madvise) +#define __NR_epoll_pwait2 441 +__SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) +#define __NR_mount_setattr 442 +__SYSCALL(__NR_mount_setattr, sys_mount_setattr) +#define __NR_quotactl_fd 443 +__SYSCALL(__NR_quotactl_fd, sys_quotactl_fd) +#define __NR_landlock_create_ruleset 444 +__SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset) +#define __NR_landlock_add_rule 445 +__SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule) +#define __NR_landlock_restrict_self 446 +__SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self) + +#ifdef __ARCH_WANT_MEMFD_SECRET +#define __NR_memfd_secret 447 +__SYSCALL(__NR_memfd_secret, sys_memfd_secret) +#endif + +#define __NR_process_mrelease 448 +__SYSCALL(__NR_process_mrelease, sys_process_mrelease) +#define __NR_futex_waitv 449 +__SYSCALL(__NR_futex_waitv, sys_futex_waitv) +#define __NR_set_mempolicy_home_node 450 +__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) + +#define __NR_cachestat 451 +__SYSCALL(__NR_cachestat, sys_cachestat) + #undef __NR_syscalls -#define __NR_syscalls 436 +#define __NR_syscalls 452 /* * 32 bit systems traditionally used different diff --git a/darling/src/libsystem_kernel/emulation/linux/mach/darling_mach_syscall.S b/darling/src/libsystem_kernel/emulation/linux/mach/darling_mach_syscall.S index edd17a0..c189a91 100644 --- a/darling/src/libsystem_kernel/emulation/linux/mach/darling_mach_syscall.S +++ b/darling/src/libsystem_kernel/emulation/linux/mach/darling_mach_syscall.S @@ -2,6 +2,29 @@ .globl __darling_mach_syscall .private_extern __darling_mach_syscall +// To better understand how XTRACE_RESERVED_SPACE +// works, I recommend looking at `src/xtrace/xtracelib.c` +// for details. +#if defined(__x86_64__) +.macro XTRACE_RESERVED_SPACE + .space 13, 0x90 +.endmacro + +#elif defined(__i386__) +.macro XTRACE_RESERVED_SPACE + .space 7, 0x90 +.endmacro + +#elif defined(__arm64__) +.macro XTRACE_RESERVED_SPACE + nop ; movk + nop ; movk + nop ; movk + nop ; movk + nop ; blr +.endmacro +#endif + #if defined(__x86_64__) __darling_mach_syscall: @@ -10,7 +33,7 @@ __darling_mach_syscall: negl %eax Lpositive: Lentry_hook: - .space 13, 0x90 + XTRACE_RESERVED_SPACE movq ___mach_syscall_table@GOTPCREL(%rip), %r10 movq (%r10,%rax,8), %r10 test %r10, %r10 @@ -24,7 +47,7 @@ Lentry_hook: addq $16, %rsp .std_ret: Lexit_hook: - .space 13, 0x90 + XTRACE_RESERVED_SPACE ret .no_sys: movq %rax, %rdi @@ -51,7 +74,7 @@ __darling_mach_syscall: negl %eax Lpositive: Lentry_hook: - .space 7, 0x90 + XTRACE_RESERVED_SPACE calll 1f 1: popl %ecx @@ -82,7 +105,7 @@ Lentry_hook: addl $56, %esp .std_ret: Lexit_hook: - .space 7, 0x90 + XTRACE_RESERVED_SPACE ret .no_sys: pushl %ecx @@ -106,6 +129,50 @@ __darling_mach_syscall_exit: .subsections_via_symbols +#elif defined(__arm64__) + +.balign 4 +__darling_mach_syscall: + stp fp, lr, [sp, #-16]! + mov fp, sp + +Lentry_hook: + XTRACE_RESERVED_SPACE + + // void* x9 = &__mach_syscall_table + adrp x9, ___mach_syscall_table@PAGE + add x9, x9, ___mach_syscall_table@PAGEOFF + + neg x10, x16 // Convert negative syscall number to positive + ldr x10, [x9, x10, lsl #3] // x10 = __mach_syscall_table[x10] + + // If x9 is null + cbz x10, mach_no_syscall + + // x10(...) + blr x10 + b mach_return + +mach_no_syscall: + mov x0, x16 + bl ___unknown_mach_syscall + +mach_return: +Lexit_hook: + XTRACE_RESERVED_SPACE + + ldp fp, lr, [sp], #16 + ret + + +.section __DATA,__data +.globl __darling_mach_syscall_entry +.globl __darling_mach_syscall_exit + +__darling_mach_syscall_entry: + .long Lentry_hook +__darling_mach_syscall_exit: + .long Lexit_hook #else # error Missing assembly #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/machdep/machdep-table.S b/darling/src/libsystem_kernel/emulation/linux/machdep/machdep-table.S index e063c4b..6f985fb 100644 --- a/darling/src/libsystem_kernel/emulation/linux/machdep/machdep-table.S +++ b/darling/src/libsystem_kernel/emulation/linux/machdep/machdep-table.S @@ -63,6 +63,9 @@ L___machdep_syscall_table$non_lazy_ptr: .subsections_via_symbols +#elif defined(__arm64__) +// Not required for arm64 + #else # error Missing assembly #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/machdep/tls.c b/darling/src/libsystem_kernel/emulation/linux/machdep/tls.c index d9b8156..d5d51cb 100644 --- a/darling/src/libsystem_kernel/emulation/linux/machdep/tls.c +++ b/darling/src/libsystem_kernel/emulation/linux/machdep/tls.c @@ -1,3 +1,4 @@ +#include #include #include "tls.h" @@ -38,6 +39,10 @@ void sys_thread_set_tsd_base(void* ptr, int unk) entry_number = desc.entry_number; __asm__ ("movl %0, %%fs" :: "r" (desc.entry_number*8 + 3)); +#elif defined(__arm64__) + __darling_thread_set_tsd(ptr); +#else +#error "Missing sys_thread_set_tsd_base implementation for arch" #endif } diff --git a/darling/src/libsystem_kernel/emulation/linux/misc/sysctl_machdep.c b/darling/src/libsystem_kernel/emulation/linux/misc/sysctl_machdep.c index b3dbb87..e12bf29 100644 --- a/darling/src/libsystem_kernel/emulation/linux/misc/sysctl_machdep.c +++ b/darling/src/libsystem_kernel/emulation/linux/misc/sysctl_machdep.c @@ -50,6 +50,7 @@ const struct known_sysctl sysctls_machdep[] = { { .oid = -1 } }; +#if defined(__x86_64__) || defined(__i386__) #ifndef __cpuid #define __cpuid(level, a, b, c, d) \ __asm__ ("cpuid\n\t" \ @@ -65,7 +66,7 @@ const struct known_sysctl sysctls_machdep[] = { unsigned int edx; \ unsigned int ecx #endif - +#endif // defined(__x86_64__) || defined(__i386__) static inline void copyout_int(int value, char* to_copy, size_t* to_copy_length) { @@ -77,6 +78,7 @@ static inline void copyout_int(int value, char* to_copy, size_t* to_copy_length) sysctl_handler(handle_vendor) { +#if defined(__x64_64__) || defined(__i386__) unsigned int level = 0; unsigned int eax = 0; union @@ -95,11 +97,16 @@ sysctl_handler(handle_vendor) v.name[12] = 0; copyout_string(v.name, (char*) old, oldlen); +#else +#warning "Missing sysctl_handler(handle_vendor) implementation for arch" +#endif + return 0; } sysctl_handler(handle_max_basic) { +#if defined(__x86_64__) || defined(__i386__) setup(0); @@ -107,11 +114,16 @@ sysctl_handler(handle_max_basic) copyout_int(eax, (char*)old,oldlen); +#else +#warning "Missing sysctl_handler(handle_max_basic) implementation for arch" +#endif + return 0; } sysctl_handler(handle_family) { +#if defined(__x86_64__) || defined(__i386__) setup(1); __cpuid(level, eax, ebx, ecx, edx); @@ -121,11 +133,16 @@ sysctl_handler(handle_family) copyout_int(eax, old, oldlen); +#else +#warning "Missing sysctl_handler(handle_family) implementation for arch" +#endif + return 0; } sysctl_handler(handle_model) { +#if defined(__x86_64__) || defined(__i386__) setup(1); __cpuid(level, eax, ebx, ecx, edx); @@ -135,11 +152,16 @@ sysctl_handler(handle_model) copyout_int(eax,(char*)old, oldlen); +#else +#warning "Missing sysctl_handler(handle_model) implementation for arch" +#endif + return 0; } sysctl_handler(handle_stepping) { +#if defined(__x86_64__) || defined(__i386__) setup(1); __cpuid(level, eax, ebx, ecx, edx); @@ -148,11 +170,16 @@ sysctl_handler(handle_stepping) copyout_int(eax,(char*)old, oldlen); +#else +#warning "Missing sysctl_handler(handle_stepping) implementation for arch" +#endif + return 0; } sysctl_handler(handle_brand_string) { +#if defined(__x86_64__) || defined(__i386__) setup(0x80000000); __cpuid(level,eax,ebx, ecx, edx); @@ -181,12 +208,16 @@ sysctl_handler(handle_brand_string) v.name[48] = 0; copyout_string(v.name, (char*) old, oldlen); +#else +#warning "Missing sysctl_handler(handle_brand_string) implementation for arch" +#endif + return 0; } sysctl_handler(handle_features) { - +#if defined(__x86_64__) || defined(__i386__) setup(1); static const char features[][7] = {"FPU","VME", "DE", "PSE", "TSC", "MSR", "PAE", "MCE", "CX8", "APIC", "","SEP","MTRR","PGE", @@ -256,7 +287,9 @@ sysctl_handler(handle_features) } - +#else +#warning "Missing sysctl_handler(handle_features) implementation for arch" +#endif return 0; diff --git a/darling/src/libsystem_kernel/emulation/linux/resources/dserver-rpc-defs.c b/darling/src/libsystem_kernel/emulation/linux/resources/dserver-rpc-defs.c index 9627431..c8f4b26 100644 --- a/darling/src/libsystem_kernel/emulation/linux/resources/dserver-rpc-defs.c +++ b/darling/src/libsystem_kernel/emulation/linux/resources/dserver-rpc-defs.c @@ -7,6 +7,8 @@ #include "../unistd/pipe.h" #include "../unistd/read.h" +#include "../common_at.h" + #ifndef DSERVER_RPC_USE_LOG_FILE // CHANGE TO 0 BEFORE COMMITTING #define DSERVER_RPC_USE_LOG_FILE 1 @@ -85,7 +87,7 @@ static int printf_file = -1; static libsimple_once_t printf_file_token = LIBSIMPLE_ONCE_INITIALIZER; static void printf_file_init(void* context) { - printf_file = LINUX_SYSCALL(__NR_open, "/tmp/dserver-client-rpc.log", LINUX_O_WRONLY | LINUX_O_CREAT | LINUX_O_APPEND, 0644); + printf_file = LINUX_SYSCALL(__NR_openat, LINUX_AT_FDCWD, "/tmp/dserver-client-rpc.log", LINUX_O_WRONLY | LINUX_O_CREAT | LINUX_O_APPEND, 0644); }; #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/select/select.c b/darling/src/libsystem_kernel/emulation/linux/select/select.c index ad64400..047d3fa 100644 --- a/darling/src/libsystem_kernel/emulation/linux/select/select.c +++ b/darling/src/libsystem_kernel/emulation/linux/select/select.c @@ -1,6 +1,7 @@ #include "select.h" #include "../base.h" #include "../errno.h" +#include "pselect.h" #include #include #include "../bsdthread/cancelable.h" diff --git a/darling/src/libsystem_kernel/emulation/linux/signal/sig_restorer.S b/darling/src/libsystem_kernel/emulation/linux/signal/sig_restorer.S index 4d3230d..6427b04 100644 --- a/darling/src/libsystem_kernel/emulation/linux/signal/sig_restorer.S +++ b/darling/src/libsystem_kernel/emulation/linux/signal/sig_restorer.S @@ -3,14 +3,25 @@ .private_extern _sig_restorer #ifdef __x86_64__ +#define __NR_rt_sigreturn 15 _sig_restorer: - movl $15, %eax + movl $__NR_rt_sigreturn, %eax syscall #elif defined(__i386__) - +#define __NR_rt_sigreturn 173 _sig_restorer: - movl $173, %eax + movl $__NR_rt_sigreturn, %eax int $0x80 + +#elif defined(__arm64__) +#define __NR_rt_sigreturn 139 +.balign 4 +_sig_restorer: + mov w8, #__NR_rt_sigreturn + svc #0 + +#else +#error "Missing sig_restorer implementation for arch" #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.c b/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.c index 098198d..74eda4d 100644 --- a/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.c +++ b/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.c @@ -171,6 +171,29 @@ long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sig } #endif +#ifdef __arm64__ +// Some values are stored in the __reserved array. +void grab_contexts_from_reserved(struct linux_mcontext* lm, struct fpsimd_context** reserved_neon_context, struct esr_context** reserved_esr_el1_context) { + struct _aarch64_ctx* reserved_header = (struct _aarch64_ctx*)lm->__reserved; + const struct _aarch64_ctx* RESERVED_MAX_LIMIT = (struct _aarch64_ctx*)lm->__reserved + 4096; + do { + if (reserved_header + reserved_header->size > RESERVED_MAX_LIMIT) { + break; + } + + if (reserved_header->magic == FPSIMD_MAGIC) { + *reserved_neon_context = (struct fpsimd_context*)reserved_header; + } else if (reserved_header->magic == ESR_MAGIC) { + *reserved_esr_el1_context = (struct esr_context*)reserved_header; + } + + reserved_header += reserved_header->size; + + // The last structure must be a dummy one with the magic and size set to 0 + } while (reserved_header->magic != 0 && reserved_header->size != 0); +} +#endif + static void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_ucontext* bc, struct bsd_mcontext* bm) { bc->uc_onstack = 1; @@ -182,18 +205,44 @@ static void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_uc bc->uc_stack.ss_flags = lc->uc_stack.ss_flags; bc->uc_stack.ss_size = lc->uc_stack.ss_size; bc->uc_stack.ss_sp = lc->uc_stack.ss_sp; + +#ifdef __arm64__ + struct fpsimd_context* reserved_neon_context = NULL; + struct esr_context* reserved_esr_el1_context = NULL; + grab_contexts_from_reserved(&lc->uc_mcontext, &reserved_neon_context, &reserved_esr_el1_context); +#endif + +#if defined(__x86_64__) || defined(__i386__) bm->es.trapno = lc->uc_mcontext.gregs.trapno; bm->es.cpu = 0; bm->es.err = lc->uc_mcontext.gregs.err; #ifdef __x86_64__ bm->es.faultvaddr = lc->uc_mcontext.gregs.rip; -#else +#elif defined(__i386__) bm->es.faultvaddr = lc->uc_mcontext.gregs.eip; #endif - +#elif defined(__arm64__) + bm->es.far = lc->uc_mcontext.fault_address; + bm->es.esr = 0; + bm->es.exception = 0; + if (reserved_esr_el1_context != NULL) { + // I not really sure how I should handle this... + // esr on Linux is 64bits, while esr on macOS is 32bits + bm->es.esr = 0xFFFFFFFF & reserved_esr_el1_context->esr; + bm->es.exception = 0xFFFFFFFF & (reserved_esr_el1_context->esr >> 32); + } +#else +#error "Missing exception state (Linux to BSD) conversion" +#endif + +#if defined(__x86_64__) || defined(__i386___) #define copyreg(__name) bm->ss.__name = lc->uc_mcontext.gregs.__name - +#elif defined(__arm64__) +#define copyreg2(__bsdname, __linuxname) bm->ss.__bsdname = lc->uc_mcontext.__linuxname +#define copyreg(__name) copyreg2(__name, __name) +#endif + #ifdef __x86_64__ copyreg(rax); copyreg(rbx); copyreg(rcx); copyreg(rdx); copyreg(rdi); copyreg(rsi); copyreg(rbp); copyreg(rsp); copyreg(r8); copyreg(r9); copyreg(r10); @@ -207,16 +256,62 @@ static void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_uc copyreg(eip); copyreg(cs); copyreg(ds); copyreg(es); copyreg(fs); copyreg(gs); bm->ss.eflags = lc->uc_mcontext.gregs.efl; bm->ss.ss = 0; + +#elif defined(__arm64__) + for (int i=0; i<29; i++) { + copyreg2(x[i],regs[i]); + } + copyreg2(fp,regs[29]); copyreg2(lr,regs[30]); + copyreg(sp); copyreg(pc); + + bm->ss.cpsr = 0xFFFFFFFF & lc->uc_mcontext.pstate; + bm->ss.flags = 0xFFFFFFFF & (lc->uc_mcontext.pstate >> 32); + #else -# warning Missing code for current arch +#error Missing thread state (Linux to BSD) conversion #endif - + #undef copyreg +#undef copyreg2 + +#if defined(__x86_64__) || defined(__i386__) +#warning "Missing float state (Linux to BSD) conversion for x86_64/i386" + +#elif defined(__arm64__) +#define copyreg2(__bsdname, __linuxname) bm->ns.__bsdname = reserved_neon_context->__linuxname +#define copyreg(__name) copyreg2(__name, __name) + + if (reserved_neon_context != NULL) { + for (int i=0; i<32; i++) { + copyreg2(q[i], vregs[i]); + } + copyreg(fpsr); + copyreg(fpcr); + } + +#else +#error "Missing float/simd state (Linux to BSD) conversion" +#endif + +#undef copyreg +#undef copyreg2 + } static void mcontext_bsd_to_linux(const struct bsd_mcontext* bm, struct linux_mcontext* lm) { +#if defined(__x86_64__) || defined(__i386__) #define copyreg(__name) lm->gregs.__name = bm->ss.__name +#elif defined(__arm64__) +#define copyreg2(__linuxname, __bsdname) lm->__linuxname = bm->ss.__bsdname; +#define copyreg(__name) copyreg2(__name, __name) +#endif + +#ifdef __arm64__ + struct fpsimd_context* reserved_neon_context = NULL; + struct esr_context* reserved_esr_el1_context = NULL; + grab_contexts_from_reserved(lm, &reserved_neon_context, &reserved_esr_el1_context); +#endif #ifdef __x86_64__ copyreg(rax); copyreg(rbx); copyreg(rcx); copyreg(rdx); copyreg(rdi); copyreg(rsi); @@ -229,10 +324,45 @@ static void mcontext_bsd_to_linux(const struct bsd_mcontext* bm, struct linux_mc copyreg(ebp); copyreg(esp); copyreg(eip); copyreg(cs); copyreg(ds); copyreg(es); copyreg(fs); copyreg(gs); lm->gregs.efl = bm->ss.eflags; +#elif defined(__arm64__) + for (int i=0; i<29; i++) { + copyreg2(regs[i],x[i]); + } + copyreg2(regs[29],fp); copyreg2(regs[30],lr); + copyreg(sp); copyreg(pc); + + lm->pstate = bm->ss.cpsr; + lm->pstate |= (long long int)bm->ss.flags << 32; + + if (reserved_esr_el1_context != NULL) { + reserved_esr_el1_context->esr = bm->es.esr; + reserved_esr_el1_context->esr |= (__uint64_t)reserved_esr_el1_context->esr << 32; + } #else -# warning Missing code for current arch +#error Missing thread state (BSD to Linux) conversion +#endif + +#undef copyreg +#undef copyreg2 + +#if defined(__arm64__) +#define copyreg2(__linuxname, __bsdname) reserved_neon_context->__linuxname = bm->ns.__bsdname; +#define copyreg(__name) copyreg2(__name, __name) #endif +#ifdef __arm64__ + if (reserved_neon_context != NULL) { + for (int i=0; i<32; i++) { + copyreg2(vregs[i],q[i]); + } + copyreg(fpsr); + copyreg(fpcr); + } +#endif + +#undef copyreg +#undef copyreg2 + } static void handler_linux_to_bsd_wrapper(int linux_signum, struct linux_siginfo* info, void* ctxt) { diff --git a/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.h b/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.h index 6fe97d4..8ddae3e 100644 --- a/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.h +++ b/darling/src/libsystem_kernel/emulation/linux/signal/sigaction.h @@ -124,7 +124,7 @@ struct linux_gregset long long err, trapno, oldmask, cr2; }; -#else // now the i386 version +#elif defined(__i386__) typedef struct _fpstate { unsigned long cw, sw, tag, ipoff, cssel, dataoff, datasel; @@ -151,20 +151,60 @@ struct linux_gregset int trapno, err, eip, cs, efl, uesp; int ss; }; + #endif +// /usr/include/sys/ucontext.h (based on `typedef struct {...} mcontext_t`) struct linux_mcontext { +#if defined(__x86_64__) || defined(__i386__) struct linux_gregset gregs; linux_fpregset_t fpregs; #ifdef __x86_64__ unsigned long long __reserved[8]; -#else +#elif defined(__i386__) unsigned long oldmask, cr2; #endif // +reserved + +#elif defined(__arm64__) + unsigned long long int fault_address; + unsigned long long int regs[31]; + unsigned long long int sp; + unsigned long long int pc; + unsigned long long int pstate; + unsigned char __reserved[4096] __attribute__((__aligned__(16))); + +#else +#error "Missing linux_mcontext implementation for arch" +#endif +}; + +// /usr/include/asm/sigcontext.h +#ifdef __arm64__ +struct _aarch64_ctx { + __uint32_t magic; + __uint32_t size; +}; + +#define FPSIMD_MAGIC 0x46508001 + +struct fpsimd_context { + struct _aarch64_ctx head; + __uint32_t fpsr; + __uint32_t fpcr; + __uint128_t vregs[32]; +}; + +#define ESR_MAGIC 0x45535201 + +struct esr_context { + struct _aarch64_ctx head; + __uint64_t esr; }; +#endif +// /usr/include/asm-generic/ucontext.h (based on struct ucontext) struct linux_ucontext { unsigned long uc_flags; @@ -177,35 +217,74 @@ struct linux_ucontext struct bsd_exception_state { +#if defined(__x86_64__) || defined(__i386__) + // [xnu]/osfmk/mach/i386/_structs.h (based on `struct x86_exception_state64`) unsigned short trapno; unsigned short cpu; unsigned int err; unsigned long faultvaddr; +#elif defined(__arm64__) + // [xnu]/osfmk/mach/arm/_structs.h (based on `struct arm_exception_state64`) + __uint64_t far; // Fault Address Register + __uint32_t esr; // Exception Syndrome Register + __uint32_t exception; +#else +#error "Missing bsd_exception_state implementation for arch" +#endif }; struct bsd_thread_state { #ifdef __x86_64__ +// [xnu]/osfmk/mach/i386/_structs.h (based on `struct x86_thread_state64`) long long rax, rbx, rcx, rdx, rdi, rsi, rbp, rsp, r8, r9, r10; long long r11, r12, r13, r14, r15, rip, rflags, cs, fs, gs; -#else +#elif defined(__i386__) +// [xnu]/osfmk/mach/i386/_structs.h (based on `struct i386_thread_state`) int eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags; int eip, cs, ds, es, fs, gs; +#elif defined(__arm64__) +// [xnu]/osfmk/mach/arm/_structs.h (based on `struct arm_thread_state64`) + __uint64_t x[29]; + __uint64_t fp, lr, sp, pc; + __uint32_t cpsr, flags; +#else +#error "Missing bsd_thread_state implementation" #endif }; +#if defined(__x86_64__) || defined(__i386__) struct bsd_float_state { // TODO }; +#elif defined(__arm64__) +// [xnu]/osfmk/mach/arm/_structs.h (based on `struct arm_neon_state64`) +struct bsd_neon_state { + __uint128_t q[32]; + __uint32_t fpsr; + __uint32_t fpcr; +}; +#else +#error "Missing float/simd state for arch" +#endif +// [xnu]/bsd/i386/_mcontext.h (see `struct mcontext64`) +// [xnu]/bsd/arm/_mcontext.h (see `struct mcontext64`) struct bsd_mcontext { struct bsd_exception_state es; struct bsd_thread_state ss; +#if defined(__x86_64__) || defined(__i386__) struct bsd_float_state fs; +#elif defined(__arm64__) + struct bsd_neon_state ns; +#else +#error "Missing float/simd state in bsd_mcontext" +#endif }; +// [xnu]/bsd/sys/ucontext.h (based on `struct user_ucontext64`?) struct bsd_ucontext { int uc_onstack; diff --git a/darling/src/libsystem_kernel/emulation/linux/signal/sigaltstack.h b/darling/src/libsystem_kernel/emulation/linux/signal/sigaltstack.h index 8f926ee..989292b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/signal/sigaltstack.h +++ b/darling/src/libsystem_kernel/emulation/linux/signal/sigaltstack.h @@ -1,6 +1,7 @@ #ifndef LINUX_SIGALTSTACK_H #define LINUX_SIGALTSTACK_H +// [xnu]/bsd/sys/signal.h (based on `struct user64_sigaltstack`?) struct bsd_stack { void* ss_sp; @@ -8,6 +9,7 @@ struct bsd_stack int ss_flags; }; +// /usr/include/asm-generic/signal.h (based on `typedef struct sigaltstack {...} stack_t`) struct linux_stack { void* ss_sp; diff --git a/darling/src/libsystem_kernel/emulation/linux/signal/sigexc.c b/darling/src/libsystem_kernel/emulation/linux/signal/sigexc.c index 23b6334..1ef5400 100644 --- a/darling/src/libsystem_kernel/emulation/linux/signal/sigexc.c +++ b/darling/src/libsystem_kernel/emulation/linux/signal/sigexc.c @@ -15,6 +15,19 @@ #include +struct darwin_states { +#if defined(__x86_64__) + x86_thread_state64_t tstate; + x86_float_state64_t fstate; +#elif defined(__i386__) + x86_thread_state32_t tstate; + x86_float_state32_t fstate; +#elif defined(__arm64__) + arm_thread_state64_t tstate; + arm_neon_state64_t nstate; +#endif +}; + // Support for Darwin debugging. // Unlike other Unix-like systems, macOS doesn't use wait() to handle events in the debugged process. // wait() only receives termination events. @@ -54,10 +67,15 @@ static void mcontext_to_thread_state(const struct linux_gregset* regs, x86_threa static void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state32_t* s); static void thread_state_to_mcontext(const x86_thread_state32_t* s, struct linux_gregset* regs); static void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx); +#elif defined(__arm64__) +static void mcontext_to_thread_and_neon_state(const struct linux_mcontext* lm, arm_thread_state64_t* ts, arm_neon_state64_t* ns); +static void thread_and_neon_state_to_mcontext(const arm_thread_state64_t* ts, const arm_neon_state64_t* ns, struct linux_mcontext* lm); +extern void grab_contexts_from_reserved(struct linux_mcontext* lm, struct fpsimd_context** reserved_neon_context, struct esr_context** reserved_esr_el1_context); #endif -static void state_from_kernel(struct linux_ucontext* ctxt, const void* tstate, const void* fstate); -static void state_to_kernel(struct linux_ucontext* ctxt, void* tstate, void* fstate); +static void state_from_kernel(struct linux_ucontext* ctxt, const struct darwin_states* states); +static void state_to_kernel(struct linux_ucontext* ctxt, struct darwin_states* states); +int dserver_rpc_thread_suspended_wrapper(struct darwin_states* states); #define DEBUG_SIGEXC #ifdef DEBUG_SIGEXC @@ -144,6 +162,16 @@ void sigexc_setup(void) #endif } +int dserver_rpc_thread_suspended_wrapper(struct darwin_states* states) { +#if defined(__x86_64__) || defined(__i386__) + return dserver_rpc_thread_suspended(&states->tstate, &states->fstate, NULL); +#elif defined(__arm64__) + return dserver_rpc_thread_suspended(&states->tstate, NULL, &states->nstate); +#else +#error "Missing dserver_rpc_thread_suspended_wrapper implementation for arch" +#endif +} + void sigrt_handler(int signum, struct linux_siginfo* info, struct linux_ucontext* ctxt) { int status = dserver_rpc_interrupt_enter(); @@ -154,26 +182,20 @@ void sigrt_handler(int signum, struct linux_siginfo* info, struct linux_ucontext } if (signum == SIGNAL_SIGEXC_SUSPEND) { -#if defined(__x86_64__) - x86_thread_state64_t tstate; - x86_float_state64_t fstate; -#elif defined(__i386__) - x86_thread_state32_t tstate; - x86_float_state32_t fstate; -#endif + struct darwin_states states; - kern_printf("sigexc: sigrt_handler SUSPEND\n"); + kern_printf("sigexc: sigrt_handler SUSPEND\n"); - thread_t thread = mach_thread_self(); - state_to_kernel(ctxt, &tstate, &fstate); + thread_t thread = mach_thread_self(); + state_to_kernel(ctxt, &states); - int ret = dserver_rpc_thread_suspended(&tstate, &fstate); - if (ret < 0) { - __simple_printf("dserver_rpc_thread_suspended failed internally: %d", ret); - __simple_abort(); - } + int ret = dserver_rpc_thread_suspended_wrapper(&states); + if (ret < 0) { + __simple_printf("dserver_rpc_thread_suspended failed internally: %d", ret); + __simple_abort(); + } - state_from_kernel(ctxt, &tstate, &fstate); + state_from_kernel(ctxt, &states); } else if (signum == SIGNAL_S2C) { __simple_kprintf("sigexc: sigrt_handler S2C"); @@ -235,33 +257,54 @@ void darling_sigexc_self(void) } -static void state_to_kernel(struct linux_ucontext* ctxt, void* tstate, void* fstate) +static void state_to_kernel(struct linux_ucontext* ctxt, struct darwin_states* states) { #if defined(__x86_64__) - dump_gregs(&ctxt->uc_mcontext.gregs); - mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state64_t*) tstate); - mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state64_t*) fstate); + mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &states->tstate); + mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &states->fstate); #elif defined(__i386__) - mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state32_t*) tstate); - mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state32_t*) fstate); + mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &states->tstate); + mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &states->fstate); + +#elif defined(__arm64__) + mcontext_to_thread_and_neon_state(&ctxt->uc_mcontext, &states->tstate, &states->nstate); + +#else +#error "Missing mcontext to state conversion" #endif } -static void state_from_kernel(struct linux_ucontext* ctxt, const void* tstate, const void* fstate) +static void state_from_kernel(struct linux_ucontext* ctxt, const struct darwin_states* states) { #if defined(__x86_64__) - - thread_state_to_mcontext((const x86_thread_state64_t*) tstate, &ctxt->uc_mcontext.gregs); - float_state_to_mcontext((const x86_float_state64_t*) fstate, ctxt->uc_mcontext.fpregs); + thread_state_to_mcontext((const x86_thread_state64_t*) &states->tstate, &ctxt->uc_mcontext.gregs); + float_state_to_mcontext((const x86_float_state64_t*) &states->fstate, ctxt->uc_mcontext.fpregs); dump_gregs(&ctxt->uc_mcontext.gregs); #elif defined(__i386__) - thread_state_to_mcontext((const x86_thread_state32_t*) tstate, &ctxt->uc_mcontext.gregs); - float_state_to_mcontext((const x86_float_state32_t*) fstate, ctxt->uc_mcontext.fpregs); + thread_state_to_mcontext((const x86_thread_state32_t*) &states->tstate, &ctxt->uc_mcontext.gregs); + float_state_to_mcontext((const x86_float_state32_t*) &states->fstate, ctxt->uc_mcontext.fpregs); + +#elif defined(__arm64__) + thread_and_neon_state_to_mcontext(&states->tstate, &states->nstate, &ctxt->uc_mcontext); + +#else +#error "Missing state to mcontext conversion" +#endif +} + +int dserver_rpc_sigprocess_wrapper(int32_t bsd_signal_number, int32_t linux_signal_number, int32_t sender_pid, int32_t code, uint64_t signal_address, struct darwin_states* states, int32_t* out_new_bsd_signal_number) { +#if defined(__x86_64__) || defined(__i386__) + dserver_rpc_sigprocess(bsd_signal_number, linux_signal_number, sender_pid, code, signal_address, &states->tstate, &states->fstate, NULL, out_new_bsd_signal_number); +#elif defined(__arm64__) + dserver_rpc_sigprocess(bsd_signal_number, linux_signal_number, sender_pid, code, signal_address, &states->tstate, NULL, &states->nstate, out_new_bsd_signal_number); + +#else +#error "Missing dserver_rpc_sigprocess_wrapper implementation for arch" #endif } @@ -293,21 +336,15 @@ void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_u thread_t thread = mach_thread_self(); -#if defined(__x86_64__) - x86_thread_state64_t tstate; - x86_float_state64_t fstate; -#elif defined(__i386__) - x86_thread_state32_t tstate; - x86_float_state32_t fstate; -#endif + struct darwin_states states; - state_to_kernel(ctxt, &tstate, &fstate); - int ret = dserver_rpc_sigprocess(bsd_signum, linux_signum, info->si_pid, info->si_code, info->si_addr, &tstate, &fstate, &bsd_signum); + state_to_kernel(ctxt, &states); + int ret = dserver_rpc_sigprocess_wrapper(bsd_signum, linux_signum, info->si_pid, info->si_code, info->si_addr, &states, &bsd_signum); if (ret < 0) { __simple_printf("sigprocess failed internally while processing Linux signal %d: %d", linux_signum, ret); __simple_abort(); } - state_from_kernel(ctxt, &tstate, &fstate); + state_from_kernel(ctxt, &states); if (!bsd_signum) { @@ -571,6 +608,62 @@ void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx) memcpy(fx->_st, &s->__fpu_stmm0, 128); memcpy(fx->_xmm, &s->__fpu_xmm0, 128); } + +#elif defined(__arm64__) +static void mcontext_to_thread_and_neon_state(const struct linux_mcontext* lm, arm_thread_state64_t* ts, arm_neon_state64_t* ns) { + struct fpsimd_context* reserved_neon_context = NULL; + struct esr_context* reserved_esr_el1_context = NULL; + grab_contexts_from_reserved(lm, &reserved_neon_context, &reserved_esr_el1_context); + + for (int i=0; i<29; i++) { + ts->__x[i] = lm->regs[i]; + } + ts->__fp = lm->regs[29]; + ts->__lr = lm->regs[30]; + ts->__sp = lm->sp; + ts->__pc = lm->pc; + + // Not sure about this one... + ts->__cpsr = 0xFFFFFFFF & lm->pstate; + ts->__pad = 0xFFFFFFFF & (lm->pstate >> 32); + + if (reserved_neon_context != NULL) { + for (int i=0; i<32; i++) { + ns->__v[i] = reserved_neon_context->vregs[i]; + } + ns->__fpsr = reserved_neon_context->fpsr; + ns->__fpcr = reserved_neon_context->fpcr; + } +} + +static void thread_and_neon_state_to_mcontext(const arm_thread_state64_t* ts, const arm_neon_state64_t* ns, struct linux_mcontext* lm) { + struct fpsimd_context* reserved_neon_context; + struct esr_context* reserved_esr_el1_context; + grab_contexts_from_reserved(lm, &reserved_neon_context, &reserved_esr_el1_context); + + for (int i=0; i<29; i++) { + lm->regs[i] = ts->__x[i]; + } + lm->regs[29] = ts->__fp; + lm->regs[30] = ts->__lr; + lm->sp = ts->__sp; + lm->pc = ts->__pc; + + lm->pstate = (ts->__cpsr & 0xFFFFFFFF); + lm->pstate |= ((unsigned long long int)ts->__pad << 32) & 0xFFFFFFFF00000000; + + if (reserved_neon_context != NULL) { + for (int i=0; i<32; i++) { + reserved_neon_context->vregs[i] = ns->__v[i]; + } + + reserved_neon_context->fpsr = ns->__fpsr; + reserved_neon_context->fpcr = ns->__fpcr; + } +} + +#else +#error #error "Missing mcontext to state conversion functions" #endif void sigexc_thread_setup(void) diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/common.c b/darling/src/libsystem_kernel/emulation/linux/stat/common.c index c4b47f5..803c184 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/common.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/common.c @@ -1,5 +1,9 @@ +#if defined(__x86_64__) || defined(__i386__) // This is needed so stat is not stat64 +// Only i386/x86_64 are allowed to have seperate stat/stat64 (this is due to +// `__DARWIN_ONLY_64_BIT_INO_T` being set to false only on those architectures) #define _DARWIN_NO_64_BIT_INODE +#endif // NOTE: in this case, platform-include/sys/stat.h is used #include @@ -7,6 +11,7 @@ #include "../unistd/getuid.h" #include "../unistd/getgid.h" +#if defined(__i386__) || defined(__x86_64__) void stat_linux_to_bsd(const struct linux_stat* lstat, struct stat* stat) { stat->st_dev = lstat->st_dev; @@ -27,8 +32,14 @@ void stat_linux_to_bsd(const struct linux_stat* lstat, struct stat* stat) stat->st_ctimespec.tv_nsec = lstat->st_ctime_nsec; stat->st_flags = 0; } +#endif +#if defined(__i386__) || defined(__x86_64__) void stat_linux_to_bsd64(const struct linux_stat* lstat, struct stat64* stat) +#elif defined(__arm64__) +// For arm64, stat is the same as stat64 +void stat_linux_to_bsd(const struct linux_stat* lstat, struct stat* stat) +#endif { stat->st_dev = lstat->st_dev; stat->st_mode = lstat->st_mode; diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/common.h b/darling/src/libsystem_kernel/emulation/linux/stat/common.h index 613a362..499387c 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/common.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/common.h @@ -42,7 +42,7 @@ struct linux_stat { unsigned long long st_ino; }; -#else +#elif defined(__x86_64__) typedef unsigned long long __kernel_ulong_t; typedef long long __kernel_long_t; @@ -77,6 +77,50 @@ struct linux_stat { __kernel_long_t __unused_var[3]; }; +#elif defined(__arm64__) + +typedef unsigned long int __linux_dev_t; +typedef unsigned long int __linux_ino64_t; +typedef unsigned int __linux_mode_t; +typedef unsigned int __linux_nlink_t; +typedef unsigned int __linux_uid_t; +typedef unsigned int __linux_gid_t; +typedef long int __linux_off64_t; +typedef int __linux_blksize_t; +typedef long int __linux_blkcnt64_t; +typedef long int __linux_time_t; + +#ifdef st_atime +# undef st_atime +# undef st_mtime +# undef st_ctime +#endif + +struct linux_stat + { + __linux_dev_t st_dev; + __linux_ino64_t st_ino; + __linux_mode_t st_mode; + __linux_nlink_t st_nlink; + __linux_uid_t st_uid; + __linux_gid_t st_gid; + __linux_dev_t st_rdev; + __linux_dev_t __pad1; + __linux_off64_t st_size; + __linux_blksize_t st_blksize; + int __pad2; + __linux_blkcnt64_t st_blocks; + __linux_time_t st_atime; + unsigned long int st_atime_nsec; + __linux_time_t st_mtime; + unsigned long int st_mtime_nsec; + __linux_time_t st_ctime; + unsigned long int st_ctime_nsec; + int __glibc_reserved[2]; + }; + +#else +#error "Missing stat for arch" #endif struct bsd_statfs diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstat.c b/darling/src/libsystem_kernel/emulation/linux/stat/fstat.c index b714aa0..aa0081b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstat.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstat.c @@ -23,7 +23,11 @@ long sys_fstat(int fd, struct stat* stat) return 0; } +#if defined(__i386__) || defined(__x86_64__) long sys_fstat64(int fd, struct stat64* stat) +#elif defined(__arm64__) +long sys_fstat64(int fd, struct stat* stat) +#endif { int ret; struct linux_stat lstat; @@ -37,7 +41,13 @@ long sys_fstat64(int fd, struct stat64* stat) if (ret < 0) return errno_linux_to_bsd(ret); +#if defined(__i386__) || defined(__x86_64__) stat_linux_to_bsd64(&lstat, stat); +#elif defined(__arm64__) + stat_linux_to_bsd(&lstat, stat); +#else +#error "Missing stat conversion method for arch" +#endif return 0; } diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstat.h b/darling/src/libsystem_kernel/emulation/linux/stat/fstat.h index 5a45cfa..5fc7ea5 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstat.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstat.h @@ -5,7 +5,12 @@ struct stat; struct stat64; long sys_fstat(int fd, struct stat* stat); + +#if defined(__i386__) || defined(__x86_64__) long sys_fstat64(int fd, struct stat64* stat); +#elif defined(__arm64__) +long sys_fstat64(int fd, struct stat* stat); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.c b/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.c index 04643f7..3d672e1 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.c @@ -5,7 +5,11 @@ #include "../errno.h" #include +#if defined(__i386__) || defined(__x86_64__) long sys_fstat64_extended(int fd, struct stat64* stat, void* xsec, unsigned long* xsec_size) +#elif defined(__arm64__) +long sys_fstat64_extended(int fd, struct stat* stat, void* xsec, unsigned long* xsec_size) +#endif { if (xsec_size) *xsec_size = 0; diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.h b/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.h index f1d6a19..fcee94b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstat64_extended.h @@ -1,9 +1,13 @@ #ifndef LINUX_FSTAT64_EXTENDED_H #define LINUX_FSTAT64_EXTENDED_H +#if defined(__i386__) || defined(__x86_64__) struct stat64; - long sys_fstat64_extended(int fd, struct stat64* stat, void* xsec, unsigned long* xsec_size); +#elif defined(__arm64__) +struct stat; +long sys_fstat64_extended(int fd, struct stat* stat, void* xsec, unsigned long* xsec_size); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.c b/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.c index 6a5476c..03532e5 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.c @@ -46,7 +46,11 @@ long sys_fstatat(int fd, const char* path, struct stat* stat, int flag) return 0; } +#if defined(__i386__) || defined(__x86_64__) long sys_fstatat64(int fd, const char* path, struct stat64* stat, int flag) +#elif defined(__arm64__) +long sys_fstatat64(int fd, const char* path, struct stat* stat, int flag) +#endif { int ret; struct linux_stat lstat; @@ -77,7 +81,13 @@ long sys_fstatat64(int fd, const char* path, struct stat64* stat, int flag) if (ret < 0) return errno_linux_to_bsd(ret); +#if defined(__i386__) || defined(__x86_64__) stat_linux_to_bsd64(&lstat, stat); +#elif defined(__arm64__) + stat_linux_to_bsd(&lstat, stat); +#else +#error "Missing stat conversion method for arch" +#endif return 0; } diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.h b/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.h index 74f2c1b..9e6b2d7 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/fstatat.h @@ -5,7 +5,12 @@ struct stat; struct stat64; long sys_fstatat(int fd, const char* path, struct stat* stat, int flag); + +#if defined(__i386__) || defined(__x86_64__) long sys_fstatat64(int fd, const char* path, struct stat64* stat, int flag); +#elif defined(__arm64__) +long sys_fstatat64(int fd, const char* path, struct stat* stat, int flag); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/lstat.c b/darling/src/libsystem_kernel/emulation/linux/stat/lstat.c index 7750933..e3fb35d 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/lstat.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/lstat.c @@ -46,7 +46,11 @@ long sys_lstat(const char* path, struct stat* stat) return 0; } +#if defined(__i386__) || defined(__x86_64__) long sys_lstat64(const char* path, struct stat64* stat) +#elif defined(__arm64__) +long sys_lstat64(const char* path, struct stat* stat) +#endif { int ret; struct linux_stat lstat; @@ -76,7 +80,13 @@ long sys_lstat64(const char* path, struct stat64* stat) if (ret < 0) return errno_linux_to_bsd(ret); +#if defined(__i386__) || defined(__x86_64__) stat_linux_to_bsd64(&lstat, stat); +#elif defined(__arm64__) + stat_linux_to_bsd(&lstat, stat); +#else +#error "Missing stat conversion method for arch" +#endif return 0; } diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/lstat.h b/darling/src/libsystem_kernel/emulation/linux/stat/lstat.h index 3b80682..52eebea 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/lstat.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/lstat.h @@ -5,7 +5,12 @@ struct stat; struct stat64; long sys_lstat(const char* path, struct stat* stat); + +#if defined(__i386__) || defined(__x86_64__) long sys_lstat64(const char* path, struct stat64* stat); +#elif defined(__arm64__) +long sys_lstat64(const char* path, struct stat* stat); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.c b/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.c index aa084a6..76607d4 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.c @@ -5,7 +5,11 @@ #include "../errno.h" #include +#if defined(__i386__) || defined(__x86_64__) long sys_lstat64_extended(const char* path, struct stat64* stat, void* xsec, unsigned long* xsec_size) +#elif defined(__arm64__) +long sys_lstat64_extended(const char* path, struct stat* stat, void* xsec, unsigned long* xsec_size) +#endif { if (xsec_size) *xsec_size = 0; diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.h b/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.h index 703cab5..d0d7de6 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/lstat64_extended.h @@ -1,9 +1,13 @@ #ifndef LINUX_LSTAT64_EXTENDED_H #define LINUX_LSTAT64_EXTENDED_H +#if defined(__i386__) || defined(__x86_64__) struct stat64; - long sys_lstat64_extended(const char* path, struct stat64* stat, void* xsec, unsigned long* xsec_size); +#elif defined(__arm64__) +struct stat; +long sys_lstat64_extended(const char* path, struct stat* stat, void* xsec, unsigned long* xsec_size); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/stat.c b/darling/src/libsystem_kernel/emulation/linux/stat/stat.c index ee16de3..9483265 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/stat.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/stat.c @@ -11,7 +11,11 @@ long sys_stat(const char* path, struct stat* stat) return sys_fstatat(get_perthread_wd(), path, stat, 0); } +#if defined(__i386__) || defined(__x86_64__) long sys_stat64(const char* path, struct stat64* stat) +#elif defined(__arm64__) +long sys_stat64(const char* path, struct stat* stat) +#endif { return sys_fstatat64(get_perthread_wd(), path, stat, 0); } diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/stat.h b/darling/src/libsystem_kernel/emulation/linux/stat/stat.h index 4dcf15a..5d98509 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/stat.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/stat.h @@ -5,7 +5,12 @@ struct stat; struct stat64; long sys_stat(const char* path, struct stat* stat); + +#if defined(__i386__) || defined(__x86_64__) long sys_stat64(const char* path, struct stat64* stat); +#elif defined(__arm64__) +long sys_stat64(const char* path, struct stat* stat); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.c b/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.c index afa3d25..5872341 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.c +++ b/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.c @@ -5,7 +5,11 @@ #include "../errno.h" #include +#if defined(__i386__) || defined(__x86_64__) long sys_stat64_extended(const char* path, struct stat64* stat, void* xsec, unsigned long* xsec_size) +#elif defined(__arm64__) +long sys_stat64_extended(const char* path, struct stat* stat, void* xsec, unsigned long* xsec_size) +#endif { if (xsec_size) *xsec_size = 0; diff --git a/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.h b/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.h index 9ba31b1..aa7de1b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.h +++ b/darling/src/libsystem_kernel/emulation/linux/stat/stat64_extended.h @@ -1,9 +1,13 @@ #ifndef LINUX_STAT64_EXTENDED_H #define LINUX_STAT64_EXTENDED_H +#if defined(__i386__) || defined(__x86_64__) struct stat64; - long sys_stat64_extended(const char* path, struct stat64* stat, void* xsec, unsigned long* xsec_size); +#elif defined(__arm64__) +struct stat; +long sys_stat64_extended(const char* path, struct stat* stat, void* xsec, unsigned long* xsec_size); +#endif #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/syscalls-table.S b/darling/src/libsystem_kernel/emulation/linux/syscalls-table.S index a26ae39..5212625 100644 --- a/darling/src/libsystem_kernel/emulation/linux/syscalls-table.S +++ b/darling/src/libsystem_kernel/emulation/linux/syscalls-table.S @@ -2,11 +2,35 @@ .globl __darling_bsd_syscall .private_extern __darling_bsd_syscall +// To better understand how XTRACE_RESERVED_SPACE +// works, I recommend looking at `src/xtrace/xtracelib.c` +// for details. +#if defined(__x86_64__) +.macro XTRACE_RESERVED_SPACE + .space 13, 0x90 +.endmacro + +#elif defined( __i386__) +.macro XTRACE_RESERVED_SPACE + .space 7, 0x90 +.endmacro + +#elif defined(__arm64__) +.macro XTRACE_RESERVED_SPACE + nop ; movk + nop ; movk + nop ; movk + nop ; movk + nop ; blr +.endmacro + +#endif + #if defined(__x86_64__) __darling_bsd_syscall: Lentry_hook: - .space 13, 0x90 + XTRACE_RESERVED_SPACE movq ___bsd_syscall_table@GOTPCREL(%rip), %r10 movq (%r10,%rax,8), %r10 test %r10, %r10 @@ -20,7 +44,7 @@ Lentry_hook: addq $16, %rsp .std_ret: Lexit_hook: - .space 13, 0x90 + XTRACE_RESERVED_SPACE ret .no_sys: movq %rax, %rdi @@ -43,7 +67,7 @@ __darling_bsd_syscall_exit: __darling_bsd_syscall: Lentry_hook: - .space 7, 0x90 + XTRACE_RESERVED_SPACE calll 1f 1: popl %ecx @@ -73,7 +97,7 @@ Lentry_hook: addl $56, %esp .std_ret: Lexit_hook: - .space 7, 0x90 + XTRACE_RESERVED_SPACE ret .no_sys: pushl %ecx @@ -96,6 +120,134 @@ __darling_bsd_syscall_exit: .subsections_via_symbols +#elif defined(__arm64__) + +// On ARM64, the syscall number lives in x16 +.globl __darling_handle_svc +.balign 4 +__darling_handle_svc: + stp fp, lr, [sp, #-16]! + mov fp, sp + + // if (trap_no == 0x80000000) + mov w9, 0x80000000 + cmp w16, w9 + b.ne not_platform_syscall + + bl __darling_platform_syscall + // Apple's code throw an exception, but does it make sense to implement that here... + b darling_svc_return + +not_platform_syscall: + // if (trap_no < 0) { + cmp x16, #0 + b.pl trap_no_is_positive_or_zero_branch + + // if (trap_no == -3) + cmn w8, #3 + b.eq mach_absolute_time_trap_branch + // else if (trap_no == -4) + cmn w8, #4 + b.eq mach_continuous_time_trap_branch + // else + b darling_mach_syscall_branch + + mach_absolute_time_trap_branch: + // Call mach_approximate_time() and return + bl _mach_approximate_time + b darling_svc_return + + mach_continuous_time_trap_branch: + // Call mach_continuous_time() and return + bl _mach_continuous_time + b darling_svc_return + + darling_mach_syscall_branch: + // Call mach syscalls and return + bl __darling_mach_syscall + b darling_svc_return + +trap_no_is_positive_or_zero_branch: + // Call UNIX syscalls + bl __darling_bsd_syscall +darling_svc_return: + ldp fp, lr, [sp], #16 + ret + + +__darling_bsd_syscall: + stp fp, lr, [sp, #-16]! + mov fp, sp + +Lentry_hook: + XTRACE_RESERVED_SPACE + + // void* x9 = &__bsd_syscall_table + adrp x9, ___bsd_syscall_table@PAGE + add x9, x9, ___bsd_syscall_table@PAGEOFF + + // void* x9 = __bsd_syscall_table[x16] + ldr x9, [x9, x16, lsl #3] + + // If x9 is null + cbz x9, bsd_no_syscall + + // x9(...) + blr x9 + b bsd_return + +bsd_no_syscall: + mov x0, x16 + bl ___unknown_syscall + +bsd_return: +Lexit_hook: + XTRACE_RESERVED_SPACE + + ldp fp, lr, [sp], #16 + ret + + +__darling_platform_syscall: + stp fp, lr, [sp, #-16]! + mov fp, sp + +Lentry_hook_platform: + XTRACE_RESERVED_SPACE + + cmp x3, #2 + b.ne dont_set_tpidr + bl ___darling_thread_set_tsd + b return_platform_syscall + +dont_set_tpidr: + cmp x3, #3 + b.ne dont_get_tpidr + bl ___darling_thread_get_tsd + +return_platform_syscall: +dont_get_tpidr: +Lexit_hook_platform: + XTRACE_RESERVED_SPACE + + ldp fp, lr, [sp], #16 + ret + +.section __DATA,__data +.globl __darling_bsd_syscall_entry +.globl __darling_bsd_syscall_exit +__darling_bsd_syscall_entry: + .quad Lentry_hook +__darling_bsd_syscall_exit: + .quad Lexit_hook + +.globl __darling_platform_syscall_entry +.globl __darling_platform_syscall_exit +__darling_platform_syscall_entry: + .quad Lentry_hook_platform +__darling_platform_syscall_exit: + .quad Lexit_hook_platform + #else # error Missing assembly #endif diff --git a/darling/src/libsystem_kernel/emulation/linux/unistd/getpgrp.c b/darling/src/libsystem_kernel/emulation/linux/unistd/getpgrp.c index fd6e714..b3bf1fd 100644 --- a/darling/src/libsystem_kernel/emulation/linux/unistd/getpgrp.c +++ b/darling/src/libsystem_kernel/emulation/linux/unistd/getpgrp.c @@ -1,20 +1,11 @@ #include "getpgrp.h" +#include "getpgid.h" #include "../base.h" #include "../errno.h" #include long sys_getpgrp(void) { - #if defined(__NR_getpgrp) - int ret; - - ret = LINUX_SYSCALL0(__NR_getpgrp); - if (ret < 0) - ret = errno_linux_to_bsd(ret); - - return ret; - #else - return sys_getpgid(0); - #endif + return sys_getpgid(0); } diff --git a/darling/src/libsystem_kernel/emulation/linux/xtrace-hooks.S b/darling/src/libsystem_kernel/emulation/linux/xtrace-hooks.S index 76e3f5f..75bc88b 100644 --- a/darling/src/libsystem_kernel/emulation/linux/xtrace-hooks.S +++ b/darling/src/libsystem_kernel/emulation/linux/xtrace-hooks.S @@ -18,6 +18,21 @@ ret .endm +#elif defined(__arm64__) + +.macro xtrace_hook name + .text + .balign 4 + .globl _\name + _\name\(): + nop + nop + nop + nop + nop + ret +.endm + #else #error Missing xtrace hook dummy function macro for this architecture diff --git a/gen/bsdsyscalls/SYS.h b/gen/bsdsyscalls/SYS.h index 1367abd..1f9974b 100644 --- a/gen/bsdsyscalls/SYS.h +++ b/gen/bsdsyscalls/SYS.h @@ -475,6 +475,29 @@ pseudo: ;\ * TBD */ +#ifdef DARLING +// Changes compared to Apple's implementation: +// * Replace `svc` instruction by calling `__darling_handle_svc` (as a +// consequence, an additional `PUSH_FRAME` and `POP_FRAME` has been +// added) +// * Set the carry flag, by using the `cmn` instruction. +// * Convert the negative error code into a positive error code before +// calling `cerror` (errno must be a positive integer). +#define DO_SYSCALL(num, cerror) \ + mov x16, #(num) %%\ + PUSH_FRAME %%\ + bl __darling_handle_svc %%\ + POP_FRAME %%\ + cmn x0, #4095 %%\ + b.cc 2f %%\ + ARM64_STACK_PROLOG %%\ + PUSH_FRAME %%\ + neg x0, x0 %%\ + bl _##cerror %%\ + POP_FRAME %%\ + ARM64_STACK_EPILOG %%\ +2: +#else #define DO_SYSCALL(num, cerror) \ mov x16, #(num) %%\ svc #SWI_SYSCALL %%\ @@ -485,6 +508,7 @@ pseudo: ;\ POP_FRAME %%\ ARM64_STACK_EPILOG %%\ 2: +#endif #define MI_GET_ADDRESS(reg,var) \ adrp reg, var@page %%\ diff --git a/gen/bsdsyscalls/___fork.S b/gen/bsdsyscalls/___fork.S index 9f4de9d..b66fbd3 100644 --- a/gen/bsdsyscalls/___fork.S +++ b/gen/bsdsyscalls/___fork.S @@ -154,7 +154,15 @@ MI_ENTRY_POINT(___fork) PUSH_FRAME // ARM moves a 1 in to r1 here, but I can't see why. mov x16, #SYS_fork // Syscall code +#ifdef DARLING + bl __darling_handle_svc + mov x1, #0 // The fork syscall in XNU seems to always set the second return + // value to 0 (parent return). See [xnu]/bsd/kern/kern_fork.c + // for details. + cmn x0, #4095 // Check if result is negative +#else svc #SWI_SYSCALL // Trap to kernel +#endif b.cs Lbotch // Carry bit indicates failure cbz x1, Lparent // x1 == 0 indicates that we are the parent @@ -166,6 +174,9 @@ MI_ENTRY_POINT(___fork) ARM64_STACK_EPILOG Lbotch: +#ifdef DARLING + neg x0, x0 // errno must be positive +#endif MI_CALL_EXTERNAL(_cerror) // Handle error mov w0, #-1 // Return value is -1 Lparent: diff --git a/gen/bsdsyscalls/___pipe.S b/gen/bsdsyscalls/___pipe.S index b8e54a0..21e441f 100644 --- a/gen/bsdsyscalls/___pipe.S +++ b/gen/bsdsyscalls/___pipe.S @@ -59,9 +59,20 @@ MI_ENTRY_POINT(___pipe) #elif defined(__arm64__) MI_ENTRY_POINT(___pipe) +#if DARLING + // Dead code due to changes below +#else mov x9, x0 // Stash FD array +#endif SYSCALL_NONAME(pipe, 0, cerror_nocancel) +#if DARLING + // the results are already stored into the fd array, + // so we don't need to worry about saving the results + // back into the fd array (plus our svc implementation, + // overwrites the x9 register anyway). +#else stp w0, w1, [x9] // Save results +#endif mov x0, #0 // Success ret // Done diff --git a/gen/bsdsyscalls/___vfork.S b/gen/bsdsyscalls/___vfork.S index b159626..edd8809 100644 --- a/gen/bsdsyscalls/___vfork.S +++ b/gen/bsdsyscalls/___vfork.S @@ -231,7 +231,18 @@ Ltry_set_vfork: // ARM sets r1 to 1 here. I don't see why. mov w16, #SYS_vfork // Set syscall code +#ifdef DARLING + PUSH_FRAME + bl __darling_handle_svc + cmp x0, #0 // if (x0 == 0) { x1 = 1 /* child flag */ } + cset x1, eq // else { x1 = 0 /* parent flag */} + // See [xnu]/bsd/kern/kern_fork.c for more details + // on the x1 values. + cmn x0, #4095 // Check if result is negative + POP_FRAME +#else svc #SWI_SYSCALL +#endif b.cs Lbotch cbz w1, Lparent @@ -242,6 +253,9 @@ Ltry_set_vfork: // Error case Lbotch: PUSH_FRAME +#ifdef DARLING + neg x0, x0 // errno must be positive +#endif bl _cerror // Update errno mov w0, #-1 // Set return value MI_GET_ADDRESS(x9, __current_pid) // Reload current pid address diff --git a/gen/bsdsyscalls/custom.S b/gen/bsdsyscalls/custom.S index 4d8f04f..7dc3506 100644 --- a/gen/bsdsyscalls/custom.S +++ b/gen/bsdsyscalls/custom.S @@ -137,10 +137,22 @@ __thread_set_tsd_base: .align 2 .globl __thread_set_tsd_base __thread_set_tsd_base: +#ifdef DARLING + stp fp, lr, [sp, #-16]! + mov fp, sp + + mov x3, #2 + mov x16, #0x80000000 + bl __darling_handle_svc + + ldp fp, lr, [sp], #16 + ret +#else mov x3, #2 mov x16, #0x80000000 svc #SWI_SYSCALL ret +#endif #else #error unknown architecture diff --git a/libsyscall/CMakeLists.txt b/libsyscall/CMakeLists.txt index c16b498..d5b5b31 100755 --- a/libsyscall/CMakeLists.txt +++ b/libsyscall/CMakeLists.txt @@ -82,7 +82,11 @@ create_symlink( ) remove_definitions(-DLIBSYSCALL_INTERFACE=1) -set(MIG_MULTIARCH i386 x86_64) +if(TARGET_i386 OR TARGET_x86_64) + set(MIG_MULTIARCH i386 x86_64) +elseif(TARGET_ARM64) + set(MIG_MULTIARCH armv7 arm64) +endif() set(MIG_USER_HEADER_SUFFIX "_unused_user.h") set(MIG_USER_SOURCE_SUFFIX) set(MIG_SERVER_HEADER_SUFFIX) @@ -92,8 +96,13 @@ set(MIG_NO_XTRACE) foreach(MIG_FILENAME IN LISTS LIBSYSCALL_MIGS) mig("${MIG_FILENAME}.defs") - list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-i386-User.c") - list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-x86_64-User.c") + if(TARGET_i386 OR TARGET_x86_64) + list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-i386-User.c") + list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-x86_64-User.c") + elseif(TARGET_ARM64) + list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-armv7-User.c") + list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/${MIG_FILENAME}-arm64-User.c") + endif() get_filename_component(MIG_HEADER_DIR ${MIG_FILENAME} DIRECTORY) @@ -105,8 +114,13 @@ foreach(MIG_FILENAME IN LISTS LIBSYSCALL_MIGS) endforeach() # mach/exc also needs the server component -list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-i386-Server.c") -list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-x86_64-Server.c") +if(TARGET_i386 OR TARGET_x86_64) + list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-i386-Server.c") + list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-x86_64-Server.c") +elseif(TARGET_ARM64) + list(APPEND syscall_mig_sources_32 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-armv7-Server.c") + list(APPEND syscall_mig_sources_64 "${CMAKE_CURRENT_BINARY_DIR}/mach/exc-arm64-Server.c") +endif() unset(MIG_MULTIARCH) set(MIG_USER_HEADER_SUFFIX "_internal.h") diff --git a/libsyscall/custom/SYS.h b/libsyscall/custom/SYS.h index 1367abd..1f9974b 100644 --- a/libsyscall/custom/SYS.h +++ b/libsyscall/custom/SYS.h @@ -475,6 +475,29 @@ pseudo: ;\ * TBD */ +#ifdef DARLING +// Changes compared to Apple's implementation: +// * Replace `svc` instruction by calling `__darling_handle_svc` (as a +// consequence, an additional `PUSH_FRAME` and `POP_FRAME` has been +// added) +// * Set the carry flag, by using the `cmn` instruction. +// * Convert the negative error code into a positive error code before +// calling `cerror` (errno must be a positive integer). +#define DO_SYSCALL(num, cerror) \ + mov x16, #(num) %%\ + PUSH_FRAME %%\ + bl __darling_handle_svc %%\ + POP_FRAME %%\ + cmn x0, #4095 %%\ + b.cc 2f %%\ + ARM64_STACK_PROLOG %%\ + PUSH_FRAME %%\ + neg x0, x0 %%\ + bl _##cerror %%\ + POP_FRAME %%\ + ARM64_STACK_EPILOG %%\ +2: +#else #define DO_SYSCALL(num, cerror) \ mov x16, #(num) %%\ svc #SWI_SYSCALL %%\ @@ -485,6 +508,7 @@ pseudo: ;\ POP_FRAME %%\ ARM64_STACK_EPILOG %%\ 2: +#endif #define MI_GET_ADDRESS(reg,var) \ adrp reg, var@page %%\ diff --git a/libsyscall/custom/__fork.S b/libsyscall/custom/__fork.S index 9f4de9d..b66fbd3 100644 --- a/libsyscall/custom/__fork.S +++ b/libsyscall/custom/__fork.S @@ -154,7 +154,15 @@ MI_ENTRY_POINT(___fork) PUSH_FRAME // ARM moves a 1 in to r1 here, but I can't see why. mov x16, #SYS_fork // Syscall code +#ifdef DARLING + bl __darling_handle_svc + mov x1, #0 // The fork syscall in XNU seems to always set the second return + // value to 0 (parent return). See [xnu]/bsd/kern/kern_fork.c + // for details. + cmn x0, #4095 // Check if result is negative +#else svc #SWI_SYSCALL // Trap to kernel +#endif b.cs Lbotch // Carry bit indicates failure cbz x1, Lparent // x1 == 0 indicates that we are the parent @@ -166,6 +174,9 @@ MI_ENTRY_POINT(___fork) ARM64_STACK_EPILOG Lbotch: +#ifdef DARLING + neg x0, x0 // errno must be positive +#endif MI_CALL_EXTERNAL(_cerror) // Handle error mov w0, #-1 // Return value is -1 Lparent: diff --git a/libsyscall/custom/__vfork.S b/libsyscall/custom/__vfork.S index 969c188..1b8a630 100644 --- a/libsyscall/custom/__vfork.S +++ b/libsyscall/custom/__vfork.S @@ -231,7 +231,18 @@ Ltry_set_vfork: // ARM sets r1 to 1 here. I don't see why. mov w16, #SYS_vfork // Set syscall code +#ifdef DARLING + PUSH_FRAME + bl __darling_handle_svc + cmp x0, #0 // if (x0 == 0) { x1 = 1 /* child flag */ } + cset x1, eq // else { x1 = 0 /* parent flag */} + // See [xnu]/bsd/kern/kern_fork.c for more details + // on the x1 values. + cmn x0, #4095 // Check if result is negative + POP_FRAME +#else svc #SWI_SYSCALL +#endif b.cs Lbotch cbz w1, Lparent @@ -242,6 +253,9 @@ Ltry_set_vfork: // Error case Lbotch: PUSH_FRAME +#ifdef DARLING + neg x0, x0 // errno must be positive +#endif bl _cerror // Update errno mov w0, #-1 // Set return value MI_GET_ADDRESS(x9, __current_pid) // Reload current pid address diff --git a/libsyscall/custom/custom.S b/libsyscall/custom/custom.S index 4d8f04f..7dc3506 100644 --- a/libsyscall/custom/custom.S +++ b/libsyscall/custom/custom.S @@ -137,10 +137,22 @@ __thread_set_tsd_base: .align 2 .globl __thread_set_tsd_base __thread_set_tsd_base: +#ifdef DARLING + stp fp, lr, [sp, #-16]! + mov fp, sp + + mov x3, #2 + mov x16, #0x80000000 + bl __darling_handle_svc + + ldp fp, lr, [sp], #16 + ret +#else mov x3, #2 mov x16, #0x80000000 svc #SWI_SYSCALL ret +#endif #else #error unknown architecture diff --git a/libsyscall/os/tsd.h b/libsyscall/os/tsd.h index 842fe7a..dcae65b 100644 --- a/libsyscall/os/tsd.h +++ b/libsyscall/os/tsd.h @@ -53,7 +53,9 @@ #endif #ifdef DARLING +#include #include +#include #endif extern void _thread_set_tsd_base(void *tsd_base); @@ -63,10 +65,8 @@ static __inline__ unsigned int _os_cpu_number(void) { #ifdef DARLING - extern int __linux_syscall(int nr, ...); - unsigned int cpu_num = 0; - int status = __linux_syscall(__NR_getcpu, &cpu_num, 0, 0, 0, 0, 0); + int status = __linux_syscall_3args(__NR_getcpu, (long)&cpu_num, 0, 0); // should we even check? i don't think it's possible for it to fail with these arguments if (status < 0) { return 0; // i guess? @@ -146,8 +146,12 @@ _os_tsd_get_base(void) /* lower 2-bits contain CPU number */ #elif defined(__arm64__) uint64_t tsd; +#ifdef DARLING + tsd = (uint64_t)__darling_thread_get_tsd(); +#else __asm__("mrs %0, TPIDRRO_EL0\n" "bic %0, %0, #0x7\n" : "=r" (tsd)); +#endif /* lower 3-bits contain CPU number */ #endif @@ -221,10 +225,21 @@ _os_ptr_munge(uintptr_t ptr) #elif defined(__arm64__) +#ifdef DARLING +#define _OS_PTR_MUNGE_TOKEN(_reg, _token) \ + stp fp, lr, [sp, #-16]! %% \ + mov fp, sp %% \ + bl ___darling_thread_get_tsd %% \ + ldp fp, lr, [sp], #16 %% \ + mov _reg, x0 %% \ + and _reg, _reg, #~0x7 %% \ + ldr _token, [ _reg, #_OS_TSD_OFFSET(__TSD_PTR_MUNGE) ] +#else #define _OS_PTR_MUNGE_TOKEN(_reg, _token) \ mrs _reg, TPIDRRO_EL0 %% \ and _reg, _reg, #~0x7 %% \ ldr _token, [ _reg, #_OS_TSD_OFFSET(__TSD_PTR_MUNGE) ] +#endif #endif // defined(__arm64__) diff --git a/osfmk/mach/arm/syscall_sw.h b/osfmk/mach/arm/syscall_sw.h index af11c26..4c0e7e7 100644 --- a/osfmk/mach/arm/syscall_sw.h +++ b/osfmk/mach/arm/syscall_sw.h @@ -106,7 +106,23 @@ #elif defined(__arm64__) #include +#ifdef DARLING +// For PUSH_FRAME & POP_FRAME +#include +#endif +#ifdef DARLING +#define kernel_trap(trap_name, trap_number, num_args) \ +.globl _##trap_name %% \ +.text %% \ +.align 2 %% \ +_##trap_name: %% \ + PUSH_FRAME %% \ + mov x16, #(trap_number) %% \ + bl __darling_handle_svc %% \ + POP_FRAME %% \ + ret +#else #define kernel_trap(trap_name, trap_number, num_args) \ .globl _##trap_name %% \ .text %% \ @@ -114,7 +130,8 @@ _##trap_name: %% \ mov x16, #(trap_number) %% \ svc #SWI_SYSCALL %% \ - ret + ret +#endif #else #error Unsupported architecture