diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -154,6 +154,7 @@ libc.src.unistd.rmdir libc.src.unistd.symlink libc.src.unistd.symlinkat + libc.src.unistd.__llvm_libc_syscall libc.src.unistd.truncate libc.src.unistd.unlink libc.src.unistd.unlinkat diff --git a/libc/include/llvm-libc-macros/linux/unistd-macros.h b/libc/include/llvm-libc-macros/linux/unistd-macros.h --- a/libc/include/llvm-libc-macros/linux/unistd-macros.h +++ b/libc/include/llvm-libc-macros/linux/unistd-macros.h @@ -15,4 +15,13 @@ #define W_OK 2 #define R_OK 4 +// Macro to set up the call to the __llvm_libc_syscall function +// This is to prevent the call from having fewer than 6 arguments, since six +// arguments are always passed to the syscall. Unnecessary arguments are +// ignored. +#define __syscall_helper(sysno, arg1, arg2, arg3, arg4, arg5, arg6, ...) \ + __llvm_libc_syscall((long)(sysno), (long)(arg1), (long)(arg2), (long)(arg3), \ + (long)(arg4), (long)(arg5), (long)(arg6)) +#define syscall(...) __syscall_helper(__VA_ARGS__, 1, 2, 3, 4, 5, 6) + #endif // __LLVM_LIBC_MACROS_LINUX_UNISTD_MACROS_H diff --git a/libc/loader/linux/aarch64/start.cpp b/libc/loader/linux/aarch64/start.cpp --- a/libc/loader/linux/aarch64/start.cpp +++ b/libc/loader/linux/aarch64/start.cpp @@ -68,13 +68,13 @@ // We cannot call the mmap function here as the functions set errno on // failure. Since errno is implemented via a thread local variable, we cannot // use errno before TLS is setup. - long mmap_ret_val = __llvm_libc::syscall(MMAP_SYSCALL_NUMBER, nullptr, - alloc_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + long mmap_ret_val = __llvm_libc::syscall_impl( + MMAP_SYSCALL_NUMBER, nullptr, alloc_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // We cannot check the return value with MAP_FAILED as that is the return // of the mmap function and not the mmap syscall. if (mmap_ret_val < 0 && static_cast(mmap_ret_val) > -app.pageSize) - __llvm_libc::syscall(SYS_exit, 1); + __llvm_libc::syscall_impl(SYS_exit, 1); uintptr_t thread_ptr = uintptr_t(reinterpret_cast(mmap_ret_val)); uintptr_t tls_addr = thread_ptr + size_of_pointers + padding; __llvm_libc::inline_memcpy(reinterpret_cast(tls_addr), @@ -88,7 +88,7 @@ void cleanup_tls(uintptr_t addr, uintptr_t size) { if (size == 0) return; - __llvm_libc::syscall(SYS_munmap, addr, size); + __llvm_libc::syscall_impl(SYS_munmap, addr, size); } static void set_thread_ptr(uintptr_t val) { __arm_wsr64("tpidr_el0", val); } @@ -133,9 +133,9 @@ }; __attribute__((noinline)) static void do_start() { - auto tid = __llvm_libc::syscall(SYS_gettid); + auto tid = __llvm_libc::syscall_impl(SYS_gettid); if (tid <= 0) - __llvm_libc::syscall(SYS_exit, 1); + __llvm_libc::syscall_impl(SYS_exit, 1); __llvm_libc::main_thread_attrib.tid = tid; // After the argv array, is a 8-byte long NULL value before the array of env diff --git a/libc/loader/linux/x86_64/start.cpp b/libc/loader/linux/x86_64/start.cpp --- a/libc/loader/linux/x86_64/start.cpp +++ b/libc/loader/linux/x86_64/start.cpp @@ -58,13 +58,13 @@ // We cannot call the mmap function here as the functions set errno on // failure. Since errno is implemented via a thread local variable, we cannot // use errno before TLS is setup. - long mmapRetVal = __llvm_libc::syscall( + long mmapRetVal = __llvm_libc::syscall_impl( mmapSyscallNumber, nullptr, tlsSizeWithAddr, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // We cannot check the return value with MAP_FAILED as that is the return // of the mmap function and not the mmap syscall. if (mmapRetVal < 0 && static_cast(mmapRetVal) > -app.pageSize) - __llvm_libc::syscall(SYS_exit, 1); + __llvm_libc::syscall_impl(SYS_exit, 1); uintptr_t *tlsAddr = reinterpret_cast(mmapRetVal); // x86_64 TLS faces down from the thread pointer with the first entry @@ -83,13 +83,14 @@ void cleanup_tls(uintptr_t addr, uintptr_t size) { if (size == 0) return; - __llvm_libc::syscall(SYS_munmap, addr, size); + __llvm_libc::syscall_impl(SYS_munmap, addr, size); } // Sets the thread pointer to |val|. Returns true on success, false on failure. static bool set_thread_ptr(uintptr_t val) { - return __llvm_libc::syscall(SYS_arch_prctl, ARCH_SET_FS, val) == -1 ? false - : true; + return __llvm_libc::syscall_impl(SYS_arch_prctl, ARCH_SET_FS, val) == -1 + ? false + : true; } using InitCallback = void(int, char **, char **); @@ -152,9 +153,9 @@ __asm__ __volatile__("andq $0xfffffffffffffff0, %%rsp\n\t" ::: "%rsp"); __asm__ __volatile__("andq $0xfffffffffffffff0, %%rbp\n\t" ::: "%rbp"); - auto tid = __llvm_libc::syscall(SYS_gettid); + auto tid = __llvm_libc::syscall_impl(SYS_gettid); if (tid <= 0) - __llvm_libc::syscall(SYS_exit, 1); + __llvm_libc::syscall_impl(SYS_exit, 1); __llvm_libc::main_thread_attrib.tid = tid; // After the argv array, is a 8-byte long NULL value before the array of env @@ -202,7 +203,7 @@ __llvm_libc::TLSDescriptor tls; __llvm_libc::init_tls(tls); if (tls.size != 0 && !__llvm_libc::set_thread_ptr(tls.tp)) - __llvm_libc::syscall(SYS_exit, 1); + __llvm_libc::syscall_impl(SYS_exit, 1); __llvm_libc::self.attrib = &__llvm_libc::main_thread_attrib; __llvm_libc::main_thread_attrib.atexit_callback_mgr = diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -482,6 +482,11 @@ RetValSpec, [ArgSpec, ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "__llvm_libc_syscall", + RetValSpec, + [ArgSpec,ArgSpec,ArgSpec,ArgSpec,ArgSpec,ArgSpec,ArgSpec] + >, FunctionSpec< "truncate", RetValSpec, diff --git a/libc/src/__support/File/linux_dir.cpp b/libc/src/__support/File/linux_dir.cpp --- a/libc/src/__support/File/linux_dir.cpp +++ b/libc/src/__support/File/linux_dir.cpp @@ -19,9 +19,9 @@ int platform_opendir(const char *name) { int open_flags = O_RDONLY | O_DIRECTORY | O_CLOEXEC; #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, name, open_flags); + int fd = __llvm_libc::syscall_impl(SYS_open, name, open_flags); #elif defined(SYS_openat) - int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, name, open_flags); + int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, name, open_flags); #else #error \ "SYS_open and SYS_openat syscalls not available to perform an open operation." @@ -36,7 +36,7 @@ size_t platform_fetch_dirents(int fd, cpp::span buffer) { long size = - __llvm_libc::syscall(SYS_getdents, fd, buffer.data(), buffer.size()); + __llvm_libc::syscall_impl(SYS_getdents, fd, buffer.data(), buffer.size()); if (size < 0) { errno = -size; return 0; @@ -45,7 +45,7 @@ } bool platform_closedir(int fd) { - long ret = __llvm_libc::syscall(SYS_close, fd); + long ret = __llvm_libc::syscall_impl(SYS_close, fd); if (ret < 0) { errno = -ret; return false; diff --git a/libc/src/__support/File/linux_file.cpp b/libc/src/__support/File/linux_file.cpp --- a/libc/src/__support/File/linux_file.cpp +++ b/libc/src/__support/File/linux_file.cpp @@ -53,7 +53,7 @@ size_t write_func(File *f, const void *data, size_t size) { auto *lf = reinterpret_cast(f); - long ret = __llvm_libc::syscall(SYS_write, lf->get_fd(), data, size); + long ret = __llvm_libc::syscall_impl(SYS_write, lf->get_fd(), data, size); if (ret < 0) { errno = -ret; return 0; @@ -63,7 +63,7 @@ size_t read_func(File *f, void *buf, size_t size) { auto *lf = reinterpret_cast(f); - long ret = __llvm_libc::syscall(SYS_read, lf->get_fd(), buf, size); + long ret = __llvm_libc::syscall_impl(SYS_read, lf->get_fd(), buf, size); if (ret < 0) { errno = -ret; return 0; @@ -74,11 +74,11 @@ int seek_func(File *f, long offset, int whence) { auto *lf = reinterpret_cast(f); #ifdef SYS_lseek - long ret = __llvm_libc::syscall(SYS_lseek, lf->get_fd(), offset, whence); + long ret = __llvm_libc::syscall_impl(SYS_lseek, lf->get_fd(), offset, whence); #elif defined(SYS__llseek) long result; - long ret = __llvm_libc::syscall(SYS__llseek, lf->get_fd(), offset >> 32, - offset, &result, whence); + long ret = __llvm_libc::syscall_impl(SYS__llseek, lf->get_fd(), offset >> 32, + offset, &result, whence); #else #error "lseek and _llseek syscalls not available to perform a seek operation." #endif @@ -92,7 +92,7 @@ int close_func(File *f) { auto *lf = reinterpret_cast(f); - long ret = __llvm_libc::syscall(SYS_close, lf->get_fd()); + long ret = __llvm_libc::syscall_impl(SYS_close, lf->get_fd()); if (ret < 0) { errno = -ret; return -1; @@ -102,7 +102,7 @@ int flush_func(File *f) { auto *lf = reinterpret_cast(f); - long ret = __llvm_libc::syscall(SYS_fsync, lf->get_fd()); + long ret = __llvm_libc::syscall_impl(SYS_fsync, lf->get_fd()); if (ret < 0) { errno = -ret; return -1; @@ -144,10 +144,10 @@ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, path, open_flags, OPEN_MODE); + int fd = __llvm_libc::syscall_impl(SYS_open, path, open_flags, OPEN_MODE); #elif defined(SYS_openat) - int fd = - __llvm_libc::syscall(SYS_openat, AT_FDCWD, path, open_flags, OPEN_MODE); + int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path, open_flags, + OPEN_MODE); #else #error "SYS_open and SYS_openat syscalls not available to perform a file open." #endif diff --git a/libc/src/__support/OSUtil/linux/aarch64/syscall.h b/libc/src/__support/OSUtil/linux/aarch64/syscall.h --- a/libc/src/__support/OSUtil/linux/aarch64/syscall.h +++ b/libc/src/__support/OSUtil/linux/aarch64/syscall.h @@ -44,50 +44,52 @@ namespace __llvm_libc { -__attribute__((always_inline)) inline long syscall(long number) { +__attribute__((always_inline)) inline long syscall_impl(long number) { REGISTER_DECL_0; SYSCALL_INSTR(REGISTER_CONSTRAINT_0); return x0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1) { +__attribute__((always_inline)) inline long syscall_impl(long number, + long arg1) { REGISTER_DECL_1; SYSCALL_INSTR(REGISTER_CONSTRAINT_1); return x0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2) { REGISTER_DECL_2; SYSCALL_INSTR(REGISTER_CONSTRAINT_2); return x0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2, long arg3) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3) { REGISTER_DECL_3; SYSCALL_INSTR(REGISTER_CONSTRAINT_3); return x0; } __attribute__((always_inline)) inline long -syscall(long number, long arg1, long arg2, long arg3, long arg4) { +syscall_impl(long number, long arg1, long arg2, long arg3, long arg4) { REGISTER_DECL_4; SYSCALL_INSTR(REGISTER_CONSTRAINT_4); return x0; } -__attribute__((always_inline)) inline long -syscall(long number, long arg1, long arg2, long arg3, long arg4, long arg5) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3, + long arg4, long arg5) { REGISTER_DECL_5; SYSCALL_INSTR(REGISTER_CONSTRAINT_5); return x0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long arg6) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long arg6) { REGISTER_DECL_6; SYSCALL_INSTR(REGISTER_CONSTRAINT_6); return x0; diff --git a/libc/src/__support/OSUtil/linux/arm/syscall.h b/libc/src/__support/OSUtil/linux/arm/syscall.h --- a/libc/src/__support/OSUtil/linux/arm/syscall.h +++ b/libc/src/__support/OSUtil/linux/arm/syscall.h @@ -50,50 +50,52 @@ namespace __llvm_libc { -__attribute__((always_inline)) inline long syscall(long number) { +__attribute__((always_inline)) inline long syscall_impl(long number) { REGISTER_DECL_0; SYSCALL_INSTR(REGISTER_CONSTRAINT_0); return r0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1) { +__attribute__((always_inline)) inline long syscall_impl(long number, + long arg1) { REGISTER_DECL_1; SYSCALL_INSTR(REGISTER_CONSTRAINT_1); return r0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2) { REGISTER_DECL_2; SYSCALL_INSTR(REGISTER_CONSTRAINT_2); return r0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2, long arg3) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3) { REGISTER_DECL_3; SYSCALL_INSTR(REGISTER_CONSTRAINT_3); return r0; } __attribute__((always_inline)) inline long -syscall(long number, long arg1, long arg2, long arg3, long arg4) { +syscall_impl(long number, long arg1, long arg2, long arg3, long arg4) { REGISTER_DECL_4; SYSCALL_INSTR(REGISTER_CONSTRAINT_4); return r0; } -__attribute__((always_inline)) inline long -syscall(long number, long arg1, long arg2, long arg3, long arg4, long arg5) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3, + long arg4, long arg5) { REGISTER_DECL_5; SYSCALL_INSTR(REGISTER_CONSTRAINT_5); return r0; } -__attribute__((always_inline)) inline long syscall(long number, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long arg6) { +__attribute__((always_inline)) inline long syscall_impl(long number, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long arg6) { REGISTER_DECL_6; SYSCALL_INSTR(REGISTER_CONSTRAINT_6); return r0; diff --git a/libc/src/__support/OSUtil/linux/io.h b/libc/src/__support/OSUtil/linux/io.h --- a/libc/src/__support/OSUtil/linux/io.h +++ b/libc/src/__support/OSUtil/linux/io.h @@ -17,8 +17,8 @@ namespace __llvm_libc { static inline void write_to_stderr(const char *msg) { - __llvm_libc::syscall(SYS_write, 2 /* stderr */, msg, - internal::string_length(msg)); + __llvm_libc::syscall_impl(SYS_write, 2 /* stderr */, msg, + internal::string_length(msg)); } } // namespace __llvm_libc diff --git a/libc/src/__support/OSUtil/linux/quick_exit.h b/libc/src/__support/OSUtil/linux/quick_exit.h --- a/libc/src/__support/OSUtil/linux/quick_exit.h +++ b/libc/src/__support/OSUtil/linux/quick_exit.h @@ -17,8 +17,8 @@ static inline void quick_exit(int status) { for (;;) { - __llvm_libc::syscall(SYS_exit_group, status); - __llvm_libc::syscall(SYS_exit, status); + __llvm_libc::syscall_impl(SYS_exit_group, status); + __llvm_libc::syscall_impl(SYS_exit, status); } } diff --git a/libc/src/__support/OSUtil/linux/syscall.h b/libc/src/__support/OSUtil/linux/syscall.h --- a/libc/src/__support/OSUtil/linux/syscall.h +++ b/libc/src/__support/OSUtil/linux/syscall.h @@ -22,9 +22,10 @@ namespace __llvm_libc { template -__attribute__((always_inline)) inline long syscall(long __number, Ts... ts) { +__attribute__((always_inline)) inline long syscall_impl(long __number, + Ts... ts) { static_assert(sizeof...(Ts) <= 6, "Too many arguments for syscall"); - return syscall(__number, (long)ts...); + return syscall_impl(__number, (long)ts...); } } // namespace __llvm_libc diff --git a/libc/src/__support/OSUtil/linux/x86_64/syscall.h b/libc/src/__support/OSUtil/linux/x86_64/syscall.h --- a/libc/src/__support/OSUtil/linux/x86_64/syscall.h +++ b/libc/src/__support/OSUtil/linux/x86_64/syscall.h @@ -15,7 +15,7 @@ namespace __llvm_libc { -__attribute__((always_inline)) inline long syscall(long __number) { +__attribute__((always_inline)) inline long syscall_impl(long __number) { long retcode; LIBC_INLINE_ASM("syscall" : "=a"(retcode) @@ -24,7 +24,8 @@ return retcode; } -__attribute__((always_inline)) inline long syscall(long __number, long __arg1) { +__attribute__((always_inline)) inline long syscall_impl(long __number, + long __arg1) { long retcode; LIBC_INLINE_ASM("syscall" : "=a"(retcode) @@ -33,8 +34,8 @@ return retcode; } -__attribute__((always_inline)) inline long syscall(long __number, long __arg1, - long __arg2) { +__attribute__((always_inline)) inline long +syscall_impl(long __number, long __arg1, long __arg2) { long retcode; LIBC_INLINE_ASM("syscall" : "=a"(retcode) @@ -43,8 +44,8 @@ return retcode; } -__attribute__((always_inline)) inline long syscall(long __number, long __arg1, - long __arg2, long __arg3) { +__attribute__((always_inline)) inline long +syscall_impl(long __number, long __arg1, long __arg2, long __arg3) { long retcode; LIBC_INLINE_ASM("syscall" : "=a"(retcode) @@ -54,7 +55,8 @@ } __attribute__((always_inline)) inline long -syscall(long __number, long __arg1, long __arg2, long __arg3, long __arg4) { +syscall_impl(long __number, long __arg1, long __arg2, long __arg3, + long __arg4) { long retcode; register long r10 __asm__("r10") = __arg4; LIBC_INLINE_ASM("syscall" @@ -65,9 +67,9 @@ return retcode; } -__attribute__((always_inline)) inline long syscall(long __number, long __arg1, - long __arg2, long __arg3, - long __arg4, long __arg5) { +__attribute__((always_inline)) inline long +syscall_impl(long __number, long __arg1, long __arg2, long __arg3, long __arg4, + long __arg5) { long retcode; register long r10 __asm__("r10") = __arg4; register long r8 __asm__("r8") = __arg5; @@ -79,10 +81,9 @@ return retcode; } -__attribute__((always_inline)) inline long syscall(long __number, long __arg1, - long __arg2, long __arg3, - long __arg4, long __arg5, - long __arg6) { +__attribute__((always_inline)) inline long +syscall_impl(long __number, long __arg1, long __arg2, long __arg3, long __arg4, + long __arg5, long __arg6) { long retcode; register long r10 __asm__("r10") = __arg4; register long r8 __asm__("r8") = __arg5; @@ -96,7 +97,6 @@ } #undef SYSCALL_CLOBBER_LIST - } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_X86_64_SYSCALL_H diff --git a/libc/src/__support/threads/linux/callonce.cpp b/libc/src/__support/threads/linux/callonce.cpp --- a/libc/src/__support/threads/linux/callonce.cpp +++ b/libc/src/__support/threads/linux/callonce.cpp @@ -34,9 +34,9 @@ func(); auto status = futex_word->exchange(FINISH); if (status == WAITING) { - __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE, - INT_MAX, // Wake all waiters. - 0, 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE, + INT_MAX, // Wake all waiters. + 0, 0, 0); } return 0; } @@ -44,9 +44,10 @@ FutexWordType status = START; if (futex_word->compare_exchange_strong(status, WAITING) || status == WAITING) { - __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE, - WAITING, // Block only if status is still |WAITING|. - 0, 0, 0); + __llvm_libc::syscall_impl( + SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE, + WAITING, // Block only if status is still |WAITING|. + 0, 0, 0); } return 0; diff --git a/libc/src/__support/threads/linux/mutex.h b/libc/src/__support/threads/linux/mutex.h --- a/libc/src/__support/threads/linux/mutex.h +++ b/libc/src/__support/threads/linux/mutex.h @@ -76,8 +76,9 @@ // futex syscall will block if the futex data is still // `LockState::Waiting` (the 4th argument to the syscall function // below.) - __llvm_libc::syscall(SYS_futex, &futex_word.val, FUTEX_WAIT_PRIVATE, - FutexWordType(LockState::Waiting), 0, 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &futex_word.val, + FUTEX_WAIT_PRIVATE, + FutexWordType(LockState::Waiting), 0, 0, 0); was_waiting = true; // Once woken up/unblocked, try everything all over. continue; @@ -90,8 +91,8 @@ // we will wait for the futex to be woken up. Note again that the // following syscall will block only if the futex data is still // `LockState::Waiting`. - __llvm_libc::syscall(SYS_futex, &futex_word, FUTEX_WAIT_PRIVATE, - FutexWordType(LockState::Waiting), 0, 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAIT_PRIVATE, + FutexWordType(LockState::Waiting), 0, 0, 0); was_waiting = true; } continue; @@ -108,8 +109,8 @@ if (futex_word.compare_exchange_strong(mutex_status, FutexWordType(LockState::Free))) { // If any thread is waiting to be woken up, then do it. - __llvm_libc::syscall(SYS_futex, &futex_word, FUTEX_WAKE_PRIVATE, 1, 0, - 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAKE_PRIVATE, 1, + 0, 0, 0); return MutexError::NONE; } diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp --- a/libc/src/__support/threads/linux/thread.cpp +++ b/libc/src/__support/threads/linux/thread.cpp @@ -56,13 +56,13 @@ static inline cpp::ErrorOr alloc_stack(size_t size) { long mmap_result = - __llvm_libc::syscall(MMAP_SYSCALL_NUMBER, - 0, // No special address - size, - PROT_READ | PROT_WRITE, // Read and write stack - MAP_ANONYMOUS | MAP_PRIVATE, // Process private - -1, // Not backed by any file - 0 // No offset + __llvm_libc::syscall_impl(MMAP_SYSCALL_NUMBER, + 0, // No special address + size, + PROT_READ | PROT_WRITE, // Read and write stack + MAP_ANONYMOUS | MAP_PRIVATE, // Process private + -1, // Not backed by any file + 0 // No offset ); if (mmap_result < 0 && (uintptr_t(mmap_result) >= UINTPTR_MAX - size)) return cpp::Error{int(-mmap_result)}; @@ -70,7 +70,7 @@ } static inline void free_stack(void *stack, size_t size) { - __llvm_libc::syscall(SYS_munmap, stack, size); + __llvm_libc::syscall_impl(SYS_munmap, stack, size); } struct Thread; @@ -192,7 +192,7 @@ // variables from this function will not be availalbe to the child thread. #ifdef LLVM_LIBC_ARCH_X86_64 long register clone_result asm("rax"); - clone_result = __llvm_libc::syscall( + clone_result = __llvm_libc::syscall_impl( SYS_clone, CLONE_SYSCALL_FLAGS, adjusted_stack, &attrib->tid, // The address where the child tid is written &clear_tid->val, // The futex where the child thread status is signalled @@ -200,7 +200,7 @@ ); #elif defined(LLVM_LIBC_ARCH_AARCH64) long register clone_result asm("x0"); - clone_result = __llvm_libc::syscall( + clone_result = __llvm_libc::syscall_impl( SYS_clone, CLONE_SYSCALL_FLAGS, adjusted_stack, &attrib->tid, // The address where the child tid is written tls.tp, // The thread pointer value for the new thread. @@ -264,8 +264,8 @@ while (clear_tid->load() != 0) { // We cannot do a FUTEX_WAIT_PRIVATE here as the kernel does a // FUTEX_WAKE and not a FUTEX_WAKE_PRIVATE. - __llvm_libc::syscall(SYS_futex, &clear_tid->val, FUTEX_WAIT, - CLEAR_TID_VALUE, nullptr); + __llvm_libc::syscall_impl(SYS_futex, &clear_tid->val, FUTEX_WAIT, + CLEAR_TID_VALUE, nullptr); } } @@ -293,7 +293,7 @@ if (*this == self) { // If we are setting the name of the current thread, then we can // use the syscall to set the name. - int retval = __llvm_libc::syscall(SYS_prctl, PR_SET_NAME, name.data()); + int retval = __llvm_libc::syscall_impl(SYS_prctl, PR_SET_NAME, name.data()); if (retval < 0) return -retval; else @@ -304,15 +304,17 @@ cpp::StringStream path_stream(path_name_buffer); construct_thread_name_file_path(path_stream, attrib->tid); #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, path_name_buffer, O_RDWR); + int fd = __llvm_libc::syscall_impl(SYS_open, path_name_buffer, O_RDWR); #else - int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path_name_buffer, O_RDWR); + int fd = + __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path_name_buffer, O_RDWR); #endif if (fd < 0) return -fd; - int retval = __llvm_libc::syscall(SYS_write, fd, name.data(), name.size()); - __llvm_libc::syscall(SYS_close, fd); + int retval = + __llvm_libc::syscall_impl(SYS_write, fd, name.data(), name.size()); + __llvm_libc::syscall_impl(SYS_close, fd); if (retval < 0) return -retval; @@ -331,7 +333,7 @@ if (*this == self) { // If we are getting the name of the current thread, then we can // use the syscall to get the name. - int retval = __llvm_libc::syscall(SYS_prctl, PR_GET_NAME, name_buffer); + int retval = __llvm_libc::syscall_impl(SYS_prctl, PR_GET_NAME, name_buffer); if (retval < 0) return -retval; name << name_buffer; @@ -342,16 +344,17 @@ cpp::StringStream path_stream(path_name_buffer); construct_thread_name_file_path(path_stream, attrib->tid); #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, path_name_buffer, O_RDONLY); + int fd = __llvm_libc::syscall_impl(SYS_open, path_name_buffer, O_RDONLY); #else - int fd = - __llvm_libc::syscall(SYS_openat, AT_FDCWD, path_name_buffer, O_RDONLY); + int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path_name_buffer, + O_RDONLY); #endif if (fd < 0) return -fd; - int retval = __llvm_libc::syscall(SYS_read, fd, name_buffer, NAME_SIZE_MAX); - __llvm_libc::syscall(SYS_close, fd); + int retval = + __llvm_libc::syscall_impl(SYS_read, fd, name_buffer, NAME_SIZE_MAX); + __llvm_libc::syscall_impl(SYS_close, fd); if (retval < 0) return -retval; if (retval == NAME_SIZE_MAX) @@ -385,13 +388,13 @@ // Set the CLEAR_TID address to nullptr to prevent the kernel // from signalling at a non-existent futex location. - __llvm_libc::syscall(SYS_set_tid_address, 0); + __llvm_libc::syscall_impl(SYS_set_tid_address, 0); } if (style == ThreadStyle::POSIX) - __llvm_libc::syscall(SYS_exit, retval.posix_retval); + __llvm_libc::syscall_impl(SYS_exit, retval.posix_retval); else - __llvm_libc::syscall(SYS_exit, retval.stdc_retval); + __llvm_libc::syscall_impl(SYS_exit, retval.stdc_retval); } } // namespace __llvm_libc diff --git a/libc/src/fcntl/linux/creat.cpp b/libc/src/fcntl/linux/creat.cpp --- a/libc/src/fcntl/linux/creat.cpp +++ b/libc/src/fcntl/linux/creat.cpp @@ -19,11 +19,11 @@ LLVM_LIBC_FUNCTION(int, creat, (const char *path, int mode_flags)) { #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, path, O_CREAT | O_WRONLY | O_TRUNC, - mode_flags); + int fd = __llvm_libc::syscall_impl(SYS_open, path, + O_CREAT | O_WRONLY | O_TRUNC, mode_flags); #else - int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path, - O_CREAT | O_WRONLY | O_TRUNC, mode_flags); + int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path, + O_CREAT | O_WRONLY | O_TRUNC, mode_flags); #endif if (fd > 0) diff --git a/libc/src/fcntl/linux/open.cpp b/libc/src/fcntl/linux/open.cpp --- a/libc/src/fcntl/linux/open.cpp +++ b/libc/src/fcntl/linux/open.cpp @@ -30,9 +30,10 @@ } #ifdef SYS_open - int fd = __llvm_libc::syscall(SYS_open, path, flags, mode_flags); + int fd = __llvm_libc::syscall_impl(SYS_open, path, flags, mode_flags); #else - int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path, flags, mode_flags); + int fd = + __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path, flags, mode_flags); #endif if (fd > 0) return fd; diff --git a/libc/src/fcntl/linux/openat.cpp b/libc/src/fcntl/linux/openat.cpp --- a/libc/src/fcntl/linux/openat.cpp +++ b/libc/src/fcntl/linux/openat.cpp @@ -29,7 +29,7 @@ va_end(varargs); } - int fd = __llvm_libc::syscall(SYS_openat, dfd, path, flags, mode_flags); + int fd = __llvm_libc::syscall_impl(SYS_openat, dfd, path, flags, mode_flags); if (fd > 0) return fd; diff --git a/libc/src/sched/linux/sched_getaffinity.cpp b/libc/src/sched/linux/sched_getaffinity.cpp --- a/libc/src/sched/linux/sched_getaffinity.cpp +++ b/libc/src/sched/linux/sched_getaffinity.cpp @@ -21,7 +21,7 @@ LLVM_LIBC_FUNCTION(int, sched_getaffinity, (pid_t tid, size_t cpuset_size, cpu_set_t *mask)) { long ret = - __llvm_libc::syscall(SYS_sched_getaffinity, tid, cpuset_size, mask); + __llvm_libc::syscall_impl(SYS_sched_getaffinity, tid, cpuset_size, mask); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sched/linux/sched_setaffinity.cpp b/libc/src/sched/linux/sched_setaffinity.cpp --- a/libc/src/sched/linux/sched_setaffinity.cpp +++ b/libc/src/sched/linux/sched_setaffinity.cpp @@ -20,7 +20,7 @@ LLVM_LIBC_FUNCTION(int, sched_setaffinity, (pid_t tid, size_t cpuset_size, const cpu_set_t *mask)) { long ret = - __llvm_libc::syscall(SYS_sched_setaffinity, tid, cpuset_size, mask); + __llvm_libc::syscall_impl(SYS_sched_setaffinity, tid, cpuset_size, mask); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/signal/linux/__restore.cpp b/libc/src/signal/linux/__restore.cpp --- a/libc/src/signal/linux/__restore.cpp +++ b/libc/src/signal/linux/__restore.cpp @@ -19,6 +19,6 @@ __attribute__((no_sanitize("all"), hidden)); -extern "C" void __restore_rt() { __llvm_libc::syscall(SYS_rt_sigreturn); } +extern "C" void __restore_rt() { __llvm_libc::syscall_impl(SYS_rt_sigreturn); } } // namespace __llvm_libc diff --git a/libc/src/signal/linux/raise.cpp b/libc/src/signal/linux/raise.cpp --- a/libc/src/signal/linux/raise.cpp +++ b/libc/src/signal/linux/raise.cpp @@ -16,9 +16,9 @@ LLVM_LIBC_FUNCTION(int, raise, (int sig)) { ::sigset_t sigset; block_all_signals(sigset); - long pid = __llvm_libc::syscall(SYS_getpid); - long tid = __llvm_libc::syscall(SYS_gettid); - int ret = __llvm_libc::syscall(SYS_tgkill, pid, tid, sig); + long pid = __llvm_libc::syscall_impl(SYS_getpid); + long tid = __llvm_libc::syscall_impl(SYS_gettid); + int ret = __llvm_libc::syscall_impl(SYS_tgkill, pid, tid, sig); restore_signals(sigset); return ret; } diff --git a/libc/src/signal/linux/sigaction.cpp b/libc/src/signal/linux/sigaction.cpp --- a/libc/src/signal/linux/sigaction.cpp +++ b/libc/src/signal/linux/sigaction.cpp @@ -34,8 +34,9 @@ } KernelSigaction kernel_old; - int ret = syscall(SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr, - libc_old ? &kernel_old : nullptr, sizeof(sigset_t)); + int ret = __llvm_libc::syscall_impl( + SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr, + libc_old ? &kernel_old : nullptr, sizeof(sigset_t)); if (ret) { errno = -ret; return -1; diff --git a/libc/src/signal/linux/signal_utils.h b/libc/src/signal/linux/signal_utils.h --- a/libc/src/signal/linux/signal_utils.h +++ b/libc/src/signal/linux/signal_utils.h @@ -95,13 +95,13 @@ static inline int block_all_signals(sigset_t &set) { sigset_t full = full_set(); - return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &full, &set, - sizeof(sigset_t)); + return __llvm_libc::syscall_impl(SYS_rt_sigprocmask, SIG_BLOCK, &full, &set, + sizeof(sigset_t)); } static inline int restore_signals(const sigset_t &set) { - return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, nullptr, - sizeof(sigset_t)); + return __llvm_libc::syscall_impl(SYS_rt_sigprocmask, SIG_SETMASK, &set, + nullptr, sizeof(sigset_t)); } } // namespace __llvm_libc diff --git a/libc/src/signal/linux/sigprocmask.cpp b/libc/src/signal/linux/sigprocmask.cpp --- a/libc/src/signal/linux/sigprocmask.cpp +++ b/libc/src/signal/linux/sigprocmask.cpp @@ -21,8 +21,8 @@ LLVM_LIBC_FUNCTION(int, sigprocmask, (int how, const sigset_t *__restrict set, sigset_t *__restrict oldset)) { - int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, how, set, oldset, - sizeof(sigset_t)); + int ret = __llvm_libc::syscall_impl(SYS_rt_sigprocmask, how, set, oldset, + sizeof(sigset_t)); if (!ret) return 0; diff --git a/libc/src/stdio/linux/remove.cpp b/libc/src/stdio/linux/remove.cpp --- a/libc/src/stdio/linux/remove.cpp +++ b/libc/src/stdio/linux/remove.cpp @@ -20,9 +20,9 @@ LLVM_LIBC_FUNCTION(int, remove, (const char *path)) { // We first try unlinking it as a file. If it is ia file, it will succeed. If // it fails with EISDIR, we will try unlinking it as a directory. - int ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0); + int ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, 0); if (ret == -EISDIR) - ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); + ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); if (ret >= 0) return 0; errno = -ret; diff --git a/libc/src/stdlib/linux/_Exit.cpp b/libc/src/stdlib/linux/_Exit.cpp --- a/libc/src/stdlib/linux/_Exit.cpp +++ b/libc/src/stdlib/linux/_Exit.cpp @@ -16,8 +16,8 @@ LLVM_LIBC_FUNCTION(void, _Exit, (int status)) { for (;;) { - __llvm_libc::syscall(SYS_exit_group, status); - __llvm_libc::syscall(SYS_exit, status); + __llvm_libc::syscall_impl(SYS_exit_group, status); + __llvm_libc::syscall_impl(SYS_exit, status); } } diff --git a/libc/src/sys/mman/linux/madvise.cpp b/libc/src/sys/mman/linux/madvise.cpp --- a/libc/src/sys/mman/linux/madvise.cpp +++ b/libc/src/sys/mman/linux/madvise.cpp @@ -19,8 +19,8 @@ // This function is currently linux only. It has to be refactored suitably if // madvise is to be supported on non-linux operating systems also. LLVM_LIBC_FUNCTION(int, madvise, (void *addr, size_t size, int advice)) { - long ret_val = __llvm_libc::syscall(SYS_madvise, reinterpret_cast(addr), - size, advice); + long ret_val = __llvm_libc::syscall_impl( + SYS_madvise, reinterpret_cast(addr), size, advice); // A negative return value indicates an error with the magnitude of the // value being the error code. diff --git a/libc/src/sys/mman/linux/mmap.cpp b/libc/src/sys/mman/linux/mmap.cpp --- a/libc/src/sys/mman/linux/mmap.cpp +++ b/libc/src/sys/mman/linux/mmap.cpp @@ -40,8 +40,8 @@ #endif long ret_val = - __llvm_libc::syscall(syscall_number, reinterpret_cast(addr), size, - prot, flags, fd, offset); + __llvm_libc::syscall_impl(syscall_number, reinterpret_cast(addr), + size, prot, flags, fd, offset); // The mmap/mmap2 syscalls return negative values on error. These negative // values are actually the negative values of the error codes. So, fix them diff --git a/libc/src/sys/mman/linux/mprotect.cpp b/libc/src/sys/mman/linux/mprotect.cpp --- a/libc/src/sys/mman/linux/mprotect.cpp +++ b/libc/src/sys/mman/linux/mprotect.cpp @@ -19,8 +19,8 @@ // This function is currently linux only. It has to be refactored suitably if // mprotect is to be supported on non-linux operating systems also. LLVM_LIBC_FUNCTION(int, mprotect, (void *addr, size_t size, int prot)) { - long ret_val = __llvm_libc::syscall(SYS_mprotect, - reinterpret_cast(addr), size, prot); + long ret_val = __llvm_libc::syscall_impl( + SYS_mprotect, reinterpret_cast(addr), size, prot); // A negative return value indicates an error with the magnitude of the // value being the error code. diff --git a/libc/src/sys/mman/linux/munmap.cpp b/libc/src/sys/mman/linux/munmap.cpp --- a/libc/src/sys/mman/linux/munmap.cpp +++ b/libc/src/sys/mman/linux/munmap.cpp @@ -20,7 +20,7 @@ // mmap is to be supported on non-linux operating systems also. LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) { long ret_val = - __llvm_libc::syscall(SYS_munmap, reinterpret_cast(addr), size); + __llvm_libc::syscall_impl(SYS_munmap, reinterpret_cast(addr), size); // A negative return value indicates an error with the magnitude of the // value being the error code. diff --git a/libc/src/sys/mman/linux/posix_madvise.cpp b/libc/src/sys/mman/linux/posix_madvise.cpp --- a/libc/src/sys/mman/linux/posix_madvise.cpp +++ b/libc/src/sys/mman/linux/posix_madvise.cpp @@ -23,8 +23,8 @@ if (advice == POSIX_MADV_DONTNEED) { return 0; } - long ret_val = __llvm_libc::syscall(SYS_madvise, reinterpret_cast(addr), - size, advice); + long ret_val = __llvm_libc::syscall_impl( + SYS_madvise, reinterpret_cast(addr), size, advice); return ret_val < 0 ? -ret_val : 0; } diff --git a/libc/src/sys/resource/linux/getrlimit.cpp b/libc/src/sys/resource/linux/getrlimit.cpp --- a/libc/src/sys/resource/linux/getrlimit.cpp +++ b/libc/src/sys/resource/linux/getrlimit.cpp @@ -18,7 +18,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, getrlimit, (int res, struct rlimit *limits)) { - long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, nullptr, limits); + long ret = __llvm_libc::syscall_impl(SYS_prlimit64, 0, res, nullptr, limits); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/resource/linux/setrlimit.cpp b/libc/src/sys/resource/linux/setrlimit.cpp --- a/libc/src/sys/resource/linux/setrlimit.cpp +++ b/libc/src/sys/resource/linux/setrlimit.cpp @@ -18,7 +18,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, setrlimit, (int res, const struct rlimit *limits)) { - long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, limits, nullptr); + long ret = __llvm_libc::syscall_impl(SYS_prlimit64, 0, res, limits, nullptr); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/sendfile/linux/sendfile.cpp b/libc/src/sys/sendfile/linux/sendfile.cpp --- a/libc/src/sys/sendfile/linux/sendfile.cpp +++ b/libc/src/sys/sendfile/linux/sendfile.cpp @@ -19,7 +19,8 @@ LLVM_LIBC_FUNCTION(ssize_t, sendfile, (int out_fd, int in_fd, off_t *offset, size_t count)) { - long ret = __llvm_libc::syscall(SYS_sendfile, in_fd, out_fd, offset, count); + long ret = + __llvm_libc::syscall_impl(SYS_sendfile, in_fd, out_fd, offset, count); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/stat/linux/chmod.cpp b/libc/src/sys/stat/linux/chmod.cpp --- a/libc/src/sys/stat/linux/chmod.cpp +++ b/libc/src/sys/stat/linux/chmod.cpp @@ -20,9 +20,9 @@ LLVM_LIBC_FUNCTION(int, chmod, (const char *path, mode_t mode)) { #ifdef SYS_chmod - long ret = __llvm_libc::syscall(SYS_chmod, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_chmod, path, mode); #elif defined(SYS_fchmodat) - long ret = __llvm_libc::syscall(SYS_fchmodat, AT_FDCWD, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_fchmodat, AT_FDCWD, path, mode); #else #error "chmod and chmodat syscalls not available." #endif diff --git a/libc/src/sys/stat/linux/fchmod.cpp b/libc/src/sys/stat/linux/fchmod.cpp --- a/libc/src/sys/stat/linux/fchmod.cpp +++ b/libc/src/sys/stat/linux/fchmod.cpp @@ -19,7 +19,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, fchmod, (int fd, mode_t mode)) { - long ret = __llvm_libc::syscall(SYS_fchmod, fd, mode); + long ret = __llvm_libc::syscall_impl(SYS_fchmod, fd, mode); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/stat/linux/fchmodat.cpp b/libc/src/sys/stat/linux/fchmodat.cpp --- a/libc/src/sys/stat/linux/fchmodat.cpp +++ b/libc/src/sys/stat/linux/fchmodat.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(int, fchmodat, (int dirfd, const char *path, mode_t mode, int flags)) { - long ret = __llvm_libc::syscall(SYS_fchmodat, dirfd, path, mode, flags); + long ret = __llvm_libc::syscall_impl(SYS_fchmodat, dirfd, path, mode, flags); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/stat/linux/kernel_statx.h b/libc/src/sys/stat/linux/kernel_statx.h --- a/libc/src/sys/stat/linux/kernel_statx.h +++ b/libc/src/sys/stat/linux/kernel_statx.h @@ -73,8 +73,8 @@ struct stat *__restrict statbuf) { // We make a statx syscall and copy out the result into the |statbuf|. ::statx_buf xbuf; - long ret = - syscall(SYS_statx, dirfd, path, flags, ::STATX_BASIC_STATS_MASK, &xbuf); + long ret = __llvm_libc::syscall_impl(SYS_statx, dirfd, path, flags, + ::STATX_BASIC_STATS_MASK, &xbuf); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/sys/stat/linux/mkdir.cpp b/libc/src/sys/stat/linux/mkdir.cpp --- a/libc/src/sys/stat/linux/mkdir.cpp +++ b/libc/src/sys/stat/linux/mkdir.cpp @@ -20,9 +20,9 @@ LLVM_LIBC_FUNCTION(int, mkdir, (const char *path, mode_t mode)) { #ifdef SYS_mkdir - long ret = __llvm_libc::syscall(SYS_mkdir, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_mkdir, path, mode); #elif defined(SYS_mkdirat) - long ret = __llvm_libc::syscall(SYS_mkdirat, AT_FDCWD, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_mkdirat, AT_FDCWD, path, mode); #else #error "mkdir and mkdirat syscalls not available." #endif diff --git a/libc/src/sys/stat/linux/mkdirat.cpp b/libc/src/sys/stat/linux/mkdirat.cpp --- a/libc/src/sys/stat/linux/mkdirat.cpp +++ b/libc/src/sys/stat/linux/mkdirat.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(int, mkdirat, (int dfd, const char *path, mode_t mode)) { #ifdef SYS_mkdirat - long ret = __llvm_libc::syscall(SYS_mkdirat, dfd, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_mkdirat, dfd, path, mode); #else #error "mkdirat syscalls not available." #endif diff --git a/libc/src/sys/utsname/linux/uname.cpp b/libc/src/sys/utsname/linux/uname.cpp --- a/libc/src/sys/utsname/linux/uname.cpp +++ b/libc/src/sys/utsname/linux/uname.cpp @@ -18,7 +18,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, uname, (struct utsname * name)) { - long ret = __llvm_libc::syscall(SYS_uname, name); + long ret = __llvm_libc::syscall_impl(SYS_uname, name); if (ret >= 0) return 1; diff --git a/libc/src/threads/linux/CndVar.h b/libc/src/threads/linux/CndVar.h --- a/libc/src/threads/linux/CndVar.h +++ b/libc/src/threads/linux/CndVar.h @@ -84,8 +84,8 @@ } } - __llvm_libc::syscall(SYS_futex, &waiter.futex_word.val, FUTEX_WAIT, - WS_Waiting, 0, 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &waiter.futex_word.val, FUTEX_WAIT, + WS_Waiting, 0, 0, 0); // At this point, if locking |m| fails, we can simply return as the // queued up waiter would have been removed from the queue. @@ -109,7 +109,7 @@ qmtx.futex_word = FutexWordType(Mutex::LockState::Free); - __llvm_libc::syscall( + __llvm_libc::syscall_impl( SYS_futex, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1, &first->futex_word.val, FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); @@ -126,7 +126,7 @@ // atomically update the waiter status to WS_Signalled before waking // up the waiter. A dummy location is used for the other futex of // FUTEX_WAKE_OP. - __llvm_libc::syscall( + __llvm_libc::syscall_impl( SYS_futex, &dummy_futex_word, FUTEX_WAKE_OP, 1, 1, &waiter->futex_word.val, FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); diff --git a/libc/src/threads/linux/call_once.cpp b/libc/src/threads/linux/call_once.cpp --- a/libc/src/threads/linux/call_once.cpp +++ b/libc/src/threads/linux/call_once.cpp @@ -46,9 +46,9 @@ func(); auto status = futex_word->exchange(FINISH); if (status == WAITING) { - __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE, - INT_MAX, // Wake all waiters. - 0, 0, 0); + __llvm_libc::syscall_impl(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE, + INT_MAX, // Wake all waiters. + 0, 0, 0); } return; } @@ -56,9 +56,10 @@ FutexWordType status = START; if (futex_word->compare_exchange_strong(status, WAITING) || status == WAITING) { - __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE, - WAITING, // Block only if status is still |WAITING|. - 0, 0, 0); + __llvm_libc::syscall_impl( + SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE, + WAITING, // Block only if status is still |WAITING|. + 0, 0, 0); } } diff --git a/libc/src/time/clock_gettime.cpp b/libc/src/time/clock_gettime.cpp --- a/libc/src/time/clock_gettime.cpp +++ b/libc/src/time/clock_gettime.cpp @@ -21,8 +21,8 @@ LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, struct timespec *tp)) { long ret_val = - __llvm_libc::syscall(SYS_clock_gettime, static_cast(clockid), - reinterpret_cast(tp)); + __llvm_libc::syscall_impl(SYS_clock_gettime, static_cast(clockid), + reinterpret_cast(tp)); // A negative return value indicates an error with the magnitude of the // value being the error code. if (ret_val < 0) { diff --git a/libc/src/time/nanosleep.cpp b/libc/src/time/nanosleep.cpp --- a/libc/src/time/nanosleep.cpp +++ b/libc/src/time/nanosleep.cpp @@ -18,7 +18,7 @@ LLVM_LIBC_FUNCTION(int, nanosleep, (const struct timespec *req, struct timespec *rem)) { - int ret = __llvm_libc::syscall(SYS_nanosleep, req, rem); + int ret = __llvm_libc::syscall_impl(SYS_nanosleep, req, rem); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt --- a/libc/src/unistd/CMakeLists.txt +++ b/libc/src/unistd/CMakeLists.txt @@ -170,6 +170,13 @@ .${LIBC_TARGET_OS}.symlinkat ) +add_entrypoint_object( + __llvm_libc_syscall + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.__llvm_libc_syscall +) + add_entrypoint_object( truncate ALIAS diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt --- a/libc/src/unistd/linux/CMakeLists.txt +++ b/libc/src/unistd/linux/CMakeLists.txt @@ -314,6 +314,18 @@ libc.src.errno.errno ) +add_entrypoint_object( + __llvm_libc_syscall + SRCS + syscall.cpp + HDRS + ../syscall.h + DEPENDS + libc.include.unistd + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( truncate SRCS diff --git a/libc/src/unistd/linux/access.cpp b/libc/src/unistd/linux/access.cpp --- a/libc/src/unistd/linux/access.cpp +++ b/libc/src/unistd/linux/access.cpp @@ -19,9 +19,9 @@ LLVM_LIBC_FUNCTION(int, access, (const char *path, int mode)) { #ifdef SYS_access - long ret = __llvm_libc::syscall(SYS_access, path, mode); + long ret = __llvm_libc::syscall_impl(SYS_access, path, mode); #elif defined(SYS_faccessat) - long ret = __llvm_libc::syscall(SYS_faccessat, AT_FDCWD, path, mode, 0); + long ret = __llvm_libc::syscall_impl(SYS_faccessat, AT_FDCWD, path, mode, 0); #else #error "access syscalls not available." #endif diff --git a/libc/src/unistd/linux/chdir.cpp b/libc/src/unistd/linux/chdir.cpp --- a/libc/src/unistd/linux/chdir.cpp +++ b/libc/src/unistd/linux/chdir.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, chdir, (const char *path)) { - long ret = __llvm_libc::syscall(SYS_chdir, path); + long ret = __llvm_libc::syscall_impl(SYS_chdir, path); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/close.cpp b/libc/src/unistd/linux/close.cpp --- a/libc/src/unistd/linux/close.cpp +++ b/libc/src/unistd/linux/close.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, close, (int fd)) { - long ret = __llvm_libc::syscall(SYS_close, fd); + long ret = __llvm_libc::syscall_impl(SYS_close, fd); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/dup.cpp b/libc/src/unistd/linux/dup.cpp --- a/libc/src/unistd/linux/dup.cpp +++ b/libc/src/unistd/linux/dup.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, dup, (int fd)) { - long ret = __llvm_libc::syscall(SYS_dup, fd); + long ret = __llvm_libc::syscall_impl(SYS_dup, fd); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/dup2.cpp b/libc/src/unistd/linux/dup2.cpp --- a/libc/src/unistd/linux/dup2.cpp +++ b/libc/src/unistd/linux/dup2.cpp @@ -20,20 +20,20 @@ LLVM_LIBC_FUNCTION(int, dup2, (int oldfd, int newfd)) { #ifdef SYS_dup2 // If dup2 syscall is available, we make use of directly. - long ret = __llvm_libc::syscall(SYS_dup2, oldfd, newfd); + long ret = __llvm_libc::syscall_impl(SYS_dup2, oldfd, newfd); #elif defined(SYS_dup3) // If dup2 syscall is not available, we try using the dup3 syscall. However, // dup3 fails if oldfd is the same as newfd. So, we handle that case // separately before making the dup3 syscall. if (oldfd == newfd) { // Check if oldfd is actually a valid file descriptor. - long ret = __llvm_libc::syscall(SYS_fcntl, oldfd, F_GETFD); + long ret = __llvm_libc::syscall_impl(SYS_fcntl, oldfd, F_GETFD); if (ret >= 0) return oldfd; errno = -ret; return -1; } - long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, 0); + long ret = __llvm_libc::syscall_impl(SYS_dup3, oldfd, newfd, 0); #else #error "SYS_dup2 and SYS_dup3 not available for the target." #endif diff --git a/libc/src/unistd/linux/dup3.cpp b/libc/src/unistd/linux/dup3.cpp --- a/libc/src/unistd/linux/dup3.cpp +++ b/libc/src/unistd/linux/dup3.cpp @@ -18,7 +18,7 @@ LLVM_LIBC_FUNCTION(int, dup3, (int oldfd, int newfd, int flags)) { // If dup2 syscall is available, we make use of directly. - long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, flags); + long ret = __llvm_libc::syscall_impl(SYS_dup3, oldfd, newfd, flags); if (ret >= 0) return ret; errno = -ret; diff --git a/libc/src/unistd/linux/fchdir.cpp b/libc/src/unistd/linux/fchdir.cpp --- a/libc/src/unistd/linux/fchdir.cpp +++ b/libc/src/unistd/linux/fchdir.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, fchdir, (int fd)) { - long ret = __llvm_libc::syscall(SYS_fchdir, fd); + long ret = __llvm_libc::syscall_impl(SYS_fchdir, fd); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/fsync.cpp b/libc/src/unistd/linux/fsync.cpp --- a/libc/src/unistd/linux/fsync.cpp +++ b/libc/src/unistd/linux/fsync.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, fsync, (int fd)) { - long ret = __llvm_libc::syscall(SYS_fsync, fd); + long ret = __llvm_libc::syscall_impl(SYS_fsync, fd); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/ftruncate.cpp b/libc/src/unistd/linux/ftruncate.cpp --- a/libc/src/unistd/linux/ftruncate.cpp +++ b/libc/src/unistd/linux/ftruncate.cpp @@ -18,7 +18,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, ftruncate, (int fd, off_t len)) { - int ret = __llvm_libc::syscall(SYS_ftruncate, fd, len); + int ret = __llvm_libc::syscall_impl(SYS_ftruncate, fd, len); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/geteuid.cpp b/libc/src/unistd/linux/geteuid.cpp --- a/libc/src/unistd/linux/geteuid.cpp +++ b/libc/src/unistd/linux/geteuid.cpp @@ -16,7 +16,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(uid_t, geteuid, ()) { - return __llvm_libc::syscall(SYS_geteuid); + return __llvm_libc::syscall_impl(SYS_geteuid); } } // namespace __llvm_libc diff --git a/libc/src/unistd/linux/getpid.cpp b/libc/src/unistd/linux/getpid.cpp --- a/libc/src/unistd/linux/getpid.cpp +++ b/libc/src/unistd/linux/getpid.cpp @@ -16,7 +16,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(pid_t, getpid, ()) { - return __llvm_libc::syscall(SYS_getpid); + return __llvm_libc::syscall_impl(SYS_getpid); } } // namespace __llvm_libc diff --git a/libc/src/unistd/linux/getppid.cpp b/libc/src/unistd/linux/getppid.cpp --- a/libc/src/unistd/linux/getppid.cpp +++ b/libc/src/unistd/linux/getppid.cpp @@ -16,7 +16,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(pid_t, getppid, ()) { - return __llvm_libc::syscall(SYS_getppid); + return __llvm_libc::syscall_impl(SYS_getppid); } } // namespace __llvm_libc diff --git a/libc/src/unistd/linux/getuid.cpp b/libc/src/unistd/linux/getuid.cpp --- a/libc/src/unistd/linux/getuid.cpp +++ b/libc/src/unistd/linux/getuid.cpp @@ -16,7 +16,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(uid_t, getuid, ()) { - return __llvm_libc::syscall(SYS_getuid); + return __llvm_libc::syscall_impl(SYS_getuid); } } // namespace __llvm_libc diff --git a/libc/src/unistd/linux/link.cpp b/libc/src/unistd/linux/link.cpp --- a/libc/src/unistd/linux/link.cpp +++ b/libc/src/unistd/linux/link.cpp @@ -19,10 +19,10 @@ LLVM_LIBC_FUNCTION(int, link, (const char *path1, const char *path2)) { #ifdef SYS_link - long ret = __llvm_libc::syscall(SYS_link, path1, path2); + long ret = __llvm_libc::syscall_impl(SYS_link, path1, path2); #elif defined(SYS_linkat) - long ret = - __llvm_libc::syscall(SYS_linkat, AT_FDCWD, path1, AT_FDCWD, path2, 0); + long ret = __llvm_libc::syscall_impl(SYS_linkat, AT_FDCWD, path1, AT_FDCWD, + path2, 0); #else #error "SYS_link or SYS_linkat not available." #endif diff --git a/libc/src/unistd/linux/linkat.cpp b/libc/src/unistd/linux/linkat.cpp --- a/libc/src/unistd/linux/linkat.cpp +++ b/libc/src/unistd/linux/linkat.cpp @@ -20,7 +20,8 @@ LLVM_LIBC_FUNCTION(int, linkat, (int fd1, const char *path1, int fd2, const char *path2, int flags)) { - long ret = __llvm_libc::syscall(SYS_linkat, fd1, path1, fd2, path2, flags); + long ret = + __llvm_libc::syscall_impl(SYS_linkat, fd1, path1, fd2, path2, flags); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/lseek.cpp b/libc/src/unistd/linux/lseek.cpp --- a/libc/src/unistd/linux/lseek.cpp +++ b/libc/src/unistd/linux/lseek.cpp @@ -20,11 +20,11 @@ LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) { off_t result; #ifdef SYS_lseek - long ret = __llvm_libc::syscall(SYS_lseek, fd, offset, whence); + long ret = __llvm_libc::syscall_impl(SYS_lseek, fd, offset, whence); result = ret; #elif defined(SYS__llseek) - long ret = __llvm_libc::syscall(SYS__llseek, fd, offset >> 32, offset, - &result, whence); + long ret = __llvm_libc::syscall_impl(SYS__llseek, fd, offset >> 32, offset, + &result, whence); #else #error "lseek and _llseek syscalls not available." #endif diff --git a/libc/src/unistd/linux/pread.cpp b/libc/src/unistd/linux/pread.cpp --- a/libc/src/unistd/linux/pread.cpp +++ b/libc/src/unistd/linux/pread.cpp @@ -18,7 +18,7 @@ LLVM_LIBC_FUNCTION(ssize_t, pread, (int fd, void *buf, size_t count, off_t offset)) { - long ret = __llvm_libc::syscall(SYS_pread64, fd, buf, count, offset); + long ret = __llvm_libc::syscall_impl(SYS_pread64, fd, buf, count, offset); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/pwrite.cpp b/libc/src/unistd/linux/pwrite.cpp --- a/libc/src/unistd/linux/pwrite.cpp +++ b/libc/src/unistd/linux/pwrite.cpp @@ -18,7 +18,7 @@ LLVM_LIBC_FUNCTION(ssize_t, pwrite, (int fd, const void *buf, size_t count, off_t offset)) { - long ret = __llvm_libc::syscall(SYS_pwrite64, fd, buf, count, offset); + long ret = __llvm_libc::syscall_impl(SYS_pwrite64, fd, buf, count, offset); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp --- a/libc/src/unistd/linux/read.cpp +++ b/libc/src/unistd/linux/read.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) { - long ret = __llvm_libc::syscall(SYS_read, fd, buf, count); + long ret = __llvm_libc::syscall_impl(SYS_read, fd, buf, count); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/readlink.cpp b/libc/src/unistd/linux/readlink.cpp --- a/libc/src/unistd/linux/readlink.cpp +++ b/libc/src/unistd/linux/readlink.cpp @@ -21,10 +21,10 @@ (const char *__restrict path, char *__restrict buf, size_t bufsize)) { #ifdef SYS_readlink - ssize_t ret = __llvm_libc::syscall(SYS_readlink, path, buf, bufsize); + ssize_t ret = __llvm_libc::syscall_impl(SYS_readlink, path, buf, bufsize); #elif defined(SYS_readlinkat) ssize_t ret = - __llvm_libc::syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize); + __llvm_libc::syscall_impl(SYS_readlinkat, AT_FDCWD, path, buf, bufsize); #else #error "SYS_readlink or SYS_readlinkat not available." #endif diff --git a/libc/src/unistd/linux/readlinkat.cpp b/libc/src/unistd/linux/readlinkat.cpp --- a/libc/src/unistd/linux/readlinkat.cpp +++ b/libc/src/unistd/linux/readlinkat.cpp @@ -20,7 +20,8 @@ LLVM_LIBC_FUNCTION(ssize_t, readlinkat, (int fd, const char *__restrict path, char *__restrict buf, size_t bufsize)) { - ssize_t ret = __llvm_libc::syscall(SYS_readlinkat, fd, path, buf, bufsize); + ssize_t ret = + __llvm_libc::syscall_impl(SYS_readlinkat, fd, path, buf, bufsize); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/rmdir.cpp b/libc/src/unistd/linux/rmdir.cpp --- a/libc/src/unistd/linux/rmdir.cpp +++ b/libc/src/unistd/linux/rmdir.cpp @@ -19,9 +19,10 @@ LLVM_LIBC_FUNCTION(int, rmdir, (const char *path)) { #ifdef SYS_rmdir - long ret = __llvm_libc::syscall(SYS_rmdir, path); + long ret = __llvm_libc::syscall_impl(SYS_rmdir, path); #elif defined(SYS_unlinkat) - long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); + long ret = + __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); #else #error "rmdir and unlinkat syscalls not available." #endif diff --git a/libc/src/unistd/linux/symlink.cpp b/libc/src/unistd/linux/symlink.cpp --- a/libc/src/unistd/linux/symlink.cpp +++ b/libc/src/unistd/linux/symlink.cpp @@ -19,9 +19,9 @@ LLVM_LIBC_FUNCTION(int, symlink, (const char *path1, const char *path2)) { #ifdef SYS_symlink - long ret = __llvm_libc::syscall(SYS_symlink, path1, path2); + long ret = __llvm_libc::syscall_impl(SYS_symlink, path1, path2); #elif defined(SYS_symlinkat) - long ret = __llvm_libc::syscall(SYS_symlinkat, path1, AT_FDCWD, path2); + long ret = __llvm_libc::syscall_impl(SYS_symlinkat, path1, AT_FDCWD, path2); #else #error "SYS_symlink or SYS_symlinkat not available." #endif diff --git a/libc/src/unistd/linux/symlinkat.cpp b/libc/src/unistd/linux/symlinkat.cpp --- a/libc/src/unistd/linux/symlinkat.cpp +++ b/libc/src/unistd/linux/symlinkat.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(int, symlinkat, (const char *path1, int fd, const char *path2)) { - long ret = __llvm_libc::syscall(SYS_symlinkat, path1, fd, path2); + long ret = __llvm_libc::syscall_impl(SYS_symlinkat, path1, fd, path2); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/link.cpp b/libc/src/unistd/linux/syscall.cpp copy from libc/src/unistd/linux/link.cpp copy to libc/src/unistd/linux/syscall.cpp --- a/libc/src/unistd/linux/link.cpp +++ b/libc/src/unistd/linux/syscall.cpp @@ -1,4 +1,4 @@ -//===-- Linux implementation of link --------------------------------------===// +//===-- Linux implementation of syscall -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,27 +6,24 @@ // //===----------------------------------------------------------------------===// -#include "src/unistd/link.h" +#include "src/unistd/syscall.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" #include -#include -#include // For syscall numbers. +#include namespace __llvm_libc { -LLVM_LIBC_FUNCTION(int, link, (const char *path1, const char *path2)) { -#ifdef SYS_link - long ret = __llvm_libc::syscall(SYS_link, path1, path2); -#elif defined(SYS_linkat) +LLVM_LIBC_FUNCTION(long, __llvm_libc_syscall, + (long number, long arg1, long arg2, long arg3, long arg4, + long arg5, long arg6)) { long ret = - __llvm_libc::syscall(SYS_linkat, AT_FDCWD, path1, AT_FDCWD, path2, 0); -#else -#error "SYS_link or SYS_linkat not available." -#endif - if (ret < 0) { + __llvm_libc::syscall_impl(number, arg1, arg2, arg3, arg4, arg5, arg6); + // Syscalls may return large positive values that overflow, but will never + // return values between -4096 and -1 + if (static_cast(ret) > -4096UL) { errno = -ret; return -1; } diff --git a/libc/src/unistd/linux/truncate.cpp b/libc/src/unistd/linux/truncate.cpp --- a/libc/src/unistd/linux/truncate.cpp +++ b/libc/src/unistd/linux/truncate.cpp @@ -18,7 +18,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, truncate, (const char *path, off_t len)) { - int ret = __llvm_libc::syscall(SYS_truncate, path, len); + int ret = __llvm_libc::syscall_impl(SYS_truncate, path, len); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/linux/unlink.cpp b/libc/src/unistd/linux/unlink.cpp --- a/libc/src/unistd/linux/unlink.cpp +++ b/libc/src/unistd/linux/unlink.cpp @@ -19,9 +19,9 @@ LLVM_LIBC_FUNCTION(int, unlink, (const char *path)) { #ifdef SYS_unlink - long ret = __llvm_libc::syscall(SYS_unlink, path); + long ret = __llvm_libc::syscall_impl(SYS_unlink, path); #elif defined(SYS_unlinkat) - long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0); + long ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, 0); #else #error "Unlink syscalls not available." #endif diff --git a/libc/src/unistd/linux/unlinkat.cpp b/libc/src/unistd/linux/unlinkat.cpp --- a/libc/src/unistd/linux/unlinkat.cpp +++ b/libc/src/unistd/linux/unlinkat.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(int, unlinkat, (int dfd, const char *path, int flags)) { #ifdef SYS_unlinkat - long ret = __llvm_libc::syscall(SYS_unlinkat, dfd, path, flags); + long ret = __llvm_libc::syscall_impl(SYS_unlinkat, dfd, path, flags); #else #error "unlinkat syscall not available." #endif diff --git a/libc/src/unistd/linux/write.cpp b/libc/src/unistd/linux/write.cpp --- a/libc/src/unistd/linux/write.cpp +++ b/libc/src/unistd/linux/write.cpp @@ -17,7 +17,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(ssize_t, write, (int fd, const void *buf, size_t count)) { - long ret = __llvm_libc::syscall(SYS_write, fd, buf, count); + long ret = __llvm_libc::syscall_impl(SYS_write, fd, buf, count); if (ret < 0) { errno = -ret; return -1; diff --git a/libc/src/unistd/syscall.h b/libc/src/unistd/syscall.h new file mode 100644 --- /dev/null +++ b/libc/src/unistd/syscall.h @@ -0,0 +1,22 @@ +//===-- Implementation header for syscall -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_UNISTD_SYSCALL_H +#define LLVM_LIBC_SRC_UNISTD_SYSCALL_H + +#include +#include + +namespace __llvm_libc { + +long __llvm_libc_syscall(long number, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_UNISTD_SYSCALL_H diff --git a/libc/test/src/__support/OSUtil/linux/x86_64/syscall_test.cpp b/libc/test/src/__support/OSUtil/linux/x86_64/syscall_test.cpp --- a/libc/test/src/__support/OSUtil/linux/x86_64/syscall_test.cpp +++ b/libc/test/src/__support/OSUtil/linux/x86_64/syscall_test.cpp @@ -16,28 +16,29 @@ using __llvm_libc::cpp::function; - function f([](long n) { return __llvm_libc::syscall(n); }); + function f([](long n) { return __llvm_libc::syscall_impl(n); }); function f1( - [](long n, long a1) { return __llvm_libc::syscall(n, a1); }); - function f2( - [](long n, long a1, long a2) { return __llvm_libc::syscall(n, a1, a2); }); + [](long n, long a1) { return __llvm_libc::syscall_impl(n, a1); }); + function f2([](long n, long a1, long a2) { + return __llvm_libc::syscall_impl(n, a1, a2); + }); function f3( [](long n, long a1, long a2, long a3) { - return __llvm_libc::syscall(n, a1, a2, a3); + return __llvm_libc::syscall_impl(n, a1, a2, a3); }); function f4( [](long n, long a1, long a2, long a3, long a4) { - return __llvm_libc::syscall(n, a1, a2, a3, a4); + return __llvm_libc::syscall_impl(n, a1, a2, a3, a4); }); function f5( [](long n, long a1, long a2, long a3, long a4, long a5) { - return __llvm_libc::syscall(n, a1, a2, a3, a4, a5); + return __llvm_libc::syscall_impl(n, a1, a2, a3, a4, a5); }); function f6( [](long n, long a1, long a2, long a3, long a4, long a5, long a6) { - return __llvm_libc::syscall(n, a1, a2, a3, a4, a5, a6); + return __llvm_libc::syscall_impl(n, a1, a2, a3, a4, a5, a6); }); function not_long_type( - [](long n, void *a1) { return __llvm_libc::syscall(n, a1); }); + [](long n, void *a1) { return __llvm_libc::syscall_impl(n, a1); }); } diff --git a/libc/test/src/sched/affinity_test.cpp b/libc/test/src/sched/affinity_test.cpp --- a/libc/test/src/sched/affinity_test.cpp +++ b/libc/test/src/sched/affinity_test.cpp @@ -19,7 +19,7 @@ cpu_set_t mask; errno = 0; using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds; - pid_t tid = __llvm_libc::syscall(SYS_gettid); + pid_t tid = __llvm_libc::syscall_impl(SYS_gettid); ASSERT_GT(tid, pid_t(0)); // We just get and set the same mask. ASSERT_THAT(__llvm_libc::sched_getaffinity(tid, sizeof(cpu_set_t), &mask), @@ -30,7 +30,7 @@ TEST(LlvmLibcSchedAffinityTest, BadMask) { using __llvm_libc::testing::ErrnoSetterMatcher::Fails; - pid_t tid = __llvm_libc::syscall(SYS_gettid); + pid_t tid = __llvm_libc::syscall_impl(SYS_gettid); errno = 0; ASSERT_THAT(__llvm_libc::sched_getaffinity(tid, sizeof(cpu_set_t), nullptr), diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt --- a/libc/test/src/unistd/CMakeLists.txt +++ b/libc/test/src/unistd/CMakeLists.txt @@ -361,3 +361,18 @@ DEPENDS libc.src.unistd.geteuid ) + +add_libc_unittest( + syscall_test + SUITE + libc_unistd_unittests + SRCS + syscall_test.cpp + DEPENDS + libc.src.unistd.__llvm_libc_syscall + libc.include.errno + libc.include.unistd + libc.include.fcntl + libc.include.sys_syscall + libc.test.errno_setter_matcher +) diff --git a/libc/test/src/unistd/syscall_test.cpp b/libc/test/src/unistd/syscall_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/unistd/syscall_test.cpp @@ -0,0 +1,115 @@ +//===-- Unittests for syscalls --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/unistd/syscall.h" +#include "test/ErrnoSetterMatcher.h" +#include "utils/UnitTest/Test.h" + +#include +#include +#include // For syscall numbers. +#include + +using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds; + +// We only do a smoke test here. Actual functionality tests are +// done by the unit tests of the syscall wrappers like mmap. +// The goal is to test syscalls with a wide number of args. + +// There is no function named "syscall" in llvm-libc, we instead use a macro to +// set up the arguments properly. We still need to specify the namespace though +// because the macro generates a call to the actual internal function +// (__llvm_libc_syscall) which is inside the namespace. +TEST(LlvmLibcSyscallTest, TrivialCall) { + errno = 0; + + ASSERT_GE(__llvm_libc::syscall(SYS_gettid), 0l); + ASSERT_EQ(errno, 0); +} + +TEST(LlvmLibcSyscallTest, SymlinkCreateDestroy) { + constexpr const char LINK_VAL[] = "syscall_readlink_test_value"; + constexpr const char LINK[] = "testdata/syscall_readlink.test.link"; + + ASSERT_GE(__llvm_libc::syscall(SYS_symlink, LINK_VAL, LINK), 0l); + ASSERT_EQ(errno, 0); + + char buf[sizeof(LINK_VAL)]; + + ASSERT_GE(__llvm_libc::syscall(SYS_readlink, LINK, buf, sizeof(buf)), 0l); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_unlink, LINK), 0l); + ASSERT_EQ(errno, 0); +} + +TEST(LlvmLibcSyscallTest, FileReadWrite) { + constexpr const char HELLO[] = "hello"; + constexpr int HELLO_SIZE = sizeof(HELLO); + + constexpr const char *TEST_FILE = "testdata/syscall_pread_pwrite.test"; + + int fd = + __llvm_libc::syscall(SYS_open, TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU); + ASSERT_GT(fd, 0); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_pwrite64, fd, HELLO, HELLO_SIZE, 0), 0l); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_fsync, fd), 0l); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_close, fd), 0l); + ASSERT_EQ(errno, 0); +} + +TEST(LlvmLibcSyscallTest, FileLinkCreateDestroy) { + constexpr const char *TEST_DIR = "testdata"; + constexpr const char *TEST_FILE = "syscall_linkat.test"; + constexpr const char *TEST_FILE_PATH = "testdata/syscall_linkat.test"; + constexpr const char *TEST_FILE_LINK = "syscall_linkat.test.link"; + constexpr const char *TEST_FILE_LINK_PATH = + "testdata/syscall_linkat.test.link"; + + // The test strategy is as follows: + // 1. Create a normal file + // 2. Create a link to that file. + // 3. Open the link to check that the link was created. + // 4. Cleanup the file and its link. + + int write_fd = __llvm_libc::syscall(SYS_open, TEST_FILE_PATH, + O_WRONLY | O_CREAT, S_IRWXU); + ASSERT_GT(write_fd, 0); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_close, write_fd), 0l); + ASSERT_EQ(errno, 0); + + int dir_fd = __llvm_libc::syscall(SYS_open, TEST_DIR, O_DIRECTORY, 0); + ASSERT_GT(dir_fd, 0); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_linkat, dir_fd, TEST_FILE, dir_fd, + TEST_FILE_LINK, 0), + 0l); + ASSERT_EQ(errno, 0); + + int link_fd = __llvm_libc::syscall(SYS_open, TEST_FILE_LINK_PATH, O_PATH, 0); + ASSERT_GT(link_fd, 0); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_unlink, TEST_FILE_PATH), 0l); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_unlink, TEST_FILE_LINK_PATH), 0l); + ASSERT_EQ(errno, 0); + + ASSERT_GE(__llvm_libc::syscall(SYS_close, dir_fd), 0l); + ASSERT_EQ(errno, 0); +}