diff options
Diffstat (limited to 'lib/mlibc/sysdeps')
567 files changed, 24922 insertions, 0 deletions
diff --git a/lib/mlibc/sysdeps/aero/crt-x86_64/crt0.S b/lib/mlibc/sysdeps/aero/crt-x86_64/crt0.S new file mode 100644 index 0000000..62298e3 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/crt-x86_64/crt0.S @@ -0,0 +1,10 @@ +.section .text + +.global _start +_start: + mov $main, %rdi + call __mlibc_entry + +.size _start, . - _start +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/aero/generic/aero.cpp b/lib/mlibc/sysdeps/aero/generic/aero.cpp new file mode 100644 index 0000000..e6bd277 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/aero.cpp @@ -0,0 +1,360 @@ +#include <abi-bits/pid_t.h> +#include <aero/syscall.h> +#include <bits/ensure.h> +#include <errno.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/thread-entry.hpp> +#include <stddef.h> + +#include <frg/vector.hpp> +#include <mlibc/allocator.hpp> + +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +struct Slice { + void *ptr; + uint64_t len; +}; + +/// Helper function to construct a slice vector from the provided argument +/// array. A slice basically consists of a pointer to the data and the length of +/// it. +/// +/// ## Examples +/// ```cc +/// auto slice = create_slice({ "hello", "world" }); +/// ``` +/// +/// The `slice` will look like the following: +/// +/// ```cc +/// vector<Slice>( +/// Slice { .ptr: hello_ptr, .size: hello_size }, +/// Slice { .ptr: world_ptr, .size: world_size } +/// ) +/// ``` +static frg::vector<Slice, MemoryAllocator> create_slice(char *const arg[]) { + if (arg == nullptr) { + return frg::vector<Slice, MemoryAllocator>{getAllocator()}; + } + + // Find out the length of arg: + size_t len = 0; + + while (arg[len] != nullptr) { + len += 1; + } + + frg::vector<Slice, MemoryAllocator> params{getAllocator()}; + params.resize(len); + + // Construct the slice vector: + for (size_t i = 0; i < len; ++i) { + params[i].ptr = (void *)arg[i]; + params[i].len = strlen(arg[i]); + } + + return params; +} + +namespace mlibc { +int sys_uname(struct utsname *buf) { + auto result = syscall(SYS_UNAME, buf); + + if (result < 0) { + return -result; + } + + return result; +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + // auto result = syscall(SYS_FUTEX_WAIT, pointer, expected, time); + // + // if (result < 0) { + // return -result; + // } + // + return 0; +} + +int sys_futex_wake(int *pointer) { + // auto result = syscall(SYS_FUTEX_WAKE, pointer); + // + // if (result < 0) { + // return -result; + // } + // + return 0; +} + +int sys_tcb_set(void *pointer) { + auto result = syscall(SYS_ARCH_PRCTL, ARCH_SET_FS, (uint64_t)pointer); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, + off_t offset, void **window) { + auto result = syscall(SYS_MMAP, hint, size, prot, flags, fd, offset); + + if (result < 0) { + return -result; + } + + *window = (void *)result; + return 0; +} + +int sys_vm_unmap(void *address, size_t size) { + return syscall(SYS_MUNMAP, address, size); +} + +int sys_vm_protect(void *pointer, size_t size, int prot) { + auto res = syscall(SYS_MPROTECT, pointer, size, prot); + if (res < 0) + return -res; + + return 0; +} + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(nullptr, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, pointer); +} + +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +void sys_libc_panic() { + mlibc::infoLogger() << "libc_panic: panicked at 'unknown'" << frg::endlog; + __ensure(!syscall(SYS_BACKTRACE)); + + sys_exit(1); +} + +void sys_libc_log(const char *msg) { syscall(SYS_LOG, msg, strlen(msg)); } + +void sys_exit(int status) { + syscall(SYS_EXIT, status); + + __builtin_unreachable(); +} + +#ifndef MLIBC_BUILDING_RTDL + +pid_t sys_getpid() { + auto result = syscall(SYS_GETPID); + __ensure(result >= 0); + + return result; +} + +pid_t sys_getppid() { + auto result = syscall(SYS_GETPPID); + __ensure(result != 0); + + return result; +} + +int sys_kill(int pid, int sig) { + auto result = syscall(SYS_KILL, pid, sig); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + struct timespec ts; + auto result = syscall(SYS_GETTIME, clock, &ts); + + if (result < 0) { + return -result; + } + + *secs = ts.tv_sec; + *nanos = ts.tv_nsec; + + return 0; +} + +int sys_getcwd(char *buffer, size_t size) { + auto result = syscall(SYS_GETCWD, buffer, size); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_chdir(const char *path) { + auto result = syscall(SYS_CHDIR, path, strlen(path)); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_gethostname(char *buffer, size_t bufsize) { + auto result = syscall(SYS_GETHOSTNAME, buffer, bufsize); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_sleep(time_t *sec, long *nanosec) { + struct timespec ts = {.tv_sec = *sec, .tv_nsec = *nanosec}; + + auto result = syscall(SYS_SLEEP, &ts); + + if (result < 0) { + return -result; + } + + return 0; +} + +pid_t sys_getpgid(pid_t pid, pid_t *pgid) { + auto ret = syscall(SYS_GETPGID, pid); + if(int e = sc_error(ret); e) + return e; + *pgid = ret; + return 0; +} + +int sys_setpgid(pid_t pid, pid_t pgid) { + auto ret = syscall(SYS_SETPGID, pid, pgid); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +uid_t sys_getuid() { + mlibc::infoLogger() << "mlibc: sys_setuid is a stub" << frg::endlog; + return 0; +} + +uid_t sys_geteuid() { + mlibc::infoLogger() << "mlibc: sys_seteuid is a stub" << frg::endlog; + return 0; +} + +int sys_setsid(pid_t *sid) { + auto ret = syscall(SYS_SETSID); + if(int e = sc_error(ret); e) + return e; + *sid = ret; + return 0; +} + +int sys_seteuid(uid_t euid) UNIMPLEMENTED("sys_seteuid") + + gid_t sys_getgid() { + mlibc::infoLogger() << "mlibc: sys_setgid is a stub" << frg::endlog; + return 0; +} + +gid_t sys_getegid() { + mlibc::infoLogger() << "mlibc: sys_getegid is a stub" << frg::endlog; + return 0; +} + +int sys_setgid(gid_t gid) { + mlibc::infoLogger() << "mlibc: sys_setgid is a stub" << frg::endlog; + return 0; +} + +int sys_setegid(gid_t egid) { + mlibc::infoLogger() << "mlibc: sys_setegid is a stub" << frg::endlog; + return 0; +} + +void sys_yield() { + mlibc::infoLogger() << "mlibc: sys_yield is a stub" << frg::endlog; + __ensure(!syscall(SYS_BACKTRACE)); +} + +int sys_clone(void *tcb, pid_t *tid_out, void *stack) { + auto result = syscall(SYS_CLONE, (uintptr_t)__mlibc_start_thread, stack); + + if (result < 0) { + return -result; + } + + *tid_out = (pid_t)result; + return 0; +} + +void sys_thread_exit() UNIMPLEMENTED("sys_thread_exit") + + int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, + pid_t *ret_pid) { + if (ru) { + mlibc::infoLogger() + << "mlibc: struct rusage in sys_waitpid is unsupported" + << frg::endlog; + return ENOSYS; + } + + auto result = syscall(SYS_WAITPID, pid, status, flags); + + if (result < 0) { + return -result; + } + + *ret_pid = result; + return 0; +} + +int sys_fork(pid_t *child) { + auto result = syscall(SYS_FORK); + + if (result < 0) { + return -result; + } + + *child = result; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + auto envv_slice = create_slice(envp); + auto argv_slice = create_slice(argv); + + auto path_ptr = (uintptr_t)path; + auto path_len = strlen(path); + + auto result = + syscall(SYS_EXEC, path_ptr, path_len, argv_slice.data(), + argv_slice.size(), envv_slice.data(), envv_slice.size()); + + if (result < 0) { + return -result; + } + + __builtin_unreachable(); +} + +// int sys_getentropy(void *buffer, size_t length) +// UNIMPLEMENTED("sys_getentropy") + +#endif +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/aero/generic/entry.cpp b/lib/mlibc/sysdeps/aero/generic/entry.cpp new file mode 100644 index 0000000..77d6ed5 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/entry.cpp @@ -0,0 +1,36 @@ +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> +#include <stdint.h> +#include <stdlib.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], + char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux + // sysdeps) + auto result = + main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/aero/generic/filesystem.cpp b/lib/mlibc/sysdeps/aero/generic/filesystem.cpp new file mode 100644 index 0000000..049f4c0 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/filesystem.cpp @@ -0,0 +1,472 @@ +#include "mlibc/fsfd_target.hpp" +#include <aero/syscall.h> + +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> + +#include <unistd.h> + +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> + +namespace mlibc { +int sys_write(int fd, const void *buffer, size_t count, ssize_t *written) { + auto result = syscall(SYS_WRITE, fd, buffer, count); + + if (result < 0) { + return -result; + } + + *written = result; + return 0; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + auto result = syscall(SYS_READ, fd, buf, count); + + if (result < 0) { + *bytes_read = 0; + return -result; + } + + *bytes_read = result; + return 0; +} + +// clang-format off +int sys_pwrite(int fd, const void *buffer, size_t count, off_t off, + ssize_t *written) UNIMPLEMENTED("sys_pwrite") + +// clang-format off +int sys_pread(int fd, void *buf, size_t count, + off_t off, ssize_t *bytes_read) UNIMPLEMENTED("sys_pread") + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + auto result = syscall(SYS_SEEK, fd, offset, whence); + + if (result < 0) { + return -result; + } + + *new_offset = result; + return 0; +} + +int sys_open(const char *filename, int flags, mode_t mode, int *fd) { + auto result = syscall(SYS_OPEN, 0, filename, strlen(filename), flags); + + if (result < 0) { + return -result; + } + + *fd = result; + return 0; +} + +int sys_close(int fd) { + auto result = syscall(SYS_CLOSE, fd); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_access(const char *filename, int mode) { + auto result = + syscall(SYS_ACCESS, AT_FDCWD, filename, strlen(filename), mode, 0); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, + struct stat *statbuf) { + switch (fsfdt) { + case fsfd_target::path: + fd = AT_FDCWD; + break; + case fsfd_target::fd: + flags |= AT_EMPTY_PATH; + + case fsfd_target::fd_path: + break; + + default: + __ensure(!"Invalid fsfd_target"); + __builtin_unreachable(); + } + + auto ret = syscall(SYS_FSTAT, fd, path, strlen(path), flags, statbuf); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { + auto sys_res = syscall(SYS_IOCTL, fd, request, arg); + + if (sys_res < 0) { + return -sys_res; + } + + if (result) + *result = sys_res; + return 0; +} + +int sys_isatty(int fd) { + // NOTE: The easiest way to check if a file descriptor is a TTY is to + // do an ioctl of TIOCGWINSZ on it and see if it succeeds :^) + struct winsize ws; + int result; + + if (!sys_ioctl(fd, TIOCGWINSZ, &ws, &result)) { + return 0; + } + + return ENOTTY; +} + +int sys_tcgetattr(int fd, struct termios *attr) { + int result; + + if (int e = sys_ioctl(fd, TCGETS, (void *)attr, &result); e) + return e; + + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + int req; + + switch (optional_action) { + case TCSANOW: req = TCSETS; break; + case TCSADRAIN: req = TCSETSW; break; + case TCSAFLUSH: req = TCSETSF; break; + default: return EINVAL; + } + + if (int e = sys_ioctl(fd, req, (void *)attr, NULL); e) + return e; + + return 0; +} + +int sys_mkdir(const char *path, mode_t) { + auto result = syscall(SYS_MKDIR, path, strlen(path)); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_link(const char *srcpath, const char *destpath) { + auto result = + syscall(SYS_LINK, srcpath, strlen(srcpath), destpath, strlen(destpath)); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_rmdir(const char *path) { + return sys_unlinkat(AT_FDCWD, path, AT_REMOVEDIR); +} + +int sys_unlinkat(int fd, const char *path, int flags) { + auto ret = syscall(SYS_UNLINK, fd, path, strlen(path), flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +struct aero_dir_entry { + size_t inode; + size_t offset; + size_t reclen; + size_t filetyp; + char name[]; +} __attribute__((__packed__)); + +int sys_read_entries(int handle, void *buffer, size_t max_size, + size_t *bytes_read) { + auto result = syscall(SYS_GETDENTS, handle, buffer, max_size); + + // Check if we got an error. + if (result < 0) { + *bytes_read = 0; + return -result; + } + + // Nothing to read. + if (result == 0) { + *bytes_read = 0; + return 0; + } + + auto entry = (struct aero_dir_entry *)buffer; + + struct dirent dirent = { + .d_ino = static_cast<ino_t>(entry->inode), + .d_off = static_cast<off_t>(entry->offset), + .d_reclen = static_cast<unsigned short>(entry->reclen), + .d_type = static_cast<unsigned char>(entry->filetyp), + }; + + // The reclen is the size of the dirent struct, plus the size of the name. + auto name_size = entry->reclen - sizeof(struct aero_dir_entry); + __ensure(name_size < 255); + + memcpy(&dirent.d_name, entry->name, name_size); + *bytes_read = entry->reclen; + + memcpy(buffer, &dirent, sizeof(struct dirent)); + return 0; +} + +int sys_open_dir(const char *path, int *handle) { + return sys_open(path, O_DIRECTORY, 0, handle); +} + +int sys_rename(const char *path, const char *new_path) { + auto result = + syscall(SYS_RENAME, path, strlen(path), new_path, strlen(new_path)); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_readlink(const char *path, void *buffer, size_t max_size, + ssize_t *length) { + auto result = syscall(SYS_READ_LINK, path, strlen(path), buffer, max_size); + + if (result < 0) { + return -result; + } + + *length = result; + return 0; +} + +int sys_dup(int fd, int flags, int *newfd) { + auto result = syscall(SYS_DUP, fd, flags); + + if (result < 0) { + return -result; + } + + *newfd = result; + return 0; +} + +int sys_dup2(int fd, int flags, int newfd) { + auto result = syscall(SYS_DUP2, fd, newfd, flags); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_fcntl(int fd, int request, va_list args, int *result_value) { + auto result = syscall(SYS_FCNTL, fd, request, va_arg(args, uint64_t)); + + if (result < 0) { + return -result; + } + + *result_value = result; + return 0; +} + +// int sys_chmod(const char *pathname, mode_t mode) UNIMPLEMENTED("sys_chmod") + +int sys_pipe(int *fds, int flags) { + auto result = syscall(SYS_PIPE, fds, flags); + + if (result < 0) { + return -result; + } + + return 0; +} + +// epoll API syscalls: +int sys_epoll_create(int flags, int *fd) { + auto result = syscall(SYS_EPOLL_CREATE, flags); + + if (result < 0) { + return -result; + } + + *fd = result; + return 0; +} + +int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { + auto result = syscall(SYS_EPOLL_CTL, epfd, mode, fd, ev); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, int timeout, + const sigset_t *sigmask, int *raised) { + auto result = syscall(SYS_EPOLL_PWAIT, epfd, ev, n, timeout, sigmask); + + if (result < 0) { + return -result; + } + + *raised = result; + return 0; +} + +int sys_eventfd_create(unsigned int initval, int flags, int *fd) { + auto result = syscall(SYS_EVENT_FD, initval, flags); + + if (result < 0) { + return -result; + } + + *fd = result; + return 0; +} + +int sys_ppoll(struct pollfd *fds, int nfds, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) { + auto result = syscall(SYS_POLL, fds, nfds, timeout, sigmask); + + if (result < 0) { + return -result; + } + + *num_events = result; + return 0; +} + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { + struct timespec ts; + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + + return sys_ppoll(fds, count, &ts, NULL, num_events); +} + +#ifndef MLIBC_BUILDING_RTDL +#include <stdio.h> +int sys_ptsname(int fd, char *buffer, size_t length) { + int index; + if (int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) + return e; + if ((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { + return ERANGE; + } + return 0; +} + +int sys_pselect(int num_fds, fd_set *read_set, fd_set *write_set, + fd_set *except_set, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) { + int fd = epoll_create1(0); + if (fd == -1) + return -1; + + for (int k = 0; k < FD_SETSIZE; k++) { + struct epoll_event ev; + memset(&ev, 0, sizeof(struct epoll_event)); + + if (read_set && FD_ISSET(k, read_set)) + ev.events |= EPOLLIN; + if (write_set && FD_ISSET(k, write_set)) + ev.events |= EPOLLOUT; + if (except_set && FD_ISSET(k, except_set)) + ev.events |= EPOLLPRI; + + if (!ev.events) + continue; + + ev.data.u32 = k; + if (epoll_ctl(fd, EPOLL_CTL_ADD, k, &ev)) + return -1; + } + + struct epoll_event evnts[16]; + int n = epoll_pwait( + fd, evnts, 16, + timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 100) : -1, + sigmask); + + if (n == -1) + return -1; + + fd_set res_read_set; + fd_set res_write_set; + fd_set res_except_set; + FD_ZERO(&res_read_set); + FD_ZERO(&res_write_set); + FD_ZERO(&res_except_set); + + int m = 0; + + for (int i = 0; i < n; i++) { + int k = evnts[i].data.u32; + + if (read_set && FD_ISSET(k, read_set) && + evnts[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) { + FD_SET(k, &res_read_set); + m++; + } + + if (write_set && FD_ISSET(k, write_set) && + evnts[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) { + FD_SET(k, &res_write_set); + m++; + } + + if (except_set && FD_ISSET(k, except_set) && + evnts[i].events & EPOLLPRI) { + FD_SET(k, &res_except_set); + m++; + } + } + + if (close(fd)) + __ensure("mlibc::pselect: close() failed on epoll file"); + + if (read_set) + memcpy(read_set, &res_read_set, sizeof(fd_set)); + + if (write_set) + memcpy(write_set, &res_write_set, sizeof(fd_set)); + + if (except_set) + memcpy(except_set, &res_except_set, sizeof(fd_set)); + + *num_events = m; + return 0; +} +#endif // #ifndef MLIBC_BUILDING_RTDL +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/aero/generic/signals.S b/lib/mlibc/sysdeps/aero/generic/signals.S new file mode 100644 index 0000000..62dee9b --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/signals.S @@ -0,0 +1,9 @@ +.section .text +.global __mlibc_signal_restore + +__mlibc_signal_restore: + mov $39, %rax + syscall + ud2 +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/aero/generic/signals.cpp b/lib/mlibc/sysdeps/aero/generic/signals.cpp new file mode 100644 index 0000000..a6f69ff --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/signals.cpp @@ -0,0 +1,53 @@ +#include <mlibc/ansi-sysdeps.hpp> +#include <mlibc/debug.hpp> + +#include <aero/syscall.h> +#include <sys/types.h> + +#define LOG_SIGACTION_INSTALL 0 + +extern "C" void __mlibc_signal_restore(); // defined in `signals.S` + +namespace mlibc { +int sys_sigaction(int how, const struct sigaction *__restrict action, + struct sigaction *__restrict old_action) { +#if LOG_SIGACTION_INSTALL + mlibc::infoLogger() << "sys_sigaction: signal " << how << frg::endlog; + mlibc::infoLogger() << "sys_sigaction: size: " << sizeof(*action) + << frg::endlog; + + if (action != NULL) { + mlibc::infoLogger() << "sys_sigaction: handler " + << (int64_t)action->sa_handler << frg::endlog; + mlibc::infoLogger() << "sys_sigaction: action " + << (int64_t)action->sa_sigaction << frg::endlog; + mlibc::infoLogger() << "sys_sigaction: flags " + << (int64_t)action->sa_flags << frg::endlog; + } + + mlibc::infoLogger() << frg::endlog; +#endif + + auto sigreturn = (sc_word_t)__mlibc_signal_restore; + + auto res = syscall(SYS_SIGACTION, how, (sc_word_t)action, sigreturn, + (sc_word_t)old_action); + + if (res < 0) { + return -res; + } + + return 0; +} + +int sys_sigprocmask(int how, const sigset_t *__restrict set, + sigset_t *__restrict retrieve) { + auto result = syscall(SYS_SIGPROCMASK, how, set, retrieve); + + if (result < 0) { + return -result; + } + + return 0; +} +} // namespace mlibc
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/generic/sockets.cpp b/lib/mlibc/sysdeps/aero/generic/sockets.cpp new file mode 100644 index 0000000..0cce3c0 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/sockets.cpp @@ -0,0 +1,250 @@ +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> +#include <mlibc/debug.hpp> +#include <abi-bits/in.h> +#include <abi-bits/errno.h> + +#include <aero/syscall.h> + +#include <unistd.h> +#include <stdint.h> +#include <net/if.h> +#include <sys/ioctl.h> + +namespace { + +int fcntl_helper(int fd, int request, int *result, ...) { + va_list args; + va_start(args, result); + if(!mlibc::sys_fcntl) { + return ENOSYS; + } + int ret = mlibc::sys_fcntl(fd, request, args, result); + va_end(args); + return ret; +} + +} + +namespace mlibc { +int sys_socket(int family, int type, int protocol, int *fd) { + auto result = syscall(SYS_SOCKET, family, type, protocol); + + if (result < 0) { + return -result; + } + + *fd = result; + return 0; +} + +int sys_bind(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + auto result = syscall(SYS_BIND, fd, addr_ptr, (sc_word_t)addr_length); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_connect(int fd, const struct sockaddr *addr_ptr, + socklen_t addr_length) { + auto result = syscall(SYS_CONNECT, fd, addr_ptr, (sc_word_t)addr_length); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_listen(int fd, int backlog) { + auto result = syscall(SYS_LISTEN, fd, backlog); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_accept(int sockfd, int *newfd, struct sockaddr *addr_ptr, + socklen_t *addr_length, int flags) { + auto result = syscall(SYS_ACCEPT, sockfd, addr_ptr, addr_length); + + if (result < 0) { + return -result; + } + + *newfd = result; + + if(flags & SOCK_NONBLOCK) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFL, &fcntl_ret); + fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK); + } + + if(flags & SOCK_CLOEXEC) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFD, &fcntl_ret); + fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC); + } + + return 0; +} + +int sys_msg_send(int fd, const struct msghdr *hdr, int flags, ssize_t *length) { + auto result = syscall(SYS_SOCK_SEND, fd, hdr, flags); + if (result < 0) + return -result; + + *length = result; + return 0; +} + +int sys_msg_recv(int sockfd, struct msghdr *msg_hdr, int flags, + ssize_t *length) { + auto result = syscall(SYS_SOCK_RECV, sockfd, msg_hdr, flags); + + if (result < 0) { + return -result; + } + + *length = result; + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { + auto result = syscall(SYS_SOCKET_PAIR, domain, type_and_flags, proto, fds); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, + socklen_t *__restrict size) { + (void)fd; + (void)size; + if (layer == SOL_SOCKET && number == SO_PEERCRED) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET " + "and SO_PEERCRED is unimplemented\e[39m" + << frg::endlog; + *(int *)buffer = 0; + return 0; + } else if (layer == SOL_SOCKET && number == SO_SNDBUF) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET " + "and SO_SNDBUF is unimplemented\e[39m" + << frg::endlog; + *(int *)buffer = 4096; + return 0; + } else if (layer == SOL_SOCKET && number == SO_TYPE) { + mlibc::infoLogger() + << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_TYPE is " + "unimplemented, hardcoding SOCK_STREAM\e[39m" + << frg::endlog; + *(int *)buffer = SOCK_STREAM; + return 0; + } else if (layer == SOL_SOCKET && number == SO_ERROR) { + mlibc::infoLogger() + << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_ERROR is " + "unimplemented, hardcoding 0\e[39m" + << frg::endlog; + *(int *)buffer = 0; + return 0; + } else if (layer == SOL_SOCKET && number == SO_KEEPALIVE) { + mlibc::infoLogger() + << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and " + "SO_KEEPALIVE is unimplemented, hardcoding 0\e[39m" + << frg::endlog; + *(int *)buffer = 0; + return 0; + } else { + mlibc::panicLogger() + << "\e[31mmlibc: Unexpected getsockopt() call, layer: " << layer + << " number: " << number << "\e[39m" << frg::endlog; + __builtin_unreachable(); + } + + return 0; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, + socklen_t size) { + (void)fd; + (void)buffer; + (void)size; + + if (layer == SOL_SOCKET && number == SO_PASSCRED) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_PASSCRED) is not " + "implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_ATTACH_FILTER) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_ATTACH_FILTER) is " + "not implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_RCVBUFFORCE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_RCVBUFFORCE) is not " + "implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_SNDBUF) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_SNDBUF is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_KEEPALIVE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_KEEPALIVE is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_REUSEADDR) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_REUSEADDR is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == AF_NETLINK && number == SO_ACCEPTCONN) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with AF_NETLINK " + "and SO_ACCEPTCONN is unimplemented\e[39m" + << frg::endlog; + return 0; + } else { + mlibc::infoLogger() + << "\e[31mmlibc: Unexpected setsockopt() call, layer: " << layer + << " number: " << number << "\e[39m" << frg::endlog; + return 0; + } +} + +int sys_shutdown(int sockfd, int how) { + auto ret = syscall(SYS_SOCK_SHUTDOWN, sockfd, how); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_if_nametoindex(const char *name, unsigned int *ret) { + int fd = 0; + int r = sys_socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, &fd); + + if (r) + return r; + + struct ifreq ifr; + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + + r = sys_ioctl(fd, SIOCGIFINDEX, &ifr, NULL); + close(fd); + + if (r) + return r; + + *ret = ifr.ifr_ifindex; + return 0; +} +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/aero/generic/thread.cpp b/lib/mlibc/sysdeps/aero/generic/thread.cpp new file mode 100644 index 0000000..bc9a449 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/thread.cpp @@ -0,0 +1,55 @@ +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> + +#include <bits/ensure.h> +#include <mlibc/tcb.hpp> + +#include <sys/mman.h> + +#include <stddef.h> +#include <stdint.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID: + while (!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if (mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x1000000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, + size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void *>(sp); + return 0; +} +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/aero/generic/thread_entry.S b/lib/mlibc/sysdeps/aero/generic/thread_entry.S new file mode 100644 index 0000000..498fda3 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/thread_entry.S @@ -0,0 +1,10 @@ +.section .text +.global __mlibc_start_thread + +__mlibc_start_thread: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_enter_thread +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/aero/generic/time.cpp b/lib/mlibc/sysdeps/aero/generic/time.cpp new file mode 100644 index 0000000..c995148 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/generic/time.cpp @@ -0,0 +1,25 @@ +#include <mlibc/all-sysdeps.hpp> +#include <aero/syscall.h> + +namespace mlibc { +int sys_setitimer(int which, const struct itimerval *new_value, + struct itimerval *old_value) { + auto result = syscall(SYS_SETITIMER, which, new_value, old_value); + + if (result < 0) { + return -result; + } + + return 0; +} + +int sys_getitimer(int which, struct itimerval *curr_value) { + auto result = syscall(SYS_GETITIMER, which, curr_value); + + if (result < 0) { + return -result; + } + + return 0; +} +} // namespace mlibc
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/access.h b/lib/mlibc/sysdeps/aero/include/abi-bits/access.h new file mode 120000 index 0000000..171f75f --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/mlibc/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/aero/include/abi-bits/auxv.h new file mode 120000 index 0000000..86157e8 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/aero/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..e9d9f1b --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..c6dfb6e --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..71f37bb --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/dev_t.h new file mode 120000 index 0000000..0c1143b --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/aero/include/abi-bits/epoll.h new file mode 120000 index 0000000..9efc3a0 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/errno.h b/lib/mlibc/sysdeps/aero/include/abi-bits/errno.h new file mode 120000 index 0000000..589859f --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/mlibc/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/aero/include/abi-bits/fcntl.h new file mode 120000 index 0000000..ea5323a --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/mlibc/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/gid_t.h new file mode 120000 index 0000000..6a77218 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/in.h b/lib/mlibc/sysdeps/aero/include/abi-bits/in.h new file mode 120000 index 0000000..b58c683 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/mlibc/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/ino_t.h new file mode 120000 index 0000000..10d644e --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/aero/include/abi-bits/inotify.h new file mode 120000 index 0000000..3f19ef6 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/mlibc/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/aero/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/limits.h b/lib/mlibc/sysdeps/aero/include/abi-bits/limits.h new file mode 120000 index 0000000..1aa5894 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/mlibc/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/mode_t.h new file mode 120000 index 0000000..29d7733 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/aero/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/msg.h b/lib/mlibc/sysdeps/aero/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..7618c27 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/packet.h b/lib/mlibc/sysdeps/aero/include/abi-bits/packet.h new file mode 120000 index 0000000..47067e2 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/mlibc/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/pid_t.h new file mode 120000 index 0000000..3fd26a7 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/poll.h b/lib/mlibc/sysdeps/aero/include/abi-bits/poll.h new file mode 120000 index 0000000..ab989c7 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/aero/include/abi-bits/ptrace.h new file mode 120000 index 0000000..f391fb7 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/aero/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/resource.h b/lib/mlibc/sysdeps/aero/include/abi-bits/resource.h new file mode 120000 index 0000000..3e59c75 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/mlibc/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/aero/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..3bd41ef --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/mlibc/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/shm.h b/lib/mlibc/sysdeps/aero/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/signal.h b/lib/mlibc/sysdeps/aero/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/socket.h b/lib/mlibc/sysdeps/aero/include/abi-bits/socket.h new file mode 120000 index 0000000..0e1d6be --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/mlibc/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/stat.h b/lib/mlibc/sysdeps/aero/include/abi-bits/stat.h new file mode 120000 index 0000000..82642c3 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/mlibc/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/aero/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/aero/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/termios.h b/lib/mlibc/sysdeps/aero/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/time.h b/lib/mlibc/sysdeps/aero/include/abi-bits/time.h new file mode 120000 index 0000000..97f3d52 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/mlibc/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/aero/include/abi-bits/uid_t.h new file mode 120000 index 0000000..1113eba --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/aero/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/aero/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..f1a985e --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/mlibc/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/wait.h b/lib/mlibc/sysdeps/aero/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/aero/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/aero/include/aero/syscall.h b/lib/mlibc/sysdeps/aero/include/aero/syscall.h new file mode 100644 index 0000000..3f36e4d --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/aero/syscall.h @@ -0,0 +1,231 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include <bits/ensure.h> +#include <stdint.h> + +#define SYS_READ 0 +#define SYS_WRITE 1 +#define SYS_OPEN 2 +#define SYS_CLOSE 3 +#define SYS_SHUTDOWN 4 +#define SYS_EXIT 5 +#define SYS_FORK 6 +#define SYS_REBOOT 7 +#define SYS_MMAP 8 +#define SYS_MUNMAP 9 +#define SYS_ARCH_PRCTL 10 +#define SYS_GETDENTS 11 +#define SYS_GETCWD 12 +#define SYS_CHDIR 13 +#define SYS_MKDIR 14 +#define SYS_MKDIR_AT 15 +#define SYS_RMDIR 16 +#define SYS_EXEC 17 +#define SYS_LOG 18 +#define SYS_UNAME 19 +#define SYS_WAITPID 20 +#define SYS_IOCTL 21 +#define SYS_GETPID 22 +#define SYS_SOCKET 23 +#define SYS_CONNECT 24 +#define SYS_BIND 25 +#define SYS_LISTEN 26 +#define SYS_ACCEPT 27 +#define SYS_SEEK 28 +#define SYS_GETTID 29 +#define SYS_GETTIME 30 +#define SYS_SLEEP 31 +#define SYS_ACCESS 32 +#define SYS_PIPE 33 +#define SYS_UNLINK 34 +#define SYS_GETHOSTNAME 35 +#define SYS_SETHOSTNAME 36 +#define SYS_INFO 37 +#define SYS_CLONE 38 +#define SYS_SIGRETURN 39 +#define SYS_SIGACTION 40 +#define SYS_SIGPROCMASK 41 +#define SYS_DUP 42 +#define SYS_FCNTL 43 +#define SYS_DUP2 44 +#define SYS_IPC_SEND 45 +#define SYS_IPC_RECV 46 +#define SYS_DISCOVER_ROOT 47 +#define SYS_BECOME_ROOT 48 +#define SYS_STAT 49 +#define SYS_FSTAT 50 +#define SYS_READ_LINK 51 +#define SYS_EPOLL_CREATE 52 +#define SYS_EPOLL_PWAIT 53 +#define SYS_EPOLL_CTL 54 +#define SYS_EVENT_FD 55 +#define SYS_KILL 56 +#define SYS_FUTEX_WAIT 57 +#define SYS_FUTEX_WAKE 58 +#define SYS_LINK 59 +#define SYS_BACKTRACE 60 +#define SYS_POLL 61 +#define SYS_EXIT_THREAD 62 +#define SYS_SOCK_RECV 63 +#define SYS_SETITIMER 64 +#define SYS_GETITIMER 65 +#define SYS_GETPPID 66 +#define SYS_SOCKET_PAIR 67 +#define SYS_RENAME 68 +#define SYS_MPROTECT 69 +#define SYS_SOCK_SEND 70 +#define SYS_TRACE 71 +#define SYS_SETPGID 72 +#define SYS_SETSID 73 +#define SYS_GETPGID 74 +#define SYS_SOCK_SHUTDOWN 75 + +// Invalid syscall used to trigger a log error in the kernel (as a hint) +// so, that we can implement the syscall in the kernel. +#define UNIMPLEMENTED(FUNCTION_NAME) \ + { \ + sys_libc_log("Unimplemented syscall: " FUNCTION_NAME); \ + sys_exit(1); \ + __builtin_unreachable(); \ + } + +extern "C" { +using sc_word_t = long; + +static sc_word_t syscall0(int sc) { + sc_word_t ret; + asm volatile("syscall" : "=a"(ret) : "a"(sc) : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall1(int sc, sc_word_t arg1) { + sc_word_t ret; + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1) + : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall2(int sc, sc_word_t arg1, sc_word_t arg2) { + sc_word_t ret; + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2) + : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall3(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3) { + sc_word_t ret; + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3) + : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall4(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4) { + sc_word_t ret; + + register sc_word_t arg4_reg asm("r10") = arg4; + + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), "r"(arg4_reg) + : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall5(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4, sc_word_t arg5) { + sc_word_t ret; + + register sc_word_t arg4_reg asm("r10") = arg4; + register sc_word_t arg5_reg asm("r8") = arg5; + + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), "r"(arg4_reg), + "r"(arg5_reg) + : "rcx", "r11", "memory"); + return ret; +} + +static sc_word_t syscall6(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4, sc_word_t arg5, + sc_word_t arg6) { + sc_word_t ret; + + register sc_word_t arg4_reg asm("r10") = arg4; + register sc_word_t arg5_reg asm("r8") = arg5; + register sc_word_t arg6_reg asm("r9") = arg6; + + asm volatile("syscall" + : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), "r"(arg4_reg), + "r"(arg5_reg), "r"(arg6_reg) + : "rcx", "r11", "memory"); + return ret; +} +} // extern "C" + +// Cast to the argument type of the extern "C" functions. +__attribute__((__always_inline__)) inline sc_word_t sc_cast(long x) { return x; } +__attribute__((__always_inline__)) inline sc_word_t sc_cast(const void *x) { + return reinterpret_cast<sc_word_t>(x); +} + +// C++ wrappers for the extern "C" functions. +__attribute__((__always_inline__)) static inline long _syscall(int call) { + return syscall0(call); +} + +__attribute__((__always_inline__)) static inline long _syscall(int call, + sc_word_t arg0) { + return syscall1(call, arg0); +} + +__attribute__((__always_inline__)) static inline long +_syscall(int call, sc_word_t arg0, sc_word_t arg1) { + return syscall2(call, arg0, arg1); +} + +__attribute__((__always_inline__)) static inline long +_syscall(int call, sc_word_t arg0, sc_word_t arg1, sc_word_t arg2) { + return syscall3(call, arg0, arg1, arg2); +} + +__attribute__((__always_inline__)) static inline long +_syscall(int call, sc_word_t arg0, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3) { + return syscall4(call, arg0, arg1, arg2, arg3); +} + +__attribute__((__always_inline__)) static inline long +_syscall(int call, sc_word_t arg0, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4) { + return syscall5(call, arg0, arg1, arg2, arg3, arg4); +} + +__attribute__((__always_inline__)) static inline long +_syscall(int call, sc_word_t arg0, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4, sc_word_t arg5) { + return syscall6(call, arg0, arg1, arg2, arg3, arg4, arg5); +} + +template <typename... T> +__attribute__((__always_inline__)) static inline long syscall(sc_word_t call, + T... args) { + return _syscall(call, sc_cast(args)...); +} + +inline int sc_error(long ret) { + if (ret < 0) + return -ret; + return 0; +} +#endif // SYSCALL_H diff --git a/lib/mlibc/sysdeps/aero/include/mlibc/thread-entry.hpp b/lib/mlibc/sysdeps/aero/include/mlibc/thread-entry.hpp new file mode 100644 index 0000000..a241479 --- /dev/null +++ b/lib/mlibc/sysdeps/aero/include/mlibc/thread-entry.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_start_thread(void); +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb); + +namespace mlibc { +int prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, + size_t *guard_size); +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/aero/meson.build b/lib/mlibc/sysdeps/aero/meson.build new file mode 100644 index 0000000..20cf6cf --- /dev/null +++ b/lib/mlibc/sysdeps/aero/meson.build @@ -0,0 +1,85 @@ +rtdl_dso_sources += files( + 'generic/aero.cpp', + 'generic/filesystem.cpp', +) + +libc_sources += files( + 'generic/aero.cpp', + 'generic/entry.cpp', + 'generic/thread_entry.S', + 'generic/thread.cpp', + 'generic/filesystem.cpp', + 'generic/sockets.cpp', + 'generic/signals.cpp', + 'generic/time.cpp', +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + install_headers( + 'include/aero/syscall.h', + subdir: 'aero' + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) +endif + +if host_machine.cpu_family() == 'x86_64' + libc_sources += files('generic/signals.S') +else + error('Unknown architecture') +endif diff --git a/lib/mlibc/sysdeps/dripos/crt-x86_64/crt1.S b/lib/mlibc/sysdeps/dripos/crt-x86_64/crt1.S new file mode 100644 index 0000000..18d109e --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/crt-x86_64/crt1.S @@ -0,0 +1,9 @@ + +.section .text +.global _start +_start: + mov $main, %rdi + call __mlibc_entry + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/dripos/generic/entry.cpp b/lib/mlibc/sysdeps/dripos/generic/entry.cpp new file mode 100644 index 0000000..2b8b914 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/generic/entry.cpp @@ -0,0 +1,35 @@ + +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} + diff --git a/lib/mlibc/sysdeps/dripos/generic/generic.cpp b/lib/mlibc/sysdeps/dripos/generic/generic.cpp new file mode 100644 index 0000000..89203c3 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/generic/generic.cpp @@ -0,0 +1,298 @@ +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> +#include <errno.h> +#include <dirent.h> +#include <fcntl.h> +#include <limits.h> + +namespace mlibc { + +void sys_libc_log(const char *message) { + unsigned long res; + asm volatile ("syscall" : "=a"(res) + : "a"(50), "D"(message) + : "rcx", "r11", "rdx"); +} + +void sys_libc_panic() { + mlibc::infoLogger() << "\e[31mmlibc: panic!" << frg::endlog; + asm volatile ("syscall" : + : "a"(12), "D"(1) + : "rcx", "r11", "rdx"); +} + +int sys_tcb_set(void *pointer) { + int res; + asm volatile ("syscall" : "=a"(res) + : "a"(300), "D"(pointer) + : "rcx", "r11", "rdx"); + return res; +} + +int sys_anon_allocate(size_t size, void **pointer) { + void *ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(9), "D"(0), "S"(size) + : "rcx", "r11"); + + if (!ret) + return sys_errno; + + *pointer = ret; + return 0; +} + +int sys_anon_free(void *pointer, size_t size) { + int unused_return; + int sys_errno; + + asm volatile ("syscall" + : "=a"(unused_return), "=d"(sys_errno) + : "a"(11), "D"(pointer), "S"(size) + : "rcx", "r11"); + + if (unused_return) + return sys_errno; + + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL +void sys_exit(int status) { + asm volatile ("syscall" : + : "a"(12), "D"(status) + : "rcx", "r11", "rdx"); +} +#endif + +#ifndef MLIBC_BUILDING_RTDL +int sys_clock_get(int clock, time_t *secs, long *nanos) { + return 0; +} +#endif + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + int ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(2), "D"(path), "S"(flags), "d"(0) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + *fd = ret; + return 0; +} + +int sys_close(int fd) { + int ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(3), "D"(fd) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + return 0; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + ssize_t ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(0), "D"(fd), "S"(buf), "d"(count) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + *bytes_read = ret; + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL +int sys_write(int fd, const void *buf, size_t count, ssize_t *bytes_written) { + ssize_t ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(1), "D"(fd), "S"(buf), "d"(count) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + *bytes_written = ret; + return 0; +} +#endif + + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + off_t ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(8), "D"(fd), "S"(offset), "d"(whence) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + *new_offset = ret; + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, + int fd, off_t offset, void **window) { + __ensure(flags & MAP_ANONYMOUS); + void *ret; + int sys_errno; + + // mlibc::infoLogger() << "calling sys_vm_map with size: " << size << frg::endlog; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(9), "D"(hint), "S"(size) + : "rcx", "r11"); + + if (!ret) + return sys_errno; + + *window = ret; + + return 0; +} + +int sys_vm_unmap(void *pointer, size_t size) { + return sys_anon_free(pointer, size); +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + uint64_t err; + asm volatile ("syscall" + : "=d"(err) + : "a"(66), "D"(pointer), "S"(expected) + : "rcx", "r11"); + + if (err) { + return -1; + } + + return 0; +} + +int sys_futex_wake(int *pointer) { + uint64_t err; + asm volatile ("syscall" + : "=d"(err) + : "a"(65), "D"(pointer) + : "rcx", "r11"); + + if (err) { + return -1; + } + + return 0; +} + +// All remaining functions are disabled in ldso. +#ifndef MLIBC_BUILDING_RTDL + +int sys_clone(void *tcb, pid_t *tid_out, void *stack) { + int tid; + + asm volatile ("syscall" + : "=a"(tid) + : "a"(67), "D"(__mlibc_start_thread), "S"(stack), "d"(tcb) + : "rcx", "r11"); + + if (tid_out) + *tid_out = tid; + + return 0; +} + +void sys_thread_exit() { + asm volatile ("syscall" + : + : "a"(68) + : "rcx", "r11"); + __builtin_trap(); +} + +int sys_sleep(time_t *secs, long *nanos) { + long ms = (*nanos / 1000000) + (*secs * 1000); + asm volatile ("syscall" + : + : "a"(6), "D"(ms) + : "rcx", "r11"); + *secs = 0; + *nanos = 0; + return 0; +} + +int sys_fork(pid_t *child) { + pid_t ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(57) + : "rcx", "r11"); + + if (ret == -1) + return sys_errno; + + *child = ret; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + int ret; + int sys_errno; + + asm volatile ("syscall" + : "=a"(ret), "=d"(sys_errno) + : "a"(59), "D"(path), "S"(argv), "d"(envp) + : "rcx", "r11"); + + if (sys_errno != 0) + return sys_errno; + + return 0; +} + +pid_t sys_getpid() { + pid_t pid; + asm volatile ("syscall" : "=a"(pid) + : "a"(5) + : "rcx", "r11", "rdx"); + return pid; +} +pid_t sys_getppid() { + pid_t ppid; + asm volatile ("syscall" : "=a"(ppid) + : "a"(14) + : "rcx", "r11", "rdx"); + return ppid; +} + +#endif // MLIBC_BUILDING_RTDL + +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/dripos/generic/thread.cpp b/lib/mlibc/sysdeps/dripos/generic/thread.cpp new file mode 100644 index 0000000..42cd758 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/generic/thread.cpp @@ -0,0 +1,53 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/tcb.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <stdint.h> +#include <stddef.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if(mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/dripos/generic/thread_entry.S b/lib/mlibc/sysdeps/dripos/generic/thread_entry.S new file mode 100644 index 0000000..51e703b --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/generic/thread_entry.S @@ -0,0 +1,11 @@ + +.section .text +.global __mlibc_start_thread +__mlibc_start_thread: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_enter_thread + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/access.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/access.h new file mode 120000 index 0000000..171f75f --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/mlibc/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/auxv.h new file mode 120000 index 0000000..866c8bb --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/dripos/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..e9d9f1b --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..c6dfb6e --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..71f37bb --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/dev_t.h new file mode 120000 index 0000000..0c1143b --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/epoll.h new file mode 120000 index 0000000..9efc3a0 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/errno.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/errno.h new file mode 120000 index 0000000..2a2ab26 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/dripos/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/fcntl.h new file mode 120000 index 0000000..ea5323a --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/mlibc/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/gid_t.h new file mode 120000 index 0000000..6a77218 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/in.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/in.h new file mode 120000 index 0000000..b58c683 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/mlibc/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/ino_t.h new file mode 120000 index 0000000..10d644e --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/inotify.h new file mode 120000 index 0000000..3f19ef6 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/mlibc/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/limits.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/limits.h new file mode 120000 index 0000000..1aa5894 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/mlibc/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/mode_t.h new file mode 120000 index 0000000..29d7733 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/msg.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..7618c27 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/packet.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/packet.h new file mode 120000 index 0000000..47067e2 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/mlibc/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/pid_t.h new file mode 120000 index 0000000..3fd26a7 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/poll.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/poll.h new file mode 120000 index 0000000..ab989c7 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/ptrace.h new file mode 120000 index 0000000..f391fb7 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/resource.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/resource.h new file mode 120000 index 0000000..3e59c75 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/mlibc/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..3bd41ef --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/mlibc/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/shm.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/signal.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/signal.h new file mode 120000 index 0000000..b20e511 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/mlibc/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/socket.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/socket.h new file mode 120000 index 0000000..0e1d6be --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/mlibc/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/stat.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/stat.h new file mode 120000 index 0000000..82642c3 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/mlibc/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/termios.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/termios.h new file mode 120000 index 0000000..cfcfe76 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/mlibc/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/time.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/uid_t.h new file mode 120000 index 0000000..1113eba --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/utsname.h new file mode 120000 index 0000000..17b993f --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/mlibc/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..f1a985e --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/mlibc/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/wait.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/wait.h new file mode 120000 index 0000000..6d911c7 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/mlibc/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/dripos/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/dripos/include/mlibc/thread-entry.hpp b/lib/mlibc/sysdeps/dripos/include/mlibc/thread-entry.hpp new file mode 100644 index 0000000..2dd88a6 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/include/mlibc/thread-entry.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_start_thread(void); +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb); + +namespace mlibc { + void *prepare_stack(void *entry, void *user_arg, void *tcb); +} diff --git a/lib/mlibc/sysdeps/dripos/meson.build b/lib/mlibc/sysdeps/dripos/meson.build new file mode 100644 index 0000000..afecf25 --- /dev/null +++ b/lib/mlibc/sysdeps/dripos/meson.build @@ -0,0 +1,71 @@ + +rtdl_sources += files( + 'generic/generic.cpp' +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/generic.cpp', + 'generic/thread.cpp', + 'generic/thread_entry.S' +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) +endif + +if not headers_only + crt = custom_target('crt1', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crt1.S', + output: 'crt1.o', + install: true, + install_dir: get_option('libdir') + ) +endif + diff --git a/lib/mlibc/sysdeps/hyra/crt-x86_64/crt0.S b/lib/mlibc/sysdeps/hyra/crt-x86_64/crt0.S new file mode 100644 index 0000000..57f0dd1 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/crt-x86_64/crt0.S @@ -0,0 +1,9 @@ +.section .text + +.global _start +_start: + mov $main, %rdi + call __mlibc_entry + +.size _start, . - _start +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/hyra/generic/entry.cpp b/lib/mlibc/sysdeps/hyra/generic/entry.cpp new file mode 100644 index 0000000..d5129af --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/generic/entry.cpp @@ -0,0 +1,35 @@ +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> +#include <stdint.h> +#include <stdlib.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], + char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux + // sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/hyra/generic/hyra.cpp b/lib/mlibc/sysdeps/hyra/generic/hyra.cpp new file mode 100644 index 0000000..fb555b9 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/generic/hyra.cpp @@ -0,0 +1,121 @@ +#include <stddef.h> +#include <sys/types.h> +#include <hyra/syscall.h> + +namespace mlibc { +void sys_libc_log(const char *msg) { + __syscall(0, (uintptr_t)msg); +} + +int sys_anon_allocate(size_t size, void **pointer) { + (void)size; + (void)pointer; + while (1); +} + +void sys_libc_panic() { + sys_libc_log("\n** MLIBC PANIC **\n"); + while (1); +} + +int sys_tcb_set(void *pointer) { + (void)pointer; + + while (1); +} + +void sys_exit(int status) { +} + +void sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + (void)fd; + (void)offset; + (void)whence; + (void)new_offset; + + while (1); +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, + off_t offset, void **window) { + (void)hint; + (void)size; + (void)prot; + (void)flags; + (void)fd; + (void)offset; + (void)window; + + while (1); +} + +int sys_vm_unmap(void *address, size_t size) { + (void)address; + (void)size; + + while (1); +} + +int sys_anon_free(void *pointer, size_t size) { + (void)pointer; + (void)size; + + while (1); +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + (void)clock; + (void)secs; + (void)nanos; + + while (1); +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + (void)pointer; + (void)expected; + (void)time; + + return 0; +} + +int sys_futex_wake(int *pointer) { + (void)pointer; + + return 0; +} + +int sys_open(const char *filename, int flags, mode_t mode, int *fd) { + (void)filename; + (void)flags; + (void)mode; + (void)fd; + + while (1); +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + (void)fd; + (void)buf; + (void)count; + (void)bytes_read; + + while (1); +} + +int sys_write(int fd, const void *buffer, size_t count, ssize_t *written) { + (void)fd; + (void)buffer; + (void)count; + (void)written; + + while (1); +} + +int sys_close(int fd) { + (void)fd; + + while (1); +} + +} diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/access.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/access.h new file mode 120000 index 0000000..cb83931 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/linux/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/auxv.h new file mode 120000 index 0000000..6959fac --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/hyra/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..0b0ec27 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..7dc8d7c --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..6a42da5 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/dev_t.h new file mode 120000 index 0000000..bca881e --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/linux/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/epoll.h new file mode 120000 index 0000000..eb4b76d --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/linux/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/errno.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/errno.h new file mode 120000 index 0000000..6e507de --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/linux/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/fcntl.h new file mode 120000 index 0000000..463e2c9 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/linux/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/gid_t.h new file mode 120000 index 0000000..abce6d6 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/in.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/in.h new file mode 120000 index 0000000..418d1d5 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/linux/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/ino_t.h new file mode 120000 index 0000000..4c20aca --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/linux/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/inotify.h new file mode 120000 index 0000000..b5cb282 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/linux/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/limits.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/limits.h new file mode 120000 index 0000000..6c88db2 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/linux/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/mode_t.h new file mode 120000 index 0000000..5d78fdf --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/linux/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/msg.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..bb3b625 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/linux/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/packet.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/packet.h new file mode 120000 index 0000000..998ef1a --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/linux/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/pid_t.h new file mode 120000 index 0000000..baa90f6 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/poll.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/poll.h new file mode 120000 index 0000000..8ea6a0a --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/linux/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/ptrace.h new file mode 120000 index 0000000..b2517b2 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/linux/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/resource.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/resource.h new file mode 120000 index 0000000..88d7402 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/linux/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/shm.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/signal.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/socket.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/stat.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/stat.h new file mode 120000 index 0000000..1f63b41 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/linux/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/termios.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/time.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/uid_t.h new file mode 120000 index 0000000..b306777 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..bbe258c --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/linux/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/vt.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/vt.h new file mode 120000 index 0000000..5798a4a --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/vt.h @@ -0,0 +1 @@ +../../../../abis/linux/vt.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/wait.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/hyra/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/hyra/include/hyra/syscall.h b/lib/mlibc/sysdeps/hyra/include/hyra/syscall.h new file mode 100644 index 0000000..f38a59b --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/include/hyra/syscall.h @@ -0,0 +1,55 @@ +#ifndef _HYRA_SYSCALL_H_ +#define _HYRA_SYSCALL_H_ + +#define SYS_debug 0 +#define SYS_exit 1 + +__attribute__((__always_inline__)) +static inline long syscall0() { + volatile long ret; + asm volatile("int $0x80" : "=a"(ret)); + return ret; +} + +__attribute__((__always_inline__)) +static inline long syscall1(uint64_t code, uint64_t arg0) { + volatile long ret; + asm volatile("int $0x80" + : "=a"(ret) + : "a"(code), + "D"(arg0) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long syscall2(uint64_t code, uint64_t arg0, uint64_t arg1) { + volatile long ret; + asm volatile("int $0x80" + : "=a"(ret) + : "a"(code), + "D"(arg0), + "S"(arg1) + : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long syscall3(uint64_t code, uint64_t arg0, uint64_t arg1, uint64_t arg2) { + volatile long ret; + asm volatile("int $0x80" + : "=a"(ret) + : "a"(code), + "D"(arg0), + "S"(arg1), + "d"(arg2) + : "memory"); + return ret; +} + +#define _GET_SYSCALL(a0, a1, a2, a3, name, ...) name + +#define __syscall(...) \ + _GET_SYSCALL(__VA_ARGS__, syscall3, syscall2, syscall1, \ + syscall0)(__VA_ARGS__) + +#endif /* !_HYRA_SYSCALL_H_ */ diff --git a/lib/mlibc/sysdeps/hyra/meson.build b/lib/mlibc/sysdeps/hyra/meson.build new file mode 100644 index 0000000..80136db --- /dev/null +++ b/lib/mlibc/sysdeps/hyra/meson.build @@ -0,0 +1,69 @@ +rtdl_dso_sources += files( + 'generic/hyra.cpp' +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/hyra.cpp', +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + install_headers( + 'include/hyra/syscall.h', + subdir: 'hyra' + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) +endif + +if host_machine.cpu_family() == 'x86_64' + # libc_sources += files('generic/signals.S') +else + error('Unknown architecture') +endif diff --git a/lib/mlibc/sysdeps/ironclad/crt-x86_64/crt0.S b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crt0.S new file mode 100644 index 0000000..18d109e --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crt0.S @@ -0,0 +1,9 @@ + +.section .text +.global _start +_start: + mov $main, %rdi + call __mlibc_entry + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/ironclad/crt-x86_64/crti.S b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crti.S new file mode 100644 index 0000000..911b078 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + push %rax + +.section .fini +.global _fini +_fini: + push %rax +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/ironclad/crt-x86_64/crtn.S b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crtn.S new file mode 100644 index 0000000..0187e50 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/crt-x86_64/crtn.S @@ -0,0 +1,9 @@ +.section .init + pop %rax + ret + +.section .fini + pop %rax + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/ironclad/generic/entry.cpp b/lib/mlibc/sysdeps/ironclad/generic/entry.cpp new file mode 100644 index 0000000..2b8b914 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/entry.cpp @@ -0,0 +1,35 @@ + +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} + diff --git a/lib/mlibc/sysdeps/ironclad/generic/generic.cpp b/lib/mlibc/sysdeps/ironclad/generic/generic.cpp new file mode 100644 index 0000000..3d15365 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/generic.cpp @@ -0,0 +1,1266 @@ +#include <mlibc-config.h> +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <errno.h> +#include <dirent.h> +#include <fcntl.h> +#include <limits.h> +#include <asm/ioctls.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/syscall.h> +#include <sys/ironclad_devices.h> +#include <sched.h> +#include <sys/mman.h> +#include <unistd.h> +#include <sys/file.h> +#include <mlibc/tcb.hpp> + +namespace mlibc { + +void sys_libc_log(const char *message) { + ssize_t unused; + char new_line = '\n'; + sys_write(2, message, strlen(message), &unused); + sys_write(2, &new_line, 1, &unused); +} + +void sys_libc_panic() { + ssize_t unused; + char const *message = "mlibc panicked unrecoverably\n"; + sys_write(2, message, strlen(message), &unused); + sys_exit(1); +} + +void sys_exit(int status) { + int ret, errno; + SYSCALL1(SYSCALL_EXIT, status); + __builtin_unreachable(); +} + +int sys_tcb_set(void *pointer) { + int ret, errno; + SYSCALL2(SYSCALL_ARCH_PRCTL, 1, pointer); + return errno; +} + +int sys_thread_getname(void *tcb, char *name, size_t size) { + int ret, errno; + auto t = reinterpret_cast<Tcb *>(tcb); + SYSCALL3(SYSCALL_GETTIDID, t->tid, name, size); + return errno; +} + +int sys_thread_setname(void *tcb, const char *name) { + int ret, errno; + size_t len = strlen(name); + auto t = reinterpret_cast<Tcb *>(tcb); + SYSCALL3(SYSCALL_SETTIDID, t->tid, name, len); + return errno; +} + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + return sys_openat(AT_FDCWD, path, flags, mode, fd); +} + +int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) { + int ret, errno; + + int path_len = strlen (path); + SYSCALL4(SYSCALL_OPEN, dirfd, path, path_len, flags); + if (ret != -1 && (flags & O_EXCL)) { + SYSCALL1(SYSCALL_CLOSE, ret); + return EEXIST; + } + + if (ret == -1 && (flags & O_CREAT)) { + SYSCALL5(SYSCALL_MAKENODE, AT_FDCWD, path, path_len, mode, 0); + if (ret == -1) { + return errno; + } + SYSCALL4(SYSCALL_OPEN, AT_FDCWD, path, path_len, flags); + } else if (ret != -1 && (flags & O_TRUNC)) { + // If the file cannot be truncated, dont sweat it, some software + // depends on some things being truncate-able that ironclad does not + // allow. For example, some devices. + sys_ftruncate(ret, 0); + } else if (ret != -1 && (flags & O_DIRECTORY)) { + struct stat st; + sys_stat(fsfd_target::fd, ret, NULL, 0, &st); + if (!S_ISDIR (st.st_mode)) { + ret = -1; + errno = ENOTDIR; + } + } + + *fd = ret; + return errno; +} + +int sys_open_dir(const char *path, int *handle) { + return sys_open(path, O_RDONLY | O_DIRECTORY, 0660, handle); +} + +int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read) { + size_t ret; + int errno; + SYSCALL3(SYSCALL_GETDENTS, handle, buffer, max_size); + if (errno != 0) { + return errno; + } else { + *bytes_read = ret; + return 0; + } +} + +void sys_thread_exit() { + int ret, errno; + SYSCALL0(SYSCALL_EXIT_THREAD); + __builtin_unreachable(); +} + +int sys_close(int fd) { + int ret, errno; + SYSCALL1(SYSCALL_CLOSE, fd); + return errno; +} + +void sys_sync() { + int ret, errno; + SYSCALL0(SYSCALL_SYNC); + if (ret != 0) { + sys_libc_log("mlibc: sync failed"); + } +} + +int sys_fsync(int fd) { + int ret, errno; + SYSCALL2(SYSCALL_FSYNC, fd, 0); + return errno; +} + +int sys_fdatasync(int fd) { + int ret, errno; + SYSCALL2(SYSCALL_FSYNC, fd, 1); + return errno; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + ssize_t ret; + int errno; + SYSCALL3(SYSCALL_READ, fd, buf, count); + *bytes_read = ret; + return errno; +} + +int sys_write(int fd, const void *buf, size_t count, ssize_t *bytes_written) { + ssize_t ret; + int errno; + SYSCALL3(SYSCALL_WRITE, fd, buf, count); + *bytes_written = ret; + return errno; +} + +int sys_pread(int fd, void *buf, size_t n, off_t off, ssize_t *bytes_read) { + ssize_t ret; + int errno; + SYSCALL4(SYSCALL_PREAD, fd, buf, n, off); + *bytes_read = ret; + return errno; +} + +int sys_pwrite(int fd, const void *buf, size_t n, off_t off, ssize_t *bytes_written) { + ssize_t ret; + int errno; + SYSCALL4(SYSCALL_WRITE, fd, buf, n, off); + *bytes_written = ret; + return errno; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + ssize_t ret; + int errno; + SYSCALL3(SYSCALL_SEEK, fd, offset, whence); + *new_offset = ret; + return errno; +} + +int sys_ftruncate (int fd, size_t size) { + int ret, errno; + SYSCALL2(SYSCALL_TRUNCATE, fd, size); + return errno; +} + +int sys_flock(int fd, int options) { + // XXX: Shouldnt this use F_SETLKW and F_SETLK only when LOCK_NB ? + struct flock lock; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = (off_t)((uint64_t)-1); + lock.l_pid = sys_getpid(); + + switch (options & ~(LOCK_NB)) { + case LOCK_SH: + lock.l_type = F_RDLCK; + break; + case LOCK_EX: + lock.l_type = F_WRLCK; + break; + case LOCK_UN: + lock.l_type = F_UNLCK; + break; + default: + return -1; + } + + int ret, errno; + SYSCALL3(SYSCALL_FCNTL, fd, F_SETLK, &lock); + return errno; +} + +int sys_getpriority(int which, id_t who, int *value) { + int ret, errno; + SYSCALL2(SYSCALL_GETPRIO, which, who); + *value = ret; + return errno; +} + +int sys_setpriority(int which, id_t who, int value) { + int ret, errno; + SYSCALL3(SYSCALL_SETPRIO, which, who, value); + return errno; +} + +int sys_getrusage(int scope, struct rusage *usage) { + int ret, errno; + SYSCALL2(SYSCALL_GETRUSAGE, scope, usage); + + // Ironclad returns nanoseconds instead of microseconds for usage, so we + // have to compensate for that. + usage->ru_utime.tv_usec = usage->ru_utime.tv_usec / 1000; + usage->ru_stime.tv_usec = usage->ru_stime.tv_usec / 1000; + + return errno; +} + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0, pointer); +} + +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { + void *ret; + int errno; + SYSCALL6(SYSCALL_MMAP, hint, size, prot, flags, fd, offset); + *window = ret; + return errno; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size) { + int ret, errno; + SYSCALL5(SYSCALL_GETSOCKOPT, fd, layer, number, buffer, size); + return errno; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size) { + int ret, errno; + SYSCALL5(SYSCALL_SETSOCKOPT, fd, layer, number, buffer, size); + return errno; +} + +int sys_vm_unmap(void *pointer, size_t size) { + int ret; + int errno; + SYSCALL2(SYSCALL_MUNMAP, pointer, size); + if (ret != 0) { + return errno; + } else { + return 0; + } +} + +int sys_getcwd(char *buf, size_t size) { + buf[0] = '/'; + buf[1] = '\0'; + return 0; +} + +int sys_vm_protect(void *pointer, size_t size, int prot) { + int ret; + int errno; + SYSCALL3(SYSCALL_MPROTECT, pointer, size, prot); + if (ret != 0) { + return errno; + } + return 0; +} + +int sys_getsid(pid_t pid, pid_t *sid) { + // STUB. + return 0; +} + +pid_t sys_getpid() { + pid_t ret; + int errno; + SYSCALL0(SYSCALL_GETPID); + return ret; +} + +pid_t sys_getppid() { + pid_t ret; + int errno; + SYSCALL0(SYSCALL_GETPPID); + return ret; +} + +int sys_getgroups(size_t size, const gid_t *list, int *retval) { + int ret, errno; + SYSCALL2(SYSCALL_GETGROUPS, size, list); + *retval = ret; + return errno; +} + +int sys_setgroups(size_t size, const gid_t *list) { + int ret, errno; + SYSCALL2(SYSCALL_SETGROUPS, size, list); + return errno; +} + +int sys_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { + return 0; +} + +int sys_ptrace(long req, pid_t pid, void *addr, void *data, long *out) { + int ret, errno; + SYSCALL4(SYSCALL_PTRACE, req, pid, addr, data); + *out = (long)ret; + return errno; +} + +int sys_fcntl(int fd, int request, va_list args, int *result) { + int ret, errno; + SYSCALL3(SYSCALL_FCNTL, fd, request, va_arg(args, uint64_t)); + *result = ret; + return errno; +} + +int sys_sigprocmask(int how, const sigset_t *__restrict set, sigset_t *__restrict retrieve) { + return 0; +} + +int sys_isatty(int fd) { + struct termios t; + if (sys_tcgetattr(fd, &t) == 0) { + return 0; + } else { + return ENOTTY; + } +} + +int sys_getpgid(pid_t pid, pid_t *pgid) { + (void)pid; + // FIXME: Stub needed by mlibc. + *pgid = 0; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + int ret, errno, argv_len, envp_len; + for (argv_len = 0; argv[argv_len] != NULL; argv_len++); + for (envp_len = 0; envp[envp_len] != NULL; envp_len++); + + size_t path_len = strlen (path); + SYSCALL6(SYSCALL_EXEC, path, path_len, argv, argv_len, envp, envp_len); + + if (ret == -1) { + return errno; + } + + return 0; +} + +int sys_fork(pid_t *child) { + pid_t ret; + int errno; + + SYSCALL6(SYSCALL_CLONE, 0, 0, 0, 0, 0, 1); + + if (ret == -1) { + return errno; + } + + if (child != NULL) { + *child = ret; + } + + return 0; +} + +int sys_getrlimit(int resource, struct rlimit *limit) { + uint64_t ret, errno; + SYSCALL1(SYSCALL_GETRLIMIT, resource); + limit->rlim_cur = ret; + limit->rlim_max = ret; + return errno; +} + +int sys_setrlimit(int resource, const struct rlimit *limit) { + int ret, errno; + SYSCALL2(SYSCALL_SETRLIMIT, resource, limit->rlim_cur); + return errno; +} + +int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { + pid_t ret; + int errno; + + if(ru) { + mlibc::infoLogger() << "mlibc: struct rusage in sys_waitpid is unsupported" << frg::endlog; + return ENOSYS; + } + + SYSCALL3(SYSCALL_WAIT, pid, status, flags); + + if (ret == -1) { + return errno; + } + + *ret_pid = ret; + return errno; +} + +int sys_uname(struct utsname *buf) { + int ret, errno; + + SYSCALL3(SYSCALL_SYSCONF, 10, buf, sizeof(struct utsname)); + + if (ret == -1) { + return errno; + } + + return 0; +} + + + +int sys_setpgid(pid_t pid, pid_t pgid) { + (void)pid; + (void)pgid; + return 0; +} + +int sys_ttyname(int fd, char *buff, size_t size) { + int ret, errno; + SYSCALL3(SYSCALL_TTYNAME, fd, buff, size); + return errno; +} + +int sys_sethostname(const char *buff, size_t size) { + int ret, errno; + + SYSCALL2(SYSCALL_SETHOSTNAME, buff, size); + + if (ret == -1) { + return errno; + } + + return 0; +} + +int sys_chdir(const char *buff) { + int ret, errno; + + size_t buff_len = strlen(buff); + SYSCALL4(SYSCALL_OPEN, AT_FDCWD, buff, buff_len, O_RDONLY); + if (ret == -1) { + return ENOENT; + } + + SYSCALL1(SYSCALL_CHDIR, ret); + + if (ret == -1) { + return errno; + } + + return 0; +} + +int sys_fchdir(int fd) { + int ret, errno; + + SYSCALL1(SYSCALL_CHDIR, fd); + + if (ret == -1) { + return errno; + } + + return 0; +} + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { + int ret, errno; + + if (request == TIOCGPGRP) { + *result = 0; + return 0; + } else if (request == TIOCSPGRP) { + return 0; + } + + SYSCALL3(SYSCALL_IOCTL, fd, request, arg); + + if (ret == -1) { + return errno; + } + + *result = ret; + return 0; +} + +void sys_yield(void) { + int ret, errno; + SYSCALL0(SYSCALL_SCHED_YIELD); +} + +int sys_kill(int pid, int sig) { + int ret, errno; + if (sig == SIGKILL) { + SYSCALL1(SYSCALL_ACTUALLY_KILL, pid); + } else { + SYSCALL2(SYSCALL_SEND_SIGNAL, pid, sig); + } + + return errno; +} + +int sys_dup(int fd, int flags, int *newfd) { + int ret, errno; + if (flags & O_CLOEXEC) { + SYSCALL3(SYSCALL_FCNTL, fd, F_DUPFD_CLOEXEC, 0); + } else { + SYSCALL3(SYSCALL_FCNTL, fd, F_DUPFD, 0); + } + *newfd = ret; + return errno; +} + +int sys_dup2(int fd, int flags, int newfd) { + int ret = sys_close(newfd); + if (ret != 0 && ret != EBADFD) { + return EBADFD; + } + + int errno; + if (flags & O_CLOEXEC) { + SYSCALL3(SYSCALL_FCNTL, fd, F_DUPFD_CLOEXEC, newfd); + } else { + SYSCALL3(SYSCALL_FCNTL, fd, F_DUPFD, newfd); + } + + if (ret != -1 && ret != newfd) { + return EBADFD; + } else { + return errno; + } +} + +int sys_tcgetattr(int fd, struct termios *attr) { + int ret; + + if (int r = sys_ioctl(fd, TCGETS, attr, &ret) != 0) { + return r; + } + + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + int ret; + + switch (optional_action) { + case TCSANOW: + optional_action = TCSETS; break; + case TCSADRAIN: + optional_action = TCSETSW; break; + case TCSAFLUSH: + optional_action = TCSETSF; break; + default: + __ensure(!"Unsupported tcsetattr"); + } + + if (int r = sys_ioctl(fd, optional_action, (void *)attr, &ret) != 0) { + return r; + } + + return 0; +} + +int sys_tcflow(int fd, int action) { + int ret; + return sys_ioctl(fd, TCXONC, &action, &ret); +} + +int sys_tcflush(int fd, int action) { + int ret; + return sys_ioctl(fd, TCFLSH, &action, &ret); +} + +int sys_access(const char *path, int mode) { + int ret, errno; + size_t len = strlen(path); + SYSCALL5(SYSCALL_ACCESS, AT_FDCWD, path, len, mode, 0); + return errno; +} + +int sys_faccessat(int dirfd, const char *pathname, int mode, int flags) { + int ret, errno; + size_t len = strlen(pathname); + SYSCALL5(SYSCALL_ACCESS, dirfd, pathname, len, mode, flags); + return errno; +} + +struct futex_item { + uint64_t addr; + uint32_t expected; + uint32_t flags; +}; + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + int ret, errno; + struct futex_item item = {.addr = (uint64_t)pointer, .expected = expected, .flags = 0}; + if (time == NULL) { + struct timespec t = {(time_t)-1, (time_t)-1}; + SYSCALL4(SYSCALL_FUTEX, 0b01, &item, 1, &t); + } else { + SYSCALL4(SYSCALL_FUTEX, 0b01, &item, 1, time); + } + return errno; +} + +int sys_futex_wake(int *pointer) { + int ret, errno; + struct futex_item item = {.addr = (uint64_t)pointer, .expected = 0, .flags = 0}; + struct timespec t = {(time_t)-1, (time_t)-1}; + SYSCALL4(SYSCALL_FUTEX, 0b10, &item, 1, &t); + return errno; +} + +int sys_pipe(int *fds, int flags) { + int ret, errno; + SYSCALL2(SYSCALL_PIPE, fds, flags); + return errno; +} + +int sys_getentropy(void *buffer, size_t length) { + ssize_t ret; + int errno; + SYSCALL2(SYSCALL_GETRANDOM, buffer, length); + return errno; +} + +int sys_mkdir(const char *path, mode_t mode) { + return sys_mkdirat(AT_FDCWD, path, mode); +} + +int sys_mkdirat(int dirfd, const char *path, mode_t mode) { + int ret, errno; + size_t path_len = strlen (path); + SYSCALL5(SYSCALL_MAKENODE, dirfd, path, path_len, S_IFDIR | mode, 0); + return errno; +} + +int sys_rmdir(const char* path){ + int ret, errno; + size_t path_len = strlen (path); + SYSCALL3(SYSCALL_UNLINK, AT_FDCWD, path, path_len); + return errno; +} + +int sys_unlinkat(int fd, const char *path, int flags) { + int ret, errno; + size_t path_len = strlen (path); + SYSCALL3(SYSCALL_UNLINK, fd, path, path_len); + return errno; +} + +int sys_link(const char* srcpath, const char* destpath) { + int ret, errno; + size_t src_len = strlen (srcpath); + size_t dst_len = strlen (destpath); + SYSCALL6(SYSCALL_LINK, AT_FDCWD, srcpath, src_len, AT_FDCWD, destpath, dst_len); + return errno; +} + +int sys_socket(int domain, int type, int protocol, int *fd) { + int ret, errno; + SYSCALL3(SYSCALL_SOCKET, domain, type, protocol); + if (ret != -1) { + *fd = ret; + return 0; + } else { + return errno; + } +} + +uid_t sys_getuid() { + uint64_t ret, errno; + SYSCALL0(SYSCALL_GETUID); + return (uid_t)ret; +} + +uid_t sys_geteuid() { + uint64_t ret, errno; + SYSCALL0(SYSCALL_GETEUID); + return (uid_t)ret; +} + +int sys_setuid(uid_t uid) { + int ret, errno; + SYSCALL2(SYSCALL_SETUIDS, uid, uid); + return ret; +} + +int sys_seteuid(uid_t euid) { + int ret, errno; + SYSCALL2(SYSCALL_SETUIDS, ((uint64_t)-1), euid); + return ret; +} + +int sys_setreuid(uid_t ruid, uid_t euid) { + int ret, errno; + SYSCALL2(SYSCALL_SETUIDS, ruid, euid); + return ret; +} + +gid_t sys_getgid() { + uint64_t ret, errno; + SYSCALL0(SYSCALL_GETGID); + return (gid_t)ret; +} + +gid_t sys_getegid() { + return sys_getgid(); +} + +int sys_setgid(gid_t gid) { + int ret, errno; + SYSCALL2(SYSCALL_SETGIDS, gid, gid); + return ret; +} + +int sys_setegid(gid_t egid) { + int ret, errno; + SYSCALL2(SYSCALL_SETGIDS, ((uint64_t)-1), egid); + return ret; +} + +int sys_setregid(gid_t rgid, gid_t egid) { + int ret, errno; + SYSCALL2(SYSCALL_SETGIDS, rgid, egid); + return ret; +} + +int sys_setsid(pid_t *sid) { + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +extern "C" void __mlibc_thread_entry(); + +int sys_clone(void *tcb, pid_t *tid_out, void *stack) { + int ret, errno; + SYSCALL6(SYSCALL_CLONE, (uintptr_t)__mlibc_thread_entry, 0, stack, 0b10, tcb, 1); + + if (ret == -1) { + return errno; + } + + *tid_out = (pid_t)ret; + return 0; +} + +int sys_prepare_stack(void **stack, void *entry, void *arg, void *tcb, size_t *stack_size, size_t *guard_size) { + // TODO guard + + mlibc::infoLogger() << "mlibc: sys_prepare_stack() does not setup a guard!" << frg::endlog; + + *guard_size = 0; + *stack_size = *stack_size ? *stack_size : 0x400000; + + if (!*stack) { + *stack = (void *)((char *)mmap(NULL, *stack_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0) + *stack_size); + if (*stack == MAP_FAILED) { + return errno; + } + } + + void **stack_it = (void **)*stack; + + *--stack_it = arg; + *--stack_it = tcb; + *--stack_it = entry; + + *stack = (void *)stack_it; + + return 0; +} + +int sys_clock_getres(int clock, time_t *secs, long *nanos) { + struct timespec time; + int ret, errno; + SYSCALL3(SYSCALL_CLOCK, 0, clock, &time); + *secs = time.tv_sec; + *nanos = time.tv_nsec; + return errno; +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + struct timespec time; + int ret, errno; + SYSCALL3(SYSCALL_CLOCK, 1, clock, &time); + *secs = time.tv_sec; + *nanos = time.tv_nsec; + return errno; +} + +int sys_clock_set(int clock, time_t secs, long nanos) { + struct timespec time = {.tv_sec = secs, .tv_nsec = nanos }; + int ret, errno; + SYSCALL3(SYSCALL_CLOCK, 2, clock, &time); + return errno; +} + +int sys_bind(int fd, const struct sockaddr *addr_ptr, socklen_t addrlen) { + int ret, errno; + SYSCALL3(SYSCALL_BIND, fd, addr_ptr, addrlen); + return errno; +} + +int sys_connect(int fd, const struct sockaddr *addr_ptr, socklen_t addrlen) { + int ret, errno; + SYSCALL3(SYSCALL_CONNECT, fd, addr_ptr, addrlen); + return errno; +} + +int sys_listen(int fd, int backlog) { + int ret, errno; + SYSCALL2(SYSCALL_LISTEN, fd, backlog); + return errno; +} + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags) { + int ret, errno; + SYSCALL4(SYSCALL_ACCEPT, fd, addr_ptr, addr_length, flags); + *newfd = ret; + return errno; +} + + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { + int ret, errno; + SYSCALL3(SYSCALL_GETSOCKNAME, fd, addr_ptr, &max_addr_length); + *actual_length = max_addr_length; + return errno; +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { + int ret, errno; + SYSCALL3(SYSCALL_GETPEERNAME, fd, addr_ptr, &max_addr_length); + *actual_length = max_addr_length; + return errno; +} + +int sys_shutdown(int sockfd, int how) { + int ret, errno; + SYSCALL2(SYSCALL_SHUTDOWN, sockfd, how); + return errno; +} + +int sys_setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) { + return ENOSYS; +} + +int sys_msg_recv(int fd, struct msghdr *hdr, int flags, ssize_t *length) { + if (hdr->msg_control != NULL) { + // mlibc::infoLogger() << "mlibc: recv() msg_control not supported!" << frg::endlog; + } + + int ret; + size_t count = 0; + int errno; + + for (int i = 0; i < hdr->msg_iovlen; i++) { + SYSCALL6(SYSCALL_RECVFROM, fd, hdr->msg_iov->iov_base, hdr->msg_iov->iov_len, + hdr->msg_flags, hdr->msg_name, hdr->msg_namelen); + if (ret == -1) { + return errno; + } + count += ret; + } + + *length = count; + return 0; +} + +int sys_msg_send(int fd, const struct msghdr *hdr, int flags, ssize_t *length) { + if (hdr->msg_control != NULL) { + // mlibc::infoLogger() << "mlibc: recv() msg_control not supported!" << frg::endlog; + } + + int ret; + size_t count = 0; + int errno; + + for (int i = 0; i < hdr->msg_iovlen; i++) { + SYSCALL6(SYSCALL_SENDTO, fd, hdr->msg_iov->iov_base, hdr->msg_iov->iov_len, + hdr->msg_flags, hdr->msg_name, hdr->msg_namelen); + if (ret == -1) { + return errno; + } + count += ret; + } + + *length = count; + return 0; +} + + +int sys_ppoll(struct pollfd *fds, int nfds, const struct timespec *timeout, const sigset_t *sigmask, int *num_events) { + // XXX: Ironclad has no sigprogmask so this is basically a weird ppoll poll + // chimeral abomination. + int ret, errno; + if (timeout == NULL) { + struct timespec t = {.tv_sec = (time_t)-1, .tv_nsec = (time_t)-1}; + SYSCALL3(SYSCALL_POLL, fds, nfds, &t); + } else { + SYSCALL3(SYSCALL_POLL, fds, nfds, timeout); + } + if (ret == -1) { + return errno; + } + + *num_events = ret; + return errno; +} + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { + struct timespec ts; + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + return sys_ppoll(fds, count, timeout == -1 ? NULL : &ts, NULL, num_events); +} + +int sys_pselect(int nfds, fd_set *read_set, fd_set *write_set, + fd_set *except_set, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) { + struct pollfd *fds = (struct pollfd *)calloc(nfds, sizeof(struct pollfd)); + if (fds == NULL) { + return ENOMEM; + } + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + + if (read_set && FD_ISSET(i, read_set)) { + fd->events |= POLLIN; + } + if (write_set && FD_ISSET(i, write_set)) { + fd->events |= POLLOUT; + } + if (except_set && FD_ISSET(i, except_set)) { + fd->events |= POLLPRI; + } + + if (!fd->events) { + fd->fd = -1; + continue; + } + fd->fd = i; + } + + int ret = sys_ppoll(fds, nfds, timeout, sigmask, num_events); + if (ret != 0) { + free(fds); + return ret; + } + + fd_set res_read_set, res_write_set, res_except_set; + FD_ZERO(&res_read_set); + FD_ZERO(&res_write_set); + FD_ZERO(&res_except_set); + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + + if (read_set && FD_ISSET(i, read_set) && (fd->revents & (POLLIN | POLLERR | POLLHUP)) != 0) { + FD_SET(i, &res_read_set); + } + if (write_set && FD_ISSET(i, write_set) && (fd->revents & (POLLOUT | POLLERR | POLLHUP)) != 0) { + FD_SET(i, &res_write_set); + } + if (except_set && FD_ISSET(i, except_set) && (fd->revents & POLLPRI) != 0) { + FD_SET(i, &res_except_set); + } + } + + free(fds); + if (read_set) { + *read_set = res_read_set; + } + if (write_set) { + *write_set = res_write_set; + } + if (except_set) { + *except_set = res_except_set; + } + + return 0; +} + +int sys_sleep(time_t *secs, long *nanos) { + struct timespec time = {.tv_sec = *secs, .tv_nsec = *nanos}; + struct timespec rem = {.tv_sec = 0, .tv_nsec = 0}; + + int ret, errno; + SYSCALL4(SYSCALL_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, 0, &time, &rem); + *secs = rem.tv_sec; + *nanos = rem.tv_nsec; + return errno; +} + +int sys_gethostname(char *buffer, size_t bufsize) { + struct utsname buf; + if (uname(&buf)) { + return -1; + } + + strncpy(buffer, buf.nodename, bufsize); + return 0; +} + +int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { + int ret, errno; + if (pathname == NULL) { + pathname = ""; + flags |= AT_EMPTY_PATH; + } + + size_t path_len = strlen (pathname); + if (times == NULL) { + time_t secs; + long nsec; + ret = sys_clock_get(CLOCK_REALTIME, &secs, &nsec); + if (ret) { + return ret; + } + struct timespec times2[2] = {0, 0}; + times2[0].tv_sec = secs; + times2[0].tv_nsec = nsec; + times2[1].tv_sec = secs; + times2[1].tv_nsec = nsec; + SYSCALL5(SYSCALL_UTIMES, dirfd, pathname, path_len, ×2[0], flags); + } else { + SYSCALL5(SYSCALL_UTIMES, dirfd, pathname, path_len, times, flags); + } + + return errno; +} + +int sys_sysconf(int num, long *rret) { + long ret, errno; + SYSCALL3(SYSCALL_SYSCONF, num, 0, 0); + *rret = ret; + return errno; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf) { + int ret, errno; + (void)flags; + + switch (fsfdt) { + case fsfd_target::fd: { + SYSCALL5(SYSCALL_STAT, fd, "", 0, statbuf, AT_EMPTY_PATH); + break; + } + case fsfd_target::path: { + size_t len = strlen(path); + SYSCALL5(SYSCALL_STAT, AT_FDCWD, path, len, statbuf, flags); + break; + } + case fsfd_target::fd_path: { + size_t len = strlen(path); + SYSCALL5(SYSCALL_STAT, fd, path, len, statbuf, flags); + break; + } + default: { + __ensure(!"stat: Invalid fsfdt"); + __builtin_unreachable(); + } + } + + return errno; +} + +int sys_chmod(const char *pathname, mode_t mode) { + int ret, errno; + size_t len = strlen(pathname); + SYSCALL5(SYSCALL_FCHMOD, AT_FDCWD, pathname, len, mode, 0); + return errno; +} + +int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { + int ret, errno; + size_t len = strlen(pathname); + SYSCALL5(SYSCALL_FCHMOD, fd, pathname, len, mode, flags); + return errno; +} + +int sys_fchmod(int fd, mode_t mode) { + int ret, errno; + SYSCALL5(SYSCALL_FCHMOD, fd, "", 0, mode, AT_EMPTY_PATH); + return errno; +} + +int sys_chown(const char *pathname, uid_t uid, gid_t gid) { + int ret, errno; + size_t len = strlen(pathname); + SYSCALL6(SYSCALL_FCHOWN, AT_FDCWD, pathname, len, uid, gid, 0); + return errno; +} + +int sys_fchownat(int fd, const char *pathname, uid_t uid, gid_t gid, int flags) { + int ret, errno; + size_t len = strlen(pathname); + SYSCALL6(SYSCALL_FCHOWN, fd, pathname, len, uid, gid, flags); + return errno; +} + +int sys_fchown(int fd, uid_t uid, gid_t gid) { + int ret, errno; + SYSCALL6(SYSCALL_FCHOWN, fd, "", 0, uid, gid, AT_EMPTY_PATH); + return errno; +} + +int sys_umask(mode_t mode, mode_t *old) { + mode_t ret; + int errno; + SYSCALL1(SYSCALL_UMASK, mode); + *old = (mode_t)ret; + return errno; +} + +int sys_fadvise(int fd, off_t offset, off_t length, int advice) { + int ret, errno; + SYSCALL4(SYSCALL_FADVISE, fd, offset, length, advice); + return errno; +} + +int sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length) { + ssize_t ret; + int errno; + size_t path_len = strlen(path); + SYSCALL5(SYSCALL_READLINK, AT_FDCWD, path, path_len, buffer, max_size); + if (ret == -1) { + return errno; + } else { + *length = ret; + return 0; + } +} + +int sys_rename(const char *path, const char *new_path) { + int ret; + int errno; + size_t old_len = strlen(path); + size_t new_len = strlen(new_path); + SYSCALL7(SYSCALL_RENAME, AT_FDCWD, path, old_len, AT_FDCWD, new_path, new_len, 0); + return errno; +} + +int sys_renameat(int olddirfd, const char *old_path, int newdirfd, const char *new_path) { + int ret; + int errno; + size_t old_len = strlen(old_path); + size_t new_len = strlen(new_path); + SYSCALL7(SYSCALL_RENAME, olddirfd, old_path, old_len, newdirfd, new_path, new_len, 0); + return errno; +} + +int sys_mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) { + int ret; + int errno; + size_t len = strlen(path); + SYSCALL5(SYSCALL_MAKENODE, dirfd, path, len, mode, dev); + return errno; +} + +#define SC_LIST_MOUNTS 9 +struct mountinfo { + uint32_t type; + uint32_t flags; + char source[20]; + uint32_t source_length; + char location[20]; + uint32_t location_length; + uint64_t block_size; + uint64_t fragment_size; + uint64_t size_in_fragments; + uint64_t free_blocks; + uint64_t free_blocks_user; + uint64_t inode_count; + uint64_t free_inodes; + uint64_t free_inodes_user; + uint64_t max_filename; +}; + +#include <sys/mount.h> + +int sys_fstatvfs(int fd, struct statvfs *out) { + return sys_statvfs("/", out); +} + +int sys_statvfs(const char *path, struct statvfs *out) { + long ret, errno; + struct mountinfo *buffer = (mountinfo *)malloc(5 * sizeof(struct mountinfo)); + SYSCALL3(SYSCALL_SYSCONF, SC_LIST_MOUNTS, buffer, 5 * sizeof(struct mountinfo)); + if (errno) { + free(buffer); + return errno; + } else if (ret > 5) { + free(buffer); + return 1; + } + + for (int i = 0; i < ret; i++) { + if (!strncmp(path, buffer[i].location, buffer[i].location_length)) { + out->f_bsize = buffer[i].block_size; + out->f_frsize = buffer[i].fragment_size; + out->f_blocks = buffer[i].size_in_fragments; + out->f_bfree = buffer[i].free_blocks; + out->f_bavail = buffer[i].free_blocks_user; + out->f_files = buffer[i].inode_count; + out->f_ffree = buffer[i].free_inodes; + out->f_favail = buffer[i].free_inodes_user; + out->f_fsid = 0; + out->f_flag = buffer[i].flags; + out->f_namemax = buffer[i].max_filename; + if (buffer[i].type == MNT_EXT) { + strcpy(out->f_basetype, "ext"); + } else { + strcpy(out->f_basetype, "fat"); + } + return 0; + } + } + + return EINVAL; +} +#endif +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/ironclad/generic/mac.cpp b/lib/mlibc/sysdeps/ironclad/generic/mac.cpp new file mode 100644 index 0000000..12b63d8 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/mac.cpp @@ -0,0 +1,32 @@ +#include <sys/syscall.h> +#include <sys/mac.h> +#include <errno.h> +#include <string.h> + +extern "C" { + +unsigned long get_mac_capabilities(void) { + int ret; + SYSCALL0(SYSCALL_GET_MAC_CAPABILITIES); + return ret; +} + +int set_mac_capabilities(unsigned long request) { + int ret; + SYSCALL1(SYSCALL_SET_MAC_CAPABILITIES, request); + return ret; +} + +int add_mac_permissions(const char *path, int flags) { + int ret; + SYSCALL3(SYSCALL_ADD_MAC_PERMISSIONS, path, strlen(path), flags); + return ret; +} + +int set_mac_enforcement(unsigned long enforcement) { + int ret; + SYSCALL1(SYSCALL_SET_MAC_ENFORCEMENT, enforcement); + return ret; +} + +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/mntent.cpp b/lib/mlibc/sysdeps/ironclad/generic/mntent.cpp new file mode 100644 index 0000000..d064af3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/mntent.cpp @@ -0,0 +1,97 @@ +#include <errno.h> +#include <mntent.h> +#include <stdio.h> +#include <limits.h> +#include <string.h> +#include <bits/ensure.h> + +namespace { + +char *internal_buf; +size_t internal_bufsize; + +} + +#define SENTINEL (char *)&internal_buf + +FILE *setmntent(const char *name, const char *mode) { + return fopen(name, mode); +} + +struct mntent *getmntent(FILE *f) { + static struct mntent mnt; + return getmntent_r(f, &mnt, SENTINEL, 0); +} + +int addmntent(FILE *f, const struct mntent *mnt) { + if(fseek(f, 0, SEEK_END)) { + return 1; + } + return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n", + mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts, + mnt->mnt_freq, mnt->mnt_passno) < 0; +} + +int endmntent(FILE *f) { + if(f) { + fclose(f); + } + return 1; +} + +char *hasmntopt(const struct mntent *mnt, const char *opt) { + return strstr(mnt->mnt_opts, opt); +} + +/* Adapted from musl */ +struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { + int n[8]; + bool use_internal = (linebuf == SENTINEL); + int len; + size_t i; + + mnt->mnt_freq = 0; + mnt->mnt_passno = 0; + + do { + if(use_internal) { + getline(&internal_buf, &internal_bufsize, f); + linebuf = internal_buf; + } else { + fgets(linebuf, buflen, f); + } + if(feof(f) || ferror(f)) { + return 0; + } + if(!strchr(linebuf, '\n')) { + fscanf(f, "%*[^\n]%*[\n]"); + errno = ERANGE; + return 0; + } + + len = strlen(linebuf); + if(len > INT_MAX) { + continue; + } + + for(i = 0; i < sizeof n / sizeof *n; i++) { + n[i] = len; + } + + sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + n, n + 1, n + 2, n + 3, n + 4, n + 5, n + 6, n + 7, + &mnt->mnt_freq, &mnt->mnt_passno); + } while(linebuf[n[0]] == '#' || n[1] == len); + + linebuf[n[1]] = 0; + linebuf[n[3]] = 0; + linebuf[n[5]] = 0; + linebuf[n[7]] = 0; + + mnt->mnt_fsname = linebuf + n[0]; + mnt->mnt_dir = linebuf + n[2]; + mnt->mnt_type = linebuf + n[4]; + mnt->mnt_opts = linebuf + n[6]; + + return mnt; +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/mount.cpp b/lib/mlibc/sysdeps/ironclad/generic/mount.cpp new file mode 100644 index 0000000..feb6e4c --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/mount.cpp @@ -0,0 +1,20 @@ +#include <errno.h> +#include <sys/mount.h> +#include <bits/ensure.h> +#include <sys/syscall.h> +#include <string.h> + +int mount(const char *source, const char *target, int type, int flags) { + int ret; + size_t source_len = strlen(source); + size_t target_len = strlen(target); + SYSCALL6(SYSCALL_MOUNT, source, source_len, target, target_len, type, flags); + return ret; +} + +int umount(const char *target, int flags) { + int ret; + size_t target_len = strlen(target); + SYSCALL3(SYSCALL_UMOUNT, target, target_len, flags); + return ret; +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/ptrace.cpp b/lib/mlibc/sysdeps/ironclad/generic/ptrace.cpp new file mode 100644 index 0000000..58a8dd2 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/ptrace.cpp @@ -0,0 +1,9 @@ +#include <sys/syscall.h> +#include <errno.h> +#include <sys/ptrace.h> + +int ptrace(int request, pid_t pid, void *addr, void *data) { + int ret; + SYSCALL4(SYSCALL_PTRACE, request, pid, addr, data); + return ret; +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/pty.cpp b/lib/mlibc/sysdeps/ironclad/generic/pty.cpp new file mode 100644 index 0000000..1626e4b --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/pty.cpp @@ -0,0 +1,41 @@ +#include <asm/ioctls.h> +#include <bits/ensure.h> +#include <errno.h> +#include <fcntl.h> +#include <pty.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/syscall.h> +#include <sys/ioctl.h> + +int openpty(int *mfd, int *sfd, char *name, const struct termios *ios, const struct winsize *win) { + int ret; + int fds[2]; + SYSCALL1(SYSCALL_OPENPTY, fds); + if (errno) { + return -1; + } + *mfd = fds[0]; + *sfd = fds[1]; + + if (name != NULL) { + ret = ttyname_r(*mfd, name, (size_t)-1); + if (ret) { + return -1; + } + } + if (ios != NULL) { + ret = tcsetattr(*mfd, TCSANOW, ios); + if (ret) { + return -1; + } + } + if (win != NULL) { + ret = ioctl(*mfd, TIOCGWINSZ, win); + if (ret) { + return -1; + } + } + return ret; +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/reboot.cpp b/lib/mlibc/sysdeps/ironclad/generic/reboot.cpp new file mode 100644 index 0000000..45e8f03 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/reboot.cpp @@ -0,0 +1,9 @@ +#include <errno.h> +#include <sys/reboot.h> +#include <sys/syscall.h> + +int reboot(int what) { + int ret, errno; + SYSCALL2(SYSCALL_REBOOT, what, 0); + return ret; +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/sched2.cpp b/lib/mlibc/sysdeps/ironclad/generic/sched2.cpp new file mode 100644 index 0000000..9699517 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/sched2.cpp @@ -0,0 +1,20 @@ +#include <sys/syscall.h> +#include <sys/sched2.h> +#include <errno.h> +#include <string.h> + +extern "C" { + +int get_thread_sched(void) { + return 0; +} + +int set_thread_sched(int flags) { + return 0; +} + +int set_deadlines(int runtime, int period) { + return 0; +} + +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/thread.S b/lib/mlibc/sysdeps/ironclad/generic/thread.S new file mode 100644 index 0000000..47ab6a9 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/thread.S @@ -0,0 +1,9 @@ +.section .text +.global __mlibc_thread_entry +__mlibc_thread_entry: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_thread_trampoline + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/ironclad/generic/thread.cpp b/lib/mlibc/sysdeps/ironclad/generic/thread.cpp new file mode 100644 index 0000000..1b2f040 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/thread.cpp @@ -0,0 +1,54 @@ +#include <sys/mman.h> +#include <mlibc/debug.hpp> +#include <errno.h> +#include <mlibc/all-sysdeps.hpp> +#include <bits/ensure.h> +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_thread_trampoline(void *(*fn)(void *), Tcb *tcb, void *arg) { + while (__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED) == 0) { + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + } + + tcb->invokeThreadFunc(reinterpret_cast<void *>(fn), arg); + + __atomic_store_n(&tcb->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&tcb->didExit); + + mlibc::sys_thread_exit(); +} + +#define DEFAULT_STACK 0x20000 + +namespace mlibc { + int sys_prepare_stack(void **stack, void *entry, void *arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + // TODO guard + + mlibc::infoLogger() << "mlibc: sys_prepare_stack() does not setup a guard!" << frg::endlog; + + *guard_size = 0; + + *stack_size = *stack_size ? *stack_size : DEFAULT_STACK; + + if (!*stack) { + *stack_base = mmap(NULL, *stack_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (*stack_base == MAP_FAILED) { + return errno; + } + } else { + *stack_base = *stack; + } + + *stack = (void *)((char *)*stack_base + *stack_size); + + void **stack_it = (void **)*stack; + + *--stack_it = arg; + *--stack_it = tcb; + *--stack_it = entry; + + *stack = (void *)stack_it; + + return 0; + } +} diff --git a/lib/mlibc/sysdeps/ironclad/generic/utmpx.cpp b/lib/mlibc/sysdeps/ironclad/generic/utmpx.cpp new file mode 100644 index 0000000..ec74e22 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/generic/utmpx.cpp @@ -0,0 +1,76 @@ +#include <bits/ensure.h> +#include <stddef.h> +#include <errno.h> +#include <utmpx.h> +#include <stdio.h> +#include <time.h> +#include <paths.h> +#include <unistd.h> +#include <fcntl.h> + +int utmpx_file = -1; + +void updwtmpx(const char *, const struct utmpx *) { + // Empty as musl does +} + +void endutxent(void) { + if (utmpx_file >= 0) { + close(utmpx_file); + } +} + +void setutxent(void) { + if (utmpx_file < 0) { + utmpx_file = open(UTMPX_FILE, O_RDWR | O_CREAT, 0755); + } else { + lseek(utmpx_file, 0, SEEK_SET); + } +} + +struct utmpx returned; + +struct utmpx *getutxent(void) { + if (utmpx_file < 0) { + setutxent(); + if (utmpx_file < 0) { + return NULL; + } + } + + if (read(utmpx_file, &returned, sizeof(struct utmpx)) != sizeof(struct utmpx)) { + return NULL; + } + + return &returned; +} + +struct utmpx *pututxline(const struct utmpx *added) { + if (utmpx_file < 0) { + setutxent(); + if (utmpx_file < 0) { + return NULL; + } + } + + lseek(utmpx_file, 0, SEEK_END); + if (write(utmpx_file, added, sizeof(struct utmpx)) != sizeof(struct utmpx)) { + return NULL; + } + + return (struct utmpx *)added; +} + +int utmpxname(const char *path) { + if (utmpx_file > 0) { + close(utmpx_file); + } + + utmpx_file = open(path, O_RDWR | O_CREAT, 0755); + if (utmpx_file > 0) { + lseek(utmpx_file, 0, SEEK_END); + return 1; + } else { + return 0; + } +} diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/access.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/access.h new file mode 120000 index 0000000..8f0556a --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/ironclad/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/auxv.h new file mode 120000 index 0000000..f9be899 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/ironclad/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..02c7cf3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..1745393 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..b05d507 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/dev_t.h new file mode 120000 index 0000000..e403f5b --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/epoll.h new file mode 120000 index 0000000..0364554 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/ironclad/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/errno.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/errno.h new file mode 120000 index 0000000..ec9b8f6 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/ironclad/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fcntl.h new file mode 120000 index 0000000..c60789c --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/ironclad/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..c5e0d6a --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..b8925b8 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/gid_t.h new file mode 120000 index 0000000..1ee9676 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/in.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/in.h new file mode 120000 index 0000000..e10e010 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/ironclad/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ino_t.h new file mode 120000 index 0000000..8da8d60 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/inotify.h new file mode 120000 index 0000000..95578b0 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/ironclad/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ioctls.h new file mode 120000 index 0000000..d532c47 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/ironclad/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/limits.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/limits.h new file mode 120000 index 0000000..9f4938c --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/ironclad/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/mode_t.h new file mode 120000 index 0000000..47764b7 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/mqueue.h new file mode 120000 index 0000000..394c37d --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/ironclad/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/msg.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/msg.h new file mode 120000 index 0000000..7c59866 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/ironclad/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..a5c8e25 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/packet.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/packet.h new file mode 120000 index 0000000..5a7a333 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/ironclad/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/pid_t.h new file mode 120000 index 0000000..36e4068 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/poll.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/poll.h new file mode 120000 index 0000000..156ddd9 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/ironclad/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ptrace.h new file mode 120000 index 0000000..1260bf7 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/ironclad/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/reboot.h new file mode 120000 index 0000000..23c9af3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/ironclad/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/resource.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/resource.h new file mode 120000 index 0000000..e950420 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/ironclad/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..fbd0a8f --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/ironclad/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/shm.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/shm.h new file mode 120000 index 0000000..f20c4fc --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/ironclad/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/signal.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/signal.h new file mode 120000 index 0000000..ae8aa10 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/ironclad/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/socket.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/socket.h new file mode 120000 index 0000000..5ddea1c --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/ironclad/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..7db34a4 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/stat.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/stat.h new file mode 120000 index 0000000..a307c32 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/ironclad/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/statfs.h new file mode 120000 index 0000000..bc1f622 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/ironclad/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/statvfs.h new file mode 120000 index 0000000..e0b90f0 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/ironclad/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..88197dd --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/termios.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/termios.h new file mode 120000 index 0000000..a6bacb3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/ironclad/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/time.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/time.h new file mode 120000 index 0000000..fa8e486 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/ironclad/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/uid_t.h new file mode 120000 index 0000000..1aebbe3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/ironclad/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/utsname.h new file mode 120000 index 0000000..0a5dbc8 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/ironclad/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..6dc4788 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/ironclad/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/wait.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/wait.h new file mode 120000 index 0000000..a87457d --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/ironclad/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/ironclad/include/abi-bits/xattr.h new file mode 120000 index 0000000..99e5aa3 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/ironclad/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/ironclad/include/asm/ioctls.h b/lib/mlibc/sysdeps/ironclad/include/asm/ioctls.h new file mode 100644 index 0000000..aa9f0b4 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/asm/ioctls.h @@ -0,0 +1,102 @@ +#ifndef _ASM_IOCTLS_H +#define _ASM_IOCTLS_H + +// List of all the IOCTLs supported, for further explanation on the meanings +// please refer to documentation. If you did not get any, good luck! +// Some IOCTL codes may be the same, in which case the device they are used in +// gives them meaning. Cross-device IOCTLs have more distinct values. + +#define PS2MOUSE_2_1_SCALING 1 +#define PS2MOUSE_1_1_SCALING 2 +#define PS2MOUSE_SET_RES 3 +#define PS2MOUSE_SET_SAMPLE_RATE 4 +#define RTC_RD_TIME 1 +#define RTC_SET_TIME 2 +#define FIOQSIZE 0x5460 +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 +#define TIOCSBRK 0x5427 +#define TIOCCBRK 0x5428 +#define TIOCGSID 0x5429 +#define TCGETS2 3 +#define TCSETS2 3 +#define TCSETSW2 3 +#define TCSETSF2 3 +#define TIOCGRS485 0x542E +#define TIOCSRS485 0x542F +#define TIOCGPTN 3 +#define TIOCSPTLCK 3 +#define TIOCGDEV 3 +#define TCGETX 0x5432 +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 +#define TIOCSIG 0x36 +#define TIOCVHANGUP 0x5437 +#define TIOCGPKT 3 +#define TIOCGPTLCK 3 +#define TIOCGEXCL 3 +#define TIOCGPTPEER 3 +#define TIOCGISO7816 3 +#define TIOCSISO7816 3 +#define FIONCLEX 0x5450 +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 +#define TIOCSERGETLSR 0x5459 +#define TIOCSERGETMULTI 0x545A +#define TIOCSERSETMULTI 0x545B +#define TIOCMIWAIT 0x545C +#define TIOCGICOUNT 0x545D +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 +#define TIOCSER_TEMT 0x01 + +#endif /* _ASM_IOCTLS_H */ diff --git a/lib/mlibc/sysdeps/ironclad/include/linux/fb.h b/lib/mlibc/sysdeps/ironclad/include/linux/fb.h new file mode 100644 index 0000000..563ce82 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/linux/fb.h @@ -0,0 +1,397 @@ +#ifndef _SYS_FB_H +#define _SYS_FB_H + +#include <stddef.h> + +/* Definitions of frame buffers */ + +#define FB_MAX 32 /* sufficient for now */ + +/* ioctls + 0x46 is 'F' */ +#define FBIOGET_VSCREENINFO 0x4600 +#define FBIOPUT_VSCREENINFO 0x4601 +#define FBIOGET_FSCREENINFO 0x4602 +#define FBIOGETCMAP 0x4604 +#define FBIOPUTCMAP 0x4605 +#define FBIOPAN_DISPLAY 0x4606 +#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) +/* 0x4607-0x460B are defined below */ +/* #define FBIOGET_MONITORSPEC 0x460C */ +/* #define FBIOPUT_MONITORSPEC 0x460D */ +/* #define FBIOSWITCH_MONIBIT 0x460E */ +#define FBIOGET_CON2FBMAP 0x460F +#define FBIOPUT_CON2FBMAP 0x4610 +#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */ +#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank) +#define FBIO_ALLOC 0x4613 +#define FBIO_FREE 0x4614 +#define FBIOGET_GLYPH 0x4615 +#define FBIOGET_HWCINFO 0x4616 +#define FBIOPUT_MODEINFO 0x4617 +#define FBIOGET_DISPINFO 0x4618 + +#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ +#define FB_TYPE_PLANES 1 /* Non interleaved planes */ +#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ +#define FB_TYPE_TEXT 3 /* Text/attributes */ +#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ +#define FB_TYPE_FOURCC 5 /* Type identified by a V4L2 FOURCC */ + +#define FB_AUX_TEXT_MDA 0 /* Monochrome text */ +#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ +#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ +#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ +#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */ +#define FB_AUX_TEXT_SVGA_GROUP 8 /* 8-15: SVGA tileblit compatible modes */ +#define FB_AUX_TEXT_SVGA_MASK 7 /* lower three bits says step */ +#define FB_AUX_TEXT_SVGA_STEP2 8 /* SVGA text mode: text, attr */ +#define FB_AUX_TEXT_SVGA_STEP4 9 /* SVGA text mode: text, attr, 2 reserved bytes */ +#define FB_AUX_TEXT_SVGA_STEP8 10 /* SVGA text mode: text, attr, 6 reserved bytes */ +#define FB_AUX_TEXT_SVGA_STEP16 11 /* SVGA text mode: text, attr, 14 reserved bytes */ +#define FB_AUX_TEXT_SVGA_LAST 15 /* reserved up to 15 */ + +#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */ +#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */ +#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */ + +#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */ +#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */ +#define FB_VISUAL_TRUECOLOR 2 /* True color */ +#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ +#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ +#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ +#define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */ + +#define FB_ACCEL_NONE 0 /* no hardware accelerator */ +#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ +#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ +#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */ +#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */ +#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */ +#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */ +#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */ +#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */ +#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */ +#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */ +#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */ +#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */ +#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */ +#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */ +#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */ +#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */ +#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ +#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */ +#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */ +#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */ +#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */ +#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */ +#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */ +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */ +#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */ +#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */ +#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */ +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */ +#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */ +#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */ +#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */ +#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */ +#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */ +#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon family */ +#define FB_ACCEL_I810 39 /* Intel 810/815 */ +#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */ +#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */ +#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */ +#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */ +#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */ +#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */ +#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */ +#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */ +#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */ +#define FB_ACCEL_OMAP1610 49 /* TI OMAP16xx */ +#define FB_ACCEL_TRIDENT_TGUI 50 /* Trident TGUI */ +#define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */ +#define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */ +#define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */ +#define FB_ACCEL_CIRRUS_ALPINE 53 /* Cirrus Logic 543x/544x/5480 */ +#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ +#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ +#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ +#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */ +#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */ +#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */ +#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */ +#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */ +#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */ +#define FB_ACCEL_PXA3XX 99 /* PXA3xx */ + +#define FB_ACCEL_SAVAGE4 0x80 /* S3 Savage4 */ +#define FB_ACCEL_SAVAGE3D 0x81 /* S3 Savage3D */ +#define FB_ACCEL_SAVAGE3D_MV 0x82 /* S3 Savage3D-MV */ +#define FB_ACCEL_SAVAGE2000 0x83 /* S3 Savage2000 */ +#define FB_ACCEL_SAVAGE_MX_MV 0x84 /* S3 Savage/MX-MV */ +#define FB_ACCEL_SAVAGE_MX 0x85 /* S3 Savage/MX */ +#define FB_ACCEL_SAVAGE_IX_MV 0x86 /* S3 Savage/IX-MV */ +#define FB_ACCEL_SAVAGE_IX 0x87 /* S3 Savage/IX */ +#define FB_ACCEL_PROSAVAGE_PM 0x88 /* S3 ProSavage PM133 */ +#define FB_ACCEL_PROSAVAGE_KM 0x89 /* S3 ProSavage KM133 */ +#define FB_ACCEL_S3TWISTER_P 0x8a /* S3 Twister */ +#define FB_ACCEL_S3TWISTER_K 0x8b /* S3 TwisterK */ +#define FB_ACCEL_SUPERSAVAGE 0x8c /* S3 Supersavage */ +#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */ +#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */ + +#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */ + +#define FB_CAP_FOURCC 1 /* Device supports FOURCC-based formats */ + +struct fb_fix_screeninfo { + char id[16]; /* identification string eg "TT Builtin" */ + unsigned long smem_start; /* Start of frame buffer mem */ + /* (physical address) */ + uint32_t smem_len; /* Length of frame buffer mem */ + uint32_t type; /* see FB_TYPE_* */ + uint32_t type_aux; /* Interleave for interleaved Planes */ + uint32_t visual; /* see FB_VISUAL_* */ + uint16_t xpanstep; /* zero if no hardware panning */ + uint16_t ypanstep; /* zero if no hardware panning */ + uint16_t ywrapstep; /* zero if no hardware ywrap */ + uint32_t line_length; /* length of a line in bytes */ + unsigned long mmio_start; /* Start of Memory Mapped I/O */ + /* (physical address) */ + uint32_t mmio_len; /* Length of Memory Mapped I/O */ + uint32_t accel; /* Indicate to driver which */ + /* specific chip/card we have */ + uint16_t capabilities; /* see FB_CAP_* */ + uint16_t reserved[2]; /* Reserved for future compatibility */ +}; + +/* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. + * + * For pseudocolor: offset and length should be the same for all color + * components. Offset specifies the position of the least significant bit + * of the palette index in a pixel value. Length indicates the number + * of available palette entries (i.e. # of entries = 1 << length). + */ +struct fb_bitfield { + uint32_t offset; /* beginning of bitfield */ + uint32_t length; /* length of bitfield */ + uint32_t msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */ +#define FB_NONSTD_REV_PIX_IN_B 2 /* order of pixels in each byte is reversed */ + +#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/ +#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */ +#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */ +#define FB_ACTIVATE_MASK 15 + /* values */ +#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */ +#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */ +#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */ +#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ +#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */ +#define FB_ACTIVATE_KD_TEXT 512 /* for KDSET vt ioctl */ + +#define FB_ACCELF_TEXT 1 /* (OBSOLETE) see fb_info.flags and vc_mode */ + +#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define FB_SYNC_EXT 4 /* external sync */ +#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define FB_SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ +#define FB_SYNC_ON_GREEN 32 /* sync on green */ + +#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ +#define FB_VMODE_INTERLACED 1 /* interlaced */ +#define FB_VMODE_DOUBLE 2 /* double scan */ +#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */ +#define FB_VMODE_MASK 255 + +#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */ +#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +/* + * Display rotation support + */ +#define FB_ROTATE_UR 0 +#define FB_ROTATE_CW 1 +#define FB_ROTATE_UD 2 +#define FB_ROTATE_CCW 3 + +#define PICOS2KHZ(a) (1000000000UL/(a)) +#define KHZ2PICOS(a) (1000000000UL/(a)) + +struct fb_var_screeninfo { + uint32_t xres; /* visible resolution */ + uint32_t yres; + uint32_t xres_virtual; /* virtual resolution */ + uint32_t yres_virtual; + uint32_t xoffset; /* offset from virtual to visible */ + uint32_t yoffset; /* resolution */ + + uint32_t bits_per_pixel; /* guess what */ + uint32_t grayscale; /* 0 = color, 1 = grayscale, */ + /* >1 = FOURCC */ + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + uint32_t nonstd; /* != 0 Non standard pixel format */ + + uint32_t activate; /* see FB_ACTIVATE_* */ + + uint32_t height; /* height of picture in mm */ + uint32_t width; /* width of picture in mm */ + + uint32_t accel_flags; /* (OBSOLETE) see fb_info.flags */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + uint32_t pixclock; /* pixel clock in ps (pico seconds) */ + uint32_t left_margin; /* time from sync to picture */ + uint32_t right_margin; /* time from picture to sync */ + uint32_t upper_margin; /* time from sync to picture */ + uint32_t lower_margin; + uint32_t hsync_len; /* length of horizontal sync */ + uint32_t vsync_len; /* length of vertical sync */ + uint32_t sync; /* see FB_SYNC_* */ + uint32_t vmode; /* see FB_VMODE_* */ + uint32_t rotate; /* angle we rotate counter clockwise */ + uint32_t colorspace; /* colorspace for FOURCC-based modes */ + uint32_t reserved[4]; /* Reserved for future compatibility */ +}; + +struct fb_cmap { + uint32_t start; /* First entry */ + uint32_t len; /* Number of entries */ + uint16_t *red; /* Red values */ + uint16_t *green; + uint16_t *blue; + uint16_t *transp; /* transparency, can be NULL */ +}; + +struct fb_con2fbmap { + uint32_t console; + uint32_t framebuffer; +}; + +/* VESA Blanking Levels */ +#define VESA_NO_BLANKING 0 +#define VESA_VSYNC_SUSPEND 1 +#define VESA_HSYNC_SUSPEND 2 +#define VESA_POWERDOWN 3 + + +enum { + /* screen: unblanked, hsync: on, vsync: on */ + FB_BLANK_UNBLANK = VESA_NO_BLANKING, + + /* screen: blanked, hsync: on, vsync: on */ + FB_BLANK_NORMAL = VESA_NO_BLANKING + 1, + + /* screen: blanked, hsync: on, vsync: off */ + FB_BLANK_VSYNC_SUSPEND = VESA_VSYNC_SUSPEND + 1, + + /* screen: blanked, hsync: off, vsync: on */ + FB_BLANK_HSYNC_SUSPEND = VESA_HSYNC_SUSPEND + 1, + + /* screen: blanked, hsync: off, vsync: off */ + FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1 +}; + +#define FB_VBLANK_VBLANKING 0x001 /* currently in a vertical blank */ +#define FB_VBLANK_HBLANKING 0x002 /* currently in a horizontal blank */ +#define FB_VBLANK_HAVE_VBLANK 0x004 /* vertical blanks can be detected */ +#define FB_VBLANK_HAVE_HBLANK 0x008 /* horizontal blanks can be detected */ +#define FB_VBLANK_HAVE_COUNT 0x010 /* global retrace counter is available */ +#define FB_VBLANK_HAVE_VCOUNT 0x020 /* the vcount field is valid */ +#define FB_VBLANK_HAVE_HCOUNT 0x040 /* the hcount field is valid */ +#define FB_VBLANK_VSYNCING 0x080 /* currently in a vsync */ +#define FB_VBLANK_HAVE_VSYNC 0x100 /* verical syncs can be detected */ + +struct fb_vblank { + uint32_t flags; /* FB_VBLANK flags */ + uint32_t count; /* counter of retraces since boot */ + uint32_t vcount; /* current scanline position */ + uint32_t hcount; /* current scandot position */ + uint32_t reserved[4]; /* reserved for future compatibility */ +}; + +/* Internal HW accel */ +#define ROP_COPY 0 +#define ROP_XOR 1 + +struct fb_copyarea { + uint32_t dx; + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t sx; + uint32_t sy; +}; + +struct fb_fillrect { + uint32_t dx; /* screen-relative */ + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t color; + uint32_t rop; +}; + +struct fb_image { + uint32_t dx; /* Where to place image */ + uint32_t dy; + uint32_t width; /* Size of image */ + uint32_t height; + uint32_t fg_color; /* Only used when a mono bitmap */ + uint32_t bg_color; + uint8_t depth; /* Depth of the image */ + const char *data; /* Pointer to image data */ + struct fb_cmap cmap; /* color map info */ +}; + +/* + * hardware cursor control + */ + +#define FB_CUR_SETIMAGE 0x01 +#define FB_CUR_SETPOS 0x02 +#define FB_CUR_SETHOT 0x04 +#define FB_CUR_SETCMAP 0x08 +#define FB_CUR_SETSHAPE 0x10 +#define FB_CUR_SETSIZE 0x20 +#define FB_CUR_SETALL 0xFF + +struct fbcurpos { + uint16_t x, y; +}; + +struct fb_cursor { + uint16_t set; /* what to set */ + uint16_t enable; /* cursor on/off */ + uint16_t rop; /* bitop operation */ + const char *mask; /* cursor mask bits */ + struct fbcurpos hot; /* cursor hot spot */ + struct fb_image image; /* Cursor image */ +}; + +/* Settings for the generic backlight code */ +#define FB_BACKLIGHT_LEVELS 128 +#define FB_BACKLIGHT_MAX 0xFF + + +#endif /* _SYS_FB_H */ diff --git a/lib/mlibc/sysdeps/ironclad/include/mntent.h b/lib/mlibc/sysdeps/ironclad/include/mntent.h new file mode 100644 index 0000000..e5e49e7 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/mntent.h @@ -0,0 +1,46 @@ +#ifndef _MNTENT_H +#define _MNTENT_H + +#include <stdio.h> + +// TODO: Refer to _PATH_MOUNTED +#define MOUNTED "/etc/mtab" + +/* Generic mount options */ +#define MNTOPT_DEFAULTS "defaults" /* Use all default options. */ +#define MNTOPT_RO "ro" /* Read only. */ +#define MNTOPT_RW "rw" /* Read/write. */ +#define MNTOPT_SUID "suid" /* Set uid allowed. */ +#define MNTOPT_NOSUID "nosuid" /* No set uid allowed. */ +#define MNTOPT_NOAUTO "noauto" /* Do not auto mount. */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct mntent { + char *mnt_fsname; + char *mnt_dir; + char *mnt_type; + char *mnt_opts; + int mnt_freq; + int mnt_passno; +}; + +FILE *setmntent(const char *, const char *); + +struct mntent *getmntent(FILE *); + +int addmntent(FILE *, const struct mntent *); + +int endmntent(FILE *); + +char *hasmntopt(const struct mntent *, const char *); + +struct mntent *getmntent_r(FILE *, struct mntent *, char *, int); + +#ifdef __cplusplus +} +#endif + +#endif // _MNTENT_H diff --git a/lib/mlibc/sysdeps/ironclad/include/pty.h b/lib/mlibc/sysdeps/ironclad/include/pty.h new file mode 100644 index 0000000..0468b46 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/pty.h @@ -0,0 +1,16 @@ +#ifndef _PTY_H +#define _PTY_H + +#include <termios.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int openpty(int *mfd, int *sfd, char *name, const struct termios *ios, const struct winsize *win); + +#ifdef __cplusplus +} +#endif + +#endif // _PTY_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/ironclad_devices.h b/lib/mlibc/sysdeps/ironclad/include/sys/ironclad_devices.h new file mode 100644 index 0000000..74f47f8 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/ironclad_devices.h @@ -0,0 +1,44 @@ +#ifndef _SYS_IRONCLAD_DEVICES_H +#define _SYS_IRONCLAD_DEVICES_H + +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> +#include <asm/ioctls.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define PS2MOUSE_2_1_SCALING 1 +#define PS2MOUSE_1_1_SCALING 2 +#define PS2MOUSE_SET_RES 3 +#define PS2MOUSE_SET_SAMPLE_RATE 4 + +struct ironclad_mouse_data { + int x_variation; + int y_variation; + bool is_left; + bool is_right; +}; + +#define RTC_RD_TIME 1 +#define RTC_SET_TIME 2 + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; /* unused */ + int tm_yday; /* unused */ + int tm_isdst; /* unused */ +}; + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_IRONCLAD_DEVICES_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/mac.h b/lib/mlibc/sysdeps/ironclad/include/sys/mac.h new file mode 100644 index 0000000..d4cf76d --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/mac.h @@ -0,0 +1,46 @@ +#ifndef _SYS_MAC_H +#define _SYS_MAC_H + +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAC_CAP_SCHED 0b00000000001 +#define MAC_CAP_SPAWN 0b00000000010 +#define MAC_CAP_ENTROPY 0b00000000100 +#define MAC_CAP_SYS_MEM 0b00000001000 +#define MAC_CAP_USE_NET 0b00000010000 +#define MAC_CAP_SYS_NET 0b00000100000 +#define MAC_CAP_SYS_MNT 0b00001000000 +#define MAC_CAP_SYS_PWR 0b00010000000 +#define MAC_CAP_PTRACE 0b00100000000 +#define MAC_CAP_SETUID 0b01000000000 +#define MAC_CAP_SYS_MAC 0b10000000000 +#define MAC_CAP_CLOCK 0b100000000000 +#define MAC_CAP_SIGNALALL 0b1000000000000 +unsigned long get_mac_capabilities(void); +int set_mac_capabilities(unsigned long request); + +#define MAC_PERM_CONTENTS 0b0000001 +#define MAC_PERM_READ 0b0000010 +#define MAC_PERM_WRITE 0b0000100 +#define MAC_PERM_EXEC 0b0001000 +#define MAC_PERM_APPEND 0b0010000 +#define MAC_PERM_FLOCK 0b0100000 +#define MAC_PERM_DEV 0b1000000 +int add_mac_permissions(const char *path, int flags); + +#define MAC_DENY 0b001 +#define MAC_DENY_AND_SCREAM 0b010 +#define MAC_KILL 0b100 +int set_mac_enforcement(unsigned long enforcement); + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_MAC_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/mount.h b/lib/mlibc/sysdeps/ironclad/include/sys/mount.h new file mode 100644 index 0000000..51263fa --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/mount.h @@ -0,0 +1,24 @@ +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MNT_EXT 1 +#define MNT_FAT 2 + +#define MS_RDONLY 0b001 +#define MS_REMOUNT 0b010 +#define MS_RELATIME 0b100 + +#define MNT_FORCE 1 + +int mount(const char *source, const char *target, int type, int flags); +int umount(const char *target, int flags); + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_MOUNT_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/ptrace.h b/lib/mlibc/sysdeps/ironclad/include/sys/ptrace.h new file mode 100644 index 0000000..3993753 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/ptrace.h @@ -0,0 +1,23 @@ +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H + +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define PTRACE_ATTACH 1 +#define PTRACE_DETACH 2 +#define PTRACE_CONT 3 +#define PTRACE_SYSCALL 4 +#define PTRACE_GETREGS 5 +int ptrace(int request, pid_t pid, void *addr, void *data); + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_PTRACE_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/reboot.h b/lib/mlibc/sysdeps/ironclad/include/sys/reboot.h new file mode 100644 index 0000000..c2dbbf2 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/reboot.h @@ -0,0 +1,16 @@ +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H + +#include <abi-bits/reboot.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int reboot(int arg); + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_REBOOT_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/sched2.h b/lib/mlibc/sysdeps/ironclad/include/sys/sched2.h new file mode 100644 index 0000000..caeb86a --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/sched2.h @@ -0,0 +1,24 @@ +#ifndef _SYS_SCHED2_H +#define _SYS_SCHED2_H + +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define THREAD_RT 0b0001 +#define THREAD_MONO 0b0010 +#define THREAD_MLOCK 0b0100 +#define THREAD_BANNED 0b1000 +int get_thread_sched(void); +int set_thread_sched(int flags); +int set_deadlines(int runtime, int period); + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_SCHED2_H diff --git a/lib/mlibc/sysdeps/ironclad/include/sys/syscall.h b/lib/mlibc/sysdeps/ironclad/include/sys/syscall.h new file mode 100644 index 0000000..01ab016 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/sys/syscall.h @@ -0,0 +1,187 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include <stddef.h> + +#define SYSCALL0(NUM) ({ \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL1(NUM, ARG0) ({ \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL2(NUM, ARG0, ARG1) ({ \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL3(NUM, ARG0, ARG1, ARG2) ({ \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL4(NUM, ARG0, ARG1, ARG2, ARG3) ({ \ + register __typeof(ARG3) arg_r12 asm("r12") = ARG3; \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2), \ + "r"(arg_r12) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL5(NUM, ARG0, ARG1, ARG2, ARG3, ARG4) ({ \ + register __typeof(ARG3) arg_r12 asm("r12") = ARG3; \ + register __typeof(ARG4) arg_r8 asm("r8") = ARG4; \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2), \ + "r"(arg_r12), "r"(arg_r8) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL6(NUM, ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \ + register __typeof(ARG3) arg_r12 asm("r12") = ARG3; \ + register __typeof(ARG4) arg_r8 asm("r8") = ARG4; \ + register __typeof(ARG5) arg_r9 asm("r9") = ARG5; \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2), \ + "r"(arg_r12), "r"(arg_r8), "r"(arg_r9) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL6(NUM, ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \ + register __typeof(ARG3) arg_r12 asm("r12") = ARG3; \ + register __typeof(ARG4) arg_r8 asm("r8") = ARG4; \ + register __typeof(ARG5) arg_r9 asm("r9") = ARG5; \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2), \ + "r"(arg_r12), "r"(arg_r8), "r"(arg_r9) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL7(NUM, ARG0, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) ({ \ + register __typeof(ARG3) arg_r12 asm("r12") = ARG3; \ + register __typeof(ARG4) arg_r8 asm("r8") = ARG4; \ + register __typeof(ARG5) arg_r9 asm("r9") = ARG5; \ + register __typeof(ARG6) arg_r10 asm("r10") = ARG6; \ + asm volatile ("syscall" \ + : "=a"(ret), "=d"(errno) \ + : "a"(NUM), "D"(ARG0), "S"(ARG1), "d"(ARG2), \ + "r"(arg_r12), "r"(arg_r8), "r"(arg_r9), "r"(arg_r10) \ + : "rcx", "r11", "memory"); \ +}) + +#define SYSCALL_EXIT 0 +#define SYSCALL_ARCH_PRCTL 1 +#define SYSCALL_OPEN 2 +#define SYSCALL_CLOSE 3 +#define SYSCALL_READ 4 +#define SYSCALL_WRITE 5 +#define SYSCALL_SEEK 6 +#define SYSCALL_MMAP 7 +#define SYSCALL_MUNMAP 8 +#define SYSCALL_GETPID 9 +#define SYSCALL_GETPPID 10 +#define SYSCALL_EXEC 11 +#define SYSCALL_CLONE 12 +#define SYSCALL_WAIT 13 +#define SYSCALL_SOCKET 14 +#define SYSCALL_SETHOSTNAME 15 +#define SYSCALL_UNLINK 16 +#define SYSCALL_STAT 17 +#define SYSCALL_GETCWD 18 +#define SYSCALL_CHDIR 19 +#define SYSCALL_IOCTL 20 +#define SYSCALL_SCHED_YIELD 21 +#define SYSCALL_DELETE_TCLUSTER 22 +#define SYSCALL_PIPE 23 +#define SYSCALL_GETUID 24 +#define SYSCALL_RENAME 25 +#define SYSCALL_SYSCONF 26 +#define SYSCALL_SPAWN 27 +#define SYSCALL_GETTID 28 +#define SYSCALL_MANAGE_TCLUSTER 29 +#define SYSCALL_FCNTL 30 +#define SYSCALL_EXIT_THREAD 31 +#define SYSCALL_GETRANDOM 32 +#define SYSCALL_MPROTECT 33 +#define SYSCALL_SYNC 34 +#define SYSCALL_SET_MAC_CAPABILITIES 35 +#define SYSCALL_GET_MAC_CAPABILITIES 36 +#define SYSCALL_ADD_MAC_PERMISSIONS 37 +#define SYSCALL_SET_MAC_ENFORCEMENT 38 +#define SYSCALL_MOUNT 39 +#define SYSCALL_UMOUNT 40 +#define SYSCALL_READLINK 41 +#define SYSCALL_GETDENTS 42 +#define SYSCALL_MAKENODE 43 +#define SYSCALL_TRUNCATE 44 +#define SYSCALL_BIND 45 +#define SYSCALL_SYMLINK 46 +#define SYSCALL_CONNECT 47 +#define SYSCALL_OPENPTY 48 +#define SYSCALL_FSYNC 49 +#define SYSCALL_LINK 50 +#define SYSCALL_PTRACE 51 +#define SYSCALL_LISTEN 52 +#define SYSCALL_ACCEPT 53 +#define SYSCALL_GETRLIMIT 54 +#define SYSCALL_SETRLIMIT 55 +#define SYSCALL_ACCESS 56 +#define SYSCALL_POLL 57 +#define SYSCALL_GETEUID 58 +#define SYSCALL_SETUIDS 59 +#define SYSCALL_FCHMOD 60 +#define SYSCALL_UMASK 61 +#define SYSCALL_REBOOT 62 +#define SYSCALL_FCHOWN 63 +#define SYSCALL_PREAD 64 +#define SYSCALL_PWRITE 65 +#define SYSCALL_GETSOCKNAME 66 +#define SYSCALL_GETPEERNAME 67 +#define SYSCALL_SHUTDOWN 68 +#define SYSCALL_FUTEX 69 +#define SYSCALL_CLOCK 70 +#define SYSCALL_CLOCK_NANOSLEEP 71 +#define SYSCALL_GETRUSAGE 72 +#define SYSCALL_RECVFROM 73 +#define SYSCALL_SENDTO 74 +#define SYSCALL_CONFIG_NETINTER 75 +#define SYSCALL_UTIMES 76 +#define SYSCALL_CREATE_TCLUSTER 77 +#define SYSCALL_SWITCH_TCLUSTER 78 +#define SYSCALL_ACTUALLY_KILL 79 +#define SYSCALL_SIGNALPOST 80 +#define SYSCALL_SEND_SIGNAL 81 +#define SYSCALL_GETPRIO 82 +#define SYSCALL_SETPRIO 83 +#define SYSCALL_GETGID 84 +#define SYSCALL_GETEGID 85 +#define SYSCALL_SETGIDS 86 +#define SYSCALL_GETGROUPS 87 +#define SYSCALL_SETGROUPS 88 +#define SYSCALL_TTYNAME 89 +#define SYSCALL_FADVISE 90 +#define SYSCALL_SHMAT 91 +#define SYSCALL_SHMCTL 92 +#define SYSCALL_SHMDT 93 +#define SYSCALL_SHMGET 94 +#define SYSCALL_GETSOCKOPT 95 +#define SYSCALL_SETSOCKOPT 96 +#define SYSCALL_GETTIDID 97 +#define SYSCALL_SETTIDID 98 + +#endif // _SYS_SYSCALL_H diff --git a/lib/mlibc/sysdeps/ironclad/include/utmpx.h b/lib/mlibc/sysdeps/ironclad/include/utmpx.h new file mode 100644 index 0000000..2d7d3e1 --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/include/utmpx.h @@ -0,0 +1,63 @@ + +#ifndef _UTMPX_H +#define _UTMPX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <abi-bits/pid_t.h> +#include <bits/posix/timeval.h> + +#define UTMPX_FILE "/var/run/utmp" +#define WTMPX_FILE "/var/run/wtmp" + +// Struct definition taken from musl +struct utmpx { + short ut_type; + short __ut_pad1; + pid_t ut_pid; + char ut_line[32]; + char ut_id[4]; + char ut_user[32]; + char ut_host[256]; + struct { + short __e_termination; + short __e_exit; + } ut_exit; + int ut_session, __ut_pad2; + struct timeval ut_tv; + unsigned ut_addr_v6[4]; + char __unused[20]; +}; + +#ifndef __MLIBC_ABI_ONLY + +void updwtmpx(const char *, const struct utmpx *); +int utmpxname(const char *); +struct utmpx *pututxline(const struct utmpx *); +struct utmpx *getutxent(void); +void setutxent(void); +void endutxent(void); + +#endif /* !__MLIBC_ABI_ONLY */ + +#define EMPTY 0 +#define RUN_LVL 1 +#define BOOT_TIME 2 +#define NEW_TIME 3 +#define OLD_TIME 4 +#define INIT_PROCESS 5 +#define LOGIN_PROCESS 6 +#define USER_PROCESS 7 +#define DEAD_PROCESS 8 + +#define __UT_HOSTSIZE 256 +#define __UT_NAMESIZE 32 +#define __UT_LINESIZE 32 + +#ifdef __cplusplus +} +#endif + +#endif // _UTMPX_H diff --git a/lib/mlibc/sysdeps/ironclad/meson.build b/lib/mlibc/sysdeps/ironclad/meson.build new file mode 100644 index 0000000..a23203c --- /dev/null +++ b/lib/mlibc/sysdeps/ironclad/meson.build @@ -0,0 +1,125 @@ + +rtdl_sources += files( + 'generic/generic.cpp' +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/ptrace.cpp', + 'generic/generic.cpp', + 'generic/mntent.cpp', + 'generic/mount.cpp', + 'generic/reboot.cpp', + 'generic/pty.cpp', + 'generic/thread.cpp', + 'generic/mac.cpp', + 'generic/sched2.cpp', + 'generic/thread.S', + 'generic/utmpx.cpp' +) + +if not no_headers + install_headers( + 'include/abi-bits/access.h', + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/reboot.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + install_headers( + 'include/sys/sched2.h', + 'include/sys/ironclad_devices.h', + 'include/sys/mac.h', + 'include/sys/syscall.h', + 'include/sys/reboot.h', + 'include/sys/mount.h', + 'include/sys/ptrace.h', + subdir: 'sys' + ) + + install_headers( + 'include/asm/ioctls.h', + subdir: 'asm' + ) + + install_headers( + 'include/linux/fb.h', + subdir: 'linux' + ) + + install_headers( + 'include/mntent.h', + 'include/pty.h', + 'include/utmpx.h' + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crti', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crti.S', + output: 'crti.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crtn', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crtn.S', + output: 'crtn.o', + install: true, + install_dir: get_option('libdir') + ) +endif + diff --git a/lib/mlibc/sysdeps/keyronex/generic/entry.cpp b/lib/mlibc/sysdeps/keyronex/generic/entry.cpp new file mode 100644 index 0000000..ff15c62 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/entry.cpp @@ -0,0 +1,108 @@ +#include <bits/ensure.h> +#include <bits/posix/posix_signal.h> +#include <keyronex/syscall.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/elf/startup.h> +#include <stdint.h> +#include <stdlib.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() +{ + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, + __mlibc_stack_data.argv, __mlibc_stack_data.envp); +} + +namespace mlibc { +int +sys_sigentry(void *sigentry) +{ + uintptr_t ret = syscall1(kPXSysSigEntry, (uintptr_t)sigentry, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +[[noreturn]] int +sys_sigreturn(ucontext_t *context) +{ + syscall1(kPXSysSigReturn, (uintptr_t)context, NULL); + __builtin_unreachable(); +} +} + +static void +do_stacktrace(ucontext_t *ctx) +{ + size_t *base_ptr = (size_t *)ctx->uc_mcontext.gregs[REG_RBP]; + + mlibc::infoLogger() << "Stacktrace:" << frg::endlog; + mlibc::infoLogger() << " [" << (void *)ctx->uc_mcontext.gregs[REG_RIP] + << "]" << frg::endlog; + for (;;) { + size_t old_bp = base_ptr[0]; + size_t ret_addr = base_ptr[1]; + if (!ret_addr) + break; + mlibc::infoLogger() + << " [" << (void *)ret_addr << "]" << frg::endlog; + if (!old_bp) + break; + base_ptr = (size_t *)old_bp; + } +} + +static void +__mlibc_sigentry(int which, siginfo_t *siginfo, void *handler, + bool is_sigaction, ucontext_t *ret_context) +{ + if ((uintptr_t)handler == (uintptr_t)SIG_DFL) { + mlibc::infoLogger() + << "mlibc: Unhandled signal " << which << frg::endlog; + do_stacktrace(ret_context); + mlibc::sys_exit(128 + which); + } else if ((uintptr_t)handler == (uintptr_t)SIG_IGN) { + /* epsilon */ + } else { + if (is_sigaction) + ((void (*)(int, siginfo_t *, void *))handler)(which, + siginfo, ret_context); + else + ((void (*)(int))handler)(which); + } + + mlibc::sys_sigreturn(ret_context); + + __builtin_unreachable(); +} + +extern "C" void +__mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) +{ + /* communicate the signal handler entry point to the kernel */ + mlibc::sys_sigentry((void *)__mlibc_sigentry); + + // TODO: call __dlapi_enter, otherwise static builds will break (see + // Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/keyronex/generic/generic.cpp b/lib/mlibc/sysdeps/keyronex/generic/generic.cpp new file mode 100644 index 0000000..a3e77fb --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/generic.cpp @@ -0,0 +1,753 @@ +#include <asm/ioctls.h> + +#include <bits/ensure.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <frg/logging.hpp> +#include <keyronex/syscall.h> +#include <limits.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> +#include <stdlib.h> + +#define STUB_ONLY \ + { \ + __ensure(!"STUB_ONLY function was called"); \ + __builtin_unreachable(); \ + } + +namespace mlibc { + +void +sys_libc_log(const char *message) +{ + syscall1(kPXSysDebug, (uintptr_t)message, NULL); +} + +void +sys_libc_panic() +{ + sys_libc_log("\nMLIBC PANIC\n"); + for (;;) + ; + STUB_ONLY +} + +void +sys_exit(int status) +{ + syscall1(kPXSysExit, status, NULL); + mlibc::panicLogger() << "sys_exit() returned!" << frg::endlog; + __builtin_unreachable(); +} + +#ifndef MLIBC_BUILDING_RTDL +int +sys_tcgetattr(int fd, struct termios *attr) +{ + int ret; + + if (int r = sys_ioctl(fd, TCGETS, attr, &ret) != 0) { + return r; + } + + return 0; +} + +int +sys_tcsetattr(int fd, int optional_action, const struct termios *attr) +{ + int ret; + + switch (optional_action) { + case TCSANOW: + optional_action = TCSETS; + break; + case TCSADRAIN: + optional_action = TCSETSW; + break; + case TCSAFLUSH: + optional_action = TCSETSF; + break; + default: + __ensure(!"Unsupported tcsetattr"); + } + + if (int r = sys_ioctl(fd, optional_action, (void *)attr, &ret) != 0) { + return r; + } + + return 0; +} +#endif + +int +sys_tcb_set(void *pointer) +{ + return syscall1(kPXSysSetFSBase, (uintptr_t)pointer, NULL); +} + +int +sys_ppoll(struct pollfd *fds, int nfds, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) +{ + uintptr_t ret = syscall4(kPXSysPPoll, (uintptr_t)fds, (uintptr_t)nfds, + (uintptr_t)timeout, (uintptr_t)sigmask, NULL); + if (int e = sc_error(ret); e) + return e; + *num_events = (ssize_t)ret; + return 0; +} + +int +sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) +{ + struct timespec ts; + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + return sys_ppoll(fds, count, timeout < 0 ? NULL : &ts, NULL, + num_events); +} + +#ifndef MLIBC_BUILDING_RTDL +int +sys_pselect(int nfds, fd_set *read_set, fd_set *write_set, fd_set *except_set, + const struct timespec *timeout, const sigset_t *sigmask, int *num_events) +{ + struct pollfd *fds = (struct pollfd *)malloc( + nfds * sizeof(struct pollfd)); + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + memset(fd, 0, sizeof(struct pollfd)); + + if (read_set && FD_ISSET(i, read_set)) + fd->events |= POLLIN; // TODO: Additional events. + if (write_set && FD_ISSET(i, write_set)) + fd->events |= POLLOUT; // TODO: Additional events. + if (except_set && FD_ISSET(i, except_set)) + fd->events |= POLLPRI; + + if (!fd->events) { + fd->fd = -1; + continue; + } + + fd->fd = i; + } + + int e = sys_ppoll(fds, nfds, timeout, sigmask, num_events); + + if (e != 0) { + free(fds); + return e; + } + + fd_set res_read_set; + fd_set res_write_set; + fd_set res_except_set; + FD_ZERO(&res_read_set); + FD_ZERO(&res_write_set); + FD_ZERO(&res_except_set); + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + + if (read_set && FD_ISSET(i, read_set) && + fd->revents & (POLLIN | POLLERR | POLLHUP)) { + FD_SET(i, &res_read_set); + } + + if (write_set && FD_ISSET(i, write_set) && + fd->revents & (POLLOUT | POLLERR | POLLHUP)) { + FD_SET(i, &res_write_set); + } + + if (except_set && FD_ISSET(i, except_set) && + fd->revents & POLLPRI) { + FD_SET(i, &res_except_set); + } + } + + free(fds); + + if (read_set) + memcpy(read_set, &res_read_set, sizeof(fd_set)); + if (write_set) + memcpy(write_set, &res_write_set, sizeof(fd_set)); + if (except_set) + memcpy(except_set, &res_except_set, sizeof(fd_set)); + + return 0; +} +#endif + +int +sys_fcntl(int fd, int request, va_list args, int *result) +{ + auto ret = syscall3(kPXSysFCntl, fd, request, va_arg(args, uint64_t), + NULL); + if (int e = sc_error(ret); e) + return e; + *result = ret; + return 0; +} + +int +sys_futex_wait(int *pointer, int expected, const struct timespec *time) +{ + auto ret = syscall3(kPXSysFutexWait, (uintptr_t)pointer, expected, + (uintptr_t)time, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_futex_wake(int *pointer) +{ + auto ret = syscall1(kPXSysFutexWake, (uintptr_t)pointer, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL +int +sys_ioctl(int fd, unsigned long request, void *arg, int *result) +{ + uintptr_t r = syscall3(kPXSysIOCtl, fd, request, (uintptr_t)arg, NULL); + if (int e = sc_error(r); e) + return e; + *result = r; + return 0; +} +#endif + +int +sys_isatty(int fd) +{ + uintptr_t ret = syscall1(kPXSysIsATTY, fd, NULL); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL +int +sys_getcwd(char *buffer, size_t size) +{ + uintptr_t ret = syscall2(kPXSysGetCWD, (uintptr_t)buffer, size, NULL); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} +#endif + +int +sys_dup(int fd, int flags, int *newfd) +{ + uintptr_t ret = syscall2(kPXSysDup, fd, flags, NULL); + if (int e = sc_error(ret); e) { + return e; + } + *newfd = ret; + return 0; +} + +int +sys_dup2(int fd, int flags, int newfd) +{ + uintptr_t ret = syscall3(kPXSysDup3, fd, newfd, flags, NULL); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +int +sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) +{ + uintptr_t r = syscall4(kPXSysOpenAt, dirfd, (uintptr_t)path, + (uintptr_t)flags, (uintptr_t)mode, NULL); + if (int e = sc_error(r); e) + return e; + *fd = (int)r; + return 0; +} + +int +sys_open(const char *path, int flags, mode_t mode, int *fd) +{ + return sys_openat(AT_FDCWD, path, flags, mode, fd); +} + +int +sys_open_dir(const char *path, int *handle) +{ + return sys_open(path, O_DIRECTORY, 0, handle); +} + +int +sys_read_entries(int fd, void *buffer, size_t max_size, size_t *bytes_read) +{ + uintptr_t r = syscall3(kPXSysReadDir, fd, (uintptr_t)buffer, max_size, + NULL); + + if (int e = sc_error(r); e) + return e; + + *bytes_read = r; + return 0; +} + +int +sys_close(int fd) +{ + return (int)syscall1(kPXSysClose, fd, NULL); +} + +int +sys_link(const char *old_path, const char *new_path) +{ + uintptr_t ret = syscall2(kPXSysLink, (uintptr_t)old_path, + (uintptr_t)new_path, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_seek(int fd, off_t offset, int whence, off_t *new_offset) +{ + uintptr_t ret = syscall3(kPXSysSeek, fd, offset, whence, NULL); + if (int e = sc_error(ret); e) + return e; + *new_offset = (ssize_t)ret; + return 0; +} + +int +sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) +{ + uintptr_t ret = syscall3(kPXSysRead, fd, (uintptr_t)buf, + (uintptr_t)count, NULL); + if (int e = sc_error(ret); e) + return e; + *bytes_read = (ssize_t)ret; + return 0; +} + +int +sys_write(int fd, const void *buf, size_t count, ssize_t *bytes_written) +{ + uintptr_t ret = syscall3(kPXSysWrite, fd, (uintptr_t)buf, + (uintptr_t)count, NULL); + if (int e = sc_error(ret); e) + return e; + *bytes_written = (ssize_t)ret; + return 0; +} + +int +sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length) +{ + uintptr_t ret = syscall3(kPXSysReadLink, (uintptr_t)path, + (uintptr_t)buffer, (uintptr_t)max_size, NULL); + if (int e = sc_error(ret); e) + return e; + *length = (ssize_t)ret; + return 0; +} + +int +sys_pipe(int *fds, int flags) +{ + uintptr_t ret = syscall2(kPXSysPipe, (uintptr_t)fds, flags, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_unlinkat(int fd, const char *path, int flags) +{ + uintptr_t ret = syscall3(kPXSysUnlinkAt, fd, (uintptr_t)path, flags, + NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, + void **window) +{ + uintptr_t r = syscall6(kPXSysMmap, (uintptr_t)hint, size, prot, flags, + fd, offset, NULL); + if (int e = sc_error(r); e) + return e; + *window = (void *)r; + return 0; +} + +int +sys_vm_unmap(void *pointer, size_t size) +{ + uintptr_t r = syscall2(kPXSysMunmap, (uintptr_t)pointer, size, NULL); + if (int e = sc_error(r); e) + return e; + return 0; +} + +int +sys_vm_protect(void *pointer, size_t size, int prot) +{ + + mlibc::infoLogger() << "mlibc: sys_vm_protect(" << pointer << ", " + << size << ", " << prot << "); stub!\n" + << frg::endlog; + return 0; +} + +int +sys_anon_allocate(size_t size, void **pointer) +{ + return sys_vm_map(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_ANONYMOUS, -1, 0, pointer); +} + +int +sys_anon_free(void *pointer, size_t size) +{ + return sys_vm_unmap(pointer, size); +} + +pid_t +sys_getpid() +{ + return syscall0(kPXSysGetPID, NULL); +} + +pid_t +sys_getppid() +{ + return syscall0(kPXSysGetPPID, NULL); +} + +uid_t +sys_getuid() +{ + return 0; +} + +uid_t +sys_geteuid() +{ + return 0; +} + +gid_t +sys_getgid() +{ + return 0; +} + +int +sys_getsid(pid_t pid, pid_t *sid) +{ + auto ret = syscall1(kPXSysGetSID, pid, NULL); + if (int e = sc_error(ret); e) + return e; + *sid = (pid_t)(ret); + return 0; +} + +int +sys_setgid(gid_t gid) +{ + (void)gid; + return 0; +} + +int +sys_getpgid(pid_t pid, pid_t *out) +{ + auto ret = syscall1(kPXSysGetPGID, pid, NULL); + if (int e = sc_error(ret); e) + return e; + *out = (pid_t)(ret); + return 0; +} + +int +sys_setpgid(pid_t pid, pid_t pgid) +{ + auto ret = syscall2(kPXSysSetPGID, pid, pgid, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_setsid(pid_t *sid) +{ + auto ret = syscall0(kPXSysSetSID, NULL); + if (int e = sc_error(ret); e) + return e; + *sid = (pid_t)ret; + return 0; +} + +gid_t +sys_getegid() +{ + mlibc::infoLogger() << "mlibc: " << __func__ << " is a stub!\n" + << frg::endlog; + return 0; +} + +pid_t +sys_gettid() +{ + return syscall0(kPXSysGetTID, NULL); +} + +int +sys_clock_get(int clock, time_t *secs, long *nanos) +{ + auto ret = syscall1(kPXSysClockGet, clock, NULL); + *secs = ret / 1000000000; + *nanos = ret % 1000000000; + return 0; +} + +int +sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, + struct stat *statbuf) +{ + uintptr_t r; + enum posix_stat_kind kind; + + switch (fsfdt) { + case fsfd_target::fd: + kind = kPXStatKindFD; + break; + + case fsfd_target::path: + kind = kPXStatKindCWD; + break; + case fsfd_target::fd_path: + kind = kPXStatKindAt; + break; + + default: + __ensure(!"stat: Invalid fsfdt"); + __builtin_unreachable(); + } + + r = syscall5(kPXSysStat, kind, fd, (uintptr_t)path, flags, + (uintptr_t)statbuf, NULL); + if (int e = sc_error(r); e) + return e; + return 0; +} + +int +sys_statfs(const char *path, struct statfs *buf) +{ + uintptr_t ret = syscall2(kPXSysStatFS, (uintptr_t)path, (uintptr_t)buf, + NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_statvfs(const char *path, struct statvfs *buf) +{ + struct statfs sb; + uintptr_t ret = syscall2(kPXSysStatFS, (uintptr_t)path, (uintptr_t)&sb, + NULL); + if (int e = sc_error(ret); e) + return e; + + buf->f_bsize = sb.f_bsize; + buf->f_frsize = sb.f_frsize; + buf->f_blocks = sb.f_blocks; + buf->f_bfree = sb.f_bfree; + buf->f_bavail = sb.f_bavail; + + buf->f_files = sb.f_files; + buf->f_ffree = sb.f_ffree; + buf->f_favail = sb.f_ffree; + + buf->f_fsid = sb.f_fsid.__val[1] | (uint64_t)sb.f_fsid.__val[0] << 32; + buf->f_flag = sb.f_flags; + buf->f_namemax = sb.f_namelen; + + return 0; +} + +int +sys_faccessat(int dirfd, const char *pathname, int mode, int flags) +{ + (void)flags; + struct stat buf; + if (int r = sys_stat(dirfd == AT_FDCWD ? fsfd_target::path : + fsfd_target::fd_path, + dirfd, pathname, mode & AT_SYMLINK_FOLLOW, &buf)) { + return r; + } + return 0; +} + +int +sys_access(const char *path, int mode) +{ + return sys_faccessat(AT_FDCWD, path, mode, 0); +} + +int +sys_fork(pid_t *child) +{ + uintptr_t ret = syscall0(kPXSysFork, NULL); + if (int e = sc_error(ret); e) + return e; + *child = (int)ret; + return 0; +} + +int +sys_execve(const char *path, char *const argv[], char *const envp[]) +{ + uintptr_t ret = syscall3(kPXSysExecVE, (uintptr_t)path, (uintptr_t)argv, + (uintptr_t)envp, NULL); + if (int e = sc_error(ret); e) + return e; + mlibc::panicLogger() << "execve returned! " << ret << frg::endlog; + __builtin_unreachable(); +} + +int +sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, + pid_t *ret_pid) +{ + (void)ru; + + uintptr_t ret = syscall3(kPXSysWaitPID, pid, (uintptr_t)status, flags, + NULL); + if (int e = sc_error(ret); e) + return e; + *ret_pid = (pid_t)ret; + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL +int +sys_sleep(time_t *sec, long *nanosec) +{ + auto ret = syscall1(kPXSysSleep, *sec * 1000000000 + *nanosec, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_uname(struct utsname *buf) +{ + uintptr_t ret = syscall1(kPXSysUTSName, (uintptr_t)buf, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_gethostname(char *buf, size_t bufsize) +{ + struct utsname uname_buf; + if (auto e = sys_uname(&uname_buf); e) + return e; + + auto node_len = strlen(uname_buf.nodename); + if (node_len >= bufsize) + return ENAMETOOLONG; + + memcpy(buf, uname_buf.nodename, node_len); + buf[node_len] = '\0'; + return 0; +} + +int +sys_fsync(int) +{ + mlibc::infoLogger() << "mlibc: fsync is a stub" << frg::endlog; + return 0; +} + +int +sys_getentropy(void *buffer, size_t length) +{ + /* todo: improve lmao */ + mlibc::infoLogger() << "mlibc: getentropy is a stub" << frg::endlog; + memset(buffer, 123, length); + return 0; +} +#endif + +int +sys_mkdir(const char *path, mode_t mode) +{ + return sys_mkdirat(AT_FDCWD, path, mode); +} + +int +sys_mkdirat(int dirfd, const char *path, mode_t mode) +{ + uintptr_t ret = syscall3(kPXSysMkDirAt, dirfd, (uintptr_t)path, mode, + NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_chdir(const char *path) +{ + uintptr_t ret = syscall1(kPXSysChDir, (uintptr_t)path, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_umask(mode_t mode, mode_t *old) +{ + uintptr_t ret = syscall1(kPXSysUMask, mode, NULL); + if (int e = sc_error(ret); e) + return e; + *old = (mode_t)ret; + return 0; +} + +int +sys_rename(const char *old_path, const char *new_path) +{ + return sys_renameat(AT_FDCWD, old_path, AT_FDCWD, new_path); +} + +int +sys_renameat(int old_dirfd, const char *old_path, int new_dirfd, + const char *new_path) +{ + auto ret = syscall4(kPXSysRenameAt, old_dirfd, (uintptr_t)old_path, + new_dirfd, (uintptr_t)new_path, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/keyronex/generic/linux.cpp b/lib/mlibc/sysdeps/keyronex/generic/linux.cpp new file mode 100644 index 0000000..9b4a4c7 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/linux.cpp @@ -0,0 +1,41 @@ +#include <sys/types.h> + +#include <keyronex/syscall.h> +#include <mlibc/ansi-sysdeps.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-sysdeps.hpp> +#include <mlibc/linux-sysdeps.hpp> + +namespace mlibc { + +int +sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, int timeout, + const sigset_t *sigmask, int *raised) +{ + uintptr_t ret = syscall5(kPXSysEPollWait, epfd, (uintptr_t)ev, n, + timeout, (uintptr_t)sigmask, NULL); + if (int e = sc_error(ret); e) + return e; + *raised = ret; + return 0; +} + +int +sys_epoll_create(int flags, int *fd) +{ + uintptr_t ret = syscall1(kPXSysEPollCreate, flags, NULL); + if (int e = sc_error(ret); e) + return e; + *fd = ret; + return 0; +} + +int +sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) +{ + uintptr_t ret = syscall4(kPXSysEPollCtl, epfd, mode, fd, (uintptr_t)ev, + NULL); + return sc_error(ret); +} + +}
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/generic/signal.cpp b/lib/mlibc/sysdeps/keyronex/generic/signal.cpp new file mode 100644 index 0000000..ead3dee --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/signal.cpp @@ -0,0 +1,66 @@ +#include <sys/types.h> + +#include <keyronex/syscall.h> +#include <mlibc/ansi-sysdeps.hpp> +#include <mlibc/posix-sysdeps.hpp> +#include <mlibc/debug.hpp> + +namespace mlibc { + +int +sys_sigprocmask(int how, const sigset_t *__restrict set, + sigset_t *__restrict retrieve) +{ + auto ret = syscall3(kPXSysSigMask, how, (uintptr_t)set, + (uintptr_t)retrieve, NULL); + if (int e = sc_error(ret); e) { + return e; + } + + return 0; +} + +int +sys_sigaction(int signal, const struct sigaction *__restrict action, + struct sigaction *__restrict oldAction) +{ + auto ret = syscall3(kPXSysSigAction, signal, (uintptr_t)action, + (uintptr_t)oldAction, NULL); + if (int e = sc_error(ret); e) { + return e; + } + + return 0; +} + +int +sys_kill(int pid, int signal) +{ + if (signal == 0) { + mlibc::infoLogger() << "Sending signal 0! Allowing" << frg::endlog; + return 0; + } + + auto ret = syscall2(kPXSysSigSend, pid, signal, NULL); + if (int e = sc_error(ret); e) { + return e; + } + + return 0; +} + +int +sys_sigsuspend(const sigset_t *set) +{ + auto ret = syscall1(kPXSysSigSuspend, (uintptr_t)set, NULL); + if (int e = sc_error(ret); e) { + return e; + } + + mlibc::panicLogger() + << "Unexpected zero return from sigsuspend()" << frg::endlog; + + return 0; +} + +}
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/generic/socket.cpp b/lib/mlibc/sysdeps/keyronex/generic/socket.cpp new file mode 100644 index 0000000..c6453bf --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/socket.cpp @@ -0,0 +1,119 @@ +#include <sys/errno.h> + +#include <keyronex/syscall.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> + +#define log_unimplemented() \ + mlibc::infoLogger() << "mlibc: " << __PRETTY_FUNCTION__ \ + << " is a stub!" << frg::endlog; + +namespace mlibc { + +int +sys_socket(int family, int type, int protocol, int *fd) +{ + auto ret = syscall3(kPXSysSocket, family, type, protocol, NULL); + if (int e = sc_error(ret); e) + return e; + *fd = ret; + return 0; +} + +int +sys_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + auto ret = syscall3(kPXSysBind, fd, (uintptr_t)addr, addrlen, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + auto ret = syscall3(kPXSysConnect, fd, (uintptr_t)addr, addrlen, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_listen(int fd, int backlog) +{ + auto ret = syscall2(kPXSysListen, fd, backlog, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_accept(int fd, int *newfd, struct sockaddr *addr, socklen_t *addrlen, + int flags) +{ + auto ret = syscall4(kPXSysAccept, fd, (uintptr_t)addr, + (uintptr_t)addrlen, flags, NULL); + if (int e = sc_error(ret); e) + return e; + *newfd = ret; + return 0; +} + +int +sys_msg_send(int fd, const struct msghdr *msg, int flags, ssize_t *length) +{ + auto ret = syscall3(kPXSysSendMsg, fd, (uintptr_t)msg, flags, NULL); + if (int e = sc_error(ret); e) + return e; + *length = ret; + return 0; +} + +int +sys_msg_recv(int fd, struct msghdr *msg, int flags, ssize_t *length) +{ + auto ret = syscall3(kPXSysRecvMsg, fd, (uintptr_t)msg, flags, NULL); + if (int e = sc_error(ret); e) + return e; + *length = ret; + return 0; +} + +int +sys_socketpair(int domain, int type_and_flags, int proto, int *fds) +{ + auto ret = syscall4(kPXSysSocketPair, domain, type_and_flags, proto, + (uintptr_t)fds, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int +sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, + socklen_t *__restrict size) +{ + (void)fd; + (void)layer; + (void)number; + (void)buffer; + (void)size; + log_unimplemented(); + return ENOSYS; +} + +int +sys_setsockopt(int fd, int layer, int number, const void *buffer, + socklen_t size) +{ + (void)fd; + (void)layer; + (void)number; + (void)buffer; + (void)size; + log_unimplemented(); + return ENOSYS; +} + +} diff --git a/lib/mlibc/sysdeps/keyronex/generic/thread.S b/lib/mlibc/sysdeps/keyronex/generic/thread.S new file mode 100644 index 0000000..47ab6a9 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/thread.S @@ -0,0 +1,9 @@ +.section .text +.global __mlibc_thread_entry +__mlibc_thread_entry: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_thread_trampoline + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/keyronex/generic/thread.cpp b/lib/mlibc/sysdeps/keyronex/generic/thread.cpp new file mode 100644 index 0000000..cafb74a --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/generic/thread.cpp @@ -0,0 +1,80 @@ +#include <sys/mman.h> +#include <mlibc/debug.hpp> +#include <errno.h> +#include <mlibc/all-sysdeps.hpp> +#include <bits/ensure.h> +#include <mlibc/tcb.hpp> +#include <keyronex/syscall.h> + +extern "C" void __mlibc_thread_trampoline(void *(*fn)(void *), Tcb *tcb, void *arg) { + if (mlibc::sys_tcb_set(tcb)) { + __ensure(!"failed to set tcb for new thread"); + } + + while (__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED) == 0) { + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + } + + tcb->invokeThreadFunc(reinterpret_cast<void *>(fn), arg); + + __atomic_store_n(&tcb->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&tcb->didExit); + + mlibc::sys_thread_exit(); +} + +#define DEFAULT_STACK 0x400000 + +namespace mlibc { + +extern "C" void __mlibc_thread_entry(); + + int sys_clone(void *tcb, pid_t *tid_out, void *stack) { + (void)tcb; + + auto ret = syscall2(kPXSysForkThread, (uintptr_t)__mlibc_thread_entry, (uintptr_t)stack, NULL); + if (int e = sc_error(ret); e) + return e; + + *tid_out = ret; + return 0; + } + + int sys_prepare_stack(void **stack, void *entry, void *arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + // TODO guard + + mlibc::infoLogger() << "mlibc: sys_prepare_stack() does not setup a guard!" << frg::endlog; + + *guard_size = 0; + + *stack_size = *stack_size ? *stack_size : DEFAULT_STACK; + + if (!*stack) { + *stack_base = mmap(NULL, *stack_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (*stack_base == MAP_FAILED) { + return errno; + } + } else { + *stack_base = *stack; + } + + *stack = (void *)((char *)*stack_base + *stack_size); + + void **stack_it = (void **)*stack; + + *--stack_it = arg; + *--stack_it = tcb; + *--stack_it = entry; + + *stack = (void *)stack_it; + + return 0; + } + + void sys_thread_exit() { + mlibc::panicLogger() << "mlibc: sys_thread_exit unimplemented!" << frg::endlog; + __builtin_unreachable(); + } + + +} diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/access.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/access.h new file mode 120000 index 0000000..cb83931 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/linux/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/auxv.h new file mode 120000 index 0000000..c43f878 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/linux/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..0b0ec27 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..7dc8d7c --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..6a42da5 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/dev_t.h new file mode 120000 index 0000000..bca881e --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/linux/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/epoll.h new file mode 120000 index 0000000..eb4b76d --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/linux/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/errno.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/errno.h new file mode 120000 index 0000000..6e507de --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/linux/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fcntl.h new file mode 120000 index 0000000..463e2c9 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/linux/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/gid_t.h new file mode 120000 index 0000000..abce6d6 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/in.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/in.h new file mode 120000 index 0000000..418d1d5 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/linux/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ino_t.h new file mode 120000 index 0000000..4c20aca --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/linux/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/inotify.h new file mode 120000 index 0000000..b5cb282 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/linux/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/limits.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/limits.h new file mode 120000 index 0000000..6c88db2 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/linux/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/mode_t.h new file mode 120000 index 0000000..5d78fdf --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/linux/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/msg.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..bb3b625 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/linux/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/packet.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/packet.h new file mode 120000 index 0000000..998ef1a --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/linux/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/pid_t.h new file mode 120000 index 0000000..baa90f6 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/poll.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/poll.h new file mode 120000 index 0000000..8ea6a0a --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/linux/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ptrace.h new file mode 120000 index 0000000..b2517b2 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/linux/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/resource.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/resource.h new file mode 120000 index 0000000..88d7402 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/linux/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/shm.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/signal.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/socket.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/stat.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/stat.h new file mode 120000 index 0000000..1f63b41 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/linux/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/termios.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/time.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/uid_t.h new file mode 120000 index 0000000..b306777 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..bbe258c --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/linux/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/wait.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/keyronex/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/keyronex/include/keyronex/syscall.h b/lib/mlibc/sysdeps/keyronex/include/keyronex/syscall.h new file mode 100644 index 0000000..9cbafd0 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/include/keyronex/syscall.h @@ -0,0 +1,213 @@ +#ifndef _KEYRONEX__SYSCALL_H +#define _KEYRONEX__SYSCALL_H + +#include <stdint.h> + +enum posix_syscall { + /*! debug print */ + kPXSysDebug, + kPXSysMmap, + kPXSysMunmap, + + kPXSysIOCtl, + kPXSysOpenAt, + kPXSysClose, + kPXSysRead, + kPXSysReadLink, + kPXSysWrite, + kPXSysSeek, + kPXSysPPoll, + kPXSysIsATTY, + kPXSysReadDir, + kPXSysStat, + kPXSysUnlinkAt, + kPXSysGetCWD, + kPXSysPipe, + kPXSysDup, + kPXSysDup3, + kPXSysLink, + kPXSysChDir, + kPXSysUMask, + kPXSysMkDirAt, + kPXSysRenameAt, + kPXSysStatFS, + kPXSysFCntl, + + kPXSysSetFSBase, + kPXSysExecVE, + kPXSysExit, + kPXSysFork, + kPXSysWaitPID, + kPXSysGetPID, + kPXSysGetPPID, + kPXSysGetPGID, + kPXSysSetPGID, + kPXSysGetSID, + kPXSysSetSID, + kPXSysGetTID, + + kPXSysSigAction, + kPXSysSigMask, + kPXSysSigSend, + kPXSysSigSuspend, + kPXSysSigTimedWait, + + kPXSysSocket, + kPXSysBind, + kPXSysConnect, + kPXSysListen, + kPXSysAccept, + kPXSysSendMsg, + kPXSysRecvMsg, + kPXSysSocketPair, + kPXSysGetSockOpt, + kPXSysSetSockOpt, + + kPXSysEPollCreate, + kPXSysEPollCtl, + kPXSysEPollWait, + + kPXSysSleep, + kPXSysUTSName, + kPXSysClockGet, + + kPXSysForkThread, + kPXSysFutexWait, + kPXSysFutexWake, + + /*! register signal entry function */ + kPXSysSigEntry, + /*! return from a signal */ + kPXSysSigReturn, +}; + +enum posix_stat_kind { + kPXStatKindFD, + kPXStatKindAt, + kPXStatKindCWD, +}; + +#if defined(__x86_64__) +static inline uintptr_t +syscall0(uintptr_t num, uintptr_t *out) +{ + uintptr_t ret, ret2; + asm volatile("int $0x80" : "=a"(ret), "=D"(ret2) : "a"(num) : "memory"); + if (out) + *out = ret2; + return ret; +} + +static inline uintptr_t +syscall1(uintptr_t num, uintptr_t arg1, uintptr_t *out) +{ + uintptr_t ret, ret2; + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1) + : "memory"); + if (out) + *out = ret2; + return ret; +} + +static inline uintptr_t +syscall2(uintptr_t num, uintptr_t arg1, uintptr_t arg2, uintptr_t *out) +{ + uintptr_t ret, ret2; + + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1), "S"(arg2) + : "memory"); + + if (out) + *out = ret2; + + return ret; +} + +static inline uintptr_t +syscall3(intptr_t num, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, + uintptr_t *out) +{ + uintptr_t ret, ret2; + + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3) + : "memory"); + + if (out) + *out = ret2; + + return ret; +} + +static inline uintptr_t +syscall4(intptr_t num, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, + uintptr_t arg4, uintptr_t *out) +{ + register uintptr_t r10 asm("r10") = arg4; + uintptr_t ret, ret2; + + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) + : "memory"); + + if (out) + *out = ret2; + + return ret; +} + +static inline uintptr_t +syscall5(uintptr_t num, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, + uintptr_t arg4, uintptr_t arg5, uintptr_t *out) +{ + register uintptr_t r10 asm("r10") = arg4, r8 asm("r8") = arg5; + uintptr_t ret, ret2; + + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), + "r"(r8) + : "memory"); + + if (out) + *out = ret2; + + return ret; +} + +static inline uintptr_t +syscall6(uintptr_t num, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, + uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, uintptr_t *out) +{ + register uintptr_t r10 asm("r10") = arg4, r8 asm("r8") = arg5, + r9 asm("r9") = arg6; + uintptr_t ret, ret2; + + asm volatile("int $0x80" + : "=a"(ret), "=D"(ret2) + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), + "r"(r8), "r"(r9) + : "memory"); + + if (out) + *out = ret2; + + return ret; +} + +static inline int +sc_error(uintptr_t ret) +{ + if (ret > -4096UL) + return -ret; + return 0; +} +#endif + +#endif diff --git a/lib/mlibc/sysdeps/keyronex/meson.build b/lib/mlibc/sysdeps/keyronex/meson.build new file mode 100644 index 0000000..42de7a8 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/meson.build @@ -0,0 +1,98 @@ + +rtdl_sources += files( + 'generic/generic.cpp' +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/generic.cpp', + 'generic/linux.cpp', + 'generic/signal.cpp', + 'generic/socket.cpp', + 'generic/thread.cpp', + 'generic/thread.S' +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/reboot.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + + install_headers( + 'include/keyronex/syscall.h', + subdir: 'keyronex', + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crti', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crti.S', + output: 'crti.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crtn', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crtn.S', + output: 'crtn.o', + install: true, + install_dir: get_option('libdir') + ) +endif + diff --git a/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crt0.S b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crt0.S new file mode 100644 index 0000000..d16a46f --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crt0.S @@ -0,0 +1,7 @@ +.section .text +.global _start +_start: + mov $main, %rdi + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crti.S b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crti.S new file mode 100644 index 0000000..911b078 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + push %rax + +.section .fini +.global _fini +_fini: + push %rax +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crtn.S b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crtn.S new file mode 100644 index 0000000..0187e50 --- /dev/null +++ b/lib/mlibc/sysdeps/keyronex/x86_64/crt-src/crtn.S @@ -0,0 +1,9 @@ +.section .init + pop %rax + ret + +.section .fini + pop %rax + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lemon/crt-x86_64/crt0.S b/lib/mlibc/sysdeps/lemon/crt-x86_64/crt0.S new file mode 100755 index 0000000..62298e3 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/crt-x86_64/crt0.S @@ -0,0 +1,10 @@ +.section .text + +.global _start +_start: + mov $main, %rdi + call __mlibc_entry + +.size _start, . - _start +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lemon/generic/entry.cpp b/lib/mlibc/sysdeps/lemon/generic/entry.cpp new file mode 100644 index 0000000..f4cf144 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/entry.cpp @@ -0,0 +1,33 @@ +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp b/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp new file mode 100755 index 0000000..4a7d780 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp @@ -0,0 +1,406 @@ +#include <lemon/syscall.h> + +#include <asm/ioctls.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <limits.h> +#include <fcntl.h> +#include <string.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> + +namespace mlibc{ + +typedef struct { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + uid_t st_gid; + dev_t st_rdev; + off_t st_size; + int64_t st_blksize; + int64_t st_blocks; +} lemon_stat_t; + +int sys_write(int fd, const void* buffer, size_t count, ssize_t* written){ + long ret = syscall(SYS_WRITE, fd, (uintptr_t)buffer, count); + + if(ret < 0) + return -ret; + + *written = ret; + return 0; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + long ret = syscall(SYS_READ, fd, (uintptr_t)buf, count); + + if(ret < 0){ + *bytes_read = 0; + return -ret; + } + + *bytes_read = ret; + return 0; +} + +int sys_pwrite(int fd, const void* buffer, size_t count, off_t off, ssize_t* written){ + int ret = syscall(SYS_PWRITE, fd, (uintptr_t)buffer, count, 0, off); + + + if(ret < 0){ + return -ret; + } + + *written = ret; + return 0; +} + +int sys_pread(int fd, void *buf, size_t count, off_t off, ssize_t *bytes_read) { + int ret = syscall(SYS_PREAD, fd, (uintptr_t)buf, count, 0, off); + + if(ret < 0){ + return -ret; + } + + *bytes_read = ret; + return 0; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + long ret = syscall(SYS_LSEEK, fd, offset, whence); + + if(ret < 0){ + return -ret; + } + + *new_offset = ret; + return 0; +} + + +int sys_open(const char* filename, int flags, mode_t mode, int* fd){ + long ret = syscall(SYS_OPEN, (uintptr_t)filename, flags); + + if(ret < 0) + return -ret; + + *fd = ret; + + return 0; +} + +int sys_close(int fd){ + syscall(SYS_CLOSE, fd); + return 0; +} + +int sys_access(const char* filename, int mode){ + int fd; + if(int e = sys_open(filename, O_RDONLY, 0, &fd)){ + return e; + } + + sys_close(fd); + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf){ + long ret = 0; + + lemon_stat_t lemonStat; + switch(fsfdt){ + case fsfd_target::fd: + ret = syscall(SYS_FSTAT, &lemonStat, fd); + break; + case fsfd_target::path: + ret = syscall(SYS_STAT, &lemonStat, path); + break; + default: + mlibc::infoLogger() << "mlibc warning: sys_stat: unsupported fsfd target" << frg::endlog; + return EINVAL; + } + + statbuf->st_dev = lemonStat.st_dev; + statbuf->st_ino = lemonStat.st_ino; + statbuf->st_mode = lemonStat.st_mode; + statbuf->st_nlink = lemonStat.st_nlink; + statbuf->st_uid = lemonStat.st_uid; + statbuf->st_gid = lemonStat.st_gid; + statbuf->st_rdev = lemonStat.st_rdev; + statbuf->st_size = lemonStat.st_size; + statbuf->st_blksize = lemonStat.st_blksize; + statbuf->st_blocks = lemonStat.st_blocks; + + return -ret; +} + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result){ + long ret = syscall(SYS_IOCTL, fd, request, arg, result); + + if(ret < 0) + return -ret; + + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events){ + long ret = syscall(SYS_POLL, fds, count, timeout); + + if(ret < 0){ + return -ret; + } + + *num_events = ret; + + return 0; +} + +int sys_mkdir(const char* path, mode_t){ + long ret = syscall(SYS_MKDIR, path); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_rmdir(const char* path){ + long ret = syscall(SYS_RMDIR, path); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_link(const char* srcpath, const char* destpath){ + long ret = syscall(SYS_LINK, srcpath, destpath); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_unlinkat(int fd, const char *path, int flags) { + long ret = syscall(SYS_UNLINK, fd, path, flags); + + if(ret < 0) { + return -ret; + } + + return 0; +} + +typedef struct lemon_dirent { + uint32_t inode; // Inode number + uint32_t type; + char name[NAME_MAX]; // Filename +} lemon_dirent_t; + +int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read){ + lemon_dirent_t lemonDirent; + long ret = syscall(SYS_READDIR_NEXT, handle, &lemonDirent); + + if(!ret){ + *bytes_read = 0; + return 0; + } else if(ret > 0){ + dirent* dir = (dirent*)buffer; + strcpy(dir->d_name, lemonDirent.name); + dir->d_ino = lemonDirent.inode; + dir->d_off = 0; + dir->d_reclen = sizeof(dirent); + dir->d_type = lemonDirent.type; + + *bytes_read = sizeof(dirent); + return 0; + } else { + return -ret; + } +} + +int sys_open_dir(const char* path, int* handle){ + return sys_open(path, O_DIRECTORY, 0, handle); +} + +int sys_rename(const char* path, const char* new_path){ + return -syscall(SYS_RENAME, path, new_path); +} + +int sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length){ + long ret = syscall(SYS_READLINK, path, buffer, max_size); + if(ret < 0){ + return -ret; + } + + *length = ret; + return 0; +} + +int sys_dup(int fd, int flags, int* newfd){ + int ret = syscall(SYS_DUP, fd, flags, -1); + if(ret < 0){ + return -ret; + } + + *newfd = ret; + return 0; +} + +int sys_dup2(int fd, int flags, int newfd){ + int ret = syscall(SYS_DUP, fd, flags, newfd); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_fcntl(int fd, int request, va_list args, int* result){ + if(request == F_DUPFD){ + return sys_dup(fd, 0, result); + } else if (request == F_DUPFD_CLOEXEC) { + return sys_dup(fd, O_CLOEXEC, result); + } else if(request == F_GETFD){ + *result = 0; + return 0; + } else if(request == F_SETFD){ + if(va_arg(args, int) & FD_CLOEXEC) { + return sys_ioctl(fd, FIOCLEX, NULL, result); + } else { + return sys_ioctl(fd, FIONCLEX, NULL, result); + } + } else if(request == F_GETFL){ + int ret = syscall(SYS_GET_FILE_STATUS_FLAGS, fd); + if(ret < 0){ + return -ret; + } + + *result = ret; + return 0; + } else if(request == F_SETFL){ + int ret = syscall(SYS_SET_FILE_STATUS_FLAGS, fd, va_arg(args, int)); + return -ret; + } else { + infoLogger() << "mlibc: sys_fcntl unsupported request (" << request << ")" << frg::endlog; + return EINVAL; + } +} + +int sys_pselect(int nfds, fd_set* readfds, fd_set* writefds, + fd_set *exceptfds, const struct timespec* timeout, const sigset_t* sigmask, int *num_events){ + int ret = syscall(SYS_SELECT, nfds, readfds, writefds, exceptfds, timeout); + if(ret < 0){ + return -ret; + } + + *num_events = ret; + return 0; +} + +int sys_chmod(const char *pathname, mode_t mode){ + int ret = syscall(SYS_CHMOD, pathname, mode); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_pipe(int *fds, int flags){ + return -syscall(SYS_PIPE, fds, flags); +} + +int sys_epoll_create(int flags, int *fd) { + int ret = syscall(SYS_EPOLL_CREATE, flags); + + if(ret < 0){ + return -ret; + } + + *fd = ret; + + return 0; +} + +int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { + int ret = syscall(SYS_EPOLL_CTL, epfd, mode, fd, ev); + + if(ret < 0) { + return -ret; + } + + return 0; +} + +int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, + int timeout, const sigset_t *sigmask, int *raised) { + int ret = syscall(SYS_EPOLL_WAIT, epfd, ev, n, timeout, sigmask); + + if(ret < 0) { + return -ret; + } + + *raised = ret; + + return 0; +} + +int sys_ttyname(int tty, char *buf, size_t size) { + char path[PATH_MAX] = {"/dev/pts/"}; + + struct stat stat; + if(int e = sys_stat(fsfd_target::fd, tty, nullptr, 0, &stat)) { + return e; + } + + if(!S_ISCHR(stat.st_mode)) { + return ENOTTY; // Not a char device, isn't a tty + } + + if(sys_isatty(tty)) { + return ENOTTY; + } + + // Look for tty in /dev/pts + int ptDir = open("/dev/pts", O_DIRECTORY); + __ensure(ptDir >= 0); + + struct dirent dirent; + size_t direntBytesRead; + while(!sys_read_entries(ptDir, &dirent, sizeof(dirent), &direntBytesRead) && direntBytesRead) { + // Compare the inodes + if(dirent.d_ino == stat.st_ino) { + __ensure(strlen(path) + strlen(dirent.d_name) < PATH_MAX); + strcat(path, dirent.d_name); + + strncpy(buf, path, size); + return 0; + } + } + + // Could not find corresponding TTY in /dev/pts + return ENODEV; +} + +int sys_fchdir(int fd) { + return syscall(SYS_FCHDIR, fd); +} +#endif + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/lemon.cpp b/lib/mlibc/sysdeps/lemon/generic/lemon.cpp new file mode 100644 index 0000000..8f15ff1 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/lemon.cpp @@ -0,0 +1,199 @@ +#include <lemon/syscall.h> +#include <stddef.h> +#include <bits/ensure.h> +#include <abi-bits/pid_t.h> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> +#include <errno.h> +#include <sys/resource.h> + +namespace mlibc{ + +int sys_futex_tid(){ + return syscall(SYS_GETTID); +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time){ + return syscall(SYS_FUTEX_WAIT, pointer, expected); +} + +int sys_futex_wake(int *pointer) { + return syscall(SYS_FUTEX_WAKE, pointer); +} + +int sys_tcb_set(void* pointer){ + syscall(SYS_SET_FS_BASE, (uintptr_t)pointer); + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { + __ensure(flags & MAP_ANONYMOUS); + + return syscall(SYS_MMAP, (uintptr_t)window, (size + 0xFFF) & ~static_cast<size_t>(0xFFF), (uintptr_t)hint, flags); +} + +int sys_vm_unmap(void* address, size_t size) { + __ensure(!(size & 0xFFF)); + + long ret = syscall(SYS_MUNMAP, (uintptr_t)address, (size + 0xFFF) & ~static_cast<size_t>(0xFFF)); + + return ret; +} + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0, pointer); +} + +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +void sys_libc_panic(){ + sys_libc_log("libc panic!"); + __builtin_trap(); + for(;;); +} + +void sys_libc_log(const char* msg){ + syscall(0, (uintptr_t)msg); +} + +#ifndef MLIBC_BUILDING_RTDL + +void sys_exit(int status){ + syscall(SYS_EXIT, status); + + __builtin_unreachable(); +} + +pid_t sys_getpid(){ + uint64_t _pid; + syscall(SYS_GETPID, (uintptr_t)&_pid); + + pid_t pid = _pid; + return pid; +} + +pid_t sys_getppid(){ + return syscall(SYS_GETPPID); +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + syscall(SYS_UPTIME, nanos); + + *secs = (*nanos) / 1000000000; + *nanos = (*nanos) - (*secs) * 1000000000; + + return 0; +} + +int sys_getcwd(char *buffer, size_t size){ + return syscall(SYS_GET_CWD, buffer, size); +} + +int sys_chdir(const char *path){ + syscall(SYS_CHDIR, path); + return 0; +} + +int sys_sleep(time_t* sec, long* nanosec){ + syscall(SYS_NANO_SLEEP, (*sec) * 1000000000 + (*nanosec)); + return 0; +} + +uid_t sys_getuid(){ + return syscall(SYS_GETUID); +} + +uid_t sys_geteuid(){ + return syscall(SYS_GETEUID); +} + +int sys_setuid(uid_t uid){ + return -syscall(SYS_SETUID, uid); +} + +int sys_seteuid(uid_t euid){ + return -syscall(SYS_SETEUID, euid); +} + +gid_t sys_getgid(){ + return syscall(SYS_GETGID); +} + +gid_t sys_getegid(){ + return syscall(SYS_GETEGID); +} + +int sys_setgid(gid_t gid){ + mlibc::infoLogger() << "mlibc: sys_setgid is a stub" << frg::endlog; + return 0; +} + +int sys_setegid(gid_t egid){ + mlibc::infoLogger() << "mlibc: sys_setegid is a stub" << frg::endlog; + return 0; +} + +void sys_yield(){ + syscall(SYS_YIELD); +} + +int sys_clone(void *tcb, pid_t *tid_out, void *stack){ + pid_t tid = syscall(SYS_SPAWN_THREAD, __mlibc_start_thread, stack); + + if(tid < 0){ + errno = tid; + return -1; + } + + *tid_out = tid; + + return 0; +} + +void sys_thread_exit(){ + syscall(SYS_EXIT_THREAD); + + __builtin_unreachable(); +} + +int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid){ + if(ru) { + mlibc::infoLogger() << "mlibc: struct rusage in sys_waitpid is unsupported" << frg::endlog; + return ENOSYS; + } + + pid_t ret = syscall(SYS_WAIT_PID, pid, status, flags); + + if(ret < 0){ + return -ret; + } + + *ret_pid = ret; + + return 0; +} + +int sys_fork(pid_t *child){ + long pid = syscall(SYS_FORK, 0); + if(pid < 0){ + errno = pid; + return -1; + } + + *child = pid; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]){ + return -syscall(SYS_EXECVE, path, argv, envp); +} + +int sys_getentropy(void *buffer, size_t length){ + return -syscall(SYS_GETENTROPY, buffer, length); +} +#endif + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/pty.cpp b/lib/mlibc/sysdeps/lemon/generic/pty.cpp new file mode 100644 index 0000000..794f74f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/pty.cpp @@ -0,0 +1,63 @@ +#include <asm/ioctls.h> +#include <sys/ioctl.h> + +#include <errno.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> + +#include <stdio.h> + +namespace mlibc { + +int sys_isatty(int fd) { + struct winsize ws; + long ret = sys_ioctl(fd, TIOCGWINSZ, &ws, 0); + + if(!ret) return 0; + + return ENOTTY; +} + +int sys_tcgetattr(int fd, struct termios *attr) { + if(int e = sys_isatty(fd)) + return e; + + int ret; + sys_ioctl(fd, TCGETS, attr, &ret); + + if(ret) + return -ret; + + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + if(int e = sys_isatty(fd)) + return e; + + if(optional_action){ + mlibc::infoLogger() << "mlibc warning: sys_tcsetattr ignores optional_action" << frg::endlog; + } + + int ret; + sys_ioctl(fd, TCSETS, const_cast<struct termios*>(attr), &ret); + + if(ret) + return -ret; + + return 0; +} + +int sys_ptsname(int fd, char *buffer, size_t length) { + int index; + if(int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) + return e; + if((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { + return ERANGE; + } + return 0; +} + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/signals.cpp b/lib/mlibc/sysdeps/lemon/generic/signals.cpp new file mode 100644 index 0000000..46b4714 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/signals.cpp @@ -0,0 +1,38 @@ +#include <lemon/syscall.h> + +#include <sys/types.h> + +#include <mlibc/ansi-sysdeps.hpp> + +namespace mlibc{ + +int sys_sigprocmask(int how, const sigset_t *__restrict set, + sigset_t *__restrict retrieve){ + int ret = syscall(SYS_SIGPROCMASK, how, set, retrieve); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_sigaction(int signal, const struct sigaction *__restrict action, + struct sigaction *__restrict oldAction) { + int ret = syscall(SYS_SIGNAL_ACTION, signal, action, oldAction); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_kill(int pid, int signal){ + int ret = syscall(SYS_KILL, pid, signal); + if(ret < 0){ + return -ret; + } + + return 0; +} + +}
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/generic/sockets.cpp b/lib/mlibc/sysdeps/lemon/generic/sockets.cpp new file mode 100755 index 0000000..7244218 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/sockets.cpp @@ -0,0 +1,132 @@ +#include <lemon/syscall.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +#include <mlibc/all-sysdeps.hpp> + +namespace { + +int fcntl_helper(int fd, int request, int *result, ...) { + va_list args; + va_start(args, result); + if(!mlibc::sys_fcntl) { + return ENOSYS; + } + int ret = mlibc::sys_fcntl(fd, request, args, result); + va_end(args); + return ret; +} + +} + +namespace mlibc{ + +int sys_socket(int domain, int type, int protocol, int *fd){ + long ret = syscall(SYS_SOCKET, domain, type, protocol); + + if(ret < 0){ + return -ret; + } + + *fd = ret; + + return 0; +} + +int sys_bind(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){ + return syscall(SYS_BIND, sockfd, addr_ptr, addrlen); +} + +int sys_connect(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){ + return syscall(SYS_CONNECT, sockfd, addr_ptr, addrlen); +} + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags){ + long ret = syscall(SYS_ACCEPT, fd); + + if(ret < 0){ + return -ret; + } + + *newfd = ret; + + if(flags & SOCK_NONBLOCK) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFL, &fcntl_ret); + fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK); + } + + if(flags & SOCK_CLOEXEC) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFD, &fcntl_ret); + fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC); + } + + return 0; +} + +int sys_listen(int fd, int backlog){ + return syscall(SYS_LISTEN, fd, backlog); +} + +int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length){ + long ret = syscall(SYS_RECVMSG, sockfd, hdr, flags); + + if(ret < 0){ + return -ret; + } + + *length = ret; + + return 0; +} + +int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length){ + long ret = syscall(SYS_SENDMSG, sockfd, hdr, flags); + + if(ret < 0){ + return -ret; + } + + *length = ret; + + return 0; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size){ + long ret = syscall(SYS_SET_SOCKET_OPTIONS, fd, layer, number, buffer, size); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size){ + long ret = syscall(SYS_GET_SOCKET_OPTIONS, fd, layer, number, buffer, size); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds){ + return -syscall(SYS_SOCKETPAIR, domain, type_and_flags, proto, fds); +} + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + return -syscall(SYS_SOCKNAME, fd, addr_ptr, max_addr_length); +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + return -syscall(SYS_PEERNAME, fd, addr_ptr, max_addr_length); +} + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/thread.cpp b/lib/mlibc/sysdeps/lemon/generic/thread.cpp new file mode 100644 index 0000000..42cd758 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/thread.cpp @@ -0,0 +1,53 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/tcb.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <stdint.h> +#include <stddef.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if(mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/lemon/generic/thread_entry.S b/lib/mlibc/sysdeps/lemon/generic/thread_entry.S new file mode 100644 index 0000000..51e703b --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/thread_entry.S @@ -0,0 +1,11 @@ + +.section .text +.global __mlibc_start_thread +__mlibc_start_thread: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_enter_thread + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/access.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/access.h new file mode 120000 index 0000000..171f75f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/mlibc/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/auxv.h new file mode 120000 index 0000000..0f14415 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/lemon/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..e9d9f1b --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..c6dfb6e --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..71f37bb --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/dev_t.h new file mode 120000 index 0000000..0c1143b --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/epoll.h new file mode 120000 index 0000000..9efc3a0 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/errno.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/errno.h new file mode 120000 index 0000000..589859f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/mlibc/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/fcntl.h new file mode 120000 index 0000000..ea5323a --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/mlibc/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/gid_t.h new file mode 120000 index 0000000..6a77218 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/in.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/in.h new file mode 120000 index 0000000..b58c683 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/mlibc/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/ino_t.h new file mode 120000 index 0000000..10d644e --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/inotify.h new file mode 120000 index 0000000..3f19ef6 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/mlibc/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/limits.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/limits.h new file mode 120000 index 0000000..1aa5894 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/mlibc/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/mode_t.h new file mode 120000 index 0000000..29d7733 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/msg.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..7618c27 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/packet.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/packet.h new file mode 120000 index 0000000..47067e2 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/mlibc/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/pid_t.h new file mode 120000 index 0000000..3fd26a7 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/poll.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/poll.h new file mode 120000 index 0000000..ab989c7 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/mlibc/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/ptrace.h new file mode 120000 index 0000000..f391fb7 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/mlibc/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/resource.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/resource.h new file mode 120000 index 0000000..3e59c75 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/mlibc/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/shm.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/signal.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/socket.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/stat.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/stat.h new file mode 120000 index 0000000..82642c3 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/mlibc/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/termios.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/time.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/time.h new file mode 120000 index 0000000..97f3d52 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/mlibc/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/uid_t.h new file mode 120000 index 0000000..1113eba --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/mlibc/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/utsname.h new file mode 120000 index 0000000..17b993f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/mlibc/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..f1a985e --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/mlibc/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/wait.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/lemon/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/include/lemon/syscall.h b/lib/mlibc/sysdeps/lemon/include/lemon/syscall.h new file mode 100755 index 0000000..98db45d --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/lemon/syscall.h @@ -0,0 +1,194 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include <stdint.h> + +#define SYS_EXIT 1 +#define SYS_EXEC 2 +#define SYS_READ 3 +#define SYS_WRITE 4 +#define SYS_OPEN 5 +#define SYS_CLOSE 6 +#define SYS_SLEEP 7 +#define SYS_CREATE 8 +#define SYS_LINK 9 +#define SYS_UNLINK 10 +#define SYS_EXECVE 11 +#define SYS_CHDIR 12 +#define SYS_TIME 13 +#define SYS_MAP_FB 14 +#define SYS_GETTID 15 +#define SYS_CHMOD 16 +#define SYS_FSTAT 17 +#define SYS_STAT 18 +#define SYS_LSEEK 19 +#define SYS_GETPID 20 +#define SYS_MOUNT 21 +#define SYS_MKDIR 22 +#define SYS_RMDIR 23 +#define SYS_RENAME 24 +#define SYS_YIELD 25 +#define SYS_READDIR_NEXT 26 +#define SYS_SEND_MESSAGE 28 +#define SYS_RECEIVE_MESSAGE 29 +#define SYS_UPTIME 30 +#define SYS_GET_VIDEO_MODE 31 +#define SYS_UNAME 32 +#define SYS_READDIR 33 +#define SYS_SET_FS_BASE 34 +#define SYS_MMAP 35 +#define SYS_GET_CWD 37 +#define SYS_WAIT_PID 38 +#define SYS_NANO_SLEEP 39 +#define SYS_PREAD 40 +#define SYS_PWRITE 41 +#define SYS_IOCTL 42 +#define SYS_INFO 43 +#define SYS_MUNMAP 44 +#define SYS_CREATE_SHARED_MEMORY 45 +#define SYS_MAP_SHARED_MEMORY 46 +#define SYS_UNMAP_SHARED_MEMORY 47 +#define SYS_DESTROY_SHARED_MEMORY 48 +#define SYS_SOCKET 49 +#define SYS_BIND 50 +#define SYS_LISTEN 51 +#define SYS_ACCEPT 52 +#define SYS_CONNECT 53 +#define SYS_SEND 54 +#define SYS_SENDTO 55 +#define SYS_RECEIVE 56 +#define SYS_RECEIVEFROM 57 +#define SYS_GETUID 58 +#define SYS_SETUID 59 +#define SYS_POLL 60 +#define SYS_SENDMSG 61 +#define SYS_RECVMSG 62 +#define SYS_GETEUID 63 +#define SYS_SETEUID 64 +#define SYS_GET_PROCESS_INFO 65 +#define SYS_GET_NEXT_PROCESS_INFO 66 +#define SYS_READLINK 67 +#define SYS_SPAWN_THREAD 68 +#define SYS_EXIT_THREAD 69 +#define SYS_FUTEX_WAKE 70 +#define SYS_FUTEX_WAIT 71 +#define SYS_DUP 72 +#define SYS_GET_FILE_STATUS_FLAGS 73 +#define SYS_SET_FILE_STATUS_FLAGS 74 +#define SYS_SELECT 75 +#define SYS_CREATE_SERVICE 76 +#define SYS_CREATE_INTERFACE 77 +#define SYS_INTERFACE_ACCEPT 78 +#define SYS_INTERFACE_CONNECT 79 +#define SYS_ENDPOINT_QUEUE 80 +#define SYS_ENDPOINT_DEQUEUE 81 +#define SYS_ENDPOINT_CALL 82 +#define SYS_ENDPOINT_INFO 83 +#define SYS_KERNELOBJECT_WAIT_ONE 84 +#define SYS_KERNELOBJECT_WAIT 85 +#define SYS_KERNELOBJECT_DESTROY 86 +#define SYS_SET_SOCKET_OPTIONS 87 +#define SYS_GET_SOCKET_OPTIONS 88 +#define SYS_DEVICE_MANAGEMENT 89 +#define SYS_INTERRUPT_THREAD 90 +#define SYS_LOAD_KERNEL_MODULE 91 +#define SYS_UNLOAD_KERNEL_MODULE 92 +#define SYS_FORK 93 +#define SYS_GETGID 94 +#define SYS_GETEGID 95 +#define SYS_GETPPID 96 +#define SYS_PIPE 97 +#define SYS_GETENTROPY 98 +#define SYS_SOCKETPAIR 99 +#define SYS_PEERNAME 100 +#define SYS_SOCKNAME 101 +#define SYS_SIGNAL_ACTION 102 +#define SYS_SIGPROCMASK 103 +#define SYS_KILL 104 +#define SYS_SIGNAL_RETURN 105 +#define SYS_ALARM 106 +#define SYS_GET_RESOURCE_LIMIT 107 +#define SYS_EPOLL_CREATE 108 +#define SYS_EPOLL_CTL 109 +#define SYS_EPOLL_WAIT 110 +#define SYS_FCHDIR 111 + +#ifdef __cplusplus +extern "C"{ +#endif + +__attribute__((__always_inline__)) +static inline long syscalln0(uint64_t call) { + volatile long ret; + asm volatile("int $0x69" : "=a"(ret) : "a"(call)); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln1(uint64_t call, uint64_t arg0) { + volatile long ret; + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln2(uint64_t call, uint64_t arg0, uint64_t arg1) { + volatile long ret; + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0), "S"(arg1) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln3(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2) { + volatile long ret; + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0), "S"(arg1), "d"(arg2) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln4(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) { + volatile long ret; + register uint64_t arg3r asm("r10") = arg3; // put arg3 in r10 + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0), "S"(arg1), "d"(arg2), "r"(arg3r) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln5(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) { + volatile long ret; + register uint64_t arg3r asm("r10") = arg3; // put arg3 in r10 + register uint64_t arg4r asm("r9") = arg4; // put arg4 in r9 + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0), "S"(arg1), "d"(arg2), "r"(arg3r), "r"(arg4r) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long syscalln6(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) { + volatile long ret; + register uint64_t arg3r asm("r10") = arg3; // put arg3 in r10 + register uint64_t arg4r asm("r9") = arg4; // put arg4 in r9 + register uint64_t arg5r asm("r8") = arg5; // put arg5 in r8 + asm volatile("int $0x69" : "=a"(ret) : "a"(call), "D"(arg0), "S"(arg1), "d"(arg2), "r"(arg3r), "r"(arg4r), "r"(arg5r) : "memory"); + return ret; +} + +#ifdef __cplusplus +} + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call) { return syscalln0(call); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0) { return syscalln1(call, arg0); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0, uint64_t arg1) { return syscalln2(call, arg0, arg1); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2) { return syscalln3(call, arg0, arg1, arg2); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) { return syscalln4(call, arg0, arg1, arg2, arg3); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) { return syscalln5(call, arg0, arg1, arg2, arg3, arg4); } + __attribute__((__always_inline__)) static inline long _syscall(uint64_t call, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) { return syscalln6(call, arg0, arg1, arg2, arg3, arg4, arg5); } + + template<typename... T> + __attribute__((__always_inline__)) static inline long syscall(uint64_t call, T... args){ + return _syscall(call, (uint64_t)(args)...); + } +#else + #define GET_SYSCALL(a0, a1, a2, a3, a4, a5, a6, name, ...) name + #define syscall(...) GET_SYSCALL(__VA_ARGS__, syscalln6, syscalln5, syscalln4, syscalln3, syscalln2, syscalln1, syscalln0)(__VA_ARGS__) +#endif + +#endif diff --git a/lib/mlibc/sysdeps/lemon/include/mlibc/thread-entry.hpp b/lib/mlibc/sysdeps/lemon/include/mlibc/thread-entry.hpp new file mode 100644 index 0000000..2dd88a6 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/include/mlibc/thread-entry.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_start_thread(void); +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb); + +namespace mlibc { + void *prepare_stack(void *entry, void *user_arg, void *tcb); +} diff --git a/lib/mlibc/sysdeps/lemon/meson.build b/lib/mlibc/sysdeps/lemon/meson.build new file mode 100644 index 0000000..8704b71 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/meson.build @@ -0,0 +1,81 @@ + +rtdl_sources += files( + 'generic/filesystem.cpp', + 'generic/lemon.cpp', +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/filesystem.cpp', + 'generic/lemon.cpp', + 'generic/pty.cpp', + 'generic/signals.cpp', + 'generic/sockets.cpp', + 'generic/thread_entry.S', + 'generic/thread.cpp' +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + install_headers( + 'include/lemon/syscall.h', + subdir: 'lemon' + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: 'crt-x86_64/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) +endif + diff --git a/lib/mlibc/sysdeps/linux/aarch64/arch-syscall.cpp b/lib/mlibc/sysdeps/linux/aarch64/arch-syscall.cpp new file mode 100644 index 0000000..b178538 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/arch-syscall.cpp @@ -0,0 +1,117 @@ +#include <sys/syscall.h> +#include <bits/syscall.h> + +using sc_word_t = __sc_word_t; + +sc_word_t __do_syscall0(long sc) { + register int sc_reg asm("x8") = sc; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : "r"(sc_reg) : "memory"); + return ret; +} + +sc_word_t __do_syscall1(long sc, + sc_word_t arg1) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall2(long sc, + sc_word_t arg1, sc_word_t arg2) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t arg2_reg asm("x1") = arg2; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall3(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t arg2_reg asm("x1") = arg2; + register sc_word_t arg3_reg asm("x2") = arg3; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall4(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t arg2_reg asm("x1") = arg2; + register sc_word_t arg3_reg asm("x2") = arg3; + register sc_word_t arg4_reg asm("x3") = arg4; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall5(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t arg2_reg asm("x1") = arg2; + register sc_word_t arg3_reg asm("x2") = arg3; + register sc_word_t arg4_reg asm("x3") = arg4; + register sc_word_t arg5_reg asm("x4") = arg5; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg), + "r"(arg5_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall6(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5, sc_word_t arg6) { + register int sc_reg asm("x8") = sc; + register sc_word_t arg1_reg asm("x0") = arg1; + register sc_word_t arg2_reg asm("x1") = arg2; + register sc_word_t arg3_reg asm("x2") = arg3; + register sc_word_t arg4_reg asm("x3") = arg4; + register sc_word_t arg5_reg asm("x4") = arg5; + register sc_word_t arg6_reg asm("x5") = arg6; + register sc_word_t ret asm("x0"); + asm volatile ("svc 0" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg), + "r"(arg5_reg), + "r"(arg6_reg) + : "memory" + ); + return ret; +} diff --git a/lib/mlibc/sysdeps/linux/aarch64/cp_syscall.S b/lib/mlibc/sysdeps/linux/aarch64/cp_syscall.S new file mode 100644 index 0000000..98690c7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/cp_syscall.S @@ -0,0 +1,31 @@ +.section .text +.global __mlibc_do_asm_cp_syscall +.global __mlibc_syscall_begin +.global __mlibc_syscall_end +.type __mlibc_do_asm_cp_syscall, "function" +__mlibc_do_asm_cp_syscall: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + + mrs x7, tpidr_el0 + ldr w7, [x7, #-80] // Tcb::cancelBits. See asserts in tcb.hpp. +__mlibc_syscall_begin: + // tcbCancelEnableBit && tcbCancelTriggerBit + mov x9, #((1 << 0) | (1 << 2)) + and x7, x7, x9 + cmp x7, x9 + b.eq cancel + svc 0 +__mlibc_syscall_end: + ret + +cancel: + bl __mlibc_do_cancel + brk #0 +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/crt-src/Scrt1.S b/lib/mlibc/sysdeps/linux/aarch64/crt-src/Scrt1.S new file mode 100644 index 0000000..547499e --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/crt-src/Scrt1.S @@ -0,0 +1,11 @@ +.section .text +.global _start +_start: + mov x0, sp + adr x1, main + + bl __mlibc_entry + brk #0 + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/crt-src/crt1.S b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crt1.S new file mode 100644 index 0000000..6550612 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crt1.S @@ -0,0 +1,9 @@ +.section .text +.global _start +_start: + mov x0, sp + adrp x1, main + add x1, x1, :lo12:main + bl __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/crt-src/crti.S b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crti.S new file mode 100644 index 0000000..0f5ca0f --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crti.S @@ -0,0 +1,13 @@ +.section .init +.global _init +_init: + stp x29, x30, [sp, -16]! + mov x29, sp + +.section .fini +.global _fini +_fini: + stp x29, x30, [sp, -16]! + mov x29, sp +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/crt-src/crtn.S b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crtn.S new file mode 100644 index 0000000..cd95321 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/crt-src/crtn.S @@ -0,0 +1,9 @@ +.section .init + ldp x29, x30, [sp], #16 + ret + +.section .fini + ldp x29, x30, [sp], #16 + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/signals.S b/lib/mlibc/sysdeps/linux/aarch64/signals.S new file mode 100644 index 0000000..923d8d7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/signals.S @@ -0,0 +1,12 @@ +.section .text + +.global __mlibc_signal_restore +.type __mlibc_signal_restore, @function +__mlibc_signal_restore: +.global __mlibc_signal_restore_rt +.type __mlibc_signal_restore_rt, @function +__mlibc_signal_restore_rt: + mov x8,#139 // SYS_rt_sigreturn + svc 0 +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/aarch64/syscallnos.h b/lib/mlibc/sysdeps/linux/aarch64/syscallnos.h new file mode 100644 index 0000000..9df2598 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/syscallnos.h @@ -0,0 +1,313 @@ +#ifndef __MLIBC_SYSCALLNOS_h +#define __MLIBC_SYSCALLNOS_h +/* This file is autogenerated. Don't bother. */ +/* Generator script: sysdeps/linux/update-syscall-list.py. */ +#define __NR_io_setup 0 +#define __NR_io_destroy 1 +#define __NR_io_submit 2 +#define __NR_io_cancel 3 +#define __NR_io_getevents 4 +#define __NR_setxattr 5 +#define __NR_lsetxattr 6 +#define __NR_fsetxattr 7 +#define __NR_getxattr 8 +#define __NR_lgetxattr 9 +#define __NR_fgetxattr 10 +#define __NR_listxattr 11 +#define __NR_llistxattr 12 +#define __NR_flistxattr 13 +#define __NR_removexattr 14 +#define __NR_lremovexattr 15 +#define __NR_fremovexattr 16 +#define __NR_getcwd 17 +#define __NR_lookup_dcookie 18 +#define __NR_eventfd2 19 +#define __NR_epoll_create1 20 +#define __NR_epoll_ctl 21 +#define __NR_epoll_pwait 22 +#define __NR_dup 23 +#define __NR_dup3 24 +#define __NR_fcntl 25 +#define __NR_inotify_init1 26 +#define __NR_inotify_add_watch 27 +#define __NR_inotify_rm_watch 28 +#define __NR_ioctl 29 +#define __NR_ioprio_set 30 +#define __NR_ioprio_get 31 +#define __NR_flock 32 +#define __NR_mknodat 33 +#define __NR_mkdirat 34 +#define __NR_unlinkat 35 +#define __NR_symlinkat 36 +#define __NR_linkat 37 +#define __NR_renameat 38 +#define __NR_umount2 39 +#define __NR_mount 40 +#define __NR_pivot_root 41 +#define __NR_nfsservctl 42 +#define __NR_statfs 43 +#define __NR_fstatfs 44 +#define __NR_truncate 45 +#define __NR_ftruncate 46 +#define __NR_fallocate 47 +#define __NR_faccessat 48 +#define __NR_chdir 49 +#define __NR_fchdir 50 +#define __NR_chroot 51 +#define __NR_fchmod 52 +#define __NR_fchmodat 53 +#define __NR_fchownat 54 +#define __NR_fchown 55 +#define __NR_openat 56 +#define __NR_close 57 +#define __NR_vhangup 58 +#define __NR_pipe2 59 +#define __NR_quotactl 60 +#define __NR_getdents64 61 +#define __NR_lseek 62 +#define __NR_read 63 +#define __NR_write 64 +#define __NR_readv 65 +#define __NR_writev 66 +#define __NR_pread64 67 +#define __NR_pwrite64 68 +#define __NR_preadv 69 +#define __NR_pwritev 70 +#define __NR_sendfile 71 +#define __NR_pselect6 72 +#define __NR_ppoll 73 +#define __NR_signalfd4 74 +#define __NR_vmsplice 75 +#define __NR_splice 76 +#define __NR_tee 77 +#define __NR_readlinkat 78 +#define __NR_newfstatat 79 +#define __NR_fstat 80 +#define __NR_sync 81 +#define __NR_fsync 82 +#define __NR_fdatasync 83 +#define __NR_sync_file_range 84 +#define __NR_timerfd_create 85 +#define __NR_timerfd_settime 86 +#define __NR_timerfd_gettime 87 +#define __NR_utimensat 88 +#define __NR_acct 89 +#define __NR_capget 90 +#define __NR_capset 91 +#define __NR_personality 92 +#define __NR_exit 93 +#define __NR_exit_group 94 +#define __NR_waitid 95 +#define __NR_set_tid_address 96 +#define __NR_unshare 97 +#define __NR_futex 98 +#define __NR_set_robust_list 99 +#define __NR_get_robust_list 100 +#define __NR_nanosleep 101 +#define __NR_getitimer 102 +#define __NR_setitimer 103 +#define __NR_kexec_load 104 +#define __NR_init_module 105 +#define __NR_delete_module 106 +#define __NR_timer_create 107 +#define __NR_timer_gettime 108 +#define __NR_timer_getoverrun 109 +#define __NR_timer_settime 110 +#define __NR_timer_delete 111 +#define __NR_clock_settime 112 +#define __NR_clock_gettime 113 +#define __NR_clock_getres 114 +#define __NR_clock_nanosleep 115 +#define __NR_syslog 116 +#define __NR_ptrace 117 +#define __NR_sched_setparam 118 +#define __NR_sched_setscheduler 119 +#define __NR_sched_getscheduler 120 +#define __NR_sched_getparam 121 +#define __NR_sched_setaffinity 122 +#define __NR_sched_getaffinity 123 +#define __NR_sched_yield 124 +#define __NR_sched_get_priority_max 125 +#define __NR_sched_get_priority_min 126 +#define __NR_sched_rr_get_interval 127 +#define __NR_restart_syscall 128 +#define __NR_kill 129 +#define __NR_tkill 130 +#define __NR_tgkill 131 +#define __NR_sigaltstack 132 +#define __NR_rt_sigsuspend 133 +#define __NR_rt_sigaction 134 +#define __NR_rt_sigprocmask 135 +#define __NR_rt_sigpending 136 +#define __NR_rt_sigtimedwait 137 +#define __NR_rt_sigqueueinfo 138 +#define __NR_rt_sigreturn 139 +#define __NR_setpriority 140 +#define __NR_getpriority 141 +#define __NR_reboot 142 +#define __NR_setregid 143 +#define __NR_setgid 144 +#define __NR_setreuid 145 +#define __NR_setuid 146 +#define __NR_setresuid 147 +#define __NR_getresuid 148 +#define __NR_setresgid 149 +#define __NR_getresgid 150 +#define __NR_setfsuid 151 +#define __NR_setfsgid 152 +#define __NR_times 153 +#define __NR_setpgid 154 +#define __NR_getpgid 155 +#define __NR_getsid 156 +#define __NR_setsid 157 +#define __NR_getgroups 158 +#define __NR_setgroups 159 +#define __NR_uname 160 +#define __NR_sethostname 161 +#define __NR_setdomainname 162 +#define __NR_getrlimit 163 +#define __NR_setrlimit 164 +#define __NR_getrusage 165 +#define __NR_umask 166 +#define __NR_prctl 167 +#define __NR_getcpu 168 +#define __NR_gettimeofday 169 +#define __NR_settimeofday 170 +#define __NR_adjtimex 171 +#define __NR_getpid 172 +#define __NR_getppid 173 +#define __NR_getuid 174 +#define __NR_geteuid 175 +#define __NR_getgid 176 +#define __NR_getegid 177 +#define __NR_gettid 178 +#define __NR_sysinfo 179 +#define __NR_mq_open 180 +#define __NR_mq_unlink 181 +#define __NR_mq_timedsend 182 +#define __NR_mq_timedreceive 183 +#define __NR_mq_notify 184 +#define __NR_mq_getsetattr 185 +#define __NR_msgget 186 +#define __NR_msgctl 187 +#define __NR_msgrcv 188 +#define __NR_msgsnd 189 +#define __NR_semget 190 +#define __NR_semctl 191 +#define __NR_semtimedop 192 +#define __NR_semop 193 +#define __NR_shmget 194 +#define __NR_shmctl 195 +#define __NR_shmat 196 +#define __NR_shmdt 197 +#define __NR_socket 198 +#define __NR_socketpair 199 +#define __NR_bind 200 +#define __NR_listen 201 +#define __NR_accept 202 +#define __NR_connect 203 +#define __NR_getsockname 204 +#define __NR_getpeername 205 +#define __NR_sendto 206 +#define __NR_recvfrom 207 +#define __NR_setsockopt 208 +#define __NR_getsockopt 209 +#define __NR_shutdown 210 +#define __NR_sendmsg 211 +#define __NR_recvmsg 212 +#define __NR_readahead 213 +#define __NR_brk 214 +#define __NR_munmap 215 +#define __NR_mremap 216 +#define __NR_add_key 217 +#define __NR_request_key 218 +#define __NR_keyctl 219 +#define __NR_clone 220 +#define __NR_execve 221 +#define __NR_mmap 222 +#define __NR_fadvise64 223 +#define __NR_swapon 224 +#define __NR_swapoff 225 +#define __NR_mprotect 226 +#define __NR_msync 227 +#define __NR_mlock 228 +#define __NR_munlock 229 +#define __NR_mlockall 230 +#define __NR_munlockall 231 +#define __NR_mincore 232 +#define __NR_madvise 233 +#define __NR_remap_file_pages 234 +#define __NR_mbind 235 +#define __NR_get_mempolicy 236 +#define __NR_set_mempolicy 237 +#define __NR_migrate_pages 238 +#define __NR_move_pages 239 +#define __NR_rt_tgsigqueueinfo 240 +#define __NR_perf_event_open 241 +#define __NR_accept4 242 +#define __NR_recvmmsg 243 +#define __NR_arch_specific_syscall 244 +#define __NR_wait4 260 +#define __NR_prlimit64 261 +#define __NR_fanotify_init 262 +#define __NR_fanotify_mark 263 +#define __NR_name_to_handle_at 264 +#define __NR_open_by_handle_at 265 +#define __NR_clock_adjtime 266 +#define __NR_syncfs 267 +#define __NR_setns 268 +#define __NR_sendmmsg 269 +#define __NR_process_vm_readv 270 +#define __NR_process_vm_writev 271 +#define __NR_kcmp 272 +#define __NR_finit_module 273 +#define __NR_sched_setattr 274 +#define __NR_sched_getattr 275 +#define __NR_renameat2 276 +#define __NR_seccomp 277 +#define __NR_getrandom 278 +#define __NR_memfd_create 279 +#define __NR_bpf 280 +#define __NR_execveat 281 +#define __NR_userfaultfd 282 +#define __NR_membarrier 283 +#define __NR_mlock2 284 +#define __NR_copy_file_range 285 +#define __NR_preadv2 286 +#define __NR_pwritev2 287 +#define __NR_pkey_mprotect 288 +#define __NR_pkey_alloc 289 +#define __NR_pkey_free 290 +#define __NR_statx 291 +#define __NR_io_pgetevents 292 +#define __NR_rseq 293 +#define __NR_kexec_file_load 294 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 +#define __NR_syscalls 451 +#endif /* __MLIBC_SYSCALLNOS_h */ diff --git a/lib/mlibc/sysdeps/linux/aarch64/thread_entry.S b/lib/mlibc/sysdeps/linux/aarch64/thread_entry.S new file mode 100644 index 0000000..a47a048 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/aarch64/thread_entry.S @@ -0,0 +1,27 @@ +.section .text +.global __mlibc_spawn_thread +.type __mlibc_spawn_thread, "function" +__mlibc_spawn_thread: + // __mlibc_spawn_thread(flags, stack, pid_out, child_tid, tls) + // x0, x1, x2, x3, x4 + // syscall(NR_clone, flags, stack, ptid, tls, ctid) + // x8, x0, x1, x2, x3, x4 + + // Swap x3 <-> x4 + mov x5, x4 + mov x4, x3 + mov x3, x5 + + mov x8, 220 // NR_clone + svc 0 + cbnz x0, .parent + + ldp x0, x1, [sp], #16 + + bl __mlibc_enter_thread + brk #0 + +.parent: + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/generic/cxx-syscall.hpp b/lib/mlibc/sysdeps/linux/generic/cxx-syscall.hpp new file mode 100644 index 0000000..aa7d17c --- /dev/null +++ b/lib/mlibc/sysdeps/linux/generic/cxx-syscall.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include <errno.h> +#include <mlibc/tcb.hpp> +#include <mlibc/thread.hpp> +#include <mlibc-config.h> +#include <utility> + +#include <sys/syscall.h> +#include <bits/syscall.h> + +using sc_word_t = __sc_word_t; + +extern "C" { + extern sc_word_t __mlibc_do_asm_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3, sc_word_t arg4, sc_word_t arg5, sc_word_t arg6); + + extern void __mlibc_do_cancel(); +} + +namespace mlibc { + // C++ wrappers for the extern "C" functions. + inline sc_word_t do_nargs_syscall(int sc) { + return __do_syscall0(sc); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1) { + return __do_syscall1(sc, arg1); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1, sc_word_t arg2) { + return __do_syscall2(sc, arg1, arg2); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3) { + return __do_syscall3(sc, arg1, arg2, arg3); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4) { + return __do_syscall4(sc, arg1, arg2, arg3, arg4); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5) { + return __do_syscall5(sc, arg1, arg2, arg3, arg4, arg5); + } + inline sc_word_t do_nargs_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5, sc_word_t arg6) { + return __do_syscall6(sc, arg1, arg2, arg3, arg4, arg5, arg6); + } + + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1) { + return __mlibc_do_asm_cp_syscall(sc, arg1, 0, 0, 0, 0, 0); + } + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2) { + return __mlibc_do_asm_cp_syscall(sc, arg1, arg2, 0, 0, 0, 0); + } + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2, + sc_word_t arg3) { + return __mlibc_do_asm_cp_syscall(sc, arg1, arg2, arg3, 0, 0, 0); + } + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4) { + return __mlibc_do_asm_cp_syscall(sc, arg1, arg2, arg3, arg4, 0, 0); + } + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5) { + return __mlibc_do_asm_cp_syscall(sc, arg1, arg2, arg3, arg4, arg5, 0); + } + inline sc_word_t do_nargs_cp_syscall(int sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5, sc_word_t arg6) { + return __mlibc_do_asm_cp_syscall(sc, arg1, arg2, arg3, arg4, arg5, arg6); + } + + // Type-safe syscall result type. + enum class sc_result_t : sc_word_t { }; + + // Cast to the argument type of the extern "C" functions. + inline sc_word_t sc_cast(long x) { return x; } + inline sc_word_t sc_cast(const void *x) { return reinterpret_cast<sc_word_t>(x); } + + template<typename... T> + sc_result_t do_syscall(int sc, T... args) { + return static_cast<sc_result_t>(do_nargs_syscall(sc, sc_cast(args)...)); + } + + inline int sc_error(sc_result_t ret) { + auto v = static_cast<sc_word_t>(ret); + if(static_cast<unsigned long>(v) > -4096UL) + return -v; + return 0; + } + + template<typename... T> + sc_result_t do_cp_syscall(int sc, T... args) { +#if __MLIBC_POSIX_OPTION && !MLIBC_BUILDING_RTDL + auto result = static_cast<sc_result_t>(do_nargs_cp_syscall(sc, sc_cast(args)...)); + if (int e = sc_error(result); e) { + auto tcb = reinterpret_cast<Tcb*>(get_current_tcb()); + if (tcb_cancelled(tcb->cancelBits) && e == EINTR) { + __mlibc_do_cancel(); + __builtin_unreachable(); + } + } + return result; +#else + return do_syscall(sc, std::forward<T>(args)...); +#endif // __MLIBC_POSIX_OPTION || !MLIBC_BUILDING_RTDL + } + // Cast from the syscall result type. + template<typename T> + T sc_int_result(sc_result_t ret) { + auto v = static_cast<sc_word_t>(ret); + return v; + } + + template<typename T> + T *sc_ptr_result(sc_result_t ret) { + auto v = static_cast<sc_word_t>(ret); + return reinterpret_cast<T *>(v); + } +} diff --git a/lib/mlibc/sysdeps/linux/generic/entry.cpp b/lib/mlibc/sysdeps/linux/generic/entry.cpp new file mode 100644 index 0000000..aa049ce --- /dev/null +++ b/lib/mlibc/sysdeps/linux/generic/entry.cpp @@ -0,0 +1,38 @@ +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> +#include <sys/auxv.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); +extern "C" void __dlapi_enter(uintptr_t *); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +size_t __hwcap; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(uintptr_t *entry_stack, int (*main_fn)(int argc, char *argv[], char *env[])) { + __dlapi_enter(entry_stack); + __hwcap = getauxval(AT_HWCAP); + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/linux/generic/sysdeps.cpp b/lib/mlibc/sysdeps/linux/generic/sysdeps.cpp new file mode 100644 index 0000000..bc33a9e --- /dev/null +++ b/lib/mlibc/sysdeps/linux/generic/sysdeps.cpp @@ -0,0 +1,2002 @@ +#include <asm/ioctls.h> +#include <errno.h> +#include <limits.h> + +#include <type_traits> + +#include <mlibc-config.h> +#include <bits/ensure.h> +#include <abi-bits/fcntl.h> +#include <abi-bits/socklen_t.h> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> +#include <limits.h> +#include <sys/syscall.h> +#include "cxx-syscall.hpp" + +#define STUB_ONLY { __ensure(!"STUB_ONLY function was called"); __builtin_unreachable(); } +#define UNUSED(x) (void)(x); + +#ifndef MLIBC_BUILDING_RTDL +extern "C" long __do_syscall_ret(unsigned long ret) { + if(ret > -4096UL) { + errno = -ret; + return -1; + } + return ret; +} +#endif + +namespace mlibc { + +void sys_libc_log(const char *message) { + size_t n = 0; + while(message[n]) + n++; + do_syscall(SYS_write, 2, message, n); + char lf = '\n'; + do_syscall(SYS_write, 2, &lf, 1); +} + +void sys_libc_panic() { + __builtin_trap(); +} + +#if defined(__i386__) + +struct user_desc { + unsigned int entry_number; + unsigned long base_addr; + unsigned int limit; + unsigned int seg_32bit: 1; + unsigned int contents: 2; + unsigned int read_exec_only: 1; + unsigned int limit_in_pages: 1; + unsigned int seg_not_present: 1; + unsigned int useable: 1; +}; + +#endif + +int sys_tcb_set(void *pointer) { +#if defined(__x86_64__) + auto ret = do_syscall(SYS_arch_prctl, 0x1002 /* ARCH_SET_FS */, pointer); + if(int e = sc_error(ret); e) + return e; +#elif defined(__i386__) + struct user_desc desc = { + .entry_number = static_cast<unsigned int>(-1), + .base_addr = uintptr_t(pointer), + .limit = 0xfffff, + .seg_32bit = 1, + .contents = 0, + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 1, + }; + auto ret = do_syscall(SYS_set_thread_area, &desc); + __ensure(!sc_error(ret)); + asm volatile ("movw %w0, %%gs" : : "q"(desc.entry_number * 8 + 3) :); +#elif defined(__riscv) + uintptr_t thread_data = reinterpret_cast<uintptr_t>(pointer) + sizeof(Tcb); + asm volatile ("mv tp, %0" :: "r"(thread_data)); +#elif defined (__aarch64__) + uintptr_t thread_data = reinterpret_cast<uintptr_t>(pointer) + sizeof(Tcb) - 0x10; + asm volatile ("msr tpidr_el0, %0" :: "r"(thread_data)); +#else +#error "Missing architecture specific code." +#endif + return 0; +} + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0, pointer); +} +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +int sys_fadvise(int fd, off_t offset, off_t length, int advice) { + auto ret = do_syscall(SYS_fadvise64, fd, offset, length, advice); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + auto ret = do_cp_syscall(SYS_openat, AT_FDCWD, path, flags, mode); + if(int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) { + auto ret = do_syscall(SYS_openat, dirfd, path, flags, mode); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_close(int fd) { + auto ret = do_cp_syscall(SYS_close, fd); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_dup2(int fd, int flags, int newfd) { + auto ret = do_cp_syscall(SYS_dup3, fd, newfd, flags); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_read(int fd, void *buffer, size_t size, ssize_t *bytes_read) { + auto ret = do_cp_syscall(SYS_read, fd, buffer, size); + if(int e = sc_error(ret); e) + return e; + *bytes_read = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { + auto ret = do_cp_syscall(SYS_readv, fd, iovs, iovc); + if(int e = sc_error(ret); e) + return e; + *bytes_read = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_write(int fd, const void *buffer, size_t size, ssize_t *bytes_written) { + auto ret = do_cp_syscall(SYS_write, fd, buffer, size); + if(int e = sc_error(ret); e) + return e; + if(bytes_written) + *bytes_written = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + auto ret = do_syscall(SYS_lseek, fd, offset, whence); + if(int e = sc_error(ret); e) + return e; + *new_offset = sc_int_result<off_t>(ret); + return 0; +} + +int sys_chmod(const char *pathname, mode_t mode) { + auto ret = do_cp_syscall(SYS_fchmodat, AT_FDCWD, pathname, mode); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fchmod(int fd, mode_t mode) { + auto ret = do_cp_syscall(SYS_fchmod, fd, mode); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { + auto ret = do_cp_syscall(SYS_fchmodat, fd, pathname, mode, flags); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) { + auto ret = do_cp_syscall(SYS_fchownat, dirfd, pathname, owner, group, flags); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { + auto ret = do_cp_syscall(SYS_utimensat, dirfd, pathname, times, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, + int fd, off_t offset, void **window) { + if(offset % 4096) + return EINVAL; + if(size >= PTRDIFF_MAX) + return ENOMEM; +#if defined(SYS_mmap2) + auto ret = do_syscall(SYS_mmap2, hint, size, prot, flags, fd, offset/4096); +#else + auto ret = do_syscall(SYS_mmap, hint, size, prot, flags, fd, offset); +#endif + // TODO: musl fixes up EPERM errors from the kernel. + if(int e = sc_error(ret); e) + return e; + *window = sc_ptr_result<void>(ret); + return 0; +} + +int sys_vm_unmap(void *pointer, size_t size) { + auto ret = do_syscall(SYS_munmap, pointer, size); + if(int e = sc_error(ret); e) + return e; + return 0; +} + +// All remaining functions are disabled in ldso. +#ifndef MLIBC_BUILDING_RTDL + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + struct timespec tp = {}; + auto ret = do_syscall(SYS_clock_gettime, clock, &tp); + if (int e = sc_error(ret); e) + return e; + *secs = tp.tv_sec; + *nanos = tp.tv_nsec; + return 0; +} + +int sys_clock_getres(int clock, time_t *secs, long *nanos) { + struct timespec tp = {}; + auto ret = do_syscall(SYS_clock_getres, clock, &tp); + if (int e = sc_error(ret); e) + return e; + *secs = tp.tv_sec; + *nanos = tp.tv_nsec; + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf) { + if (fsfdt == fsfd_target::path) + fd = AT_FDCWD; + else if (fsfdt == fsfd_target::fd) + flags |= AT_EMPTY_PATH; + else + __ensure(fsfdt == fsfd_target::fd_path); + +#if defined(SYS_newfstatat) + auto ret = do_cp_syscall(SYS_newfstatat, fd, path, statbuf, flags); +#else + auto ret = do_cp_syscall(SYS_fstatat64, fd, path, statbuf, flags); +#endif + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_statfs(const char *path, struct statfs *buf) { + auto ret = do_cp_syscall(SYS_statfs, path, buf); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fstatfs(int fd, struct statfs *buf) { + auto ret = do_cp_syscall(SYS_fstatfs, fd, buf); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +extern "C" void __mlibc_signal_restore(void); +extern "C" void __mlibc_signal_restore_rt(void); + +int sys_sigaction(int signum, const struct sigaction *act, + struct sigaction *oldact) { + struct ksigaction { + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + sigset_t mask; + }; + + struct ksigaction kernel_act, kernel_oldact; + if (act) { + kernel_act.handler = act->sa_handler; + kernel_act.flags = act->sa_flags | SA_RESTORER; + kernel_act.restorer = (act->sa_flags & SA_SIGINFO) ? __mlibc_signal_restore_rt : __mlibc_signal_restore; + kernel_act.mask = act->sa_mask; + } + + static_assert(sizeof(sigset_t) == 8); + + auto ret = do_syscall(SYS_rt_sigaction, signum, act ? + &kernel_act : NULL, oldact ? + &kernel_oldact : NULL, sizeof(sigset_t)); + if (int e = sc_error(ret); e) + return e; + + if (oldact) { + oldact->sa_handler = kernel_oldact.handler; + oldact->sa_flags = kernel_oldact.flags; + oldact->sa_restorer = kernel_oldact.restorer; + oldact->sa_mask = kernel_oldact.mask; + } + return 0; +} + +int sys_socket(int domain, int type, int protocol, int *fd) { + auto ret = do_syscall(SYS_socket, domain, type, protocol); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_msg_send(int sockfd, const struct msghdr *msg, int flags, ssize_t *length) { + auto ret = do_cp_syscall(SYS_sendmsg, sockfd, msg, flags); + if (int e = sc_error(ret); e) + return e; + *length = sc_int_result<ssize_t>(ret); + return 0; +} + +ssize_t sys_sendto(int fd, const void *buffer, size_t size, int flags, const struct sockaddr *sock_addr, socklen_t addr_length, ssize_t *length) { + auto ret = do_cp_syscall(SYS_sendto, fd, buffer, size, flags, sock_addr, addr_length); + if(int e = sc_error(ret); e) { + return e; + } + *length = sc_int_result<ssize_t>(ret); + return 0; +} + +ssize_t sys_recvfrom(int fd, void *buffer, size_t size, int flags, struct sockaddr *sock_addr, socklen_t *addr_length, ssize_t *length) { + auto ret = do_cp_syscall(SYS_recvfrom, fd, buffer, size, flags, sock_addr, addr_length); + if(int e = sc_error(ret); e) { + return e; + } + *length = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_msg_recv(int sockfd, struct msghdr *msg, int flags, ssize_t *length) { + auto ret = do_cp_syscall(SYS_recvmsg, sockfd, msg, flags); + if (int e = sc_error(ret); e) + return e; + *length = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_fcntl(int fd, int cmd, va_list args, int *result) { + auto arg = va_arg(args, unsigned long); + // TODO: the api for linux differs for each command so fcntl()s might fail with -EINVAL + // we should implement all the different fcntl()s + // TODO(geert): only some fcntl()s can fail with -EINTR, making do_cp_syscall useless + // on most fcntls(). Another reason to handle different fcntl()s seperately. + auto ret = do_cp_syscall(SYS_fcntl, fd, cmd, arg); + if (int e = sc_error(ret); e) + return e; + *result = sc_int_result<int>(ret); + return 0; +} + +int sys_getcwd(char *buf, size_t size) { + auto ret = do_syscall(SYS_getcwd, buf, size); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +int sys_unlinkat(int dfd, const char *path, int flags) { + auto ret = do_syscall(SYS_unlinkat, dfd, path, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sleep(time_t *secs, long *nanos) { + struct timespec req = { + .tv_sec = *secs, + .tv_nsec = *nanos + }; + struct timespec rem = {}; + + auto ret = do_cp_syscall(SYS_nanosleep, &req, &rem); + if (int e = sc_error(ret); e) + return e; + + *secs = rem.tv_sec; + *nanos = rem.tv_nsec; + return 0; +} + +int sys_isatty(int fd) { + unsigned short winsizeHack[4]; + auto ret = do_syscall(SYS_ioctl, fd, 0x5413 /* TIOCGWINSZ */, &winsizeHack); + if (int e = sc_error(ret); e) + return e; + auto res = sc_int_result<unsigned long>(ret); + if(!res) return 0; + return 1; +} + +#if __MLIBC_POSIX_OPTION + +#include <net/if.h> +#include <sys/ioctl.h> +#include <sys/ipc.h> +#include <sys/user.h> +#include <sys/utsname.h> +#include <sys/stat.h> +#include <sys/sysinfo.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sched.h> +#include <fcntl.h> +#include <pthread.h> + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { + auto ret = do_syscall(SYS_ioctl, fd, request, arg); + if (int e = sc_error(ret); e) + return e; + if (result) + *result = sc_int_result<unsigned long>(ret); + return 0; +} + +int sys_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + auto ret = do_cp_syscall(SYS_connect, sockfd, addr, addrlen); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask, int *num_events) { + // The Linux kernel really wants 7 arguments, even tho this is not supported + // To fix that issue, they use a struct as the last argument. + // See the man page of pselect and the glibc source code + struct { + sigset_t ss; + size_t ss_len; + } data; + data.ss = (uintptr_t)sigmask; + data.ss_len = NSIG / 8; + + auto ret = do_cp_syscall(SYS_pselect6, nfds, readfds, writefds, + exceptfds, timeout, &data); + if (int e = sc_error(ret); e) + return e; + *num_events = sc_int_result<int>(ret); + return 0; +} + +int sys_pipe(int *fds, int flags) { + if(flags) { + auto ret = do_syscall(SYS_pipe2, fds, flags); + if (int e = sc_error(ret); e) + return e; + return 0; + } else { + auto ret = do_syscall(SYS_pipe2, fds, 0); + if (int e = sc_error(ret); e) + return e; + return 0; + } +} + +int sys_fork(pid_t *child) { + auto ret = do_syscall(SYS_clone, SIGCHLD, 0); + if (int e = sc_error(ret); e) + return e; + *child = sc_int_result<int>(ret); + return 0; +} + +int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { + auto ret = do_syscall(SYS_wait4, pid, status, flags, ru); + if (int e = sc_error(ret); e) + return e; + *ret_pid = sc_int_result<pid_t>(ret); + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + auto ret = do_syscall(SYS_execve, path, argv, envp); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sigprocmask(int how, const sigset_t *set, sigset_t *old) { + auto ret = do_syscall(SYS_rt_sigprocmask, how, set, old, NSIG / 8); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) { + auto ret = do_syscall(SYS_setresuid, ruid, euid, suid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) { + auto ret = do_syscall(SYS_setresgid, rgid, egid, sgid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) { + auto ret = do_syscall(SYS_getresuid, &ruid, &euid, &suid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) { + auto ret = do_syscall(SYS_getresgid, &rgid, &egid, &sgid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setreuid(uid_t ruid, uid_t euid) { + auto ret = do_syscall(SYS_setreuid, ruid, euid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setregid(gid_t rgid, gid_t egid) { + auto ret = do_syscall(SYS_setregid, rgid, egid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sysinfo(struct sysinfo *info) { + auto ret = do_syscall(SYS_sysinfo, info); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +void sys_yield() { + do_syscall(SYS_sched_yield); +} + +int sys_clone(void *tcb, pid_t *pid_out, void *stack) { + unsigned long flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND + | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS + | CLONE_PARENT_SETTID; + +#if defined(__riscv) + // TP should point to the address immediately after the TCB. + // TODO: We should change the sysdep so that we don't need to do this. + auto tls = reinterpret_cast<char *>(tcb) + sizeof(Tcb); + tcb = reinterpret_cast<void *>(tls); +#elif defined(__aarch64__) + // TP should point to the address 16 bytes before the end of the TCB. + // TODO: We should change the sysdep so that we don't need to do this. + auto tp = reinterpret_cast<char *>(tcb) + sizeof(Tcb) - 0x10; + tcb = reinterpret_cast<void *>(tp); +#elif defined(__i386__) + /* get the entry number, as we don't request a new one here */ + uint32_t gs; + asm volatile("movw %%gs, %w0" : "=q"(gs)); + + auto user_desc = reinterpret_cast<struct user_desc *>(getAllocator().allocate(sizeof(struct user_desc))); + + user_desc->entry_number = (gs & 0xffff) >> 3; + user_desc->base_addr = uintptr_t(tcb); + user_desc->limit = 0xfffff; + user_desc->seg_32bit = 1; + user_desc->contents = 0; + user_desc->read_exec_only = 0; + user_desc->limit_in_pages = 1; + user_desc->seg_not_present = 0; + user_desc->useable = 1; + + tcb = reinterpret_cast<void *>(user_desc); +#endif + + auto ret = __mlibc_spawn_thread(flags, stack, pid_out, NULL, tcb); + if (ret < 0) + return ret; + + return 0; +} + +extern "C" const char __mlibc_syscall_begin[1]; +extern "C" const char __mlibc_syscall_end[1]; + +#if defined(__riscv) +// Disable UBSan here to work around qemu-user misaligning ucontext_t. +// https://github.com/qemu/qemu/blob/2bf40d0841b942e7ba12953d515e62a436f0af84/linux-user/riscv/signal.c#L68-L69 +[[gnu::no_sanitize("undefined")]] +#endif +int sys_before_cancellable_syscall(ucontext_t *uct) { +#if defined(__x86_64__) + auto pc = reinterpret_cast<void*>(uct->uc_mcontext.gregs[REG_RIP]); +#elif defined(__i386__) + auto pc = reinterpret_cast<void*>(uct->uc_mcontext.gregs[REG_EIP]); +#elif defined(__riscv) + auto pc = reinterpret_cast<void*>(uct->uc_mcontext.gregs[REG_PC]); +#elif defined(__aarch64__) + auto pc = reinterpret_cast<void*>(uct->uc_mcontext.pc); +#else +#error "Missing architecture specific code." +#endif + if (pc < __mlibc_syscall_begin || pc > __mlibc_syscall_end) + return 0; + return 1; +} + +int sys_tgkill(int tgid, int tid, int sig) { + auto ret = do_syscall(SYS_tgkill, tgid, tid, sig); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_tcgetattr(int fd, struct termios *attr) { + auto ret = do_syscall(SYS_ioctl, fd, TCGETS, attr); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + int req; + + switch (optional_action) { + case TCSANOW: req = TCSETS; break; + case TCSADRAIN: req = TCSETSW; break; + case TCSAFLUSH: req = TCSETSF; break; + default: return EINVAL; + } + + auto ret = do_syscall(SYS_ioctl, fd, req, attr); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_tcflush(int fd, int queue) { + auto ret = do_syscall(SYS_ioctl, fd, TCFLSH, queue); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_tcdrain(int fd) { + auto ret = do_syscall(SYS_ioctl, fd, TCSBRK, 1); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_tcflow(int fd, int action) { + auto ret = do_syscall(SYS_ioctl, fd, TCXONC, action); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_access(const char *path, int mode) { + auto ret = do_syscall(SYS_faccessat, AT_FDCWD, path, mode, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_faccessat(int dirfd, const char *pathname, int mode, int flags) { + auto ret = do_syscall(SYS_faccessat, dirfd, pathname, mode, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags) { + auto ret = do_syscall(SYS_accept4, fd, addr_ptr, addr_length, flags); + if (int e = sc_error(ret); e) + return e; + *newfd = sc_int_result<int>(ret); + return 0; +} + +int sys_bind(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + auto ret = do_syscall(SYS_bind, fd, addr_ptr, addr_length, 0, 0, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size) { + auto ret = do_syscall(SYS_setsockopt, fd, layer, number, buffer, size, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + auto ret = do_syscall(SYS_getsockname, fd, addr_ptr, &max_addr_length); + if (int e = sc_error(ret); e) + return e; + *actual_length = max_addr_length; + return 0; +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + auto ret = do_syscall(SYS_getpeername, fd, addr_ptr, &max_addr_length); + if (int e = sc_error(ret); e) + return e; + *actual_length = max_addr_length; + return 0; +} + +int sys_listen(int fd, int backlog) { + auto ret = do_syscall(SYS_listen, fd, backlog, 0, 0, 0, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_shutdown(int sockfd, int how) { + auto ret = do_syscall(SYS_shutdown, sockfd, how); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +int sys_getpriority(int which, id_t who, int *value) { + auto ret = do_syscall(SYS_getpriority, which, who); + if (int e = sc_error(ret); e) { + return e; + } + *value = 20 - sc_int_result<int>(ret); + return 0; +} + +int sys_setpriority(int which, id_t who, int prio) { + auto ret = do_syscall(SYS_setpriority, which, who, prio); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) { + auto ret = do_syscall(SYS_setitimer, which, new_value, old_value); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +/* Linux' uapi does some weird union stuff in place of `sigev_tid`, which we conveniently ignore */ +struct linux_uapi_sigevent { + union sigval sigev_value; + int sigev_signo; + int sigev_notify; + int sigev_tid; +}; + +int sys_timer_create(clockid_t clk, struct sigevent *__restrict evp, timer_t *__restrict res) { + struct linux_uapi_sigevent ksev; + struct linux_uapi_sigevent *ksevp = 0; + int timer_id; + + switch(evp ? evp->sigev_notify : SIGEV_SIGNAL) { + case SIGEV_NONE: + case SIGEV_SIGNAL: { + if(evp) { + ksev.sigev_value = evp->sigev_value; + ksev.sigev_signo = evp->sigev_signo; + ksev.sigev_notify = evp->sigev_notify; + ksev.sigev_tid = 0; + ksevp = &ksev; + } + + auto ret = do_syscall(SYS_timer_create, clk, ksevp, &timer_id); + if (int e = sc_error(ret); e) { + return e; + } + *res = (void *) (intptr_t) timer_id; + break; + } + case SIGEV_THREAD: + __ensure(!"sys_timer_create with evp->sigev_notify == SIGEV_THREAD is unimplemented"); + [[fallthrough]]; + default: + return EINVAL; + } + + return 0; +} + +int sys_timer_settime(timer_t t, int flags, const struct itimerspec *__restrict val, struct itimerspec *__restrict old) { + auto ret = do_syscall(SYS_timer_settime, t, flags, val, old); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +int sys_timer_delete(timer_t t) { + __ensure((intptr_t) t >= 0); + auto ret = do_syscall(SYS_timer_delete, t); + if (int e = sc_error(ret); e) { + return e; + } + return 0; +} + +int sys_ptrace(long req, pid_t pid, void *addr, void *data, long *out) { + auto ret = do_syscall(SYS_ptrace, req, pid, addr, data); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<long>(ret); + return 0; +} + +int sys_open_dir(const char *path, int *fd) { + return sys_open(path, O_DIRECTORY, 0, fd); +} + +int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read) { + auto ret = do_syscall(SYS_getdents64, handle, buffer, max_size); + if(int e = sc_error(ret); e) + return e; + *bytes_read = sc_int_result<int>(ret); + return 0; +} + +int sys_prctl(int op, va_list ap, int *out) { + unsigned long x[4]; + for(int i = 0; i < 4; i++) + x[i] = va_arg(ap, unsigned long); + + auto ret = do_syscall(SYS_prctl, op, x[0], x[1], x[2], x[3]); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<int>(ret); + return 0; +} + +int sys_uname(struct utsname *buf) { + auto ret = do_syscall(SYS_uname, buf); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_gethostname(char *buf, size_t bufsize) { + struct utsname uname_buf; + if (auto e = sys_uname(&uname_buf); e) + return e; + + auto node_len = strlen(uname_buf.nodename); + if (node_len >= bufsize) + return ENAMETOOLONG; + + memcpy(buf, uname_buf.nodename, node_len); + buf[node_len] = '\0'; + return 0; +} + +int sys_pread(int fd, void *buf, size_t n, off_t off, ssize_t *bytes_read) { + auto ret = do_syscall(SYS_pread64, fd, buf, n, off); + if (int e = sc_error(ret); e) + return e; + *bytes_read = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_pwrite(int fd, const void *buf, size_t n, off_t off, ssize_t *bytes_written) { + auto ret = do_syscall(SYS_pwrite64, fd, buf, n, off); + if (int e = sc_error(ret); e) + return e; + *bytes_written = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { + struct timespec tm; + tm.tv_sec = timeout / 1000; + tm.tv_nsec = timeout % 1000 * 1000000; + auto ret = do_syscall(SYS_ppoll, fds, count, timeout >= 0 ? &tm : nullptr, 0, NSIG / 8); + if (int e = sc_error(ret); e) + return e; + *num_events = sc_int_result<int>(ret); + return 0; +} + +int sys_getrusage(int scope, struct rusage *usage) { + auto ret = do_syscall(SYS_getrusage, scope, usage); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_madvise(void *addr, size_t length, int advice) { + auto ret = do_syscall(SYS_madvise, addr, length, advice); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_msync(void *addr, size_t length, int flags) { + auto ret = do_syscall(SYS_msync, addr, length, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_swapon(const char *path, int flags) { + auto ret = do_syscall(SYS_swapon, path, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_swapoff(const char *path) { + auto ret = do_syscall(SYS_swapoff, path); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { + auto ret = do_syscall(SYS_sched_getaffinity, pid, cpusetsize, mask); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_mount(const char *source, const char *target, + const char *fstype, unsigned long flags, const void *data) { + auto ret = do_syscall(SYS_mount, source, target, fstype, flags, data); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_umount2(const char *target, int flags) { + auto ret = do_syscall(SYS_umount2, target, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sethostname(const char *buffer, size_t bufsize) { + auto ret = do_syscall(SYS_sethostname, buffer, bufsize); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_epoll_create(int flags, int *fd) { + auto ret = do_syscall(SYS_epoll_create1, flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { + auto ret = do_syscall(SYS_epoll_ctl, epfd, mode, fd, ev); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, int timeout, const sigset_t *sigmask, int *raised) { + auto ret = do_syscall(SYS_epoll_pwait, epfd, ev, n, timeout, sigmask, NSIG / 8); + if (int e = sc_error(ret); e) + return e; + *raised = sc_int_result<int>(ret); + return 0; +} + +int sys_eventfd_create(unsigned int initval, int flags, int *fd) { + auto ret = do_syscall(SYS_eventfd2, initval, flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_signalfd_create(const sigset_t *masks, int flags, int *fd) { + auto ret = do_syscall(SYS_signalfd4, *fd, masks, sizeof(sigset_t), flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_timerfd_create(int clockid, int flags, int *fd) { + auto ret = do_syscall(SYS_timerfd_create, clockid, flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_timerfd_settime(int fd, int flags, const struct itimerspec *value, struct itimerspec *oldvalue) { + auto ret = do_syscall(SYS_timerfd_settime, fd, flags, value, oldvalue); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_inotify_create(int flags, int *fd) { + auto ret = do_syscall(SYS_inotify_init1, flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_init_module(void *module, unsigned long length, const char *args) { + auto ret = do_syscall(SYS_init_module, module, length, args); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_delete_module(const char *name, unsigned flags) { + auto ret = do_syscall(SYS_delete_module, name, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_klogctl(int type, char *bufp, int len, int *out) { + auto ret = do_syscall(SYS_syslog, type, bufp, len); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<int>(ret); + return 0; +} + +int sys_getcpu(int *cpu) { + auto ret = do_syscall(SYS_getcpu, cpu, NULL, NULL); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { + auto ret = do_syscall(SYS_socketpair, domain, type_and_flags, proto, fds, 0, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size) { + auto ret = do_syscall(SYS_getsockopt, fd, layer, number, buffer, size, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_inotify_add_watch(int ifd, const char *path, uint32_t mask, int *wd) { + auto ret = do_syscall(SYS_inotify_add_watch, ifd, path, mask); + if (int e = sc_error(ret); e) + return e; + *wd = sc_int_result<int>(ret); + return 0; +} + +int sys_inotify_rm_watch(int ifd, int wd) { + auto ret = do_syscall(SYS_inotify_rm_watch, ifd, wd); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_ttyname(int fd, char *buf, size_t size) { + if (!isatty(fd)) + return errno; + + char *procname; + if(int e = asprintf(&procname, "/proc/self/fd/%i", fd); e) + return ENOMEM; + __ensure(procname); + + ssize_t l = readlink(procname, buf, size); + free(procname); + + if (l < 0) + return errno; + else if ((size_t)l >= size) + return ERANGE; + + buf[l] = '\0'; + struct stat st1; + struct stat st2; + + if (stat(buf, &st1) || fstat(fd, &st2)) + return errno; + if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) + return ENODEV; + + return 0; +} + +int sys_pause() { +#ifdef SYS_pause + auto ret = do_syscall(SYS_pause); +#else + auto ret = do_syscall(SYS_ppoll, 0, 0, 0, 0); +#endif + if (int e = sc_error(ret); e) + return e; + return EINTR; +} + +int sys_mlockall(int flags) { + auto ret = do_syscall(SYS_mlockall, flags); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_get_min_priority(int policy, int *out) { + auto ret = do_syscall(SYS_sched_get_priority_min, policy); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<int>(ret); + + return 0; +} + +int sys_getschedparam(void *tcb, int *policy, struct sched_param *param) { + auto t = reinterpret_cast<Tcb *>(tcb); + + if(!t->tid) { + return ESRCH; + } + + auto ret_param = do_syscall(SYS_sched_getparam, t->tid, param); + if (int e = sc_error(ret_param); e) + return e; + + auto ret_sched = do_syscall(SYS_sched_getscheduler, t->tid, param); + if (int e = sc_error(ret_sched); e) + return e; + *policy = sc_int_result<int>(ret_sched); + + return 0; +} + +int sys_setschedparam(void *tcb, int policy, const struct sched_param *param) { + auto t = reinterpret_cast<Tcb *>(tcb); + + if(!t->tid) { + return ESRCH; + } + + auto ret = do_syscall(SYS_sched_setscheduler, t->tid, policy, param); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_if_indextoname(unsigned int index, char *name) { + int fd = 0; + int r = sys_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, &fd); + + if(r) + return r; + + struct ifreq ifr; + ifr.ifr_ifindex = index; + + int ret = sys_ioctl(fd, SIOCGIFNAME, &ifr, NULL); + close(fd); + + if(ret) { + if(ret == ENODEV) + return ENXIO; + return ret; + } + + strncpy(name, ifr.ifr_name, IF_NAMESIZE); + + return 0; +} + +int sys_if_nametoindex(const char *name, unsigned int *ret) { + int fd = 0; + int r = sys_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, &fd); + + if(r) + return r; + + struct ifreq ifr; + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + + r = sys_ioctl(fd, SIOCGIFINDEX, &ifr, NULL); + close(fd); + + if(r) { + return r; + } + + *ret = ifr.ifr_ifindex; + + return 0; +} + +int sys_ptsname(int fd, char *buffer, size_t length) { + int index; + if(int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) + return e; + if((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { + return ERANGE; + } + return 0; +} + +int sys_unlockpt(int fd) { + int unlock = 0; + + if(int e = sys_ioctl(fd, TIOCSPTLCK, &unlock, NULL); e) + return e; + + return 0; +} + +int sys_thread_setname(void *tcb, const char *name) { + if(strlen(name) > 15) { + return ERANGE; + } + + auto t = reinterpret_cast<Tcb *>(tcb); + char *path; + int cs = 0; + + if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { + return ENOMEM; + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + int fd; + if(int e = sys_open(path, O_WRONLY, 0, &fd); e) { + return e; + } + + if(int e = sys_write(fd, name, strlen(name) + 1, NULL)) { + return e; + } + + sys_close(fd); + + pthread_setcancelstate(cs, 0); + + return 0; +} + +int sys_thread_getname(void *tcb, char *name, size_t size) { + auto t = reinterpret_cast<Tcb *>(tcb); + char *path; + int cs = 0; + ssize_t real_size = 0; + + if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { + return ENOMEM; + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + int fd; + if(int e = sys_open(path, O_RDONLY | O_CLOEXEC, 0, &fd); e) { + return e; + } + + if(int e = sys_read(fd, name, size, &real_size)) { + return e; + } + + name[real_size - 1] = 0; + sys_close(fd); + + pthread_setcancelstate(cs, 0); + + if(static_cast<ssize_t>(size) <= real_size) { + return ERANGE; + } + + return 0; +} + +int sys_mlock(const void *addr, size_t length) { + auto ret = do_syscall(SYS_mlock, addr, length); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_munlock(const void *addr, size_t length) { + auto ret = do_syscall(SYS_munlock, addr, length); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_munlockall(void) { + auto ret = do_syscall(SYS_munlockall); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_mincore(void *addr, size_t length, unsigned char *vec) { + auto ret = do_syscall(SYS_mincore, addr, length, vec); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_memfd_create(const char *name, int flags, int *fd) { + auto ret = do_syscall(SYS_memfd_create, name, flags); + if (int e = sc_error(ret); e) + return e; + *fd = sc_int_result<int>(ret); + return 0; +} + +int sys_fallocate(int fd, off_t offset, size_t size) { + auto ret = do_syscall(SYS_fallocate, fd, 0, offset, size); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_flock(int fd, int options) { + auto ret = do_syscall(SYS_flock, fd, options); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_seteuid(uid_t euid) { + return sys_setresuid(-1, euid, -1); +} + +int sys_vm_remap(void *pointer, size_t size, size_t new_size, void **window) { + auto ret = do_syscall(SYS_mremap, pointer, size, new_size, MREMAP_MAYMOVE); + // TODO: musl fixes up EPERM errors from the kernel. + if(int e = sc_error(ret); e) + return e; + *window = sc_ptr_result<void>(ret); + return 0; +} + +int sys_link(const char *old_path, const char *new_path) { +#ifdef SYS_link + auto ret = do_syscall(SYS_link, old_path, new_path); + if (int e = sc_error(ret); e) + return e; + return 0; +#else + auto ret = do_syscall(SYS_linkat, AT_FDCWD, old_path, AT_FDCWD, new_path, 0); + if (int e = sc_error(ret); e) + return e; + return 0; +#endif +} + +// Inspired by musl (src/stat/statvfs.c:28 fixup function) +static void statfs_to_statvfs(struct statfs *from, struct statvfs *to) { + *to = { + .f_bsize = from->f_bsize, + .f_frsize = from->f_frsize ? from->f_frsize : from->f_bsize, + .f_blocks = from->f_blocks, + .f_bfree = from->f_bfree, + .f_bavail = from->f_bavail, + .f_files = from->f_files, + .f_ffree = from->f_ffree, + .f_favail = from->f_ffree, + .f_fsid = (unsigned long) from->f_fsid.__val[0], + .f_flag = from->f_flags, + .f_namemax = from->f_namelen, + }; +} + +int sys_statvfs(const char *path, struct statvfs *out) { + struct statfs buf; + if(auto ret = sys_statfs(path, &buf); ret != 0) { + return ret; + } + statfs_to_statvfs(&buf, out); + return 0; +} + +int sys_fstatvfs(int fd, struct statvfs *out) { + struct statfs buf; + if(auto ret = sys_fstatfs(fd, &buf); ret != 0) { + return ret; + } + statfs_to_statvfs(&buf, out); + return 0; +} + +int sys_sysconf(int num, long *ret) { + switch(num) { + case _SC_OPEN_MAX: { + struct rlimit ru; + if(int e = sys_getrlimit(RLIMIT_NOFILE, &ru); e) { + return e; + } + *ret = (ru.rlim_cur == RLIM_INFINITY) ? -1 : ru.rlim_cur; + break; + } + case _SC_NPROCESSORS_ONLN: { + cpu_set_t set; + CPU_ZERO(&set); + if(int e = sys_getaffinity(0, sizeof(set), &set); e) { + return e; + } + *ret = CPU_COUNT(&set); + break; + } + case _SC_PHYS_PAGES: { + struct sysinfo info; + if(int e = sys_sysinfo(&info); e) { + return e; + } + unsigned unit = (info.mem_unit) ? info.mem_unit : 1; + *ret = std::min(long((info.totalram * unit) / PAGE_SIZE), LONG_MAX); + break; + } + case _SC_CHILD_MAX: { + struct rlimit ru; + if(int e = sys_getrlimit(RLIMIT_NPROC, &ru); e) { + return e; + } + *ret = (ru.rlim_cur == RLIM_INFINITY) ? -1 : ru.rlim_cur; + break; + } + case _SC_LINE_MAX: { + *ret = -1; + break; + } + default: { + return EINVAL; + } + } + + return 0; +} + +int sys_semget(key_t key, int n, int fl, int *id) { + auto ret = do_syscall(SYS_semget, key, n, fl); + if(int e = sc_error(ret); e) + return e; + *id = sc_int_result<int>(ret); + return 0; +} + +int sys_semctl(int semid, int semnum, int cmd, void *semun, int *out) { + auto ret = do_syscall(SYS_semctl, semid, semnum, cmd | IPC_64, semun); + if(int e = sc_error(ret); e) + return e; + *out = sc_int_result<int>(ret); + return 0; +} + +int sys_waitid(idtype_t idtype, id_t id, siginfo_t *info, int options) { + auto ret = do_syscall(SYS_waitid, idtype, id, info, options, 0); + if(int e = sc_error(ret); e) + return e; + return sc_int_result<int>(ret); +} + +#endif // __MLIBC_POSIX_OPTION + +#if __MLIBC_LINUX_OPTION + +#include <linux/reboot.h> + +int sys_reboot(int cmd) { + auto ret = do_syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, nullptr); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +#endif // __MLIBC_LINUX_OPTION + +int sys_times(struct tms *tms, clock_t *out) { + auto ret = do_syscall(SYS_times, tms); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<long>(ret); + return 0; +} + +pid_t sys_getpid() { + auto ret = do_syscall(SYS_getpid); + // getpid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +pid_t sys_gettid() { + auto ret = do_syscall(SYS_gettid); + // gettid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +uid_t sys_getuid() { + auto ret = do_syscall(SYS_getuid); + // getuid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +uid_t sys_geteuid() { + auto ret = do_syscall(SYS_geteuid); + // geteuid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +gid_t sys_getgid() { + auto ret = do_syscall(SYS_getgid); + // getgid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +gid_t sys_getegid() { + auto ret = do_syscall(SYS_getegid); + // getegid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +int sys_kill(int pid, int sig) { + auto ret = do_syscall(SYS_kill, pid, sig); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_vm_protect(void *pointer, size_t size, int prot) { + auto ret = do_syscall(SYS_mprotect, pointer, size, prot); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +void sys_thread_exit() { + do_syscall(SYS_exit, 0); + __builtin_trap(); +} + +void sys_exit(int status) { + do_syscall(SYS_exit_group, status); + __builtin_trap(); +} + +#endif // MLIBC_BUILDING_RTDL + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +int sys_futex_tid() { + auto ret = do_syscall(SYS_gettid); + // gettid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + auto ret = do_cp_syscall(SYS_futex, pointer, FUTEX_WAIT, expected, time); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_futex_wake(int *pointer) { + auto ret = do_syscall(SYS_futex, pointer, FUTEX_WAKE, INT_MAX); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sigsuspend(const sigset_t *set) { + auto ret = do_syscall(SYS_rt_sigsuspend, set, NSIG / 8); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_sigaltstack(const stack_t *ss, stack_t *oss) { + auto ret = do_syscall(SYS_sigaltstack, ss, oss); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_mkdir(const char *path, mode_t mode) { + auto ret = do_syscall(SYS_mkdirat, AT_FDCWD, path, mode); + if (int e = sc_error(ret); e) + return e; + return 0; +} + + +int sys_mkdirat(int dirfd, const char *path, mode_t mode) { + auto ret = do_syscall(SYS_mkdirat, dirfd, path, mode); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_mknodat(int dirfd, const char *path, int mode, int dev) { + auto ret = do_syscall(SYS_mknodat, dirfd, path, mode, dev); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_mkfifoat(int dirfd, const char *path, int mode) { + return sys_mknodat(dirfd, path, mode | S_IFIFO, 0); +} + +int sys_symlink(const char *target_path, const char *link_path) { + auto ret = do_syscall(SYS_symlinkat, target_path, AT_FDCWD, link_path); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_symlinkat(const char *target_path, int dirfd, const char *link_path) { + auto ret = do_syscall(SYS_symlinkat, target_path, dirfd, link_path); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_umask(mode_t mode, mode_t *old) { + auto ret = do_syscall(SYS_umask, mode); + if (int e = sc_error(ret); e) + return e; + *old = sc_int_result<mode_t>(ret); + return 0; +} + +int sys_chdir(const char *path) { + auto ret = do_syscall(SYS_chdir, path); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fchdir(int fd) { + auto ret = do_syscall(SYS_fchdir, fd); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_rename(const char *old_path, const char *new_path) { + return sys_renameat(AT_FDCWD, old_path, AT_FDCWD, new_path); +} + +int sys_renameat(int old_dirfd, const char *old_path, int new_dirfd, const char *new_path) { +#ifdef SYS_renameat2 + auto ret = do_syscall(SYS_renameat2, old_dirfd, old_path, new_dirfd, new_path, 0); +#else + auto ret = do_syscall(SYS_renameat, old_dirfd, old_path, new_dirfd, new_path); +#endif /* defined(SYS_renameat2) */ + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_rmdir(const char *path) { + auto ret = do_syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_ftruncate(int fd, size_t size) { + auto ret = do_syscall(SYS_ftruncate, fd, size); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_readlink(const char *path, void *buf, size_t bufsiz, ssize_t *len) { + auto ret = do_syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsiz); + if (int e = sc_error(ret); e) + return e; + *len = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_getrlimit(int resource, struct rlimit *limit) { + auto ret = do_syscall(SYS_getrlimit, resource, limit); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setrlimit(int resource, const struct rlimit *limit) { + auto ret = do_syscall(SYS_setrlimit, resource, limit); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +pid_t sys_getppid() { + auto ret = do_syscall(SYS_getppid); + // getppid() always succeeds. + return sc_int_result<pid_t>(ret); +} + +int sys_setpgid(pid_t pid, pid_t pgid) { + auto ret = do_syscall(SYS_setpgid, pid, pgid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getsid(pid_t pid, pid_t *sid) { + auto ret = do_syscall(SYS_getsid, pid); + if (int e = sc_error(ret); e) + return e; + *sid = sc_int_result<pid_t>(ret); + return 0; +} + +int sys_setsid(pid_t *sid) { + auto ret = do_syscall(SYS_setsid); + if (int e = sc_error(ret); e) + return e; + *sid = sc_int_result<pid_t>(ret); + return 0; +} + +int sys_setuid(uid_t uid) { + auto ret = do_syscall(SYS_setuid, uid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_setgid(gid_t gid) { + auto ret = do_syscall(SYS_setgid, gid); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getpgid(pid_t pid, pid_t *out) { + auto ret = do_syscall(SYS_getpgid, pid); + if (int e = sc_error(ret); e) + return e; + *out = sc_int_result<pid_t>(ret); + return 0; +} + +int sys_getgroups(size_t size, const gid_t *list, int *retval) { + auto ret = do_syscall(SYS_getgroups, size, list); + if (int e = sc_error(ret); e) + return e; + *retval = sc_int_result<int>(ret); + return 0; +} + +int sys_dup(int fd, int flags, int *newfd) { + __ensure(!flags); + auto ret = do_cp_syscall(SYS_dup, fd); + if (int e = sc_error(ret); e) + return e; + *newfd = sc_int_result<int>(ret); + return 0; +} + +void sys_sync() { + do_syscall(SYS_sync); +} + +int sys_fsync(int fd) { + auto ret = do_syscall(SYS_fsync, fd); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_fdatasync(int fd) { + auto ret = do_syscall(SYS_fdatasync, fd); + if (int e = sc_error(ret); e) + return e; + return 0; +} + +int sys_getrandom(void *buffer, size_t length, int flags, ssize_t *bytes_written) { + auto ret = do_syscall(SYS_getrandom, buffer, length, flags); + if (int e = sc_error(ret); e) + return e; + *bytes_written = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_getentropy(void *buffer, size_t length) { + ssize_t written; + return sys_getrandom(buffer, length, 0, &written); +} + +int sys_setxattr(const char *path, const char *name, const void *val, + size_t size, int flags) { + auto ret = do_syscall(SYS_setxattr, path, name, val, size, flags); + return sc_error(ret); +} + +int sys_lsetxattr(const char *path, const char *name, const void *val, + size_t size, int flags) { + auto ret = do_syscall(SYS_lsetxattr, path, name, val, size, flags); + return sc_error(ret); +} + +int sys_fsetxattr(int fd, const char *name, const void *val, + size_t size, int flags) { + auto ret = do_syscall(SYS_fsetxattr, fd, name, val, size, flags); + return sc_error(ret); +} + +int sys_getxattr(const char *path, const char *name, void *val, size_t size, + ssize_t *nread) { + auto ret = do_syscall(SYS_getxattr, path, name, val, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_lgetxattr(const char *path, const char *name, void *val, size_t size, + ssize_t *nread) { + auto ret = do_syscall(SYS_lgetxattr, path, name, val, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_fgetxattr(int fd, const char *name, void *val, size_t size, + ssize_t *nread) { + auto ret = do_syscall(SYS_fgetxattr, fd, name, val, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_removexattr(const char *path, const char *name) { + auto ret = do_syscall(SYS_removexattr, path, name); + return sc_error(ret); +} + +int sys_lremovexattr(const char *path, const char *name) { + auto ret = do_syscall(SYS_lremovexattr, path, name); + return sc_error(ret); +} + +int sys_fremovexattr(int fd, const char *name) { + auto ret = do_syscall(SYS_fremovexattr, fd, name); + return sc_error(ret); +} + +int sys_listxattr(const char *path, char *list, size_t size, ssize_t *nread) { + auto ret = do_syscall(SYS_listxattr, path, list, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_llistxattr(const char *path, char *list, size_t size, ssize_t *nread) { + auto ret = do_syscall(SYS_llistxattr, path, list, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_flistxattr(int fd, char *list, size_t size, ssize_t *nread) { + auto ret = do_syscall(SYS_flistxattr, fd, list, size); + if (int e = sc_error(ret); e) { + return e; + } + + *nread = sc_int_result<ssize_t>(ret); + return 0; +} + +int sys_sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info, const struct timespec *__restrict timeout, int *out_signal) { + auto ret = do_syscall(SYS_rt_sigtimedwait, set, info, timeout, NSIG / 8); + + if (int e = sc_error(ret); e) + return e; + + *out_signal = sc_int_result<int>(ret); + + return 0; +} + +#if __MLIBC_BSD_OPTION +int sys_brk(void **out) { + auto ret = do_syscall(SYS_brk, 0); + if(int e = sc_error(ret); e) { + return e; + } + + *out = (void *) sc_int_result<uintptr_t>(ret); + return 0; +} +#endif // __MLIBC_BSD_OPTION + +#if __MLIBC_GLIBC_OPTION + +int sys_personality(unsigned long persona, int *out) { + auto ret = do_syscall(SYS_personality, persona); + + if(int e = sc_error(ret); e) { + return e; + } + + *out = sc_int_result<int>(ret); + return 0; +} + +int sys_ioperm(unsigned long int from, unsigned long int num, int turn_on) { +#if defined(SYS_ioperm) + auto ret = do_syscall(SYS_ioperm, from, num, turn_on); + + if(int e = sc_error(ret); e) { + return e; + } + + return 0; +#else + (void) from; + (void) num; + (void) turn_on; + return ENOSYS; +#endif +} + +int sys_iopl(int level) { +#if defined(SYS_iopl) + auto ret = do_syscall(SYS_iopl, level); + + if(int e = sc_error(ret); e) { + return e; + } + + return 0; +#else + (void) level; + return ENOSYS; +#endif +} + +#endif // __MLIBC_GLIBC_OPTION + +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/linux/generic/thread.cpp b/lib/mlibc/sysdeps/linux/generic/thread.cpp new file mode 100644 index 0000000..e413e4f --- /dev/null +++ b/lib/mlibc/sysdeps/linux/generic/thread.cpp @@ -0,0 +1,60 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg) { + // The linux kernel already sets the TCB in sys_clone(). + auto tcb = mlibc::get_current_tcb(); + + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + tcb->invokeThreadFunc(entry, user_arg); + + __atomic_store_n(&tcb->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&tcb->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + (void)tcb; + if (!*stack_size) + *stack_size = default_stacksize; + + uintptr_t map; + if (*stack) { + map = reinterpret_cast<uintptr_t>(*stack); + *guard_size = 0; + } else { + map = reinterpret_cast<uintptr_t>( + mmap(nullptr, *stack_size + *guard_size, + PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + ); + if (reinterpret_cast<void*>(map) == MAP_FAILED) + return EAGAIN; + int ret = mprotect(reinterpret_cast<void*>(map + *guard_size), *stack_size, + PROT_READ | PROT_WRITE); + if(ret) + return EAGAIN; + } + + *stack_base = reinterpret_cast<void*>(map); + auto sp = reinterpret_cast<uintptr_t*>(map + *guard_size + *stack_size); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/linux/include-internal/linux/unistd.h b/lib/mlibc/sysdeps/linux/include-internal/linux/unistd.h new file mode 100644 index 0000000..6a8020e --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include-internal/linux/unistd.h @@ -0,0 +1,2 @@ +/* stub header not present in practice, redirects to our internal syscallnos */ +#include <syscallnos.h> diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/access.h b/lib/mlibc/sysdeps/linux/include/abi-bits/access.h new file mode 120000 index 0000000..cb83931 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/linux/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/linux/include/abi-bits/auxv.h new file mode 120000 index 0000000..c43f878 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/linux/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..0b0ec27 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..7dc8d7c --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..6a42da5 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/dev_t.h new file mode 120000 index 0000000..bca881e --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/linux/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/linux/include/abi-bits/epoll.h new file mode 120000 index 0000000..eb4b76d --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/linux/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/errno.h b/lib/mlibc/sysdeps/linux/include/abi-bits/errno.h new file mode 120000 index 0000000..6e507de --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/linux/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/linux/include/abi-bits/fcntl.h new file mode 120000 index 0000000..463e2c9 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/linux/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/gid_t.h new file mode 120000 index 0000000..abce6d6 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/in.h b/lib/mlibc/sysdeps/linux/include/abi-bits/in.h new file mode 120000 index 0000000..418d1d5 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/linux/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/ino_t.h new file mode 120000 index 0000000..4c20aca --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/linux/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/linux/include/abi-bits/inotify.h new file mode 120000 index 0000000..b5cb282 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/linux/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/linux/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/limits.h b/lib/mlibc/sysdeps/linux/include/abi-bits/limits.h new file mode 120000 index 0000000..6c88db2 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/linux/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/mode_t.h new file mode 120000 index 0000000..5d78fdf --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/linux/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/linux/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/msg.h b/lib/mlibc/sysdeps/linux/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..bb3b625 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/linux/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/packet.h b/lib/mlibc/sysdeps/linux/include/abi-bits/packet.h new file mode 120000 index 0000000..998ef1a --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/linux/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/pid_t.h new file mode 120000 index 0000000..baa90f6 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/poll.h b/lib/mlibc/sysdeps/linux/include/abi-bits/poll.h new file mode 120000 index 0000000..8ea6a0a --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/linux/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/linux/include/abi-bits/ptrace.h new file mode 120000 index 0000000..b2517b2 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/linux/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/linux/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/resource.h b/lib/mlibc/sysdeps/linux/include/abi-bits/resource.h new file mode 120000 index 0000000..88d7402 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/linux/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/linux/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/shm.h b/lib/mlibc/sysdeps/linux/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/signal.h b/lib/mlibc/sysdeps/linux/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/socket.h b/lib/mlibc/sysdeps/linux/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/stat.h b/lib/mlibc/sysdeps/linux/include/abi-bits/stat.h new file mode 120000 index 0000000..1f63b41 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/linux/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/linux/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/linux/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/termios.h b/lib/mlibc/sysdeps/linux/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/time.h b/lib/mlibc/sysdeps/linux/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/linux/include/abi-bits/uid_t.h new file mode 120000 index 0000000..b306777 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/linux/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/linux/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..bbe258c --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/linux/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/vt.h b/lib/mlibc/sysdeps/linux/include/abi-bits/vt.h new file mode 120000 index 0000000..5798a4a --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/vt.h @@ -0,0 +1 @@ +../../../../abis/linux/vt.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/wait.h b/lib/mlibc/sysdeps/linux/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/linux/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/linux/include/bits/syscall.h b/lib/mlibc/sysdeps/linux/include/bits/syscall.h new file mode 100644 index 0000000..3023a3b --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/bits/syscall.h @@ -0,0 +1,90 @@ +#ifndef _MLIBC_SYSCALL_H +#define _MLIBC_SYSCALL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef long __sc_word_t; + +/* These functions are implemented in arch-syscall.cpp. */ +__sc_word_t __do_syscall0(long); +__sc_word_t __do_syscall1(long, __sc_word_t); +__sc_word_t __do_syscall2(long, __sc_word_t, __sc_word_t); +__sc_word_t __do_syscall3(long, __sc_word_t, __sc_word_t, __sc_word_t); +__sc_word_t __do_syscall4(long, __sc_word_t, __sc_word_t, __sc_word_t, __sc_word_t); +__sc_word_t __do_syscall5(long, __sc_word_t, __sc_word_t, __sc_word_t, __sc_word_t, + __sc_word_t); +__sc_word_t __do_syscall6(long, __sc_word_t, __sc_word_t, __sc_word_t, __sc_word_t, + __sc_word_t, __sc_word_t); +__sc_word_t __do_syscall7(long, __sc_word_t, __sc_word_t, __sc_word_t, __sc_word_t, + __sc_word_t, __sc_word_t, __sc_word_t); +long __do_syscall_ret(unsigned long); + +#ifdef __cplusplus +extern "C++" { + +/* Defining a syscall as a macro is more problematic in C++, since there's a high chance of + * a name collision e.g foo.syscall() or foo::syscall. + */ +template<typename Arg0> +long syscall(long n) { + return __do_syscall_ret(__do_syscall0(n)); +} +template<typename Arg0> +long syscall(long n, Arg0 a0) { + return __do_syscall_ret(__do_syscall1(n, (long)a0)); +} +template<typename Arg0, typename Arg1> +long syscall(long n, Arg0 a0, Arg1 a1) { + return __do_syscall_ret(__do_syscall2(n, (long)a0, (long)a1)); +} +template<typename Arg0, typename Arg1, typename Arg2> +long syscall(long n, Arg0 a0, Arg1 a1, Arg2 a2) { + return __do_syscall_ret(__do_syscall3(n, (long)a0, (long)a1, (long)a2)); +} +template<typename Arg0, typename Arg1, typename Arg2, typename Arg3> +long syscall(long n, Arg0 a0, Arg1 a1, Arg2 a2, Arg3 a3) { + return __do_syscall_ret(__do_syscall4(n, (long)a0, (long)a1, (long)a2, (long)a3)); +} +template<typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> +long syscall(long n, Arg0 a0, Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) { + return __do_syscall_ret(__do_syscall5(n, (long)a0, (long)a1, (long)a2, (long)a3, (long)a4)); +} +template<typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> +long syscall(long n, Arg0 a0, Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4, Arg5 a5) { + return __do_syscall_ret(__do_syscall6(n, (long)a0, (long)a1, (long)a2, (long)a3, (long)a4, (long)a5)); +} +template<typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> +long syscall(long n, Arg0 a0, Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4, Arg5 a5, Arg6 a6) { + return __do_syscall_ret(__do_syscall7(n, (long)a0, (long)a1, (long)a2, (long)a3, (long)a4, (long)a5, (long)a6)); +} + +} /* extern C++ */ +#else + +/* These syscall macros were copied from musl. */ +#define __scc(x) ((__sc_word_t)(x)) +#define __syscall0(n) __do_syscall0(n) +#define __syscall1(n,a) __do_syscall1(n,__scc(a)) +#define __syscall2(n,a,b) __do_syscall2(n,__scc(a),__scc(b)) +#define __syscall3(n,a,b,c) __do_syscall3(n,__scc(a),__scc(b),__scc(c)) +#define __syscall4(n,a,b,c,d) __do_syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) +#define __syscall5(n,a,b,c,d,e) __do_syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) +#define __syscall6(n,a,b,c,d,e,f) __do_syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __do_syscall7(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) +#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n +#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0,) +#define __SYSCALL_CONCAT_X(a,b) a##b +#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) +#define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) +#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) +#define syscall(...) __do_syscall_ret(__syscall(__VA_ARGS__)) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _MLIBC_SYSCALL_H diff --git a/lib/mlibc/sysdeps/linux/include/bits/syscall_aliases.h b/lib/mlibc/sysdeps/linux/include/bits/syscall_aliases.h new file mode 100644 index 0000000..b929efc --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/bits/syscall_aliases.h @@ -0,0 +1,1823 @@ +#ifndef __MLIBC_SYSCALL_ALIAS_BIT +#define __MLIBC_SYSCALL_ALIAS_BIT +/* This file is autogenerated. Don't bother. */ +/* Generator script: sysdeps/linux/update-syscall-list.py. */ +#ifdef __NR__llseek +# define SYS__llseek __NR__llseek +#endif +#ifdef __NR__newselect +# define SYS__newselect __NR__newselect +#endif +#ifdef __NR__sysctl +# define SYS__sysctl __NR__sysctl +#endif +#ifdef __NR_accept +# define SYS_accept __NR_accept +#endif +#ifdef __NR_accept4 +# define SYS_accept4 __NR_accept4 +#endif +#ifdef __NR_access +# define SYS_access __NR_access +#endif +#ifdef __NR_acct +# define SYS_acct __NR_acct +#endif +#ifdef __NR_add_key +# define SYS_add_key __NR_add_key +#endif +#ifdef __NR_adjtimex +# define SYS_adjtimex __NR_adjtimex +#endif +#ifdef __NR_alarm +# define SYS_alarm __NR_alarm +#endif +#ifdef __NR_arc_gettls +# define SYS_arc_gettls __NR_arc_gettls +#endif +#ifdef __NR_arc_settls +# define SYS_arc_settls __NR_arc_settls +#endif +#ifdef __NR_arc_usr_cmpxchg +# define SYS_arc_usr_cmpxchg __NR_arc_usr_cmpxchg +#endif +#ifdef __NR_arch_prctl +# define SYS_arch_prctl __NR_arch_prctl +#endif +#ifdef __NR_arch_specific_syscall +# define SYS_arch_specific_syscall __NR_arch_specific_syscall +#endif +#ifdef __NR_arm_fadvise64_64 +# define SYS_arm_fadvise64_64 __NR_arm_fadvise64_64 +#endif +#ifdef __NR_atomic_barrier +# define SYS_atomic_barrier __NR_atomic_barrier +#endif +#ifdef __NR_atomic_cmpxchg_32 +# define SYS_atomic_cmpxchg_32 __NR_atomic_cmpxchg_32 +#endif +#ifdef __NR_bdflush +# define SYS_bdflush __NR_bdflush +#endif +#ifdef __NR_bind +# define SYS_bind __NR_bind +#endif +#ifdef __NR_bpf +# define SYS_bpf __NR_bpf +#endif +#ifdef __NR_brk +# define SYS_brk __NR_brk +#endif +#ifdef __NR_cachectl +# define SYS_cachectl __NR_cachectl +#endif +#ifdef __NR_cacheflush +# define SYS_cacheflush __NR_cacheflush +#endif +#ifdef __NR_capget +# define SYS_capget __NR_capget +#endif +#ifdef __NR_capset +# define SYS_capset __NR_capset +#endif +#ifdef __NR_chdir +# define SYS_chdir __NR_chdir +#endif +#ifdef __NR_chmod +# define SYS_chmod __NR_chmod +#endif +#ifdef __NR_chown +# define SYS_chown __NR_chown +#endif +#ifdef __NR_chown32 +# define SYS_chown32 __NR_chown32 +#endif +#ifdef __NR_chroot +# define SYS_chroot __NR_chroot +#endif +#ifdef __NR_clock_adjtime +# define SYS_clock_adjtime __NR_clock_adjtime +#endif +#ifdef __NR_clock_adjtime64 +# define SYS_clock_adjtime64 __NR_clock_adjtime64 +#endif +#ifdef __NR_clock_getres +# define SYS_clock_getres __NR_clock_getres +#endif +#ifdef __NR_clock_getres_time64 +# define SYS_clock_getres_time64 __NR_clock_getres_time64 +#endif +#ifdef __NR_clock_gettime +# define SYS_clock_gettime __NR_clock_gettime +#endif +#ifdef __NR_clock_gettime64 +# define SYS_clock_gettime64 __NR_clock_gettime64 +#endif +#ifdef __NR_clock_nanosleep +# define SYS_clock_nanosleep __NR_clock_nanosleep +#endif +#ifdef __NR_clock_nanosleep_time64 +# define SYS_clock_nanosleep_time64 __NR_clock_nanosleep_time64 +#endif +#ifdef __NR_clock_settime +# define SYS_clock_settime __NR_clock_settime +#endif +#ifdef __NR_clock_settime64 +# define SYS_clock_settime64 __NR_clock_settime64 +#endif +#ifdef __NR_clone +# define SYS_clone __NR_clone +#endif +#ifdef __NR_clone2 +# define SYS_clone2 __NR_clone2 +#endif +#ifdef __NR_clone3 +# define SYS_clone3 __NR_clone3 +#endif +#ifdef __NR_close +# define SYS_close __NR_close +#endif +#ifdef __NR_close_range +# define SYS_close_range __NR_close_range +#endif +#ifdef __NR_connect +# define SYS_connect __NR_connect +#endif +#ifdef __NR_copy_file_range +# define SYS_copy_file_range __NR_copy_file_range +#endif +#ifdef __NR_creat +# define SYS_creat __NR_creat +#endif +#ifdef __NR_create_module +# define SYS_create_module __NR_create_module +#endif +#ifdef __NR_delete_module +# define SYS_delete_module __NR_delete_module +#endif +#ifdef __NR_dipc +# define SYS_dipc __NR_dipc +#endif +#ifdef __NR_dup +# define SYS_dup __NR_dup +#endif +#ifdef __NR_dup2 +# define SYS_dup2 __NR_dup2 +#endif +#ifdef __NR_dup3 +# define SYS_dup3 __NR_dup3 +#endif +#ifdef __NR_epoll_create +# define SYS_epoll_create __NR_epoll_create +#endif +#ifdef __NR_epoll_create1 +# define SYS_epoll_create1 __NR_epoll_create1 +#endif +#ifdef __NR_epoll_ctl +# define SYS_epoll_ctl __NR_epoll_ctl +#endif +#ifdef __NR_epoll_ctl_old +# define SYS_epoll_ctl_old __NR_epoll_ctl_old +#endif +#ifdef __NR_epoll_pwait +# define SYS_epoll_pwait __NR_epoll_pwait +#endif +#ifdef __NR_epoll_pwait2 +# define SYS_epoll_pwait2 __NR_epoll_pwait2 +#endif +#ifdef __NR_epoll_wait +# define SYS_epoll_wait __NR_epoll_wait +#endif +#ifdef __NR_epoll_wait_old +# define SYS_epoll_wait_old __NR_epoll_wait_old +#endif +#ifdef __NR_eventfd +# define SYS_eventfd __NR_eventfd +#endif +#ifdef __NR_eventfd2 +# define SYS_eventfd2 __NR_eventfd2 +#endif +#ifdef __NR_exec_with_loader +# define SYS_exec_with_loader __NR_exec_with_loader +#endif +#ifdef __NR_execv +# define SYS_execv __NR_execv +#endif +#ifdef __NR_execve +# define SYS_execve __NR_execve +#endif +#ifdef __NR_execveat +# define SYS_execveat __NR_execveat +#endif +#ifdef __NR_exit +# define SYS_exit __NR_exit +#endif +#ifdef __NR_exit_group +# define SYS_exit_group __NR_exit_group +#endif +#ifdef __NR_faccessat +# define SYS_faccessat __NR_faccessat +#endif +#ifdef __NR_faccessat2 +# define SYS_faccessat2 __NR_faccessat2 +#endif +#ifdef __NR_fadvise64 +# define SYS_fadvise64 __NR_fadvise64 +#endif +#ifdef __NR_fadvise64_64 +# define SYS_fadvise64_64 __NR_fadvise64_64 +#endif +#ifdef __NR_fallocate +# define SYS_fallocate __NR_fallocate +#endif +#ifdef __NR_fanotify_init +# define SYS_fanotify_init __NR_fanotify_init +#endif +#ifdef __NR_fanotify_mark +# define SYS_fanotify_mark __NR_fanotify_mark +#endif +#ifdef __NR_fchdir +# define SYS_fchdir __NR_fchdir +#endif +#ifdef __NR_fchmod +# define SYS_fchmod __NR_fchmod +#endif +#ifdef __NR_fchmodat +# define SYS_fchmodat __NR_fchmodat +#endif +#ifdef __NR_fchown +# define SYS_fchown __NR_fchown +#endif +#ifdef __NR_fchown32 +# define SYS_fchown32 __NR_fchown32 +#endif +#ifdef __NR_fchownat +# define SYS_fchownat __NR_fchownat +#endif +#ifdef __NR_fcntl +# define SYS_fcntl __NR_fcntl +#endif +#ifdef __NR_fcntl64 +# define SYS_fcntl64 __NR_fcntl64 +#endif +#ifdef __NR_fdatasync +# define SYS_fdatasync __NR_fdatasync +#endif +#ifdef __NR_fgetxattr +# define SYS_fgetxattr __NR_fgetxattr +#endif +#ifdef __NR_finit_module +# define SYS_finit_module __NR_finit_module +#endif +#ifdef __NR_flistxattr +# define SYS_flistxattr __NR_flistxattr +#endif +#ifdef __NR_flock +# define SYS_flock __NR_flock +#endif +#ifdef __NR_fork +# define SYS_fork __NR_fork +#endif +#ifdef __NR_fremovexattr +# define SYS_fremovexattr __NR_fremovexattr +#endif +#ifdef __NR_fsconfig +# define SYS_fsconfig __NR_fsconfig +#endif +#ifdef __NR_fsetxattr +# define SYS_fsetxattr __NR_fsetxattr +#endif +#ifdef __NR_fsmount +# define SYS_fsmount __NR_fsmount +#endif +#ifdef __NR_fsopen +# define SYS_fsopen __NR_fsopen +#endif +#ifdef __NR_fspick +# define SYS_fspick __NR_fspick +#endif +#ifdef __NR_fstat +# define SYS_fstat __NR_fstat +#endif +#ifdef __NR_fstat64 +# define SYS_fstat64 __NR_fstat64 +#endif +#ifdef __NR_fstatat64 +# define SYS_fstatat64 __NR_fstatat64 +#endif +#ifdef __NR_fstatfs +# define SYS_fstatfs __NR_fstatfs +#endif +#ifdef __NR_fstatfs64 +# define SYS_fstatfs64 __NR_fstatfs64 +#endif +#ifdef __NR_fsync +# define SYS_fsync __NR_fsync +#endif +#ifdef __NR_ftruncate +# define SYS_ftruncate __NR_ftruncate +#endif +#ifdef __NR_ftruncate64 +# define SYS_ftruncate64 __NR_ftruncate64 +#endif +#ifdef __NR_futex +# define SYS_futex __NR_futex +#endif +#ifdef __NR_futex_time64 +# define SYS_futex_time64 __NR_futex_time64 +#endif +#ifdef __NR_futex_waitv +# define SYS_futex_waitv __NR_futex_waitv +#endif +#ifdef __NR_futimesat +# define SYS_futimesat __NR_futimesat +#endif +#ifdef __NR_get_kernel_syms +# define SYS_get_kernel_syms __NR_get_kernel_syms +#endif +#ifdef __NR_get_mempolicy +# define SYS_get_mempolicy __NR_get_mempolicy +#endif +#ifdef __NR_get_robust_list +# define SYS_get_robust_list __NR_get_robust_list +#endif +#ifdef __NR_get_thread_area +# define SYS_get_thread_area __NR_get_thread_area +#endif +#ifdef __NR_getcpu +# define SYS_getcpu __NR_getcpu +#endif +#ifdef __NR_getcwd +# define SYS_getcwd __NR_getcwd +#endif +#ifdef __NR_getdents +# define SYS_getdents __NR_getdents +#endif +#ifdef __NR_getdents64 +# define SYS_getdents64 __NR_getdents64 +#endif +#ifdef __NR_getdomainname +# define SYS_getdomainname __NR_getdomainname +#endif +#ifdef __NR_getdtablesize +# define SYS_getdtablesize __NR_getdtablesize +#endif +#ifdef __NR_getegid +# define SYS_getegid __NR_getegid +#endif +#ifdef __NR_getegid32 +# define SYS_getegid32 __NR_getegid32 +#endif +#ifdef __NR_geteuid +# define SYS_geteuid __NR_geteuid +#endif +#ifdef __NR_geteuid32 +# define SYS_geteuid32 __NR_geteuid32 +#endif +#ifdef __NR_getgid +# define SYS_getgid __NR_getgid +#endif +#ifdef __NR_getgid32 +# define SYS_getgid32 __NR_getgid32 +#endif +#ifdef __NR_getgroups +# define SYS_getgroups __NR_getgroups +#endif +#ifdef __NR_getgroups32 +# define SYS_getgroups32 __NR_getgroups32 +#endif +#ifdef __NR_gethostname +# define SYS_gethostname __NR_gethostname +#endif +#ifdef __NR_getitimer +# define SYS_getitimer __NR_getitimer +#endif +#ifdef __NR_getpagesize +# define SYS_getpagesize __NR_getpagesize +#endif +#ifdef __NR_getpeername +# define SYS_getpeername __NR_getpeername +#endif +#ifdef __NR_getpgid +# define SYS_getpgid __NR_getpgid +#endif +#ifdef __NR_getpgrp +# define SYS_getpgrp __NR_getpgrp +#endif +#ifdef __NR_getpid +# define SYS_getpid __NR_getpid +#endif +#ifdef __NR_getpmsg +# define SYS_getpmsg __NR_getpmsg +#endif +#ifdef __NR_getppid +# define SYS_getppid __NR_getppid +#endif +#ifdef __NR_getpriority +# define SYS_getpriority __NR_getpriority +#endif +#ifdef __NR_getrandom +# define SYS_getrandom __NR_getrandom +#endif +#ifdef __NR_getresgid +# define SYS_getresgid __NR_getresgid +#endif +#ifdef __NR_getresgid32 +# define SYS_getresgid32 __NR_getresgid32 +#endif +#ifdef __NR_getresuid +# define SYS_getresuid __NR_getresuid +#endif +#ifdef __NR_getresuid32 +# define SYS_getresuid32 __NR_getresuid32 +#endif +#ifdef __NR_getrlimit +# define SYS_getrlimit __NR_getrlimit +#endif +#ifdef __NR_getrusage +# define SYS_getrusage __NR_getrusage +#endif +#ifdef __NR_getsid +# define SYS_getsid __NR_getsid +#endif +#ifdef __NR_getsockname +# define SYS_getsockname __NR_getsockname +#endif +#ifdef __NR_getsockopt +# define SYS_getsockopt __NR_getsockopt +#endif +#ifdef __NR_gettid +# define SYS_gettid __NR_gettid +#endif +#ifdef __NR_gettimeofday +# define SYS_gettimeofday __NR_gettimeofday +#endif +#ifdef __NR_getuid +# define SYS_getuid __NR_getuid +#endif +#ifdef __NR_getuid32 +# define SYS_getuid32 __NR_getuid32 +#endif +#ifdef __NR_getunwind +# define SYS_getunwind __NR_getunwind +#endif +#ifdef __NR_getxattr +# define SYS_getxattr __NR_getxattr +#endif +#ifdef __NR_getxgid +# define SYS_getxgid __NR_getxgid +#endif +#ifdef __NR_getxpid +# define SYS_getxpid __NR_getxpid +#endif +#ifdef __NR_getxuid +# define SYS_getxuid __NR_getxuid +#endif +#ifdef __NR_idle +# define SYS_idle __NR_idle +#endif +#ifdef __NR_init_module +# define SYS_init_module __NR_init_module +#endif +#ifdef __NR_inotify_add_watch +# define SYS_inotify_add_watch __NR_inotify_add_watch +#endif +#ifdef __NR_inotify_init +# define SYS_inotify_init __NR_inotify_init +#endif +#ifdef __NR_inotify_init1 +# define SYS_inotify_init1 __NR_inotify_init1 +#endif +#ifdef __NR_inotify_rm_watch +# define SYS_inotify_rm_watch __NR_inotify_rm_watch +#endif +#ifdef __NR_io_cancel +# define SYS_io_cancel __NR_io_cancel +#endif +#ifdef __NR_io_destroy +# define SYS_io_destroy __NR_io_destroy +#endif +#ifdef __NR_io_getevents +# define SYS_io_getevents __NR_io_getevents +#endif +#ifdef __NR_io_pgetevents +# define SYS_io_pgetevents __NR_io_pgetevents +#endif +#ifdef __NR_io_pgetevents_time64 +# define SYS_io_pgetevents_time64 __NR_io_pgetevents_time64 +#endif +#ifdef __NR_io_setup +# define SYS_io_setup __NR_io_setup +#endif +#ifdef __NR_io_submit +# define SYS_io_submit __NR_io_submit +#endif +#ifdef __NR_io_uring_enter +# define SYS_io_uring_enter __NR_io_uring_enter +#endif +#ifdef __NR_io_uring_register +# define SYS_io_uring_register __NR_io_uring_register +#endif +#ifdef __NR_io_uring_setup +# define SYS_io_uring_setup __NR_io_uring_setup +#endif +#ifdef __NR_ioctl +# define SYS_ioctl __NR_ioctl +#endif +#ifdef __NR_ioperm +# define SYS_ioperm __NR_ioperm +#endif +#ifdef __NR_iopl +# define SYS_iopl __NR_iopl +#endif +#ifdef __NR_ioprio_get +# define SYS_ioprio_get __NR_ioprio_get +#endif +#ifdef __NR_ioprio_set +# define SYS_ioprio_set __NR_ioprio_set +#endif +#ifdef __NR_ipc +# define SYS_ipc __NR_ipc +#endif +#ifdef __NR_kcmp +# define SYS_kcmp __NR_kcmp +#endif +#ifdef __NR_kern_features +# define SYS_kern_features __NR_kern_features +#endif +#ifdef __NR_kexec_file_load +# define SYS_kexec_file_load __NR_kexec_file_load +#endif +#ifdef __NR_kexec_load +# define SYS_kexec_load __NR_kexec_load +#endif +#ifdef __NR_keyctl +# define SYS_keyctl __NR_keyctl +#endif +#ifdef __NR_kill +# define SYS_kill __NR_kill +#endif +#ifdef __NR_landlock_add_rule +# define SYS_landlock_add_rule __NR_landlock_add_rule +#endif +#ifdef __NR_landlock_create_ruleset +# define SYS_landlock_create_ruleset __NR_landlock_create_ruleset +#endif +#ifdef __NR_landlock_restrict_self +# define SYS_landlock_restrict_self __NR_landlock_restrict_self +#endif +#ifdef __NR_lchown +# define SYS_lchown __NR_lchown +#endif +#ifdef __NR_lchown32 +# define SYS_lchown32 __NR_lchown32 +#endif +#ifdef __NR_lgetxattr +# define SYS_lgetxattr __NR_lgetxattr +#endif +#ifdef __NR_link +# define SYS_link __NR_link +#endif +#ifdef __NR_linkat +# define SYS_linkat __NR_linkat +#endif +#ifdef __NR_listen +# define SYS_listen __NR_listen +#endif +#ifdef __NR_listxattr +# define SYS_listxattr __NR_listxattr +#endif +#ifdef __NR_llistxattr +# define SYS_llistxattr __NR_llistxattr +#endif +#ifdef __NR_llseek +# define SYS_llseek __NR_llseek +#endif +#ifdef __NR_lookup_dcookie +# define SYS_lookup_dcookie __NR_lookup_dcookie +#endif +#ifdef __NR_lremovexattr +# define SYS_lremovexattr __NR_lremovexattr +#endif +#ifdef __NR_lseek +# define SYS_lseek __NR_lseek +#endif +#ifdef __NR_lsetxattr +# define SYS_lsetxattr __NR_lsetxattr +#endif +#ifdef __NR_lstat +# define SYS_lstat __NR_lstat +#endif +#ifdef __NR_lstat64 +# define SYS_lstat64 __NR_lstat64 +#endif +#ifdef __NR_madvise +# define SYS_madvise __NR_madvise +#endif +#ifdef __NR_mbind +# define SYS_mbind __NR_mbind +#endif +#ifdef __NR_membarrier +# define SYS_membarrier __NR_membarrier +#endif +#ifdef __NR_memfd_create +# define SYS_memfd_create __NR_memfd_create +#endif +#ifdef __NR_memfd_secret +# define SYS_memfd_secret __NR_memfd_secret +#endif +#ifdef __NR_memory_ordering +# define SYS_memory_ordering __NR_memory_ordering +#endif +#ifdef __NR_migrate_pages +# define SYS_migrate_pages __NR_migrate_pages +#endif +#ifdef __NR_mincore +# define SYS_mincore __NR_mincore +#endif +#ifdef __NR_mkdir +# define SYS_mkdir __NR_mkdir +#endif +#ifdef __NR_mkdirat +# define SYS_mkdirat __NR_mkdirat +#endif +#ifdef __NR_mknod +# define SYS_mknod __NR_mknod +#endif +#ifdef __NR_mknodat +# define SYS_mknodat __NR_mknodat +#endif +#ifdef __NR_mlock +# define SYS_mlock __NR_mlock +#endif +#ifdef __NR_mlock2 +# define SYS_mlock2 __NR_mlock2 +#endif +#ifdef __NR_mlockall +# define SYS_mlockall __NR_mlockall +#endif +#ifdef __NR_mmap +# define SYS_mmap __NR_mmap +#endif +#ifdef __NR_mmap2 +# define SYS_mmap2 __NR_mmap2 +#endif +#ifdef __NR_modify_ldt +# define SYS_modify_ldt __NR_modify_ldt +#endif +#ifdef __NR_mount +# define SYS_mount __NR_mount +#endif +#ifdef __NR_mount_setattr +# define SYS_mount_setattr __NR_mount_setattr +#endif +#ifdef __NR_move_mount +# define SYS_move_mount __NR_move_mount +#endif +#ifdef __NR_move_pages +# define SYS_move_pages __NR_move_pages +#endif +#ifdef __NR_mprotect +# define SYS_mprotect __NR_mprotect +#endif +#ifdef __NR_mq_getsetattr +# define SYS_mq_getsetattr __NR_mq_getsetattr +#endif +#ifdef __NR_mq_notify +# define SYS_mq_notify __NR_mq_notify +#endif +#ifdef __NR_mq_open +# define SYS_mq_open __NR_mq_open +#endif +#ifdef __NR_mq_timedreceive +# define SYS_mq_timedreceive __NR_mq_timedreceive +#endif +#ifdef __NR_mq_timedreceive_time64 +# define SYS_mq_timedreceive_time64 __NR_mq_timedreceive_time64 +#endif +#ifdef __NR_mq_timedsend +# define SYS_mq_timedsend __NR_mq_timedsend +#endif +#ifdef __NR_mq_timedsend_time64 +# define SYS_mq_timedsend_time64 __NR_mq_timedsend_time64 +#endif +#ifdef __NR_mq_unlink +# define SYS_mq_unlink __NR_mq_unlink +#endif +#ifdef __NR_mremap +# define SYS_mremap __NR_mremap +#endif +#ifdef __NR_msgctl +# define SYS_msgctl __NR_msgctl +#endif +#ifdef __NR_msgget +# define SYS_msgget __NR_msgget +#endif +#ifdef __NR_msgrcv +# define SYS_msgrcv __NR_msgrcv +#endif +#ifdef __NR_msgsnd +# define SYS_msgsnd __NR_msgsnd +#endif +#ifdef __NR_msync +# define SYS_msync __NR_msync +#endif +#ifdef __NR_multiplexer +# define SYS_multiplexer __NR_multiplexer +#endif +#ifdef __NR_munlock +# define SYS_munlock __NR_munlock +#endif +#ifdef __NR_munlockall +# define SYS_munlockall __NR_munlockall +#endif +#ifdef __NR_munmap +# define SYS_munmap __NR_munmap +#endif +#ifdef __NR_name_to_handle_at +# define SYS_name_to_handle_at __NR_name_to_handle_at +#endif +#ifdef __NR_nanosleep +# define SYS_nanosleep __NR_nanosleep +#endif +#ifdef __NR_newfstatat +# define SYS_newfstatat __NR_newfstatat +#endif +#ifdef __NR_nfsservctl +# define SYS_nfsservctl __NR_nfsservctl +#endif +#ifdef __NR_nice +# define SYS_nice __NR_nice +#endif +#ifdef __NR_old_adjtimex +# define SYS_old_adjtimex __NR_old_adjtimex +#endif +#ifdef __NR_old_getpagesize +# define SYS_old_getpagesize __NR_old_getpagesize +#endif +#ifdef __NR_oldfstat +# define SYS_oldfstat __NR_oldfstat +#endif +#ifdef __NR_oldlstat +# define SYS_oldlstat __NR_oldlstat +#endif +#ifdef __NR_oldolduname +# define SYS_oldolduname __NR_oldolduname +#endif +#ifdef __NR_oldstat +# define SYS_oldstat __NR_oldstat +#endif +#ifdef __NR_oldumount +# define SYS_oldumount __NR_oldumount +#endif +#ifdef __NR_olduname +# define SYS_olduname __NR_olduname +#endif +#ifdef __NR_open +# define SYS_open __NR_open +#endif +#ifdef __NR_open_by_handle_at +# define SYS_open_by_handle_at __NR_open_by_handle_at +#endif +#ifdef __NR_open_tree +# define SYS_open_tree __NR_open_tree +#endif +#ifdef __NR_openat +# define SYS_openat __NR_openat +#endif +#ifdef __NR_openat2 +# define SYS_openat2 __NR_openat2 +#endif +#ifdef __NR_or1k_atomic +# define SYS_or1k_atomic __NR_or1k_atomic +#endif +#ifdef __NR_osf_adjtime +# define SYS_osf_adjtime __NR_osf_adjtime +#endif +#ifdef __NR_osf_afs_syscall +# define SYS_osf_afs_syscall __NR_osf_afs_syscall +#endif +#ifdef __NR_osf_alt_plock +# define SYS_osf_alt_plock __NR_osf_alt_plock +#endif +#ifdef __NR_osf_alt_setsid +# define SYS_osf_alt_setsid __NR_osf_alt_setsid +#endif +#ifdef __NR_osf_alt_sigpending +# define SYS_osf_alt_sigpending __NR_osf_alt_sigpending +#endif +#ifdef __NR_osf_asynch_daemon +# define SYS_osf_asynch_daemon __NR_osf_asynch_daemon +#endif +#ifdef __NR_osf_audcntl +# define SYS_osf_audcntl __NR_osf_audcntl +#endif +#ifdef __NR_osf_audgen +# define SYS_osf_audgen __NR_osf_audgen +#endif +#ifdef __NR_osf_chflags +# define SYS_osf_chflags __NR_osf_chflags +#endif +#ifdef __NR_osf_execve +# define SYS_osf_execve __NR_osf_execve +#endif +#ifdef __NR_osf_exportfs +# define SYS_osf_exportfs __NR_osf_exportfs +#endif +#ifdef __NR_osf_fchflags +# define SYS_osf_fchflags __NR_osf_fchflags +#endif +#ifdef __NR_osf_fdatasync +# define SYS_osf_fdatasync __NR_osf_fdatasync +#endif +#ifdef __NR_osf_fpathconf +# define SYS_osf_fpathconf __NR_osf_fpathconf +#endif +#ifdef __NR_osf_fstat +# define SYS_osf_fstat __NR_osf_fstat +#endif +#ifdef __NR_osf_fstatfs +# define SYS_osf_fstatfs __NR_osf_fstatfs +#endif +#ifdef __NR_osf_fstatfs64 +# define SYS_osf_fstatfs64 __NR_osf_fstatfs64 +#endif +#ifdef __NR_osf_fuser +# define SYS_osf_fuser __NR_osf_fuser +#endif +#ifdef __NR_osf_getaddressconf +# define SYS_osf_getaddressconf __NR_osf_getaddressconf +#endif +#ifdef __NR_osf_getdirentries +# define SYS_osf_getdirentries __NR_osf_getdirentries +#endif +#ifdef __NR_osf_getdomainname +# define SYS_osf_getdomainname __NR_osf_getdomainname +#endif +#ifdef __NR_osf_getfh +# define SYS_osf_getfh __NR_osf_getfh +#endif +#ifdef __NR_osf_getfsstat +# define SYS_osf_getfsstat __NR_osf_getfsstat +#endif +#ifdef __NR_osf_gethostid +# define SYS_osf_gethostid __NR_osf_gethostid +#endif +#ifdef __NR_osf_getitimer +# define SYS_osf_getitimer __NR_osf_getitimer +#endif +#ifdef __NR_osf_getlogin +# define SYS_osf_getlogin __NR_osf_getlogin +#endif +#ifdef __NR_osf_getmnt +# define SYS_osf_getmnt __NR_osf_getmnt +#endif +#ifdef __NR_osf_getrusage +# define SYS_osf_getrusage __NR_osf_getrusage +#endif +#ifdef __NR_osf_getsysinfo +# define SYS_osf_getsysinfo __NR_osf_getsysinfo +#endif +#ifdef __NR_osf_gettimeofday +# define SYS_osf_gettimeofday __NR_osf_gettimeofday +#endif +#ifdef __NR_osf_kloadcall +# define SYS_osf_kloadcall __NR_osf_kloadcall +#endif +#ifdef __NR_osf_kmodcall +# define SYS_osf_kmodcall __NR_osf_kmodcall +#endif +#ifdef __NR_osf_lstat +# define SYS_osf_lstat __NR_osf_lstat +#endif +#ifdef __NR_osf_memcntl +# define SYS_osf_memcntl __NR_osf_memcntl +#endif +#ifdef __NR_osf_mincore +# define SYS_osf_mincore __NR_osf_mincore +#endif +#ifdef __NR_osf_mount +# define SYS_osf_mount __NR_osf_mount +#endif +#ifdef __NR_osf_mremap +# define SYS_osf_mremap __NR_osf_mremap +#endif +#ifdef __NR_osf_msfs_syscall +# define SYS_osf_msfs_syscall __NR_osf_msfs_syscall +#endif +#ifdef __NR_osf_msleep +# define SYS_osf_msleep __NR_osf_msleep +#endif +#ifdef __NR_osf_mvalid +# define SYS_osf_mvalid __NR_osf_mvalid +#endif +#ifdef __NR_osf_mwakeup +# define SYS_osf_mwakeup __NR_osf_mwakeup +#endif +#ifdef __NR_osf_naccept +# define SYS_osf_naccept __NR_osf_naccept +#endif +#ifdef __NR_osf_nfssvc +# define SYS_osf_nfssvc __NR_osf_nfssvc +#endif +#ifdef __NR_osf_ngetpeername +# define SYS_osf_ngetpeername __NR_osf_ngetpeername +#endif +#ifdef __NR_osf_ngetsockname +# define SYS_osf_ngetsockname __NR_osf_ngetsockname +#endif +#ifdef __NR_osf_nrecvfrom +# define SYS_osf_nrecvfrom __NR_osf_nrecvfrom +#endif +#ifdef __NR_osf_nrecvmsg +# define SYS_osf_nrecvmsg __NR_osf_nrecvmsg +#endif +#ifdef __NR_osf_nsendmsg +# define SYS_osf_nsendmsg __NR_osf_nsendmsg +#endif +#ifdef __NR_osf_ntp_adjtime +# define SYS_osf_ntp_adjtime __NR_osf_ntp_adjtime +#endif +#ifdef __NR_osf_ntp_gettime +# define SYS_osf_ntp_gettime __NR_osf_ntp_gettime +#endif +#ifdef __NR_osf_old_creat +# define SYS_osf_old_creat __NR_osf_old_creat +#endif +#ifdef __NR_osf_old_fstat +# define SYS_osf_old_fstat __NR_osf_old_fstat +#endif +#ifdef __NR_osf_old_getpgrp +# define SYS_osf_old_getpgrp __NR_osf_old_getpgrp +#endif +#ifdef __NR_osf_old_killpg +# define SYS_osf_old_killpg __NR_osf_old_killpg +#endif +#ifdef __NR_osf_old_lstat +# define SYS_osf_old_lstat __NR_osf_old_lstat +#endif +#ifdef __NR_osf_old_open +# define SYS_osf_old_open __NR_osf_old_open +#endif +#ifdef __NR_osf_old_sigaction +# define SYS_osf_old_sigaction __NR_osf_old_sigaction +#endif +#ifdef __NR_osf_old_sigblock +# define SYS_osf_old_sigblock __NR_osf_old_sigblock +#endif +#ifdef __NR_osf_old_sigreturn +# define SYS_osf_old_sigreturn __NR_osf_old_sigreturn +#endif +#ifdef __NR_osf_old_sigsetmask +# define SYS_osf_old_sigsetmask __NR_osf_old_sigsetmask +#endif +#ifdef __NR_osf_old_sigvec +# define SYS_osf_old_sigvec __NR_osf_old_sigvec +#endif +#ifdef __NR_osf_old_stat +# define SYS_osf_old_stat __NR_osf_old_stat +#endif +#ifdef __NR_osf_old_vadvise +# define SYS_osf_old_vadvise __NR_osf_old_vadvise +#endif +#ifdef __NR_osf_old_vtrace +# define SYS_osf_old_vtrace __NR_osf_old_vtrace +#endif +#ifdef __NR_osf_old_wait +# define SYS_osf_old_wait __NR_osf_old_wait +#endif +#ifdef __NR_osf_oldquota +# define SYS_osf_oldquota __NR_osf_oldquota +#endif +#ifdef __NR_osf_pathconf +# define SYS_osf_pathconf __NR_osf_pathconf +#endif +#ifdef __NR_osf_pid_block +# define SYS_osf_pid_block __NR_osf_pid_block +#endif +#ifdef __NR_osf_pid_unblock +# define SYS_osf_pid_unblock __NR_osf_pid_unblock +#endif +#ifdef __NR_osf_plock +# define SYS_osf_plock __NR_osf_plock +#endif +#ifdef __NR_osf_priocntlset +# define SYS_osf_priocntlset __NR_osf_priocntlset +#endif +#ifdef __NR_osf_profil +# define SYS_osf_profil __NR_osf_profil +#endif +#ifdef __NR_osf_proplist_syscall +# define SYS_osf_proplist_syscall __NR_osf_proplist_syscall +#endif +#ifdef __NR_osf_reboot +# define SYS_osf_reboot __NR_osf_reboot +#endif +#ifdef __NR_osf_revoke +# define SYS_osf_revoke __NR_osf_revoke +#endif +#ifdef __NR_osf_sbrk +# define SYS_osf_sbrk __NR_osf_sbrk +#endif +#ifdef __NR_osf_security +# define SYS_osf_security __NR_osf_security +#endif +#ifdef __NR_osf_select +# define SYS_osf_select __NR_osf_select +#endif +#ifdef __NR_osf_set_program_attributes +# define SYS_osf_set_program_attributes __NR_osf_set_program_attributes +#endif +#ifdef __NR_osf_set_speculative +# define SYS_osf_set_speculative __NR_osf_set_speculative +#endif +#ifdef __NR_osf_sethostid +# define SYS_osf_sethostid __NR_osf_sethostid +#endif +#ifdef __NR_osf_setitimer +# define SYS_osf_setitimer __NR_osf_setitimer +#endif +#ifdef __NR_osf_setlogin +# define SYS_osf_setlogin __NR_osf_setlogin +#endif +#ifdef __NR_osf_setsysinfo +# define SYS_osf_setsysinfo __NR_osf_setsysinfo +#endif +#ifdef __NR_osf_settimeofday +# define SYS_osf_settimeofday __NR_osf_settimeofday +#endif +#ifdef __NR_osf_shmat +# define SYS_osf_shmat __NR_osf_shmat +#endif +#ifdef __NR_osf_signal +# define SYS_osf_signal __NR_osf_signal +#endif +#ifdef __NR_osf_sigprocmask +# define SYS_osf_sigprocmask __NR_osf_sigprocmask +#endif +#ifdef __NR_osf_sigsendset +# define SYS_osf_sigsendset __NR_osf_sigsendset +#endif +#ifdef __NR_osf_sigstack +# define SYS_osf_sigstack __NR_osf_sigstack +#endif +#ifdef __NR_osf_sigwaitprim +# define SYS_osf_sigwaitprim __NR_osf_sigwaitprim +#endif +#ifdef __NR_osf_sstk +# define SYS_osf_sstk __NR_osf_sstk +#endif +#ifdef __NR_osf_stat +# define SYS_osf_stat __NR_osf_stat +#endif +#ifdef __NR_osf_statfs +# define SYS_osf_statfs __NR_osf_statfs +#endif +#ifdef __NR_osf_statfs64 +# define SYS_osf_statfs64 __NR_osf_statfs64 +#endif +#ifdef __NR_osf_subsys_info +# define SYS_osf_subsys_info __NR_osf_subsys_info +#endif +#ifdef __NR_osf_swapctl +# define SYS_osf_swapctl __NR_osf_swapctl +#endif +#ifdef __NR_osf_swapon +# define SYS_osf_swapon __NR_osf_swapon +#endif +#ifdef __NR_osf_syscall +# define SYS_osf_syscall __NR_osf_syscall +#endif +#ifdef __NR_osf_sysinfo +# define SYS_osf_sysinfo __NR_osf_sysinfo +#endif +#ifdef __NR_osf_table +# define SYS_osf_table __NR_osf_table +#endif +#ifdef __NR_osf_uadmin +# define SYS_osf_uadmin __NR_osf_uadmin +#endif +#ifdef __NR_osf_usleep_thread +# define SYS_osf_usleep_thread __NR_osf_usleep_thread +#endif +#ifdef __NR_osf_uswitch +# define SYS_osf_uswitch __NR_osf_uswitch +#endif +#ifdef __NR_osf_utc_adjtime +# define SYS_osf_utc_adjtime __NR_osf_utc_adjtime +#endif +#ifdef __NR_osf_utc_gettime +# define SYS_osf_utc_gettime __NR_osf_utc_gettime +#endif +#ifdef __NR_osf_utimes +# define SYS_osf_utimes __NR_osf_utimes +#endif +#ifdef __NR_osf_utsname +# define SYS_osf_utsname __NR_osf_utsname +#endif +#ifdef __NR_osf_wait4 +# define SYS_osf_wait4 __NR_osf_wait4 +#endif +#ifdef __NR_osf_waitid +# define SYS_osf_waitid __NR_osf_waitid +#endif +#ifdef __NR_pause +# define SYS_pause __NR_pause +#endif +#ifdef __NR_pciconfig_iobase +# define SYS_pciconfig_iobase __NR_pciconfig_iobase +#endif +#ifdef __NR_pciconfig_read +# define SYS_pciconfig_read __NR_pciconfig_read +#endif +#ifdef __NR_pciconfig_write +# define SYS_pciconfig_write __NR_pciconfig_write +#endif +#ifdef __NR_perf_event_open +# define SYS_perf_event_open __NR_perf_event_open +#endif +#ifdef __NR_perfctr +# define SYS_perfctr __NR_perfctr +#endif +#ifdef __NR_perfmonctl +# define SYS_perfmonctl __NR_perfmonctl +#endif +#ifdef __NR_personality +# define SYS_personality __NR_personality +#endif +#ifdef __NR_pidfd_getfd +# define SYS_pidfd_getfd __NR_pidfd_getfd +#endif +#ifdef __NR_pidfd_open +# define SYS_pidfd_open __NR_pidfd_open +#endif +#ifdef __NR_pidfd_send_signal +# define SYS_pidfd_send_signal __NR_pidfd_send_signal +#endif +#ifdef __NR_pipe +# define SYS_pipe __NR_pipe +#endif +#ifdef __NR_pipe2 +# define SYS_pipe2 __NR_pipe2 +#endif +#ifdef __NR_pivot_root +# define SYS_pivot_root __NR_pivot_root +#endif +#ifdef __NR_pkey_alloc +# define SYS_pkey_alloc __NR_pkey_alloc +#endif +#ifdef __NR_pkey_free +# define SYS_pkey_free __NR_pkey_free +#endif +#ifdef __NR_pkey_mprotect +# define SYS_pkey_mprotect __NR_pkey_mprotect +#endif +#ifdef __NR_poll +# define SYS_poll __NR_poll +#endif +#ifdef __NR_ppoll +# define SYS_ppoll __NR_ppoll +#endif +#ifdef __NR_ppoll_time64 +# define SYS_ppoll_time64 __NR_ppoll_time64 +#endif +#ifdef __NR_prctl +# define SYS_prctl __NR_prctl +#endif +#ifdef __NR_pread64 +# define SYS_pread64 __NR_pread64 +#endif +#ifdef __NR_preadv +# define SYS_preadv __NR_preadv +#endif +#ifdef __NR_preadv2 +# define SYS_preadv2 __NR_preadv2 +#endif +#ifdef __NR_prlimit64 +# define SYS_prlimit64 __NR_prlimit64 +#endif +#ifdef __NR_process_madvise +# define SYS_process_madvise __NR_process_madvise +#endif +#ifdef __NR_process_mrelease +# define SYS_process_mrelease __NR_process_mrelease +#endif +#ifdef __NR_process_vm_readv +# define SYS_process_vm_readv __NR_process_vm_readv +#endif +#ifdef __NR_process_vm_writev +# define SYS_process_vm_writev __NR_process_vm_writev +#endif +#ifdef __NR_pselect6 +# define SYS_pselect6 __NR_pselect6 +#endif +#ifdef __NR_pselect6_time64 +# define SYS_pselect6_time64 __NR_pselect6_time64 +#endif +#ifdef __NR_ptrace +# define SYS_ptrace __NR_ptrace +#endif +#ifdef __NR_pwrite64 +# define SYS_pwrite64 __NR_pwrite64 +#endif +#ifdef __NR_pwritev +# define SYS_pwritev __NR_pwritev +#endif +#ifdef __NR_pwritev2 +# define SYS_pwritev2 __NR_pwritev2 +#endif +#ifdef __NR_query_module +# define SYS_query_module __NR_query_module +#endif +#ifdef __NR_quotactl +# define SYS_quotactl __NR_quotactl +#endif +#ifdef __NR_quotactl_fd +# define SYS_quotactl_fd __NR_quotactl_fd +#endif +#ifdef __NR_read +# define SYS_read __NR_read +#endif +#ifdef __NR_readahead +# define SYS_readahead __NR_readahead +#endif +#ifdef __NR_readdir +# define SYS_readdir __NR_readdir +#endif +#ifdef __NR_readlink +# define SYS_readlink __NR_readlink +#endif +#ifdef __NR_readlinkat +# define SYS_readlinkat __NR_readlinkat +#endif +#ifdef __NR_readv +# define SYS_readv __NR_readv +#endif +#ifdef __NR_reboot +# define SYS_reboot __NR_reboot +#endif +#ifdef __NR_recv +# define SYS_recv __NR_recv +#endif +#ifdef __NR_recvfrom +# define SYS_recvfrom __NR_recvfrom +#endif +#ifdef __NR_recvmmsg +# define SYS_recvmmsg __NR_recvmmsg +#endif +#ifdef __NR_recvmmsg_time64 +# define SYS_recvmmsg_time64 __NR_recvmmsg_time64 +#endif +#ifdef __NR_recvmsg +# define SYS_recvmsg __NR_recvmsg +#endif +#ifdef __NR_remap_file_pages +# define SYS_remap_file_pages __NR_remap_file_pages +#endif +#ifdef __NR_removexattr +# define SYS_removexattr __NR_removexattr +#endif +#ifdef __NR_rename +# define SYS_rename __NR_rename +#endif +#ifdef __NR_renameat +# define SYS_renameat __NR_renameat +#endif +#ifdef __NR_renameat2 +# define SYS_renameat2 __NR_renameat2 +#endif +#ifdef __NR_request_key +# define SYS_request_key __NR_request_key +#endif +#ifdef __NR_restart_syscall +# define SYS_restart_syscall __NR_restart_syscall +#endif +#ifdef __NR_riscv_flush_icache +# define SYS_riscv_flush_icache __NR_riscv_flush_icache +#endif +#ifdef __NR_riscv_hwprobe +# define SYS_riscv_hwprobe __NR_riscv_hwprobe +#endif +#ifdef __NR_rmdir +# define SYS_rmdir __NR_rmdir +#endif +#ifdef __NR_rseq +# define SYS_rseq __NR_rseq +#endif +#ifdef __NR_rt_sigaction +# define SYS_rt_sigaction __NR_rt_sigaction +#endif +#ifdef __NR_rt_sigpending +# define SYS_rt_sigpending __NR_rt_sigpending +#endif +#ifdef __NR_rt_sigprocmask +# define SYS_rt_sigprocmask __NR_rt_sigprocmask +#endif +#ifdef __NR_rt_sigqueueinfo +# define SYS_rt_sigqueueinfo __NR_rt_sigqueueinfo +#endif +#ifdef __NR_rt_sigreturn +# define SYS_rt_sigreturn __NR_rt_sigreturn +#endif +#ifdef __NR_rt_sigsuspend +# define SYS_rt_sigsuspend __NR_rt_sigsuspend +#endif +#ifdef __NR_rt_sigtimedwait +# define SYS_rt_sigtimedwait __NR_rt_sigtimedwait +#endif +#ifdef __NR_rt_sigtimedwait_time64 +# define SYS_rt_sigtimedwait_time64 __NR_rt_sigtimedwait_time64 +#endif +#ifdef __NR_rt_tgsigqueueinfo +# define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo +#endif +#ifdef __NR_rtas +# define SYS_rtas __NR_rtas +#endif +#ifdef __NR_s390_guarded_storage +# define SYS_s390_guarded_storage __NR_s390_guarded_storage +#endif +#ifdef __NR_s390_pci_mmio_read +# define SYS_s390_pci_mmio_read __NR_s390_pci_mmio_read +#endif +#ifdef __NR_s390_pci_mmio_write +# define SYS_s390_pci_mmio_write __NR_s390_pci_mmio_write +#endif +#ifdef __NR_s390_runtime_instr +# define SYS_s390_runtime_instr __NR_s390_runtime_instr +#endif +#ifdef __NR_s390_sthyi +# define SYS_s390_sthyi __NR_s390_sthyi +#endif +#ifdef __NR_sched_get_affinity +# define SYS_sched_get_affinity __NR_sched_get_affinity +#endif +#ifdef __NR_sched_get_priority_max +# define SYS_sched_get_priority_max __NR_sched_get_priority_max +#endif +#ifdef __NR_sched_get_priority_min +# define SYS_sched_get_priority_min __NR_sched_get_priority_min +#endif +#ifdef __NR_sched_getaffinity +# define SYS_sched_getaffinity __NR_sched_getaffinity +#endif +#ifdef __NR_sched_getattr +# define SYS_sched_getattr __NR_sched_getattr +#endif +#ifdef __NR_sched_getparam +# define SYS_sched_getparam __NR_sched_getparam +#endif +#ifdef __NR_sched_getscheduler +# define SYS_sched_getscheduler __NR_sched_getscheduler +#endif +#ifdef __NR_sched_rr_get_interval +# define SYS_sched_rr_get_interval __NR_sched_rr_get_interval +#endif +#ifdef __NR_sched_rr_get_interval_time64 +# define SYS_sched_rr_get_interval_time64 __NR_sched_rr_get_interval_time64 +#endif +#ifdef __NR_sched_set_affinity +# define SYS_sched_set_affinity __NR_sched_set_affinity +#endif +#ifdef __NR_sched_setaffinity +# define SYS_sched_setaffinity __NR_sched_setaffinity +#endif +#ifdef __NR_sched_setattr +# define SYS_sched_setattr __NR_sched_setattr +#endif +#ifdef __NR_sched_setparam +# define SYS_sched_setparam __NR_sched_setparam +#endif +#ifdef __NR_sched_setscheduler +# define SYS_sched_setscheduler __NR_sched_setscheduler +#endif +#ifdef __NR_sched_yield +# define SYS_sched_yield __NR_sched_yield +#endif +#ifdef __NR_seccomp +# define SYS_seccomp __NR_seccomp +#endif +#ifdef __NR_select +# define SYS_select __NR_select +#endif +#ifdef __NR_semctl +# define SYS_semctl __NR_semctl +#endif +#ifdef __NR_semget +# define SYS_semget __NR_semget +#endif +#ifdef __NR_semop +# define SYS_semop __NR_semop +#endif +#ifdef __NR_semtimedop +# define SYS_semtimedop __NR_semtimedop +#endif +#ifdef __NR_semtimedop_time64 +# define SYS_semtimedop_time64 __NR_semtimedop_time64 +#endif +#ifdef __NR_send +# define SYS_send __NR_send +#endif +#ifdef __NR_sendfile +# define SYS_sendfile __NR_sendfile +#endif +#ifdef __NR_sendfile64 +# define SYS_sendfile64 __NR_sendfile64 +#endif +#ifdef __NR_sendmmsg +# define SYS_sendmmsg __NR_sendmmsg +#endif +#ifdef __NR_sendmsg +# define SYS_sendmsg __NR_sendmsg +#endif +#ifdef __NR_sendto +# define SYS_sendto __NR_sendto +#endif +#ifdef __NR_set_mempolicy +# define SYS_set_mempolicy __NR_set_mempolicy +#endif +#ifdef __NR_set_mempolicy_home_node +# define SYS_set_mempolicy_home_node __NR_set_mempolicy_home_node +#endif +#ifdef __NR_set_robust_list +# define SYS_set_robust_list __NR_set_robust_list +#endif +#ifdef __NR_set_thread_area +# define SYS_set_thread_area __NR_set_thread_area +#endif +#ifdef __NR_set_tid_address +# define SYS_set_tid_address __NR_set_tid_address +#endif +#ifdef __NR_setdomainname +# define SYS_setdomainname __NR_setdomainname +#endif +#ifdef __NR_setfsgid +# define SYS_setfsgid __NR_setfsgid +#endif +#ifdef __NR_setfsgid32 +# define SYS_setfsgid32 __NR_setfsgid32 +#endif +#ifdef __NR_setfsuid +# define SYS_setfsuid __NR_setfsuid +#endif +#ifdef __NR_setfsuid32 +# define SYS_setfsuid32 __NR_setfsuid32 +#endif +#ifdef __NR_setgid +# define SYS_setgid __NR_setgid +#endif +#ifdef __NR_setgid32 +# define SYS_setgid32 __NR_setgid32 +#endif +#ifdef __NR_setgroups +# define SYS_setgroups __NR_setgroups +#endif +#ifdef __NR_setgroups32 +# define SYS_setgroups32 __NR_setgroups32 +#endif +#ifdef __NR_sethae +# define SYS_sethae __NR_sethae +#endif +#ifdef __NR_sethostname +# define SYS_sethostname __NR_sethostname +#endif +#ifdef __NR_setitimer +# define SYS_setitimer __NR_setitimer +#endif +#ifdef __NR_setns +# define SYS_setns __NR_setns +#endif +#ifdef __NR_setpgid +# define SYS_setpgid __NR_setpgid +#endif +#ifdef __NR_setpgrp +# define SYS_setpgrp __NR_setpgrp +#endif +#ifdef __NR_setpriority +# define SYS_setpriority __NR_setpriority +#endif +#ifdef __NR_setregid +# define SYS_setregid __NR_setregid +#endif +#ifdef __NR_setregid32 +# define SYS_setregid32 __NR_setregid32 +#endif +#ifdef __NR_setresgid +# define SYS_setresgid __NR_setresgid +#endif +#ifdef __NR_setresgid32 +# define SYS_setresgid32 __NR_setresgid32 +#endif +#ifdef __NR_setresuid +# define SYS_setresuid __NR_setresuid +#endif +#ifdef __NR_setresuid32 +# define SYS_setresuid32 __NR_setresuid32 +#endif +#ifdef __NR_setreuid +# define SYS_setreuid __NR_setreuid +#endif +#ifdef __NR_setreuid32 +# define SYS_setreuid32 __NR_setreuid32 +#endif +#ifdef __NR_setrlimit +# define SYS_setrlimit __NR_setrlimit +#endif +#ifdef __NR_setsid +# define SYS_setsid __NR_setsid +#endif +#ifdef __NR_setsockopt +# define SYS_setsockopt __NR_setsockopt +#endif +#ifdef __NR_settimeofday +# define SYS_settimeofday __NR_settimeofday +#endif +#ifdef __NR_setuid +# define SYS_setuid __NR_setuid +#endif +#ifdef __NR_setuid32 +# define SYS_setuid32 __NR_setuid32 +#endif +#ifdef __NR_setxattr +# define SYS_setxattr __NR_setxattr +#endif +#ifdef __NR_sgetmask +# define SYS_sgetmask __NR_sgetmask +#endif +#ifdef __NR_shmat +# define SYS_shmat __NR_shmat +#endif +#ifdef __NR_shmctl +# define SYS_shmctl __NR_shmctl +#endif +#ifdef __NR_shmdt +# define SYS_shmdt __NR_shmdt +#endif +#ifdef __NR_shmget +# define SYS_shmget __NR_shmget +#endif +#ifdef __NR_shutdown +# define SYS_shutdown __NR_shutdown +#endif +#ifdef __NR_sigaction +# define SYS_sigaction __NR_sigaction +#endif +#ifdef __NR_sigaltstack +# define SYS_sigaltstack __NR_sigaltstack +#endif +#ifdef __NR_signal +# define SYS_signal __NR_signal +#endif +#ifdef __NR_signalfd +# define SYS_signalfd __NR_signalfd +#endif +#ifdef __NR_signalfd4 +# define SYS_signalfd4 __NR_signalfd4 +#endif +#ifdef __NR_sigpending +# define SYS_sigpending __NR_sigpending +#endif +#ifdef __NR_sigprocmask +# define SYS_sigprocmask __NR_sigprocmask +#endif +#ifdef __NR_sigreturn +# define SYS_sigreturn __NR_sigreturn +#endif +#ifdef __NR_sigsuspend +# define SYS_sigsuspend __NR_sigsuspend +#endif +#ifdef __NR_socket +# define SYS_socket __NR_socket +#endif +#ifdef __NR_socketcall +# define SYS_socketcall __NR_socketcall +#endif +#ifdef __NR_socketpair +# define SYS_socketpair __NR_socketpair +#endif +#ifdef __NR_spill +# define SYS_spill __NR_spill +#endif +#ifdef __NR_splice +# define SYS_splice __NR_splice +#endif +#ifdef __NR_spu_create +# define SYS_spu_create __NR_spu_create +#endif +#ifdef __NR_spu_run +# define SYS_spu_run __NR_spu_run +#endif +#ifdef __NR_ssetmask +# define SYS_ssetmask __NR_ssetmask +#endif +#ifdef __NR_stat +# define SYS_stat __NR_stat +#endif +#ifdef __NR_stat64 +# define SYS_stat64 __NR_stat64 +#endif +#ifdef __NR_statfs +# define SYS_statfs __NR_statfs +#endif +#ifdef __NR_statfs64 +# define SYS_statfs64 __NR_statfs64 +#endif +#ifdef __NR_statx +# define SYS_statx __NR_statx +#endif +#ifdef __NR_stime +# define SYS_stime __NR_stime +#endif +#ifdef __NR_subpage_prot +# define SYS_subpage_prot __NR_subpage_prot +#endif +#ifdef __NR_swapcontext +# define SYS_swapcontext __NR_swapcontext +#endif +#ifdef __NR_swapoff +# define SYS_swapoff __NR_swapoff +#endif +#ifdef __NR_swapon +# define SYS_swapon __NR_swapon +#endif +#ifdef __NR_switch_endian +# define SYS_switch_endian __NR_switch_endian +#endif +#ifdef __NR_symlink +# define SYS_symlink __NR_symlink +#endif +#ifdef __NR_symlinkat +# define SYS_symlinkat __NR_symlinkat +#endif +#ifdef __NR_sync +# define SYS_sync __NR_sync +#endif +#ifdef __NR_sync_file_range +# define SYS_sync_file_range __NR_sync_file_range +#endif +#ifdef __NR_sync_file_range2 +# define SYS_sync_file_range2 __NR_sync_file_range2 +#endif +#ifdef __NR_syncfs +# define SYS_syncfs __NR_syncfs +#endif +#ifdef __NR_sys_debug_setcontext +# define SYS_sys_debug_setcontext __NR_sys_debug_setcontext +#endif +#ifdef __NR_syscall +# define SYS_syscall __NR_syscall +#endif +#ifdef __NR_syscalls +# define SYS_syscalls __NR_syscalls +#endif +#ifdef __NR_sysfs +# define SYS_sysfs __NR_sysfs +#endif +#ifdef __NR_sysinfo +# define SYS_sysinfo __NR_sysinfo +#endif +#ifdef __NR_syslog +# define SYS_syslog __NR_syslog +#endif +#ifdef __NR_sysmips +# define SYS_sysmips __NR_sysmips +#endif +#ifdef __NR_tee +# define SYS_tee __NR_tee +#endif +#ifdef __NR_tgkill +# define SYS_tgkill __NR_tgkill +#endif +#ifdef __NR_time +# define SYS_time __NR_time +#endif +#ifdef __NR_timer_create +# define SYS_timer_create __NR_timer_create +#endif +#ifdef __NR_timer_delete +# define SYS_timer_delete __NR_timer_delete +#endif +#ifdef __NR_timer_getoverrun +# define SYS_timer_getoverrun __NR_timer_getoverrun +#endif +#ifdef __NR_timer_gettime +# define SYS_timer_gettime __NR_timer_gettime +#endif +#ifdef __NR_timer_gettime64 +# define SYS_timer_gettime64 __NR_timer_gettime64 +#endif +#ifdef __NR_timer_settime +# define SYS_timer_settime __NR_timer_settime +#endif +#ifdef __NR_timer_settime64 +# define SYS_timer_settime64 __NR_timer_settime64 +#endif +#ifdef __NR_timerfd +# define SYS_timerfd __NR_timerfd +#endif +#ifdef __NR_timerfd_create +# define SYS_timerfd_create __NR_timerfd_create +#endif +#ifdef __NR_timerfd_gettime +# define SYS_timerfd_gettime __NR_timerfd_gettime +#endif +#ifdef __NR_timerfd_gettime64 +# define SYS_timerfd_gettime64 __NR_timerfd_gettime64 +#endif +#ifdef __NR_timerfd_settime +# define SYS_timerfd_settime __NR_timerfd_settime +#endif +#ifdef __NR_timerfd_settime64 +# define SYS_timerfd_settime64 __NR_timerfd_settime64 +#endif +#ifdef __NR_times +# define SYS_times __NR_times +#endif +#ifdef __NR_tkill +# define SYS_tkill __NR_tkill +#endif +#ifdef __NR_truncate +# define SYS_truncate __NR_truncate +#endif +#ifdef __NR_truncate64 +# define SYS_truncate64 __NR_truncate64 +#endif +#ifdef __NR_ugetrlimit +# define SYS_ugetrlimit __NR_ugetrlimit +#endif +#ifdef __NR_umask +# define SYS_umask __NR_umask +#endif +#ifdef __NR_umount +# define SYS_umount __NR_umount +#endif +#ifdef __NR_umount2 +# define SYS_umount2 __NR_umount2 +#endif +#ifdef __NR_uname +# define SYS_uname __NR_uname +#endif +#ifdef __NR_unlink +# define SYS_unlink __NR_unlink +#endif +#ifdef __NR_unlinkat +# define SYS_unlinkat __NR_unlinkat +#endif +#ifdef __NR_unshare +# define SYS_unshare __NR_unshare +#endif +#ifdef __NR_uselib +# define SYS_uselib __NR_uselib +#endif +#ifdef __NR_userfaultfd +# define SYS_userfaultfd __NR_userfaultfd +#endif +#ifdef __NR_ustat +# define SYS_ustat __NR_ustat +#endif +#ifdef __NR_utime +# define SYS_utime __NR_utime +#endif +#ifdef __NR_utimensat +# define SYS_utimensat __NR_utimensat +#endif +#ifdef __NR_utimensat_time64 +# define SYS_utimensat_time64 __NR_utimensat_time64 +#endif +#ifdef __NR_utimes +# define SYS_utimes __NR_utimes +#endif +#ifdef __NR_utrap_install +# define SYS_utrap_install __NR_utrap_install +#endif +#ifdef __NR_vfork +# define SYS_vfork __NR_vfork +#endif +#ifdef __NR_vhangup +# define SYS_vhangup __NR_vhangup +#endif +#ifdef __NR_vm86 +# define SYS_vm86 __NR_vm86 +#endif +#ifdef __NR_vm86old +# define SYS_vm86old __NR_vm86old +#endif +#ifdef __NR_vmsplice +# define SYS_vmsplice __NR_vmsplice +#endif +#ifdef __NR_wait4 +# define SYS_wait4 __NR_wait4 +#endif +#ifdef __NR_waitid +# define SYS_waitid __NR_waitid +#endif +#ifdef __NR_waitpid +# define SYS_waitpid __NR_waitpid +#endif +#ifdef __NR_write +# define SYS_write __NR_write +#endif +#ifdef __NR_writev +# define SYS_writev __NR_writev +#endif +#endif /* __MLIBC_SYSCALL_ALIAS_BIT */ diff --git a/lib/mlibc/sysdeps/linux/include/mlibc/thread-entry.hpp b/lib/mlibc/sysdeps/linux/include/mlibc/thread-entry.hpp new file mode 100644 index 0000000..a20cab5 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/mlibc/thread-entry.hpp @@ -0,0 +1,12 @@ +#ifndef MLIBC_THREAD_ENTRY + +#include <mlibc/tcb.hpp> + +extern "C" int __mlibc_spawn_thread(int flags, void *stack, void *pid_out, void *child_tid, void *tcb); +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg); + +namespace mlibc { + void *prepare_stack(void *entry, void *user_arg); +} + +#endif // MLIBC_THREAD_ENTRY diff --git a/lib/mlibc/sysdeps/linux/include/sys/syscall.h b/lib/mlibc/sysdeps/linux/include/sys/syscall.h new file mode 100644 index 0000000..2084103 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/sys/syscall.h @@ -0,0 +1,12 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +/* On GNU/Linux, this header provides includes __NR_-prefixed syscall numbers, + * and their SYS_ aliases. We defer to kernel headers for the numbers + * (linux-headers, or an autogenerated stub while building), and an + * autogenerated file containing SYS_ defines. + */ +#include <linux/unistd.h> +#include <bits/syscall_aliases.h> + +#endif // _SYS_SYSCALL_H diff --git a/lib/mlibc/sysdeps/linux/include/syscall.h b/lib/mlibc/sysdeps/linux/include/syscall.h new file mode 100644 index 0000000..4c30578 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/include/syscall.h @@ -0,0 +1 @@ +#include <sys/syscall.h> diff --git a/lib/mlibc/sysdeps/linux/meson.build b/lib/mlibc/sysdeps/linux/meson.build new file mode 100644 index 0000000..0809237 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/meson.build @@ -0,0 +1,143 @@ +rtdl_dso_sources += files( + host_machine.cpu_family() / 'arch-syscall.cpp', + 'generic/sysdeps.cpp', +) + +linux_include_dirs = [ + include_directories(host_machine.cpu_family()), + include_directories('include-internal/'), +] + +rtdl_include_dirs += linux_include_dirs +libc_include_dirs += linux_include_dirs +libc_sources += files( + host_machine.cpu_family() / 'signals.S', + host_machine.cpu_family() / 'arch-syscall.cpp', + 'generic/entry.cpp', + 'generic/sysdeps.cpp', +) + +if not disable_posix_option + libc_sources += files( + 'generic/thread.cpp', + host_machine.cpu_family() / 'cp_syscall.S', + host_machine.cpu_family() / 'thread_entry.S' + ) +endif + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/reboot.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/vt.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + + install_headers('include/syscall.h') + install_headers('include/sys/syscall.h', subdir: 'sys') + install_headers( + 'include/bits/syscall.h', + 'include/bits/syscall_aliases.h', + subdir: 'bits' + ) +endif + +if not headers_only + crt = custom_target('crt1', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crt1.S', + output: 'crt1.o', + install: true, + install_dir: get_option('libdir') + ) + + crt_pie = custom_target('Scrt1', + build_by_default: true, + command: c_compiler.cmd_array() + ['-fPIE', '-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/Scrt1.S', + output: 'Scrt1.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crti', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crti.S', + output: 'crti.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crtn', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crtn.S', + output: 'crtn.o', + install: true, + install_dir: get_option('libdir') + ) + + wrapper_conf = configuration_data() + wrapper_conf.set('LIBDIR', get_option('libdir')) + wrapper_conf.set('PREFIX', get_option('prefix')) + specs = configure_file(input: 'mlibc-gcc.specs.in', + output: 'mlibc-gcc.specs', + configuration: wrapper_conf) + + wrapper_script = configure_file(input: 'mlibc-gcc.in', + output: 'mlibc-gcc', + configuration: wrapper_conf) + + install_data(specs, + install_dir: get_option('libdir') + ) + + install_data(wrapper_script, + install_dir: get_option('bindir') + ) +endif diff --git a/lib/mlibc/sysdeps/linux/mlibc-gcc.in b/lib/mlibc/sysdeps/linux/mlibc-gcc.in new file mode 100755 index 0000000..6236bd6 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/mlibc-gcc.in @@ -0,0 +1,2 @@ +#!/bin/sh +exec "${REALGCC:-gcc}" "$@" -specs "@PREFIX@/@LIBDIR@/mlibc-gcc.specs" diff --git a/lib/mlibc/sysdeps/linux/mlibc-gcc.specs.in b/lib/mlibc/sysdeps/linux/mlibc-gcc.specs.in new file mode 100644 index 0000000..4304c4d --- /dev/null +++ b/lib/mlibc/sysdeps/linux/mlibc-gcc.specs.in @@ -0,0 +1,32 @@ +%rename cpp_options old_cpp_options + +*cpp_options: +-nostdinc -isystem @PREFIX@/include -isystem include%s %(old_cpp_options) + +*cc1: +%(cc1_cpu) -nostdinc -isystem @PREFIX@/include -isystem include%s + +*link_libgcc: +-L@PREFIX@/@LIBDIR@ -L .%s + +*libgcc: +libgcc.a%s %:if-exists(libgcc_eh.a%s) + +*startfile: +%{!shared: @PREFIX@/@LIBDIR@/Scrt1.o} @PREFIX@/@LIBDIR@/crti.o crtbeginS.o%s + +*endfile: +crtendS.o%s @PREFIX@/@LIBDIR@/crtn.o + +*link: +-dynamic-linker @PREFIX@/@LIBDIR@/ld.so -rpath @PREFIX@/@LIBDIR@ -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic} + +*esp_link: + + +*esp_options: + + +*esp_cpp_options: + + diff --git a/lib/mlibc/sysdeps/linux/riscv64/arch-syscall.cpp b/lib/mlibc/sysdeps/linux/riscv64/arch-syscall.cpp new file mode 100644 index 0000000..18ac6b0 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/arch-syscall.cpp @@ -0,0 +1,117 @@ +#include <sys/syscall.h> +#include <bits/syscall.h> + +using sc_word_t = __sc_word_t; + +sc_word_t __do_syscall0(long sc) { + register int sc_reg asm("a7") = sc; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : "r"(sc_reg) : "memory", "a1"); + return ret; +} + +sc_word_t __do_syscall1(long sc, + sc_word_t arg1) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg) + : "memory", "a1"); + return ret; +} + +sc_word_t __do_syscall2(long sc, + sc_word_t arg1, sc_word_t arg2) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t arg2_reg asm("a1") = arg2; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall3(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t arg2_reg asm("a1") = arg2; + register sc_word_t arg3_reg asm("a2") = arg3; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall4(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t arg2_reg asm("a1") = arg2; + register sc_word_t arg3_reg asm("a2") = arg3; + register sc_word_t arg4_reg asm("a3") = arg4; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall5(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t arg2_reg asm("a1") = arg2; + register sc_word_t arg3_reg asm("a2") = arg3; + register sc_word_t arg4_reg asm("a3") = arg4; + register sc_word_t arg5_reg asm("a4") = arg5; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg), + "r"(arg5_reg) + : "memory"); + return ret; +} + +sc_word_t __do_syscall6(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5, sc_word_t arg6) { + register int sc_reg asm("a7") = sc; + register sc_word_t arg1_reg asm("a0") = arg1; + register sc_word_t arg2_reg asm("a1") = arg2; + register sc_word_t arg3_reg asm("a2") = arg3; + register sc_word_t arg4_reg asm("a3") = arg4; + register sc_word_t arg5_reg asm("a4") = arg5; + register sc_word_t arg6_reg asm("a5") = arg6; + register sc_word_t ret asm("a0"); + asm volatile ("ecall" : "=r"(ret) : + "r"(sc_reg), + "r"(arg1_reg), + "r"(arg2_reg), + "r"(arg3_reg), + "r"(arg4_reg), + "r"(arg5_reg), + "r"(arg6_reg) + : "memory" + ); + return ret; +} diff --git a/lib/mlibc/sysdeps/linux/riscv64/cp_syscall.S b/lib/mlibc/sysdeps/linux/riscv64/cp_syscall.S new file mode 100644 index 0000000..8d3175d --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/cp_syscall.S @@ -0,0 +1,30 @@ +.section .text +.global __mlibc_do_asm_cp_syscall +.global __mlibc_syscall_begin +.global __mlibc_syscall_end +.type __mlibc_do_asm_cp_syscall, "function" +__mlibc_do_asm_cp_syscall: + sd a7, -8(sp) + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + mv a4, a5 + mv a5, a6 + ld a6, -8(sp) // a7 + lw t0, -96(tp) // Tcb::cancelBits. See asserts in tcb.hpp. +__mlibc_syscall_begin: + // tcbCancelEnableBit && tcbCancelTriggerBit + li t1, (1 << 0) | (1 << 2) + and t0, t0, t1 + beq t0, t1, cancel + ecall +__mlibc_syscall_end: + ret + +cancel: + call __mlibc_do_cancel + unimp +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/crt-src/Scrt1.S b/lib/mlibc/sysdeps/linux/riscv64/crt-src/Scrt1.S new file mode 100644 index 0000000..9ee8625 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/crt-src/Scrt1.S @@ -0,0 +1,18 @@ +.section .text +.global _start +_start: + .weak __global_pointer$ + .hidden __global_pointer$ + .option push + .option norelax + lla gp, __global_pointer$ + .option pop + + mv a0, sp + la a1, main + call __mlibc_entry@plt + unimp + + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/crt-src/crt1.S b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crt1.S new file mode 100644 index 0000000..16c79d6 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crt1.S @@ -0,0 +1,15 @@ +.section .text +.global _start +_start: + .weak __global_pointer$ + .hidden __global_pointer$ + .option push + .option norelax + lla gp, __global_pointer$ + .option pop + + mv a0, sp + la a1, main + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/crt-src/crti.S b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crti.S new file mode 100644 index 0000000..69f23ea --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + unimp + +.section .fini +.global _fini +_fini: + unimp +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/crt-src/crtn.S b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crtn.S new file mode 100644 index 0000000..525efd6 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/crt-src/crtn.S @@ -0,0 +1,7 @@ +.section .init + unimp + +.section .fini + unimp +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/signals.S b/lib/mlibc/sysdeps/linux/riscv64/signals.S new file mode 100644 index 0000000..7769043 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/signals.S @@ -0,0 +1,12 @@ +.section .text + +.global __mlibc_signal_restore +.type __mlibc_signal_restore, @function +__mlibc_signal_restore: +.global __mlibc_signal_restore_rt +.type __mlibc_signal_restore_rt, @function +__mlibc_signal_restore_rt: + li a7, 139 + ecall +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/riscv64/syscallnos.h b/lib/mlibc/sysdeps/linux/riscv64/syscallnos.h new file mode 100644 index 0000000..a5a11bb --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/syscallnos.h @@ -0,0 +1,314 @@ +#ifndef __MLIBC_SYSCALLNOS_h +#define __MLIBC_SYSCALLNOS_h +/* This file is autogenerated. Don't bother. */ +/* Generator script: sysdeps/linux/update-syscall-list.py. */ +#define __NR_io_setup 0 +#define __NR_io_destroy 1 +#define __NR_io_submit 2 +#define __NR_io_cancel 3 +#define __NR_io_getevents 4 +#define __NR_setxattr 5 +#define __NR_lsetxattr 6 +#define __NR_fsetxattr 7 +#define __NR_getxattr 8 +#define __NR_lgetxattr 9 +#define __NR_fgetxattr 10 +#define __NR_listxattr 11 +#define __NR_llistxattr 12 +#define __NR_flistxattr 13 +#define __NR_removexattr 14 +#define __NR_lremovexattr 15 +#define __NR_fremovexattr 16 +#define __NR_getcwd 17 +#define __NR_lookup_dcookie 18 +#define __NR_eventfd2 19 +#define __NR_epoll_create1 20 +#define __NR_epoll_ctl 21 +#define __NR_epoll_pwait 22 +#define __NR_dup 23 +#define __NR_dup3 24 +#define __NR_fcntl 25 +#define __NR_inotify_init1 26 +#define __NR_inotify_add_watch 27 +#define __NR_inotify_rm_watch 28 +#define __NR_ioctl 29 +#define __NR_ioprio_set 30 +#define __NR_ioprio_get 31 +#define __NR_flock 32 +#define __NR_mknodat 33 +#define __NR_mkdirat 34 +#define __NR_unlinkat 35 +#define __NR_symlinkat 36 +#define __NR_linkat 37 +#define __NR_umount2 39 +#define __NR_mount 40 +#define __NR_pivot_root 41 +#define __NR_nfsservctl 42 +#define __NR_statfs 43 +#define __NR_fstatfs 44 +#define __NR_truncate 45 +#define __NR_ftruncate 46 +#define __NR_fallocate 47 +#define __NR_faccessat 48 +#define __NR_chdir 49 +#define __NR_fchdir 50 +#define __NR_chroot 51 +#define __NR_fchmod 52 +#define __NR_fchmodat 53 +#define __NR_fchownat 54 +#define __NR_fchown 55 +#define __NR_openat 56 +#define __NR_close 57 +#define __NR_vhangup 58 +#define __NR_pipe2 59 +#define __NR_quotactl 60 +#define __NR_getdents64 61 +#define __NR_lseek 62 +#define __NR_read 63 +#define __NR_write 64 +#define __NR_readv 65 +#define __NR_writev 66 +#define __NR_pread64 67 +#define __NR_pwrite64 68 +#define __NR_preadv 69 +#define __NR_pwritev 70 +#define __NR_sendfile 71 +#define __NR_pselect6 72 +#define __NR_ppoll 73 +#define __NR_signalfd4 74 +#define __NR_vmsplice 75 +#define __NR_splice 76 +#define __NR_tee 77 +#define __NR_readlinkat 78 +#define __NR_newfstatat 79 +#define __NR_fstat 80 +#define __NR_sync 81 +#define __NR_fsync 82 +#define __NR_fdatasync 83 +#define __NR_sync_file_range 84 +#define __NR_timerfd_create 85 +#define __NR_timerfd_settime 86 +#define __NR_timerfd_gettime 87 +#define __NR_utimensat 88 +#define __NR_acct 89 +#define __NR_capget 90 +#define __NR_capset 91 +#define __NR_personality 92 +#define __NR_exit 93 +#define __NR_exit_group 94 +#define __NR_waitid 95 +#define __NR_set_tid_address 96 +#define __NR_unshare 97 +#define __NR_futex 98 +#define __NR_set_robust_list 99 +#define __NR_get_robust_list 100 +#define __NR_nanosleep 101 +#define __NR_getitimer 102 +#define __NR_setitimer 103 +#define __NR_kexec_load 104 +#define __NR_init_module 105 +#define __NR_delete_module 106 +#define __NR_timer_create 107 +#define __NR_timer_gettime 108 +#define __NR_timer_getoverrun 109 +#define __NR_timer_settime 110 +#define __NR_timer_delete 111 +#define __NR_clock_settime 112 +#define __NR_clock_gettime 113 +#define __NR_clock_getres 114 +#define __NR_clock_nanosleep 115 +#define __NR_syslog 116 +#define __NR_ptrace 117 +#define __NR_sched_setparam 118 +#define __NR_sched_setscheduler 119 +#define __NR_sched_getscheduler 120 +#define __NR_sched_getparam 121 +#define __NR_sched_setaffinity 122 +#define __NR_sched_getaffinity 123 +#define __NR_sched_yield 124 +#define __NR_sched_get_priority_max 125 +#define __NR_sched_get_priority_min 126 +#define __NR_sched_rr_get_interval 127 +#define __NR_restart_syscall 128 +#define __NR_kill 129 +#define __NR_tkill 130 +#define __NR_tgkill 131 +#define __NR_sigaltstack 132 +#define __NR_rt_sigsuspend 133 +#define __NR_rt_sigaction 134 +#define __NR_rt_sigprocmask 135 +#define __NR_rt_sigpending 136 +#define __NR_rt_sigtimedwait 137 +#define __NR_rt_sigqueueinfo 138 +#define __NR_rt_sigreturn 139 +#define __NR_setpriority 140 +#define __NR_getpriority 141 +#define __NR_reboot 142 +#define __NR_setregid 143 +#define __NR_setgid 144 +#define __NR_setreuid 145 +#define __NR_setuid 146 +#define __NR_setresuid 147 +#define __NR_getresuid 148 +#define __NR_setresgid 149 +#define __NR_getresgid 150 +#define __NR_setfsuid 151 +#define __NR_setfsgid 152 +#define __NR_times 153 +#define __NR_setpgid 154 +#define __NR_getpgid 155 +#define __NR_getsid 156 +#define __NR_setsid 157 +#define __NR_getgroups 158 +#define __NR_setgroups 159 +#define __NR_uname 160 +#define __NR_sethostname 161 +#define __NR_setdomainname 162 +#define __NR_getrlimit 163 +#define __NR_setrlimit 164 +#define __NR_getrusage 165 +#define __NR_umask 166 +#define __NR_prctl 167 +#define __NR_getcpu 168 +#define __NR_gettimeofday 169 +#define __NR_settimeofday 170 +#define __NR_adjtimex 171 +#define __NR_getpid 172 +#define __NR_getppid 173 +#define __NR_getuid 174 +#define __NR_geteuid 175 +#define __NR_getgid 176 +#define __NR_getegid 177 +#define __NR_gettid 178 +#define __NR_sysinfo 179 +#define __NR_mq_open 180 +#define __NR_mq_unlink 181 +#define __NR_mq_timedsend 182 +#define __NR_mq_timedreceive 183 +#define __NR_mq_notify 184 +#define __NR_mq_getsetattr 185 +#define __NR_msgget 186 +#define __NR_msgctl 187 +#define __NR_msgrcv 188 +#define __NR_msgsnd 189 +#define __NR_semget 190 +#define __NR_semctl 191 +#define __NR_semtimedop 192 +#define __NR_semop 193 +#define __NR_shmget 194 +#define __NR_shmctl 195 +#define __NR_shmat 196 +#define __NR_shmdt 197 +#define __NR_socket 198 +#define __NR_socketpair 199 +#define __NR_bind 200 +#define __NR_listen 201 +#define __NR_accept 202 +#define __NR_connect 203 +#define __NR_getsockname 204 +#define __NR_getpeername 205 +#define __NR_sendto 206 +#define __NR_recvfrom 207 +#define __NR_setsockopt 208 +#define __NR_getsockopt 209 +#define __NR_shutdown 210 +#define __NR_sendmsg 211 +#define __NR_recvmsg 212 +#define __NR_readahead 213 +#define __NR_brk 214 +#define __NR_munmap 215 +#define __NR_mremap 216 +#define __NR_add_key 217 +#define __NR_request_key 218 +#define __NR_keyctl 219 +#define __NR_clone 220 +#define __NR_execve 221 +#define __NR_mmap 222 +#define __NR_fadvise64 223 +#define __NR_swapon 224 +#define __NR_swapoff 225 +#define __NR_mprotect 226 +#define __NR_msync 227 +#define __NR_mlock 228 +#define __NR_munlock 229 +#define __NR_mlockall 230 +#define __NR_munlockall 231 +#define __NR_mincore 232 +#define __NR_madvise 233 +#define __NR_remap_file_pages 234 +#define __NR_mbind 235 +#define __NR_get_mempolicy 236 +#define __NR_set_mempolicy 237 +#define __NR_migrate_pages 238 +#define __NR_move_pages 239 +#define __NR_rt_tgsigqueueinfo 240 +#define __NR_perf_event_open 241 +#define __NR_accept4 242 +#define __NR_recvmmsg 243 +#define __NR_arch_specific_syscall 244 +#define __NR_riscv_hwprobe 258 +#define __NR_riscv_flush_icache 259 +#define __NR_wait4 260 +#define __NR_prlimit64 261 +#define __NR_fanotify_init 262 +#define __NR_fanotify_mark 263 +#define __NR_name_to_handle_at 264 +#define __NR_open_by_handle_at 265 +#define __NR_clock_adjtime 266 +#define __NR_syncfs 267 +#define __NR_setns 268 +#define __NR_sendmmsg 269 +#define __NR_process_vm_readv 270 +#define __NR_process_vm_writev 271 +#define __NR_kcmp 272 +#define __NR_finit_module 273 +#define __NR_sched_setattr 274 +#define __NR_sched_getattr 275 +#define __NR_renameat2 276 +#define __NR_seccomp 277 +#define __NR_getrandom 278 +#define __NR_memfd_create 279 +#define __NR_bpf 280 +#define __NR_execveat 281 +#define __NR_userfaultfd 282 +#define __NR_membarrier 283 +#define __NR_mlock2 284 +#define __NR_copy_file_range 285 +#define __NR_preadv2 286 +#define __NR_pwritev2 287 +#define __NR_pkey_mprotect 288 +#define __NR_pkey_alloc 289 +#define __NR_pkey_free 290 +#define __NR_statx 291 +#define __NR_io_pgetevents 292 +#define __NR_rseq 293 +#define __NR_kexec_file_load 294 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 +#define __NR_syscalls 451 +#endif /* __MLIBC_SYSCALLNOS_h */ diff --git a/lib/mlibc/sysdeps/linux/riscv64/thread_entry.S b/lib/mlibc/sysdeps/linux/riscv64/thread_entry.S new file mode 100644 index 0000000..fe170fa --- /dev/null +++ b/lib/mlibc/sysdeps/linux/riscv64/thread_entry.S @@ -0,0 +1,29 @@ +.section .text +.global __mlibc_spawn_thread +.type __mlibc_spawn_thread, "function" +__mlibc_spawn_thread: + // __mlibc_spawn_thread(flags, stack, pid_out, child_tid, tls) + // a0, a1, a2, a3, a4 + // syscall(NR_clone, flags, stack, ptid, tls, ctid) + // a7, a0, a1, a2, a3, a4 + + // Swap a3 <-> a4 + mv a5, a4 + mv a4, a3 + mv a3, a5 + + li a7, 220 // NR_clone + ecall + bnez a0, .parent + + ld a0, 0(sp) + ld a1, 8(sp) + addi sp, sp, 8 + andi sp, sp, -16 + call __mlibc_enter_thread + unimp + +.parent: + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/update-syscall-list.py b/lib/mlibc/sysdeps/linux/update-syscall-list.py new file mode 100755 index 0000000..58825f7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/update-syscall-list.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT + +import argparse +import hashlib +import io +import json +import logging +import os +import os.path as path +import pathlib +import subprocess +import tarfile +import tempfile +import urllib.request as urr +from dataclasses import dataclass + +KERNEL_RELEASES = "https://www.kernel.org/releases.json" +NR_PREFIX = "__NR_" +logging.basicConfig(level=logging.DEBUG) +LOGGER = logging.getLogger(__name__) + +# ADD NEW ARCHITECTURES HERE: these should match directory names in Linuxes arch/ +# directory or the second element of one of the harnesses below +WANTED_ARCHES = ["riscv64", "x86_64", "arm64", "i386"] +# How to translate from Linux arch directory names to gnutools architecture fields +LINUX_GNU_TRANSLATION = { + "arm64": "aarch64", + "i386": "x86", +} + +argp = argparse.ArgumentParser() +argp.add_argument("kver", help="Kernel version to download", default="latest") + + +@dataclass +class Kernel: + version: str + srchash: str + srcdir: pathlib.Path + + +@dataclass +class Context: + dirpath: pathlib.Path + + +def run(args: list[str], **kwargs): + LOGGER.debug("running %s", args) + subprocess.check_call(args, **kwargs) + + +def collect(args: list[str], **kwargs): + LOGGER.debug("running %s (kw: %s)", args, kwargs) + kwargs.setdefault("text", True) + return subprocess.check_output(args, **kwargs) + + +def fetch_kernel(ctx: Context, kver: str) -> Kernel: + LOGGER.debug("fetching %s", KERNEL_RELEASES) + with urr.urlopen(KERNEL_RELEASES) as f: + if f.status != 200: + LOGGER.error("meta fetch failed: %s", f) + raise RuntimeError("failed to get kernel meta") + metadata = json.load(f) + + if kver == "latest": + kver = metadata["latest_stable"]["version"] + + LOGGER.debug("figured out kernel version: %s", kver) + + for rel in metadata["releases"]: + if rel["version"] == kver: + kernel_release = rel + break + else: + raise RuntimeError("failed to find kver " + kver) + + kurl = kernel_release["source"] + LOGGER.debug("kernel src url: %s", kurl) + source_path = ctx.dirpath / ("source.tar" + path.splitext(kurl)[1]) + + with urr.urlopen(kurl) as f, open(source_path, "wb") as g: + if f.status != 200: + LOGGER.error("ksrc fetch failed: %s", f) + raise RuntimeError("failed to get kernel source") + + hasher = hashlib.blake2b() + while buf := f.read(16 * 1024): + hasher.update(buf) + g.write(buf) + + srchash = hasher.hexdigest() + srcpath = ctx.dirpath / "src" + + with tarfile.open(source_path) as srctar: + memb: tarfile.TarInfo + for memb in srctar: + if not memb.name.startswith("linux-"): + raise RuntimeError( + "malformed tar member in %s (%s): %s has bad prefix".format( + kurl, srchash, memb.name + ) + ) + memb.name = "./" + memb.name[memb.name.find("/") + 1 :] + srctar.extract(memb, path=srcpath) + + return Kernel( + version=kver, + srchash=srchash, + srcdir=srcpath, + ) + + +def run_harness(ctx: Context, kernel: Kernel, harness: (str, str)) -> dict[str, int]: + LOGGER.debug("running harness %s", harness) + (archdir, arch, defines) = harness + flags = [f"-D{x}" for x in defines] + archout = ctx.dirpath / "headers" / archdir + if not archout.exists(): + run( + [ + "make", + "-sC", + kernel.srcdir, + f"ARCH={archdir}", + f"O={archout}", + "headers_install", + ] + ) + + hdrdir = archout / "usr/include" + callset = set() + for x in collect( + ["gcc", "-E", "-dM", "-I", hdrdir, *flags, "-"], input="#include <asm/unistd.h>" + ).splitlines(): + x = x.split(maxsplit=2) + if len(x) < 2 or x[0] != "#define": + # skip invalid lines + continue + + defname = x[1] + if not defname.startswith(NR_PREFIX): + # not a syscall + continue + + defname = defname[len(NR_PREFIX) :] + + if ( + "SYSCALL" in defname + or defname.startswith("available") + or defname.startswith("reserved") + or defname.startswith("unused") + ): + continue + + # dead syscalls + if defname in [ + "Linux", + "afs_syscall", + "break", + "ftime", + "gtty", + "lock", + "mpx", + "oldwait4", + "prof", + "profil", + "putpmsg", + "security", + "stty", + "tuxcall", + "ulimit", + "vserver", + "arm_sync_file_range", + "utimesat", + "ni_syscall", + "xtensa", + ]: + continue + callset.add(defname) + + # alright, we have the set of all syscalls, time to produce their numbers + syscall_dumper = """ +/* my sincerest apologies */ +#include <stdio.h> +""" + + for x in defines: + syscall_dumper += "#define {}\n".format(x.replace("=", " ")) + + syscall_dumper += """ +#include <asm/unistd.h> + +int main() { + puts("{"); + """ + + comma = "" + for x in callset: + syscall_dumper += 'printf("{comma}\\"{sc}\\": %d\\n", {pfx}{sc});\n '.format( + sc=x, comma=comma, pfx=NR_PREFIX + ) + comma = "," + + syscall_dumper += """ + puts("}"); +} +""" + + dumper = archout / "dumper" + with tempfile.NamedTemporaryFile(suffix=".c") as src: + src.write(syscall_dumper.encode()) + run(["gcc", "-o", dumper, "-I", hdrdir, src.name]) + return json.loads(collect([dumper])) + + +def main(ctx: Context): + args = argp.parse_args() + kernel = fetch_kernel(ctx, args.kver) + + LOGGER.info("got kernel version %s (%s)", kernel.version, kernel.srchash) + + archlist = os.listdir(kernel.srcdir / "arch") + archlist.remove("Kconfig") + archlist.remove("um") + + # harnesses converted from + # https://github.com/hrw/syscalls-table/blob/c638834d9b5d71bb40a555755ea07735cace58f2/do_all_tables.sh + # (arch_dirname, archname, list[defines]) + harnesses: (str, str, list[str]) + harnesses = [ + (arch,) + x + for arch in archlist + if not arch.startswith(".") + for x in { + # arch specific overrides + # format: (archname, list[defines]), gets prefixed with archdir outside + "arm": [ + ("armoabi", []), + ("arm", ["__ARM_EABI_"]), + ], + "loongarch": [ + ("loongarch64", ["_LOONGARCH_SZLONG=64"]), + ], + "mips": [ + ("mipso32", ["_MIPS_SIM=_MIPS_SIM_ABI32"]), + ("mips64n32", ["_MIPS_SIM=_MIPS_SIM_NABI32"]), + ("mips64", ["_MIPS_SIM=_MIPS_SIM_ABI64"]), + ], + "powerpc": [ + ("powerpc", []), + ("powerpc64", []), + ], + "riscv": [ + ("riscv32", ["__SIZEOF_POINTER__=4"]), + ("riscv64", ["__LP64__"]), + ], + "s390": [ + ("s390", []), + ("s390x", []), + ], + "sparc": [ + ("sparc", ["__32bit_syscall_numbers__"]), + ("sparc64", ["__arch64__"]), + ], + "tile": [ + ("tile", []), + ("tile64", ["__LP64__", "__tilegx__"]), + ], + "x86": [ + ("i386", ["__i386__"]), + ("x32", ["__ILP32__"]), + ("x86_64", ["__LP64__"]), + ], + }.get(arch, [(arch, [])]) + ] + + syscall_set = set() + + for x in harnesses: + syscalls = run_harness(ctx, kernel, x) + syscall_set |= syscalls.keys() + + wanted_arch = x[1] + if wanted_arch not in WANTED_ARCHES: + continue + + wanted_arch = LINUX_GNU_TRANSLATION.get(wanted_arch, wanted_arch) + + pathlib.Path(wanted_arch).mkdir(exist_ok=True) + + with open(wanted_arch + "/syscallnos.h", "w") as f: + print("#ifndef __MLIBC_SYSCALLNOS_h", file=f) + print("#define __MLIBC_SYSCALLNOS_h", file=f) + print("/* This file is autogenerated. Don't bother. */", file=f) + print( + "/* Generator script: sysdeps/linux/update-syscall-list.py. */", file=f + ) + + for name, num in sorted(syscalls.items(), key=lambda x: x[1]): + print("#define {p}{sc} {n}".format(p=NR_PREFIX, sc=name, n=num), file=f) + + print("#endif /* __MLIBC_SYSCALLNOS_h */", file=f) + + with open("include/bits/syscall_aliases.h", "w") as f: + print("#ifndef __MLIBC_SYSCALL_ALIAS_BIT", file=f) + print("#define __MLIBC_SYSCALL_ALIAS_BIT", file=f) + print("/* This file is autogenerated. Don't bother. */", file=f) + print("/* Generator script: sysdeps/linux/update-syscall-list.py. */", file=f) + + for x in sorted(list(syscall_set)): + print( + f"""\ +#ifdef\t{NR_PREFIX}{x} +#\tdefine SYS_{x} {NR_PREFIX}{x} +#endif +""", + end="", + file=f, + ) + + print("#endif /* __MLIBC_SYSCALL_ALIAS_BIT */", file=f) + + +if __name__ == "__main__": + with tempfile.TemporaryDirectory() as td: + main( + Context( + dirpath=pathlib.Path(td), + ) + ) diff --git a/lib/mlibc/sysdeps/linux/x86/arch-syscall.cpp b/lib/mlibc/sysdeps/linux/x86/arch-syscall.cpp new file mode 100644 index 0000000..35fc8aa --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/arch-syscall.cpp @@ -0,0 +1,90 @@ +#include <bits/syscall.h> +#include <sys/syscall.h> + +using sc_word_t = __sc_word_t; + +// Note: ebx is used for PIC (it holds a reference to the GOT), so we can't clobber it with gcc apparently, +// and also need to make sure to restore it after a syscall + +sc_word_t __do_syscall0(long sc) { + sc_word_t ret; + asm volatile("int $0x80" : "=a"(ret) : "a"(sc) : "memory"); + return ret; +} + +sc_word_t __do_syscall1(long sc, sc_word_t arg1) { + sc_word_t ret; + asm volatile("xchg %%ebx, %%edi;" + "int $0x80;" + "xchg %%edi, %%ebx;" + : "=a"(ret) + : "a"(sc), "D"(arg1) + : "memory"); + return ret; +} + +sc_word_t __do_syscall2(long sc, sc_word_t arg1, sc_word_t arg2) { + sc_word_t ret; + asm volatile("xchg %%ebx, %%edi;" + "int $0x80;" + "xchg %%edi, %%ebx;" + : "=a"(ret) + : "a"(sc), "D"(arg1), "c"(arg2) + : "memory"); + return ret; +} + +sc_word_t __do_syscall3(long sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3) { + sc_word_t ret; + asm volatile("xchg %%ebx, %%edi;" + "int $0x80;" + "xchg %%edi, %%ebx;" + : "=a"(ret) + : "a"(sc), "D"(arg1), "c"(arg2), "d"(arg3) + : "memory"); + return ret; +} + +sc_word_t __do_syscall4(long sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, sc_word_t arg4) { + sc_word_t ret; + asm volatile("xchg %%ebx, %%edi;" + "int $0x80;" + "xchg %%edi, %%ebx;" + : "=a"(ret) + : "a"(sc), "D"(arg1), "c"(arg2), "d"(arg3), "S"(arg4) + : "memory"); + return ret; +} + +sc_word_t __do_syscall5(long sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, sc_word_t arg4, + sc_word_t arg5) { + sc_word_t ret; + asm volatile("pushl %2;" + "push %%ebx;" + "mov 4(%%esp), %%ebx;" + "int $0x80;" + "pop %%ebx;" + "add $4, %%esp;" + : "=a"(ret) + : "a"(sc), "g"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5) + : "memory"); + return ret; +} + +sc_word_t __do_syscall6(long sc, sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, sc_word_t arg4, + sc_word_t arg5, sc_word_t arg6) { + sc_word_t ret; + sc_word_t a1a6[2] = { arg1, arg6 }; + asm volatile ("pushl %1;" + "push %%ebx;" + "push %%ebp;" + "mov 8(%%esp),%%ebx;" + "mov 4(%%ebx),%%ebp;" + "mov (%%ebx),%%ebx;" + "int $0x80;" + "pop %%ebp;" + "pop %%ebx;" + "add $4,%%esp;" + : "=a"(ret) : "g"(&a1a6), "a"(sc), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5) : "memory"); + return ret; +} diff --git a/lib/mlibc/sysdeps/linux/x86/cp_syscall.S b/lib/mlibc/sysdeps/linux/x86/cp_syscall.S new file mode 100644 index 0000000..b89e1f4 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/cp_syscall.S @@ -0,0 +1,42 @@ + +.section .text +.global __mlibc_do_asm_cp_syscall +.global __mlibc_syscall_begin +.global __mlibc_syscall_end +.type __mlibc_do_asm_cp_syscall, "function" +__mlibc_do_asm_cp_syscall: + push %ebx + push %esi + push %edi + push %ebp + ; mov 16(%esp), %eax + mov 24(%esp), %ebx + mov 28(%esp), %ecx + mov 32(%esp), %edx + mov 36(%esp), %esi + mov 40(%esp), %edi + mov 44(%esp), %ebp + mov %gs:0x18, %al +__mlibc_syscall_begin: + /* tcbCancelEnableBit && tcbCancelTriggerBit */ + and $((1 << 0) | (1 << 2)), %al + cmp $((1 << 0) | (1 << 2)), %al + je cancel + mov 20(%esp), %eax + int $0x80 +__mlibc_syscall_end: + pop %ebp + pop %edi + pop %esi + pop %ebx + ret + +cancel: + pop %ebp + pop %edi + pop %esi + pop %ebx + call __mlibc_do_cancel@PLT + hlt + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/crt-src/Scrt1.S b/lib/mlibc/sysdeps/linux/x86/crt-src/Scrt1.S new file mode 100644 index 0000000..a62b127 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/crt-src/Scrt1.S @@ -0,0 +1,29 @@ +.section .text + +.type __stack_chk_fail_local, %function +.weak __stack_chk_fail_local +__stack_chk_fail_local: + call __stack_chk_fail@plt + +.global _start + +.type _start, %function +.type main, %function +.type __mlibc_entry, %function + +.cfi_startproc +_start: +.cfi_undefined eip + xor %ebp, %ebp + mov %esp, %edi + call 1f + +1: + pop %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + push main@GOT(%ebx) + push %edi + call __mlibc_entry@plt +.cfi_endproc + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/crt-src/crt1.S b/lib/mlibc/sysdeps/linux/x86/crt-src/crt1.S new file mode 100644 index 0000000..ed45da3 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/crt-src/crt1.S @@ -0,0 +1,18 @@ +.section .text +.global _start + +.type _start, %function +.type main, %function +.type __mlibc_entry, %function + +.cfi_startproc +_start: +.cfi_undefined eip + xor %ebp, %ebp + mov %esp, %ecx + push $main + push %ecx + call __mlibc_entry +.cfi_endproc + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/crt-src/crti.S b/lib/mlibc/sysdeps/linux/x86/crt-src/crti.S new file mode 100644 index 0000000..e232557 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/crt-src/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + pushl %eax + +.section .fini +.global _fini +_fini: + pushl %eax + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/crt-src/crtn.S b/lib/mlibc/sysdeps/linux/x86/crt-src/crtn.S new file mode 100644 index 0000000..d890289 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/crt-src/crtn.S @@ -0,0 +1,9 @@ +.section .init + popl %eax + ret + +.section .fini + popl %eax + ret + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/signals.S b/lib/mlibc/sysdeps/linux/x86/signals.S new file mode 100644 index 0000000..8127ee4 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/signals.S @@ -0,0 +1,18 @@ +.section .text + +.global __mlibc_signal_restore +.type __mlibc_signal_restore, @function +__mlibc_signal_restore: + popl %eax + mov $119, %eax + int $0x80 + ud2 + +.global __mlibc_signal_restore_rt +.type __mlibc_signal_restore_rt, @function +__mlibc_signal_restore_rt: + mov $173, %eax + int $0x80 + ud2 + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86/syscallnos.h b/lib/mlibc/sysdeps/linux/x86/syscallnos.h new file mode 100644 index 0000000..f75eb0a --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/syscallnos.h @@ -0,0 +1,433 @@ +#ifndef __MLIBC_SYSCALLNOS_h +#define __MLIBC_SYSCALLNOS_h +/* This file is autogenerated. Don't bother. */ +/* Generator script: sysdeps/linux/update-syscall-list.py. */ +#define __NR_restart_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_setpgid 57 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86old 113 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_modify_ldt 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_vm86 166 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_getdents64 220 +#define __NR_fcntl64 221 +#define __NR_gettid 224 +#define __NR_readahead 225 +#define __NR_setxattr 226 +#define __NR_lsetxattr 227 +#define __NR_fsetxattr 228 +#define __NR_getxattr 229 +#define __NR_lgetxattr 230 +#define __NR_fgetxattr 231 +#define __NR_listxattr 232 +#define __NR_llistxattr 233 +#define __NR_flistxattr 234 +#define __NR_removexattr 235 +#define __NR_lremovexattr 236 +#define __NR_fremovexattr 237 +#define __NR_tkill 238 +#define __NR_sendfile64 239 +#define __NR_futex 240 +#define __NR_sched_setaffinity 241 +#define __NR_sched_getaffinity 242 +#define __NR_set_thread_area 243 +#define __NR_get_thread_area 244 +#define __NR_io_setup 245 +#define __NR_io_destroy 246 +#define __NR_io_getevents 247 +#define __NR_io_submit 248 +#define __NR_io_cancel 249 +#define __NR_fadvise64 250 +#define __NR_exit_group 252 +#define __NR_lookup_dcookie 253 +#define __NR_epoll_create 254 +#define __NR_epoll_ctl 255 +#define __NR_epoll_wait 256 +#define __NR_remap_file_pages 257 +#define __NR_set_tid_address 258 +#define __NR_timer_create 259 +#define __NR_timer_settime 260 +#define __NR_timer_gettime 261 +#define __NR_timer_getoverrun 262 +#define __NR_timer_delete 263 +#define __NR_clock_settime 264 +#define __NR_clock_gettime 265 +#define __NR_clock_getres 266 +#define __NR_clock_nanosleep 267 +#define __NR_statfs64 268 +#define __NR_fstatfs64 269 +#define __NR_tgkill 270 +#define __NR_utimes 271 +#define __NR_fadvise64_64 272 +#define __NR_mbind 274 +#define __NR_get_mempolicy 275 +#define __NR_set_mempolicy 276 +#define __NR_mq_open 277 +#define __NR_mq_unlink 278 +#define __NR_mq_timedsend 279 +#define __NR_mq_timedreceive 280 +#define __NR_mq_notify 281 +#define __NR_mq_getsetattr 282 +#define __NR_kexec_load 283 +#define __NR_waitid 284 +#define __NR_add_key 286 +#define __NR_request_key 287 +#define __NR_keyctl 288 +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#define __NR_inotify_init 291 +#define __NR_inotify_add_watch 292 +#define __NR_inotify_rm_watch 293 +#define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 +#define __NR_set_robust_list 311 +#define __NR_get_robust_list 312 +#define __NR_splice 313 +#define __NR_sync_file_range 314 +#define __NR_tee 315 +#define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 +#define __NR_utimensat 320 +#define __NR_signalfd 321 +#define __NR_timerfd_create 322 +#define __NR_eventfd 323 +#define __NR_fallocate 324 +#define __NR_timerfd_settime 325 +#define __NR_timerfd_gettime 326 +#define __NR_signalfd4 327 +#define __NR_eventfd2 328 +#define __NR_epoll_create1 329 +#define __NR_dup3 330 +#define __NR_pipe2 331 +#define __NR_inotify_init1 332 +#define __NR_preadv 333 +#define __NR_pwritev 334 +#define __NR_rt_tgsigqueueinfo 335 +#define __NR_perf_event_open 336 +#define __NR_recvmmsg 337 +#define __NR_fanotify_init 338 +#define __NR_fanotify_mark 339 +#define __NR_prlimit64 340 +#define __NR_name_to_handle_at 341 +#define __NR_open_by_handle_at 342 +#define __NR_clock_adjtime 343 +#define __NR_syncfs 344 +#define __NR_sendmmsg 345 +#define __NR_setns 346 +#define __NR_process_vm_readv 347 +#define __NR_process_vm_writev 348 +#define __NR_kcmp 349 +#define __NR_finit_module 350 +#define __NR_sched_setattr 351 +#define __NR_sched_getattr 352 +#define __NR_renameat2 353 +#define __NR_seccomp 354 +#define __NR_getrandom 355 +#define __NR_memfd_create 356 +#define __NR_bpf 357 +#define __NR_execveat 358 +#define __NR_socket 359 +#define __NR_socketpair 360 +#define __NR_bind 361 +#define __NR_connect 362 +#define __NR_listen 363 +#define __NR_accept4 364 +#define __NR_getsockopt 365 +#define __NR_setsockopt 366 +#define __NR_getsockname 367 +#define __NR_getpeername 368 +#define __NR_sendto 369 +#define __NR_sendmsg 370 +#define __NR_recvfrom 371 +#define __NR_recvmsg 372 +#define __NR_shutdown 373 +#define __NR_userfaultfd 374 +#define __NR_membarrier 375 +#define __NR_mlock2 376 +#define __NR_copy_file_range 377 +#define __NR_preadv2 378 +#define __NR_pwritev2 379 +#define __NR_pkey_mprotect 380 +#define __NR_pkey_alloc 381 +#define __NR_pkey_free 382 +#define __NR_statx 383 +#define __NR_arch_prctl 384 +#define __NR_io_pgetevents 385 +#define __NR_rseq 386 +#define __NR_semget 393 +#define __NR_semctl 394 +#define __NR_shmget 395 +#define __NR_shmctl 396 +#define __NR_shmat 397 +#define __NR_shmdt 398 +#define __NR_msgget 399 +#define __NR_msgsnd 400 +#define __NR_msgrcv 401 +#define __NR_msgctl 402 +#define __NR_clock_gettime64 403 +#define __NR_clock_settime64 404 +#define __NR_clock_adjtime64 405 +#define __NR_clock_getres_time64 406 +#define __NR_clock_nanosleep_time64 407 +#define __NR_timer_gettime64 408 +#define __NR_timer_settime64 409 +#define __NR_timerfd_gettime64 410 +#define __NR_timerfd_settime64 411 +#define __NR_utimensat_time64 412 +#define __NR_pselect6_time64 413 +#define __NR_ppoll_time64 414 +#define __NR_io_pgetevents_time64 416 +#define __NR_recvmmsg_time64 417 +#define __NR_mq_timedsend_time64 418 +#define __NR_mq_timedreceive_time64 419 +#define __NR_semtimedop_time64 420 +#define __NR_rt_sigtimedwait_time64 421 +#define __NR_futex_time64 422 +#define __NR_sched_rr_get_interval_time64 423 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 +#endif /* __MLIBC_SYSCALLNOS_h */ diff --git a/lib/mlibc/sysdeps/linux/x86/thread_entry.S b/lib/mlibc/sysdeps/linux/x86/thread_entry.S new file mode 100644 index 0000000..031a6aa --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86/thread_entry.S @@ -0,0 +1,61 @@ +#define FLAGS 4 +#define STACK FLAGS+4 +#define PTID STACK+4 +#define CTID PTID+4 +#define TLS CTID+4 + +.section .text +.global __mlibc_spawn_thread +.type __mlibc_spawn_thread, "function" +.cfi_startproc +__mlibc_spawn_thread: + push %ebx + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset ebx, 0 + push %esi + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset esi, 0 + push %edi + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset edi, 0 + + xor %eax, %eax + mov 12+FLAGS(%esp), %ebx + mov 12+STACK(%esp), %ecx + mov 12+PTID(%esp), %edx + /* On x86-32 tls and child_tid have to be reversed */ + mov 12+TLS(%esp), %esi + mov 12+CTID(%esp), %edi + mov $120, %al + + int $0x80 + + test %eax, %eax + jnz .parent_exit + + xor %ebp, %ebp + .cfi_undefined %eip + .cfi_undefined %ebp + + call 1f +1: + pop %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + + call __mlibc_enter_thread@plt + hlt + +.parent_exit: + pop %edi + .cfi_adjust_cfa_offset -4 + .cfi_restore edi + pop %esi + .cfi_adjust_cfa_offset -4 + .cfi_restore esi + pop %ebx + .cfi_adjust_cfa_offset -4 + .cfi_restore ebx + ret +.cfi_endproc + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/linux/x86_64/arch-syscall.cpp b/lib/mlibc/sysdeps/linux/x86_64/arch-syscall.cpp new file mode 100644 index 0000000..d2ebbe7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/arch-syscall.cpp @@ -0,0 +1,78 @@ +#include <sys/syscall.h> +#include <bits/syscall.h> + +using sc_word_t = __sc_word_t; + +sc_word_t __do_syscall0(long sc) { + sc_word_t ret; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall1(long sc, + sc_word_t arg1) { + sc_word_t ret; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall2(long sc, + sc_word_t arg1, sc_word_t arg2) { + sc_word_t ret; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall3(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3) { + sc_word_t ret; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall4(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4) { + sc_word_t ret; + register sc_word_t arg4_reg asm("r10") = arg4; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), + "r"(arg4_reg) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall5(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5) { + sc_word_t ret; + register sc_word_t arg4_reg asm("r10") = arg4; + register sc_word_t arg5_reg asm("r8") = arg5; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), + "r"(arg4_reg), "r"(arg5_reg) + : "rcx", "r11", "memory"); + return ret; +} + +sc_word_t __do_syscall6(long sc, + sc_word_t arg1, sc_word_t arg2, sc_word_t arg3, + sc_word_t arg4, sc_word_t arg5, sc_word_t arg6) { + sc_word_t ret; + register sc_word_t arg4_reg asm("r10") = arg4; + register sc_word_t arg5_reg asm("r8") = arg5; + register sc_word_t arg6_reg asm("r9") = arg6; + asm volatile ("syscall" : "=a"(ret) + : "a"(sc), "D"(arg1), "S"(arg2), "d"(arg3), + "r"(arg4_reg), "r"(arg5_reg), "r"(arg6_reg) + : "rcx", "r11", "memory"); + return ret; +} diff --git a/lib/mlibc/sysdeps/linux/x86_64/cp_syscall.S b/lib/mlibc/sysdeps/linux/x86_64/cp_syscall.S new file mode 100644 index 0000000..5db1f1d --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/cp_syscall.S @@ -0,0 +1,29 @@ + +.section .text +.global __mlibc_do_asm_cp_syscall +.global __mlibc_syscall_begin +.global __mlibc_syscall_end +.type __mlibc_do_asm_cp_syscall, "function" +__mlibc_do_asm_cp_syscall: + mov %rdi, %rax + mov %rsi, %rdi + mov %rdx, %rsi + mov %rcx, %rdx + mov %r8, %r10 + mov %r9, %r8 + mov 8(%rsp), %r9 + mov %fs:0x30, %r11 +__mlibc_syscall_begin: + /* tcbCancelEnableBit && tcbCancelTriggerBit */ + and $((1 << 0) | (1 << 2)), %r11 + cmp $((1 << 0) | (1 << 2)), %r11 + je cancel + syscall +__mlibc_syscall_end: + ret + +cancel: + call __mlibc_do_cancel + hlt +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/crt-src/Scrt1.S b/lib/mlibc/sysdeps/linux/x86_64/crt-src/Scrt1.S new file mode 100644 index 0000000..d0e8213 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/crt-src/Scrt1.S @@ -0,0 +1,8 @@ +.section .text +.global _start +_start: + mov %rsp, %rdi + lea main(%rip), %rsi + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/crt-src/crt1.S b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crt1.S new file mode 100644 index 0000000..9b77ee7 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crt1.S @@ -0,0 +1,8 @@ +.section .text +.global _start +_start: + mov %rsp, %rdi + mov $main, %rsi + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/crt-src/crti.S b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crti.S new file mode 100644 index 0000000..911b078 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + push %rax + +.section .fini +.global _fini +_fini: + push %rax +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/crt-src/crtn.S b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crtn.S new file mode 100644 index 0000000..0187e50 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/crt-src/crtn.S @@ -0,0 +1,9 @@ +.section .init + pop %rax + ret + +.section .fini + pop %rax + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/signals.S b/lib/mlibc/sysdeps/linux/x86_64/signals.S new file mode 100644 index 0000000..09b4387 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/signals.S @@ -0,0 +1,14 @@ + +.section .text + +.global __mlibc_signal_restore +.type __mlibc_signal_restore, @function +__mlibc_signal_restore: +.global __mlibc_signal_restore_rt +.type __mlibc_signal_restore_rt, @function +__mlibc_signal_restore_rt: + mov $15, %rax + syscall + ud2 +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/linux/x86_64/syscallnos.h b/lib/mlibc/sysdeps/linux/x86_64/syscallnos.h new file mode 100644 index 0000000..6c07e69 --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/syscallnos.h @@ -0,0 +1,362 @@ +#ifndef __MLIBC_SYSCALLNOS_h +#define __MLIBC_SYSCALLNOS_h +/* This file is autogenerated. Don't bother. */ +/* Generator script: sysdeps/linux/update-syscall-list.py. */ +#define __NR_read 0 +#define __NR_write 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_stat 4 +#define __NR_fstat 5 +#define __NR_lstat 6 +#define __NR_poll 7 +#define __NR_lseek 8 +#define __NR_mmap 9 +#define __NR_mprotect 10 +#define __NR_munmap 11 +#define __NR_brk 12 +#define __NR_rt_sigaction 13 +#define __NR_rt_sigprocmask 14 +#define __NR_rt_sigreturn 15 +#define __NR_ioctl 16 +#define __NR_pread64 17 +#define __NR_pwrite64 18 +#define __NR_readv 19 +#define __NR_writev 20 +#define __NR_access 21 +#define __NR_pipe 22 +#define __NR_select 23 +#define __NR_sched_yield 24 +#define __NR_mremap 25 +#define __NR_msync 26 +#define __NR_mincore 27 +#define __NR_madvise 28 +#define __NR_shmget 29 +#define __NR_shmat 30 +#define __NR_shmctl 31 +#define __NR_dup 32 +#define __NR_dup2 33 +#define __NR_pause 34 +#define __NR_nanosleep 35 +#define __NR_getitimer 36 +#define __NR_alarm 37 +#define __NR_setitimer 38 +#define __NR_getpid 39 +#define __NR_sendfile 40 +#define __NR_socket 41 +#define __NR_connect 42 +#define __NR_accept 43 +#define __NR_sendto 44 +#define __NR_recvfrom 45 +#define __NR_sendmsg 46 +#define __NR_recvmsg 47 +#define __NR_shutdown 48 +#define __NR_bind 49 +#define __NR_listen 50 +#define __NR_getsockname 51 +#define __NR_getpeername 52 +#define __NR_socketpair 53 +#define __NR_setsockopt 54 +#define __NR_getsockopt 55 +#define __NR_clone 56 +#define __NR_fork 57 +#define __NR_vfork 58 +#define __NR_execve 59 +#define __NR_exit 60 +#define __NR_wait4 61 +#define __NR_kill 62 +#define __NR_uname 63 +#define __NR_semget 64 +#define __NR_semop 65 +#define __NR_semctl 66 +#define __NR_shmdt 67 +#define __NR_msgget 68 +#define __NR_msgsnd 69 +#define __NR_msgrcv 70 +#define __NR_msgctl 71 +#define __NR_fcntl 72 +#define __NR_flock 73 +#define __NR_fsync 74 +#define __NR_fdatasync 75 +#define __NR_truncate 76 +#define __NR_ftruncate 77 +#define __NR_getdents 78 +#define __NR_getcwd 79 +#define __NR_chdir 80 +#define __NR_fchdir 81 +#define __NR_rename 82 +#define __NR_mkdir 83 +#define __NR_rmdir 84 +#define __NR_creat 85 +#define __NR_link 86 +#define __NR_unlink 87 +#define __NR_symlink 88 +#define __NR_readlink 89 +#define __NR_chmod 90 +#define __NR_fchmod 91 +#define __NR_chown 92 +#define __NR_fchown 93 +#define __NR_lchown 94 +#define __NR_umask 95 +#define __NR_gettimeofday 96 +#define __NR_getrlimit 97 +#define __NR_getrusage 98 +#define __NR_sysinfo 99 +#define __NR_times 100 +#define __NR_ptrace 101 +#define __NR_getuid 102 +#define __NR_syslog 103 +#define __NR_getgid 104 +#define __NR_setuid 105 +#define __NR_setgid 106 +#define __NR_geteuid 107 +#define __NR_getegid 108 +#define __NR_setpgid 109 +#define __NR_getppid 110 +#define __NR_getpgrp 111 +#define __NR_setsid 112 +#define __NR_setreuid 113 +#define __NR_setregid 114 +#define __NR_getgroups 115 +#define __NR_setgroups 116 +#define __NR_setresuid 117 +#define __NR_getresuid 118 +#define __NR_setresgid 119 +#define __NR_getresgid 120 +#define __NR_getpgid 121 +#define __NR_setfsuid 122 +#define __NR_setfsgid 123 +#define __NR_getsid 124 +#define __NR_capget 125 +#define __NR_capset 126 +#define __NR_rt_sigpending 127 +#define __NR_rt_sigtimedwait 128 +#define __NR_rt_sigqueueinfo 129 +#define __NR_rt_sigsuspend 130 +#define __NR_sigaltstack 131 +#define __NR_utime 132 +#define __NR_mknod 133 +#define __NR_uselib 134 +#define __NR_personality 135 +#define __NR_ustat 136 +#define __NR_statfs 137 +#define __NR_fstatfs 138 +#define __NR_sysfs 139 +#define __NR_getpriority 140 +#define __NR_setpriority 141 +#define __NR_sched_setparam 142 +#define __NR_sched_getparam 143 +#define __NR_sched_setscheduler 144 +#define __NR_sched_getscheduler 145 +#define __NR_sched_get_priority_max 146 +#define __NR_sched_get_priority_min 147 +#define __NR_sched_rr_get_interval 148 +#define __NR_mlock 149 +#define __NR_munlock 150 +#define __NR_mlockall 151 +#define __NR_munlockall 152 +#define __NR_vhangup 153 +#define __NR_modify_ldt 154 +#define __NR_pivot_root 155 +#define __NR__sysctl 156 +#define __NR_prctl 157 +#define __NR_arch_prctl 158 +#define __NR_adjtimex 159 +#define __NR_setrlimit 160 +#define __NR_chroot 161 +#define __NR_sync 162 +#define __NR_acct 163 +#define __NR_settimeofday 164 +#define __NR_mount 165 +#define __NR_umount2 166 +#define __NR_swapon 167 +#define __NR_swapoff 168 +#define __NR_reboot 169 +#define __NR_sethostname 170 +#define __NR_setdomainname 171 +#define __NR_iopl 172 +#define __NR_ioperm 173 +#define __NR_create_module 174 +#define __NR_init_module 175 +#define __NR_delete_module 176 +#define __NR_get_kernel_syms 177 +#define __NR_query_module 178 +#define __NR_quotactl 179 +#define __NR_nfsservctl 180 +#define __NR_getpmsg 181 +#define __NR_gettid 186 +#define __NR_readahead 187 +#define __NR_setxattr 188 +#define __NR_lsetxattr 189 +#define __NR_fsetxattr 190 +#define __NR_getxattr 191 +#define __NR_lgetxattr 192 +#define __NR_fgetxattr 193 +#define __NR_listxattr 194 +#define __NR_llistxattr 195 +#define __NR_flistxattr 196 +#define __NR_removexattr 197 +#define __NR_lremovexattr 198 +#define __NR_fremovexattr 199 +#define __NR_tkill 200 +#define __NR_time 201 +#define __NR_futex 202 +#define __NR_sched_setaffinity 203 +#define __NR_sched_getaffinity 204 +#define __NR_set_thread_area 205 +#define __NR_io_setup 206 +#define __NR_io_destroy 207 +#define __NR_io_getevents 208 +#define __NR_io_submit 209 +#define __NR_io_cancel 210 +#define __NR_get_thread_area 211 +#define __NR_lookup_dcookie 212 +#define __NR_epoll_create 213 +#define __NR_epoll_ctl_old 214 +#define __NR_epoll_wait_old 215 +#define __NR_remap_file_pages 216 +#define __NR_getdents64 217 +#define __NR_set_tid_address 218 +#define __NR_restart_syscall 219 +#define __NR_semtimedop 220 +#define __NR_fadvise64 221 +#define __NR_timer_create 222 +#define __NR_timer_settime 223 +#define __NR_timer_gettime 224 +#define __NR_timer_getoverrun 225 +#define __NR_timer_delete 226 +#define __NR_clock_settime 227 +#define __NR_clock_gettime 228 +#define __NR_clock_getres 229 +#define __NR_clock_nanosleep 230 +#define __NR_exit_group 231 +#define __NR_epoll_wait 232 +#define __NR_epoll_ctl 233 +#define __NR_tgkill 234 +#define __NR_utimes 235 +#define __NR_mbind 237 +#define __NR_set_mempolicy 238 +#define __NR_get_mempolicy 239 +#define __NR_mq_open 240 +#define __NR_mq_unlink 241 +#define __NR_mq_timedsend 242 +#define __NR_mq_timedreceive 243 +#define __NR_mq_notify 244 +#define __NR_mq_getsetattr 245 +#define __NR_kexec_load 246 +#define __NR_waitid 247 +#define __NR_add_key 248 +#define __NR_request_key 249 +#define __NR_keyctl 250 +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#define __NR_inotify_init 253 +#define __NR_inotify_add_watch 254 +#define __NR_inotify_rm_watch 255 +#define __NR_migrate_pages 256 +#define __NR_openat 257 +#define __NR_mkdirat 258 +#define __NR_mknodat 259 +#define __NR_fchownat 260 +#define __NR_futimesat 261 +#define __NR_newfstatat 262 +#define __NR_unlinkat 263 +#define __NR_renameat 264 +#define __NR_linkat 265 +#define __NR_symlinkat 266 +#define __NR_readlinkat 267 +#define __NR_fchmodat 268 +#define __NR_faccessat 269 +#define __NR_pselect6 270 +#define __NR_ppoll 271 +#define __NR_unshare 272 +#define __NR_set_robust_list 273 +#define __NR_get_robust_list 274 +#define __NR_splice 275 +#define __NR_tee 276 +#define __NR_sync_file_range 277 +#define __NR_vmsplice 278 +#define __NR_move_pages 279 +#define __NR_utimensat 280 +#define __NR_epoll_pwait 281 +#define __NR_signalfd 282 +#define __NR_timerfd_create 283 +#define __NR_eventfd 284 +#define __NR_fallocate 285 +#define __NR_timerfd_settime 286 +#define __NR_timerfd_gettime 287 +#define __NR_accept4 288 +#define __NR_signalfd4 289 +#define __NR_eventfd2 290 +#define __NR_epoll_create1 291 +#define __NR_dup3 292 +#define __NR_pipe2 293 +#define __NR_inotify_init1 294 +#define __NR_preadv 295 +#define __NR_pwritev 296 +#define __NR_rt_tgsigqueueinfo 297 +#define __NR_perf_event_open 298 +#define __NR_recvmmsg 299 +#define __NR_fanotify_init 300 +#define __NR_fanotify_mark 301 +#define __NR_prlimit64 302 +#define __NR_name_to_handle_at 303 +#define __NR_open_by_handle_at 304 +#define __NR_clock_adjtime 305 +#define __NR_syncfs 306 +#define __NR_sendmmsg 307 +#define __NR_setns 308 +#define __NR_getcpu 309 +#define __NR_process_vm_readv 310 +#define __NR_process_vm_writev 311 +#define __NR_kcmp 312 +#define __NR_finit_module 313 +#define __NR_sched_setattr 314 +#define __NR_sched_getattr 315 +#define __NR_renameat2 316 +#define __NR_seccomp 317 +#define __NR_getrandom 318 +#define __NR_memfd_create 319 +#define __NR_kexec_file_load 320 +#define __NR_bpf 321 +#define __NR_execveat 322 +#define __NR_userfaultfd 323 +#define __NR_membarrier 324 +#define __NR_mlock2 325 +#define __NR_copy_file_range 326 +#define __NR_preadv2 327 +#define __NR_pwritev2 328 +#define __NR_pkey_mprotect 329 +#define __NR_pkey_alloc 330 +#define __NR_pkey_free 331 +#define __NR_statx 332 +#define __NR_io_pgetevents 333 +#define __NR_rseq 334 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 +#endif /* __MLIBC_SYSCALLNOS_h */ diff --git a/lib/mlibc/sysdeps/linux/x86_64/thread_entry.S b/lib/mlibc/sysdeps/linux/x86_64/thread_entry.S new file mode 100644 index 0000000..954c6dd --- /dev/null +++ b/lib/mlibc/sysdeps/linux/x86_64/thread_entry.S @@ -0,0 +1,23 @@ + +.section .text +.global __mlibc_spawn_thread +.type __mlibc_spawn_thread, "function" +__mlibc_spawn_thread: + xor %eax, %eax + /* The rest of the args are already in the right registers, + * only need to fixup rcx to r10 + */ + mov %rcx, %r10 + mov $56, %al + syscall + test %eax, %eax + jnz 1f + xor %ebp, %ebp + pop %rdi + pop %rsi + call __mlibc_enter_thread + hlt +1: + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lyre/generic/entry.cpp b/lib/mlibc/sysdeps/lyre/generic/entry.cpp new file mode 100644 index 0000000..4fb0179 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/entry.cpp @@ -0,0 +1,120 @@ +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/elf/startup.h> +#include <mlibc/all-sysdeps.hpp> +#include <bits/posix/posix_signal.h> +#include <lyre/syscall.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +struct GPRState { + uint64_t ds; + uint64_t es; + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t err; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +}; + +namespace mlibc { + int sys_sigentry(void *sigentry) { + __syscall_ret ret = __syscall(27, sigentry); + if (ret.errno != 0) + return ret.errno; + return 0; + } + + [[noreturn]] int sys_sigreturn(void *context, sigset_t old_mask) { + __syscall(30, context, old_mask); + __builtin_unreachable(); + } +} + +static void __mlibc_sigentry(int which, siginfo_t *siginfo, + void (*sa)(int, siginfo_t *, void *), + GPRState *ret_context, sigset_t prev_mask) { + +/* + size_t *base_ptr = (size_t *)ret_context->rbp; + + mlibc::infoLogger() << "Stacktrace:" << frg::endlog; + mlibc::infoLogger() << " [" << (void *)ret_context->rip << "]" << frg::endlog; + for (;;) { + size_t old_bp = base_ptr[0]; + size_t ret_addr = base_ptr[1]; + if (!ret_addr) + break; + size_t off; + mlibc::infoLogger() << " [" << (void *)ret_addr << "]" << frg::endlog; + if (!old_bp) + break; + base_ptr = (size_t *)old_bp; + } +*/ + + switch ((uintptr_t)sa) { + // DFL + case (uintptr_t)(-2): + mlibc::infoLogger() << "mlibc: Unhandled signal " << which << frg::endlog; + mlibc::sys_exit(128 + which); + // IGN + case (uintptr_t)(-3): + break; + default: + sa(which, siginfo, NULL); + break; + } + + mlibc::sys_sigreturn(ret_context, prev_mask); + + __builtin_unreachable(); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) { + //mlibc::sys_sigentry((void *)__mlibc_sigentry); + + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} + diff --git a/lib/mlibc/sysdeps/lyre/generic/generic.cpp b/lib/mlibc/sysdeps/lyre/generic/generic.cpp new file mode 100644 index 0000000..549e9f0 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/generic.cpp @@ -0,0 +1,860 @@ +#include <bits/ensure.h> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <errno.h> +#include <dirent.h> +#include <fcntl.h> +#include <limits.h> +#include <asm/ioctls.h> +#include <stdlib.h> +#include <abi-bits/fcntl.h> +#include <lyre/syscall.h> +#include <frg/hash.hpp> +#include <frg/hash_map.hpp> + +#define STRINGIFY_(X) #X +#define STRINGIFY(X) STRINGIFY_(X) +#define STUB_ONLY { \ + sys_libc_log("STUB_ONLY function on line " STRINGIFY(__LINE__) " was called"); \ + sys_libc_panic(); \ +} + +namespace { + +int fcntl_helper(int fd, int request, int *result, ...) { + va_list args; + va_start(args, result); + if(!mlibc::sys_fcntl) { + return ENOSYS; + } + int ret = mlibc::sys_fcntl(fd, request, args, result); + va_end(args); + return ret; +} + +} + +namespace mlibc { + +void sys_libc_log(const char *message) { + __syscall(SYS_debug, message); +} + +void sys_libc_panic() { + sys_libc_log("\nMLIBC PANIC\n"); + sys_exit(1); + __builtin_unreachable(); +} + +void sys_exit(int status) { + __syscall(SYS_exit, status); + __builtin_unreachable(); +} + +#ifndef MLIBC_BUILDING_RTDL + +[[noreturn]] void sys_thread_exit() { + __syscall(SYS_exit_thread); + __builtin_unreachable(); +} + +extern "C" void __mlibc_thread_entry(); + +int sys_clone(void *tcb, pid_t *pid_out, void *stack) { + (void)tcb; + + __syscall_ret ret = __syscall(SYS_new_thread, (uintptr_t)__mlibc_thread_entry, (uintptr_t)stack); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + + *pid_out = ret_value; + return 0; +} + +int sys_kill(pid_t, int) STUB_ONLY + +int sys_tcgetattr(int fd, struct termios *attr) { + int ret; + if (int r = sys_ioctl(fd, TCGETS, attr, &ret) != 0) { + return r; + } + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + int ret; + switch (optional_action) { + case TCSANOW: + optional_action = TCSETS; break; + case TCSADRAIN: + optional_action = TCSETSW; break; + case TCSAFLUSH: + optional_action = TCSETSF; break; + default: + __ensure(!"Unsupported tcsetattr"); + } + + if (int r = sys_ioctl(fd, optional_action, (void *)attr, &ret) != 0) { + return r; + } + + return 0; +} + +#endif + +int sys_tcb_set(void *pointer) { + __syscall(SYS_set_fs_base, pointer); + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_ppoll(struct pollfd *fds, int nfds, const struct timespec *timeout, const sigset_t *sigmask, int *num_events) { + __syscall_ret ret = __syscall(SYS_ppoll, fds, nfds, timeout, sigmask); + int ret_value = (int)ret.ret; + + if (ret_value == -1) + return ret.errno; + + *num_events = ret_value; + return 0; +} + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { + struct timespec ts; + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + return sys_ppoll(fds, count, timeout < 0 ? NULL : &ts, NULL, num_events); +} + +int sys_epoll_pwait(int, struct epoll_event *, int, + int, const sigset_t *, int *) STUB_ONLY + +int sys_epoll_create(int, int *) STUB_ONLY + +int sys_epoll_ctl(int, int, int, struct epoll_event *) STUB_ONLY + +int sys_pselect(int nfds, fd_set *read_set, fd_set *write_set, + fd_set *except_set, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) { + struct pollfd *fds = (struct pollfd *)calloc(nfds, sizeof(struct pollfd)); + if (fds == NULL) { + return ENOMEM; + } + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + + if (read_set && FD_ISSET(i, read_set)) { + fd->events |= POLLIN; + } + if (write_set && FD_ISSET(i, write_set)) { + fd->events |= POLLOUT; + } + if (except_set && FD_ISSET(i, except_set)) { + fd->events |= POLLPRI; + } + + if (!fd->events) { + fd->fd = -1; + continue; + } + fd->fd = i; + } + + int ret = sys_ppoll(fds, nfds, timeout, sigmask, num_events); + if (ret != 0) { + free(fds); + return ret; + } + + fd_set res_read_set, res_write_set, res_except_set; + FD_ZERO(&res_read_set); + FD_ZERO(&res_write_set); + FD_ZERO(&res_except_set); + + for (int i = 0; i < nfds; i++) { + struct pollfd *fd = &fds[i]; + + if (read_set && FD_ISSET(i, read_set) && (fd->revents & (POLLIN | POLLERR | POLLHUP)) != 0) { + FD_SET(i, &res_read_set); + } + if (write_set && FD_ISSET(i, write_set) && (fd->revents & (POLLOUT | POLLERR | POLLHUP)) != 0) { + FD_SET(i, &res_write_set); + } + if (except_set && FD_ISSET(i, except_set) && (fd->revents & POLLPRI) != 0) { + FD_SET(i, &res_except_set); + } + } + + free(fds); + if (read_set) { + *read_set = res_read_set; + } + if (write_set) { + *write_set = res_write_set; + } + if (except_set) { + *except_set = res_except_set; + } + + return 0; +} + +#endif + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + __syscall_ret ret = __syscall(SYS_futex_wait, pointer, expected, time); + + if ((int)ret.ret == -1) + return ret.errno; + + return 0; +} + +int sys_futex_wake(int *pointer) { + __syscall_ret ret = __syscall(SYS_futex_wake, pointer); + + if ((int)ret.ret == -1) + return ret.errno; + + int num_woken = ret.ret; + + __ensure(num_woken >= 0 && num_woken <= 1); + return num_woken; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_timerfd_create(int, int *) STUB_ONLY + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { + __syscall_ret ret = __syscall(SYS_ioctl, fd, request, arg); + + if ((int)ret.ret == -1) + return ret.errno; + + *result = (int)ret.ret; + return 0; +} + +int sys_isatty(int fd) { + struct winsize ws; + int ret; + + if (!sys_ioctl(fd, TIOCGWINSZ, &ws, &ret)) + return 0; + + return ENOTTY; +} + +int sys_getcwd(char *buffer, size_t size) { + __syscall_ret ret = __syscall(SYS_getcwd, buffer, size); + + if ((int)ret.ret == -1) + return ret.errno; + + return 0; +} + +#endif + +int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) { + __syscall_ret ret = __syscall(SYS_openat, dirfd, path, flags, mode); + + if ((int)ret.ret == -1) + return ret.errno; + + *fd = (int)ret.ret; + return 0; +} + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + return sys_openat(AT_FDCWD, path, flags, mode, fd); +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_open_dir(const char *path, int *handle) { + return sys_openat(AT_FDCWD, path, O_DIRECTORY, 0, handle); +} + +struct ReadDirState { + size_t offset; + size_t capacity; + void *buffer; +}; + +static frg::hash_map<int, ReadDirState *, frg::hash<int>, MemoryAllocator> open_dirs{frg::hash<int>{}, getAllocator()}; + +static ReadDirState *get_dir_state(int fdnum) { + ReadDirState *result; + if (auto value = open_dirs.get(fdnum)) { + result = *value; + } else { + result = (ReadDirState *)malloc(sizeof(ReadDirState)); + result->offset = 0; + result->capacity = 1024; + result->buffer = malloc(result->capacity); + open_dirs.insert(fdnum, result); + } + return result; +} + +int sys_read_entries(int fdnum, void *buffer, size_t max_size, size_t *bytes_read) { + ReadDirState *state = get_dir_state(fdnum); + +retry: + __syscall_ret ret = __syscall(SYS_readdir, fdnum, state->buffer, &state->capacity); + if ((int)ret.ret == -1) { + if (ret.errno == ENOBUFS) { + state->buffer = realloc(state->buffer, state->capacity); + goto retry; + } else { + return ret.errno; + } + } + + size_t offset = 0; + while (offset < max_size) { + struct dirent *ent = (struct dirent *)((char *)state->buffer + state->offset); + if (ent->d_reclen == 0) { + break; + } + + if (offset + ent->d_reclen >= max_size) { + break; + } + + memcpy((char *)buffer + offset, ent, ent->d_reclen); + offset += ent->d_reclen; + state->offset += ent->d_reclen; + } + + *bytes_read = offset; + return 0; +} + +#endif + +int sys_close(int fd) { + __syscall_ret ret = __syscall(SYS_close, fd); + if ((int)ret.ret == -1) { + return ret.errno; + } +#ifndef MLIBC_BUILDING_RTDL + open_dirs.remove(fd); +#endif + return 0; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + __syscall_ret ret = __syscall(SYS_seek, fd, offset, whence); + off_t ret_value = (off_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *new_offset = ret_value; + return 0; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + __syscall_ret ret = __syscall(SYS_read, fd, buf, count); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *bytes_read = ret_value; + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_write(int fd, const void *buf, size_t count, ssize_t *bytes_written) { + __syscall_ret ret = __syscall(SYS_write, fd, buf, count); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *bytes_written = ret_value; + return 0; +} + +int sys_readlink(const char *path, void *data, size_t max_size, ssize_t *length) { + __syscall_ret ret = __syscall(SYS_readlinkat, AT_FDCWD, path, data, max_size); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *length = ret_value; + return 0; +} + +int sys_link(const char *old_path, const char *new_path) { + return sys_linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0); +} + +int sys_linkat(int olddirfd, const char *old_path, int newdirfd, const char *new_path, int flags) { + __syscall_ret ret = __syscall(SYS_linkat, olddirfd, old_path, newdirfd, new_path, flags); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_unlinkat(int fd, const char *path, int flags) { + __syscall_ret ret = __syscall(SYS_unlinkat, fd, path, flags); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { + __syscall_ret ret = __syscall(SYS_fchmodat, fd, pathname, mode, flags); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_fchmod(int fd, mode_t mode) { + return sys_fchmodat(fd, "", mode, AT_EMPTY_PATH); +} + +int sys_chmod(const char *pathname, mode_t mode) { + return sys_fchmodat(AT_FDCWD, pathname, mode, 0); +} + +int sys_rmdir(const char *) STUB_ONLY + +#endif + +int sys_vm_map(void *hint, size_t size, int prot, int flags, + int fd, off_t offset, void **window) { + __syscall_ret ret = __syscall(SYS_mmap, hint, size, (uint64_t)prot << 32 | flags, fd, offset); + void *ret_value = (void *)ret.ret; + if (ret_value == MAP_FAILED) { + return ret.errno; + } + *window = ret_value; + return 0; +} + +int sys_vm_unmap(void *pointer, size_t size) { + __syscall_ret ret = __syscall(SYS_unmmap, pointer, size); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_vm_protect(void *pointer, size_t size, int prot) { + __syscall_ret ret = __syscall(SYS_mprotect, pointer, size, prot); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +#endif + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0, pointer); +} + +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +#ifndef MLIBC_BUILDING_RTDL + +pid_t sys_getpid() { + __syscall_ret ret = __syscall(SYS_getpid); + return (pid_t)ret.ret; +} + +pid_t sys_getppid() { + return 0; +} + +uid_t sys_getuid() { + return 0; +} + +uid_t sys_geteuid() { + return 0; +} + +gid_t sys_getgid() { + return 0; +} + +int sys_setgid(gid_t) { + return 0; +} + +int sys_getpgid(pid_t, pid_t *) { + return 0; +} + +gid_t sys_getegid() { + return 0; +} + +int sys_setpgid(pid_t, pid_t) { + return 0; +} + +int sys_ttyname(int, char *, size_t) { + return ENOSYS; +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + struct timespec buf; + __syscall_ret ret = __syscall(SYS_getclock, clock, &buf); + if ((int)ret.ret == -1) { + return ret.errno; + } + *secs = buf.tv_sec; + *nanos = buf.tv_nsec; + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf) { + __syscall_ret ret; + switch (fsfdt) { + case fsfd_target::fd: + ret = __syscall(SYS_stat, fd, "", flags | AT_EMPTY_PATH, statbuf); + break; + case fsfd_target::path: + ret = __syscall(SYS_stat, AT_FDCWD, path, flags, statbuf); + break; + case fsfd_target::fd_path: + ret = __syscall(SYS_stat, fd, path, flags, statbuf); + break; + default: + __ensure(!"sys_stat: Invalid fsfdt"); + __builtin_unreachable(); + } + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_faccessat(int dirfd, const char *pathname, int mode, int flags) { + (void)flags; + struct stat buf; + if (int r = sys_stat(fsfd_target::fd_path, dirfd, pathname, mode & AT_SYMLINK_FOLLOW, &buf)) { + return r; + } + return 0; +} + +int sys_access(const char *path, int mode) { + return sys_faccessat(AT_FDCWD, path, mode, 0); +} + +int sys_pipe(int *fds, int flags) { + __syscall_ret ret = __syscall(SYS_pipe, fds, flags); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_chdir(const char *path) { + __syscall_ret ret = __syscall(SYS_chdir, path); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_mkdir(const char *path, mode_t mode) { + return sys_mkdirat(AT_FDCWD, path, mode); +} + +int sys_mkdirat(int dirfd, const char *path, mode_t mode) { + __syscall_ret ret = __syscall(SYS_mkdirat, dirfd, path, mode); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_socket(int domain, int type_and_flags, int proto, int *fd) { + __syscall_ret ret = __syscall(SYS_socket, domain, type_and_flags, proto); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *fd = ret_value; + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { + __syscall_ret ret = __syscall(SYS_socketpair, domain, type_and_flags, proto, fds); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + return 0; +} + +int sys_bind(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + __syscall_ret ret = __syscall(SYS_bind, fd, addr_ptr, addr_length); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_connect(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + __syscall_ret ret = __syscall(SYS_connect, fd, addr_ptr, addr_length); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags) { + __syscall_ret ret = __syscall(SYS_accept, fd, addr_ptr, addr_length); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *newfd = ret_value; + + if(flags & SOCK_NONBLOCK) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFL, &fcntl_ret); + fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK); + } + + if(flags & SOCK_CLOEXEC) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFD, &fcntl_ret); + fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC); + } + + return 0; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size) { + __syscall_ret ret = __syscall(SYS_getsockopt, fd, layer, number, buffer, size); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + return 0; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size) { + __syscall_ret ret = __syscall(SYS_setsockopt, fd, layer, number, buffer, size); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + return 0; +} + +int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length) { + __syscall_ret ret = __syscall(SYS_recvmsg, sockfd, hdr, flags); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *length = ret_value; + return 0; +} + +int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length) { + __syscall_ret ret = __syscall(SYS_sendmsg, sockfd, hdr, flags); + ssize_t ret_value = (ssize_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *length = ret_value; + return 0; +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { + __syscall_ret ret = __syscall(SYS_getpeername, fd, addr_ptr, &max_addr_length); + if ((int)ret.ret == -1) { + return ret.errno; + } + *actual_length = max_addr_length; + return 0; +} + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { + __syscall_ret ret = __syscall(SYS_getsockname, fd, addr_ptr, &max_addr_length); + if ((int)ret.ret == -1) { + return ret.errno; + } + *actual_length = max_addr_length; + return 0; +} + +int sys_listen(int fd, int backlog) { + __syscall_ret ret = __syscall(SYS_listen, fd, backlog); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_inotify_create(int, int *) { + mlibc::infoLogger() << "mlibc: sys_inotify_create() is unimplemented" << frg::endlog; + return ENOSYS; +} + +int sys_fork(pid_t *child) { + __syscall_ret ret = __syscall(SYS_fork); + pid_t ret_value = (pid_t)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *child = ret_value; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + __syscall_ret ret = __syscall(SYS_exec, path, argv, envp); + return ret.errno; +} + +int sys_fcntl(int fd, int request, va_list args, int *result) { + __syscall_ret ret = __syscall(SYS_fcntl, fd, request, va_arg(args, uint64_t)); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *result = ret_value; + return 0; +} + +int sys_dup(int fd, int flags, int *newfd) { + (void)flags; + __syscall_ret ret = __syscall(SYS_fcntl, fd, F_DUPFD, 0); + int ret_value = (int)ret.ret; + if (ret_value == -1) { + return ret.errno; + } + *newfd = ret_value; + return 0; +} + +int sys_dup2(int fd, int flags, int newfd) { + __syscall_ret ret = __syscall(SYS_dup3, fd, newfd, flags); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_sigprocmask(int, const sigset_t *__restrict, sigset_t *__restrict) { + mlibc::infoLogger() << "mlibc: sys_sigprocmask() is a stub" << frg::endlog; + return 0; +} + +int sys_sigaction(int, const struct sigaction *, struct sigaction *) { + mlibc::infoLogger() << "mlibc: sys_sigaction() is a stub" << frg::endlog; + return 0; +} + +int sys_signalfd_create(sigset_t, int, int *) STUB_ONLY + +int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { + if (ru != NULL) { + mlibc::infoLogger() << "mlibc: struct rusage in sys_waitpid is unsupported" << frg::endlog; + return ENOSYS; + } +again: + __syscall_ret ret = __syscall(SYS_waitpid, pid, status, flags); + pid_t ret_value = (pid_t)ret.ret; + if (ret_value == -1) { + if (ret.errno == EINTR) { + goto again; + } + return ret.errno; + } + *ret_pid = ret_value; + return 0; +} + +int sys_getgroups(size_t, const gid_t *, int *) { + mlibc::infoLogger() << "mlibc: sys_getgroups() is unimplemented" << frg::endlog; + return ENOSYS; +} + +int sys_mount(const char *, const char *, const char *, unsigned long, const void *) STUB_ONLY + +int sys_umount2(const char *, int) STUB_ONLY + +int sys_gethostname(char *buffer, size_t bufsize) { + struct utsname utsname; + if (int err = sys_uname(&utsname)) { + return err; + } + if (strlen(utsname.nodename) >= bufsize) { + return ENAMETOOLONG; + } + strncpy(buffer, utsname.nodename, bufsize); + return 0; +} + +int sys_sethostname(const char *, size_t) STUB_ONLY + +int sys_sleep(time_t *secs, long *nanos) { + struct timespec time = {.tv_sec = *secs, .tv_nsec = *nanos}; + struct timespec rem = {.tv_sec = 0, .tv_nsec = 0}; + __syscall_ret ret = __syscall(SYS_sleep, &time, &rem); + if ((int)ret.ret == -1) { + return ret.errno; + } + *secs = rem.tv_sec; + *nanos = rem.tv_nsec; + return 0; +} + +int sys_getitimer(int, struct itimerval *) { + mlibc::infoLogger() << "mlibc: sys_getitimer() is unimplemented" << frg::endlog; + return ENOSYS; +} + +int sys_setitimer(int, const struct itimerval *, struct itimerval *) { + mlibc::infoLogger() << "mlibc: sys_setitimer() is unimplemented" << frg::endlog; + return ENOSYS; +} + +int sys_umask(mode_t mode, mode_t *old) { + __syscall_ret ret = __syscall(SYS_umask, mode); + *old = (mode_t)ret.ret; + return 0; +} + +int sys_uname(struct utsname *buf) { + __syscall_ret ret = __syscall(SYS_uname, buf); + if ((int)ret.ret == -1) { + return ret.errno; + } + return 0; +} + +int sys_fsync(int) { + mlibc::infoLogger() << "sys_fsync is a stub" << frg::endlog; + return 0; +} + +#endif + +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/lyre/generic/mntent.cpp b/lib/mlibc/sysdeps/lyre/generic/mntent.cpp new file mode 100644 index 0000000..d064af3 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/mntent.cpp @@ -0,0 +1,97 @@ +#include <errno.h> +#include <mntent.h> +#include <stdio.h> +#include <limits.h> +#include <string.h> +#include <bits/ensure.h> + +namespace { + +char *internal_buf; +size_t internal_bufsize; + +} + +#define SENTINEL (char *)&internal_buf + +FILE *setmntent(const char *name, const char *mode) { + return fopen(name, mode); +} + +struct mntent *getmntent(FILE *f) { + static struct mntent mnt; + return getmntent_r(f, &mnt, SENTINEL, 0); +} + +int addmntent(FILE *f, const struct mntent *mnt) { + if(fseek(f, 0, SEEK_END)) { + return 1; + } + return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n", + mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts, + mnt->mnt_freq, mnt->mnt_passno) < 0; +} + +int endmntent(FILE *f) { + if(f) { + fclose(f); + } + return 1; +} + +char *hasmntopt(const struct mntent *mnt, const char *opt) { + return strstr(mnt->mnt_opts, opt); +} + +/* Adapted from musl */ +struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { + int n[8]; + bool use_internal = (linebuf == SENTINEL); + int len; + size_t i; + + mnt->mnt_freq = 0; + mnt->mnt_passno = 0; + + do { + if(use_internal) { + getline(&internal_buf, &internal_bufsize, f); + linebuf = internal_buf; + } else { + fgets(linebuf, buflen, f); + } + if(feof(f) || ferror(f)) { + return 0; + } + if(!strchr(linebuf, '\n')) { + fscanf(f, "%*[^\n]%*[\n]"); + errno = ERANGE; + return 0; + } + + len = strlen(linebuf); + if(len > INT_MAX) { + continue; + } + + for(i = 0; i < sizeof n / sizeof *n; i++) { + n[i] = len; + } + + sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + n, n + 1, n + 2, n + 3, n + 4, n + 5, n + 6, n + 7, + &mnt->mnt_freq, &mnt->mnt_passno); + } while(linebuf[n[0]] == '#' || n[1] == len); + + linebuf[n[1]] = 0; + linebuf[n[3]] = 0; + linebuf[n[5]] = 0; + linebuf[n[7]] = 0; + + mnt->mnt_fsname = linebuf + n[0]; + mnt->mnt_dir = linebuf + n[2]; + mnt->mnt_type = linebuf + n[4]; + mnt->mnt_opts = linebuf + n[6]; + + return mnt; +} diff --git a/lib/mlibc/sysdeps/lyre/generic/mount.cpp b/lib/mlibc/sysdeps/lyre/generic/mount.cpp new file mode 100644 index 0000000..f10254d --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/mount.cpp @@ -0,0 +1,16 @@ +#include <errno.h> +#include <sys/mount.h> +#include <bits/ensure.h> + +int mount(const char *source, const char *target, + const char *fstype, unsigned long flags, const void *data) { + return 0; +} + +int umount(const char *target) { + return umount2(target, 0); +} + +int umount2(const char *target, int flags) { + return 0; +} diff --git a/lib/mlibc/sysdeps/lyre/generic/reboot.cpp b/lib/mlibc/sysdeps/lyre/generic/reboot.cpp new file mode 100644 index 0000000..7c86ffd --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/reboot.cpp @@ -0,0 +1,7 @@ +#include <errno.h> +#include <sys/reboot.h> +#include <bits/ensure.h> + +int reboot(int what) { + return 0; +} diff --git a/lib/mlibc/sysdeps/lyre/generic/thread.S b/lib/mlibc/sysdeps/lyre/generic/thread.S new file mode 100644 index 0000000..47ab6a9 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/thread.S @@ -0,0 +1,9 @@ +.section .text +.global __mlibc_thread_entry +__mlibc_thread_entry: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_thread_trampoline + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/lyre/generic/thread.cpp b/lib/mlibc/sysdeps/lyre/generic/thread.cpp new file mode 100644 index 0000000..5186e1f --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/generic/thread.cpp @@ -0,0 +1,58 @@ +#include <sys/mman.h> +#include <mlibc/debug.hpp> +#include <errno.h> +#include <mlibc/all-sysdeps.hpp> +#include <bits/ensure.h> +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_thread_trampoline(void *(*fn)(void *), Tcb *tcb, void *arg) { + if (mlibc::sys_tcb_set(tcb)) { + __ensure(!"failed to set tcb for new thread"); + } + + while (__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED) == 0) { + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + } + + tcb->invokeThreadFunc(reinterpret_cast<void *>(fn), arg); + + __atomic_store_n(&tcb->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&tcb->didExit); + + mlibc::sys_thread_exit(); +} + +#define DEFAULT_STACK 0x400000 + +namespace mlibc { + int sys_prepare_stack(void **stack, void *entry, void *arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + // TODO guard + + mlibc::infoLogger() << "mlibc: sys_prepare_stack() does not setup a guard!" << frg::endlog; + + *guard_size = 0; + + *stack_size = *stack_size ? *stack_size : DEFAULT_STACK; + + if (!*stack) { + *stack_base = mmap(NULL, *stack_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (*stack_base == MAP_FAILED) { + return errno; + } + } else { + *stack_base = *stack; + } + + *stack = (void *)((char *)*stack_base + *stack_size); + + void **stack_it = (void **)*stack; + + *--stack_it = arg; + *--stack_it = tcb; + *--stack_it = entry; + + *stack = (void *)stack_it; + + return 0; + } +} diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/access.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/access.h new file mode 120000 index 0000000..cb83931 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/linux/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/auxv.h new file mode 120000 index 0000000..c43f878 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/linux/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..0b0ec27 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..7dc8d7c --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..6a42da5 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/dev_t.h new file mode 120000 index 0000000..bca881e --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/linux/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/epoll.h new file mode 120000 index 0000000..eb4b76d --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/linux/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/errno.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/errno.h new file mode 120000 index 0000000..6e507de --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/linux/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/fcntl.h new file mode 120000 index 0000000..463e2c9 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/linux/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/gid_t.h new file mode 120000 index 0000000..abce6d6 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/in.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/in.h new file mode 120000 index 0000000..418d1d5 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/linux/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/ino_t.h new file mode 120000 index 0000000..4c20aca --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/linux/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/inotify.h new file mode 120000 index 0000000..b5cb282 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/linux/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/limits.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/limits.h new file mode 120000 index 0000000..6c88db2 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/linux/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/mode_t.h new file mode 120000 index 0000000..5d78fdf --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/linux/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/msg.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..bb3b625 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/linux/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/packet.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/packet.h new file mode 120000 index 0000000..998ef1a --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/linux/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/pid_t.h new file mode 120000 index 0000000..baa90f6 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/poll.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/poll.h new file mode 120000 index 0000000..8ea6a0a --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/linux/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/ptrace.h new file mode 120000 index 0000000..b2517b2 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/linux/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/resource.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/resource.h new file mode 120000 index 0000000..88d7402 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/linux/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/shm.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/signal.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/socket.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/stat.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/stat.h new file mode 120000 index 0000000..1f63b41 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/linux/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/statvfs.h new file mode 120000 index 0000000..d0bdd40 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/lyre/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/termios.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/time.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/uid_t.h new file mode 120000 index 0000000..b306777 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..bbe258c --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/linux/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/wait.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/lyre/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lyre/include/asm/ioctl.h b/lib/mlibc/sysdeps/lyre/include/asm/ioctl.h new file mode 100644 index 0000000..8cbb364 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/asm/ioctl.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_GENERIC_IOCTL_H +#define _ASM_GENERIC_IOCTL_H + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The generic ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 + +/* + * Let any architecture override either of the following before + * including this file. + */ + +#ifndef _IOC_SIZEBITS +# define _IOC_SIZEBITS 14 +#endif + +#ifndef _IOC_DIRBITS +# define _IOC_DIRBITS 2 +#endif + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits, which any architecture can choose to override + * before including this file. + * + * NOTE: _IOC_WRITE means userland is writing and kernel is + * reading. _IOC_READ means userland is reading and kernel is writing. + */ + +#ifndef _IOC_NONE +# define _IOC_NONE 0U +#endif + +#ifndef _IOC_WRITE +# define _IOC_WRITE 1U +#endif + +#ifndef _IOC_READ +# define _IOC_READ 2U +#endif + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +#define _IOC_TYPECHECK(t) (sizeof(t)) + +/* + * Used to create numbers. + * + * NOTE: _IOW means userland is writing and kernel is reading. _IOR + * means userland is reading and kernel is writing. + */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASM_GENERIC_IOCTL_H */ diff --git a/lib/mlibc/sysdeps/lyre/include/asm/ioctls.h b/lib/mlibc/sysdeps/lyre/include/asm/ioctls.h new file mode 100644 index 0000000..bdbba9b --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/asm/ioctls.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __ASM_GENERIC_IOCTLS_H +#define __ASM_GENERIC_IOCTLS_H + +#include <asm/ioctl.h> + +/* + * These are the most common definitions for tty ioctl numbers. + * Most of them do not use the recommended _IOC(), but there is + * probably some source code out there hardcoding the number, + * so we might as well use them for all new platforms. + * + * The architectures that use different values here typically + * try to be compatible with some Unix variants for the same + * architecture. + */ + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TCGETS2 _IOR('T', 0x2A, struct termios2) +#define TCSETS2 _IOW('T', 0x2B, struct termios2) +#define TCSETSW2 _IOW('T', 0x2C, struct termios2) +#define TCSETSF2 _IOW('T', 0x2D, struct termios2) +#define TIOCGRS485 0x542E +#ifndef TIOCSRS485 +#define TIOCSRS485 0x542F +#endif +#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ +#define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */ +#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */ +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 +#define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */ +#define TIOCVHANGUP 0x5437 +#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ +#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ +#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) + +#define FIONCLEX 0x5450 +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port __inline__ interrupt counts */ + +/* + * Some arches already define FIOQSIZE due to a historical + * conflict with a Hayes modem-specific ioctl value. + */ +#ifndef FIOQSIZE +# define FIOQSIZE 0x5460 +#endif + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif /* __ASM_GENERIC_IOCTLS_H */ diff --git a/lib/mlibc/sysdeps/lyre/include/linux/fb.h b/lib/mlibc/sysdeps/lyre/include/linux/fb.h new file mode 100644 index 0000000..d5e6d88 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/linux/fb.h @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_FB_H +#define _LINUX_FB_H + +#include <stddef.h> +#include <asm/ioctl.h> + +/* Definitions of frame buffers */ + +#define FB_MAX 32 /* sufficient for now */ + +/* ioctls + 0x46 is 'F' */ +#define FBIOGET_VSCREENINFO 0x4600 +#define FBIOPUT_VSCREENINFO 0x4601 +#define FBIOGET_FSCREENINFO 0x4602 +#define FBIOGETCMAP 0x4604 +#define FBIOPUTCMAP 0x4605 +#define FBIOPAN_DISPLAY 0x4606 +#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) +/* 0x4607-0x460B are defined below */ +/* #define FBIOGET_MONITORSPEC 0x460C */ +/* #define FBIOPUT_MONITORSPEC 0x460D */ +/* #define FBIOSWITCH_MONIBIT 0x460E */ +#define FBIOGET_CON2FBMAP 0x460F +#define FBIOPUT_CON2FBMAP 0x4610 +#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */ +#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank) +#define FBIO_ALLOC 0x4613 +#define FBIO_FREE 0x4614 +#define FBIOGET_GLYPH 0x4615 +#define FBIOGET_HWCINFO 0x4616 +#define FBIOPUT_MODEINFO 0x4617 +#define FBIOGET_DISPINFO 0x4618 +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, uint32_t) + +#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ +#define FB_TYPE_PLANES 1 /* Non interleaved planes */ +#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ +#define FB_TYPE_TEXT 3 /* Text/attributes */ +#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ +#define FB_TYPE_FOURCC 5 /* Type identified by a V4L2 FOURCC */ + +#define FB_AUX_TEXT_MDA 0 /* Monochrome text */ +#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ +#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ +#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ +#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */ +#define FB_AUX_TEXT_SVGA_GROUP 8 /* 8-15: SVGA tileblit compatible modes */ +#define FB_AUX_TEXT_SVGA_MASK 7 /* lower three bits says step */ +#define FB_AUX_TEXT_SVGA_STEP2 8 /* SVGA text mode: text, attr */ +#define FB_AUX_TEXT_SVGA_STEP4 9 /* SVGA text mode: text, attr, 2 reserved bytes */ +#define FB_AUX_TEXT_SVGA_STEP8 10 /* SVGA text mode: text, attr, 6 reserved bytes */ +#define FB_AUX_TEXT_SVGA_STEP16 11 /* SVGA text mode: text, attr, 14 reserved bytes */ +#define FB_AUX_TEXT_SVGA_LAST 15 /* reserved up to 15 */ + +#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */ +#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */ +#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */ + +#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */ +#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */ +#define FB_VISUAL_TRUECOLOR 2 /* True color */ +#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ +#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ +#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ +#define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */ + +#define FB_ACCEL_NONE 0 /* no hardware accelerator */ +#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ +#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ +#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */ +#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */ +#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */ +#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */ +#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */ +#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */ +#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */ +#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */ +#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */ +#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */ +#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */ +#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */ +#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */ +#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */ +#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ +#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */ +#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */ +#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */ +#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */ +#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */ +#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */ +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */ +#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */ +#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */ +#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */ +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */ +#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */ +#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */ +#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */ +#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */ +#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */ +#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon family */ +#define FB_ACCEL_I810 39 /* Intel 810/815 */ +#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */ +#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */ +#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */ +#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */ +#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */ +#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */ +#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */ +#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */ +#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */ +#define FB_ACCEL_OMAP1610 49 /* TI OMAP16xx */ +#define FB_ACCEL_TRIDENT_TGUI 50 /* Trident TGUI */ +#define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */ +#define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */ +#define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */ +#define FB_ACCEL_CIRRUS_ALPINE 53 /* Cirrus Logic 543x/544x/5480 */ +#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ +#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ +#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ +#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */ +#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */ +#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */ +#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */ +#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */ +#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */ +#define FB_ACCEL_PXA3XX 99 /* PXA3xx */ + +#define FB_ACCEL_SAVAGE4 0x80 /* S3 Savage4 */ +#define FB_ACCEL_SAVAGE3D 0x81 /* S3 Savage3D */ +#define FB_ACCEL_SAVAGE3D_MV 0x82 /* S3 Savage3D-MV */ +#define FB_ACCEL_SAVAGE2000 0x83 /* S3 Savage2000 */ +#define FB_ACCEL_SAVAGE_MX_MV 0x84 /* S3 Savage/MX-MV */ +#define FB_ACCEL_SAVAGE_MX 0x85 /* S3 Savage/MX */ +#define FB_ACCEL_SAVAGE_IX_MV 0x86 /* S3 Savage/IX-MV */ +#define FB_ACCEL_SAVAGE_IX 0x87 /* S3 Savage/IX */ +#define FB_ACCEL_PROSAVAGE_PM 0x88 /* S3 ProSavage PM133 */ +#define FB_ACCEL_PROSAVAGE_KM 0x89 /* S3 ProSavage KM133 */ +#define FB_ACCEL_S3TWISTER_P 0x8a /* S3 Twister */ +#define FB_ACCEL_S3TWISTER_K 0x8b /* S3 TwisterK */ +#define FB_ACCEL_SUPERSAVAGE 0x8c /* S3 Supersavage */ +#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */ +#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */ + +#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */ + +#define FB_CAP_FOURCC 1 /* Device supports FOURCC-based formats */ + +struct fb_fix_screeninfo { + char id[16]; /* identification string eg "TT Builtin" */ + unsigned long smem_start; /* Start of frame buffer mem */ + /* (physical address) */ + uint32_t smem_len; /* Length of frame buffer mem */ + uint32_t type; /* see FB_TYPE_* */ + uint32_t type_aux; /* Interleave for interleaved Planes */ + uint32_t visual; /* see FB_VISUAL_* */ + uint16_t xpanstep; /* zero if no hardware panning */ + uint16_t ypanstep; /* zero if no hardware panning */ + uint16_t ywrapstep; /* zero if no hardware ywrap */ + uint32_t line_length; /* length of a line in bytes */ + unsigned long mmio_start; /* Start of Memory Mapped I/O */ + /* (physical address) */ + uint32_t mmio_len; /* Length of Memory Mapped I/O */ + uint32_t accel; /* Indicate to driver which */ + /* specific chip/card we have */ + uint16_t capabilities; /* see FB_CAP_* */ + uint16_t reserved[2]; /* Reserved for future compatibility */ +}; + +/* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. + * + * For pseudocolor: offset and length should be the same for all color + * components. Offset specifies the position of the least significant bit + * of the palette index in a pixel value. Length indicates the number + * of available palette entries (i.e. # of entries = 1 << length). + */ +struct fb_bitfield { + uint32_t offset; /* beginning of bitfield */ + uint32_t length; /* length of bitfield */ + uint32_t msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */ +#define FB_NONSTD_REV_PIX_IN_B 2 /* order of pixels in each byte is reversed */ + +#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/ +#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */ +#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */ +#define FB_ACTIVATE_MASK 15 + /* values */ +#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */ +#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */ +#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */ +#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ +#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */ +#define FB_ACTIVATE_KD_TEXT 512 /* for KDSET vt ioctl */ + +#define FB_ACCELF_TEXT 1 /* (OBSOLETE) see fb_info.flags and vc_mode */ + +#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define FB_SYNC_EXT 4 /* external sync */ +#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define FB_SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ +#define FB_SYNC_ON_GREEN 32 /* sync on green */ + +#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ +#define FB_VMODE_INTERLACED 1 /* interlaced */ +#define FB_VMODE_DOUBLE 2 /* double scan */ +#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */ +#define FB_VMODE_MASK 255 + +#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */ +#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +/* + * Display rotation support + */ +#define FB_ROTATE_UR 0 +#define FB_ROTATE_CW 1 +#define FB_ROTATE_UD 2 +#define FB_ROTATE_CCW 3 + +#define PICOS2KHZ(a) (1000000000UL/(a)) +#define KHZ2PICOS(a) (1000000000UL/(a)) + +struct fb_var_screeninfo { + uint32_t xres; /* visible resolution */ + uint32_t yres; + uint32_t xres_virtual; /* virtual resolution */ + uint32_t yres_virtual; + uint32_t xoffset; /* offset from virtual to visible */ + uint32_t yoffset; /* resolution */ + + uint32_t bits_per_pixel; /* guess what */ + uint32_t grayscale; /* 0 = color, 1 = grayscale, */ + /* >1 = FOURCC */ + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + uint32_t nonstd; /* != 0 Non standard pixel format */ + + uint32_t activate; /* see FB_ACTIVATE_* */ + + uint32_t height; /* height of picture in mm */ + uint32_t width; /* width of picture in mm */ + + uint32_t accel_flags; /* (OBSOLETE) see fb_info.flags */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + uint32_t pixclock; /* pixel clock in ps (pico seconds) */ + uint32_t left_margin; /* time from sync to picture */ + uint32_t right_margin; /* time from picture to sync */ + uint32_t upper_margin; /* time from sync to picture */ + uint32_t lower_margin; + uint32_t hsync_len; /* length of horizontal sync */ + uint32_t vsync_len; /* length of vertical sync */ + uint32_t sync; /* see FB_SYNC_* */ + uint32_t vmode; /* see FB_VMODE_* */ + uint32_t rotate; /* angle we rotate counter clockwise */ + uint32_t colorspace; /* colorspace for FOURCC-based modes */ + uint32_t reserved[4]; /* Reserved for future compatibility */ +}; + +struct fb_cmap { + uint32_t start; /* First entry */ + uint32_t len; /* Number of entries */ + uint16_t *red; /* Red values */ + uint16_t *green; + uint16_t *blue; + uint16_t *transp; /* transparency, can be NULL */ +}; + +struct fb_con2fbmap { + uint32_t console; + uint32_t framebuffer; +}; + +/* VESA Blanking Levels */ +#define VESA_NO_BLANKING 0 +#define VESA_VSYNC_SUSPEND 1 +#define VESA_HSYNC_SUSPEND 2 +#define VESA_POWERDOWN 3 + + +enum { + /* screen: unblanked, hsync: on, vsync: on */ + FB_BLANK_UNBLANK = VESA_NO_BLANKING, + + /* screen: blanked, hsync: on, vsync: on */ + FB_BLANK_NORMAL = VESA_NO_BLANKING + 1, + + /* screen: blanked, hsync: on, vsync: off */ + FB_BLANK_VSYNC_SUSPEND = VESA_VSYNC_SUSPEND + 1, + + /* screen: blanked, hsync: off, vsync: on */ + FB_BLANK_HSYNC_SUSPEND = VESA_HSYNC_SUSPEND + 1, + + /* screen: blanked, hsync: off, vsync: off */ + FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1 +}; + +#define FB_VBLANK_VBLANKING 0x001 /* currently in a vertical blank */ +#define FB_VBLANK_HBLANKING 0x002 /* currently in a horizontal blank */ +#define FB_VBLANK_HAVE_VBLANK 0x004 /* vertical blanks can be detected */ +#define FB_VBLANK_HAVE_HBLANK 0x008 /* horizontal blanks can be detected */ +#define FB_VBLANK_HAVE_COUNT 0x010 /* global retrace counter is available */ +#define FB_VBLANK_HAVE_VCOUNT 0x020 /* the vcount field is valid */ +#define FB_VBLANK_HAVE_HCOUNT 0x040 /* the hcount field is valid */ +#define FB_VBLANK_VSYNCING 0x080 /* currently in a vsync */ +#define FB_VBLANK_HAVE_VSYNC 0x100 /* verical syncs can be detected */ + +struct fb_vblank { + uint32_t flags; /* FB_VBLANK flags */ + uint32_t count; /* counter of retraces since boot */ + uint32_t vcount; /* current scanline position */ + uint32_t hcount; /* current scandot position */ + uint32_t reserved[4]; /* reserved for future compatibility */ +}; + +/* Internal HW accel */ +#define ROP_COPY 0 +#define ROP_XOR 1 + +struct fb_copyarea { + uint32_t dx; + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t sx; + uint32_t sy; +}; + +struct fb_fillrect { + uint32_t dx; /* screen-relative */ + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t color; + uint32_t rop; +}; + +struct fb_image { + uint32_t dx; /* Where to place image */ + uint32_t dy; + uint32_t width; /* Size of image */ + uint32_t height; + uint32_t fg_color; /* Only used when a mono bitmap */ + uint32_t bg_color; + uint8_t depth; /* Depth of the image */ + const char *data; /* Pointer to image data */ + struct fb_cmap cmap; /* color map info */ +}; + +/* + * hardware cursor control + */ + +#define FB_CUR_SETIMAGE 0x01 +#define FB_CUR_SETPOS 0x02 +#define FB_CUR_SETHOT 0x04 +#define FB_CUR_SETCMAP 0x08 +#define FB_CUR_SETSHAPE 0x10 +#define FB_CUR_SETSIZE 0x20 +#define FB_CUR_SETALL 0xFF + +struct fbcurpos { + uint16_t x, y; +}; + +struct fb_cursor { + uint16_t set; /* what to set */ + uint16_t enable; /* cursor on/off */ + uint16_t rop; /* bitop operation */ + const char *mask; /* cursor mask bits */ + struct fbcurpos hot; /* cursor hot spot */ + struct fb_image image; /* Cursor image */ +}; + +/* Settings for the generic backlight code */ +#define FB_BACKLIGHT_LEVELS 128 +#define FB_BACKLIGHT_MAX 0xFF + + +#endif /* _LINUX_FB_H */ diff --git a/lib/mlibc/sysdeps/lyre/include/lyre/sockios.h b/lib/mlibc/sysdeps/lyre/include/lyre/sockios.h new file mode 100644 index 0000000..9c5a318 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/lyre/sockios.h @@ -0,0 +1,25 @@ +#ifndef _LYRE__SOCKIOS_H +#define _LYRE__SOCKIOS_H + +#include <asm/ioctls.h> + +#define SIOCINQ FIONREAD +#define SIOCOUTQ TIOCOUTQ + +#define SIOCGIFNAME 0x8910 /* get interface name */ +#define SIOCGIFFLAGS 0x8911 /* get flags */ +#define SIOCSIFFLAGS 0x8912 /* set flags */ +#define SIOCGIFADDR 0x8913 /* get interface ip */ +#define SIOCSIFADDR 0x8914 /* set interface ip */ +#define SIOCGIFNETMASK 0x8915 /* set netmask */ +#define SIOCSIFNETMASK 0x8916 /* get netmask */ +#define SIOCGIFMTU 0x8917 /* get mtu */ +#define SIOCSIFMTU 0x8918 /* set mtu */ +#define SIOCSIFNAME 0x8919 /* set interface name */ +#define SIOCSIFHWADDR 0x891a /* set mac address */ +#define SIOCGIFHWADDR 0x891b /* get mac address */ +#define SIOCGIFINDEX 0x891c /* get interface index */ +#define SIOCGIFGATEWAY 0x891d /* get gateway ip */ +#define SIOCSIFGATEWAY 0x891e /* set gateway ip */ + +#endif diff --git a/lib/mlibc/sysdeps/lyre/include/lyre/syscall.h b/lib/mlibc/sysdeps/lyre/include/lyre/syscall.h new file mode 100644 index 0000000..531b869 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/lyre/syscall.h @@ -0,0 +1,113 @@ +#ifndef _LYRE__SYSCALL_H +#define _LYRE__SYSCALL_H + +#include <stdint.h> + +#define SYS_debug 0 +#define SYS_mmap 1 +#define SYS_openat 2 +#define SYS_close 3 +#define SYS_read 4 +#define SYS_write 5 +#define SYS_seek 6 +#define SYS_set_fs_base 7 +#define SYS_set_gs_base 8 +#define SYS_stat 9 +#define SYS_fcntl 10 +#define SYS_dup3 11 +#define SYS_ioctl 12 +#define SYS_fork 13 +#define SYS_exec 14 +#define SYS_getpid 15 +#define SYS_waitpid 16 +#define SYS_exit 17 +#define SYS_getcwd 18 +#define SYS_chdir 19 +#define SYS_unmmap 20 +#define SYS_pipe 21 +#define SYS_readlinkat 22 +#define SYS_linkat 23 +#define SYS_unlinkat 24 +#define SYS_readdir 25 +#define SYS_uname 26 +#define SYS_futex_wait 27 +#define SYS_futex_wake 28 +#define SYS_mkdirat 29 +#define SYS_fchmodat 30 +#define SYS_sleep 31 +#define SYS_ppoll 32 +#define SYS_umask 33 +#define SYS_mprotect 34 +#define SYS_getclock 35 +#define SYS_socket 36 +#define SYS_bind 37 +#define SYS_connect 38 +#define SYS_listen 39 +#define SYS_accept 40 +#define SYS_getpeername 41 +#define SYS_recvmsg 42 +#define SYS_new_thread 43 +#define SYS_exit_thread 44 +#define SYS_sendmsg 45 +#define SYS_socketpair 46 +#define SYS_getsockopt 47 +#define SYS_setsockopt 48 +#define SYS_getsockname 49 + +struct __syscall_ret { + uint64_t ret; + uint64_t errno; +}; + +#define __SYSCALL_EXPAND(...) \ + struct __syscall_ret ret; \ + asm volatile ( \ + "mov %%rsp, %%r10\n\t" \ + "lea 1f(%%rip), %%r11\n\t" \ + "sysenter\n\t" \ + "1:" \ + : "=a"(ret.ret), "=b"(ret.errno) __VA_ARGS__ \ + "r10", "r11", "memory" \ + ); \ + return ret + +static inline struct __syscall_ret __syscall5(int number, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e) { + register uint64_t r8 asm("%r8") = d; + register uint64_t r9 asm("%r9") = e; + __SYSCALL_EXPAND(, "+d"(b), "+c"(c) : "D"(number), "S"(a), "r"(r8), "r"(r9) :); +} + +static inline struct __syscall_ret __syscall4(int number, uint64_t a, uint64_t b, uint64_t c, uint64_t d) { + register uint64_t r8 asm("%r8") = d; + __SYSCALL_EXPAND(, "+d"(b), "+c"(c) : "D"(number), "S"(a), "r"(r8) :); +} + +static inline struct __syscall_ret __syscall3(int number, uint64_t a, uint64_t b, uint64_t c) { + __SYSCALL_EXPAND(, "+d"(b), "+c"(c) : "D"(number), "S"(a) :); +} + +static inline struct __syscall_ret __syscall2(int number, uint64_t a, uint64_t b) { + __SYSCALL_EXPAND(, "+d"(b) : "D"(number), "S"(a) : "rcx", ); +} + +static inline struct __syscall_ret __syscall1(int number, uint64_t a) { + __SYSCALL_EXPAND( : "D"(number), "S"(a) : "rcx", "rdx", ); +} + +static inline struct __syscall_ret __syscall0(int number) { + __SYSCALL_EXPAND( : "D"(number) : "rcx", "rdx", ); +} + +#define __SYSCALL_NARGS_SEQ(_0,_1,_2,_3,_4,_5,_6,_7,N,...) N +#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_SEQ(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) + +#define __SYSCALL_CONCAT1(X, Y) X##Y +#define __SYSCALL_CONCAT(X, Y) __SYSCALL_CONCAT1(X, Y) + +#define __syscall(...) ({ \ + struct __syscall_ret (*__SYSCALL_f)(int, ...); \ + __SYSCALL_f = (struct __syscall_ret (*)(int, ...))__SYSCALL_CONCAT(__syscall, __SYSCALL_NARGS(__VA_ARGS__)); \ + __SYSCALL_f(__VA_ARGS__); \ +}) + +#endif diff --git a/lib/mlibc/sysdeps/lyre/include/mntent.h b/lib/mlibc/sysdeps/lyre/include/mntent.h new file mode 100644 index 0000000..bafd289 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/mntent.h @@ -0,0 +1,50 @@ +#ifndef _MNTENT_H +#define _MNTENT_H + +#include <stdio.h> + +// TODO: Refer to _PATH_MOUNTED +#define MOUNTED "/etc/mtab" + +/* Generic mount options */ +#define MNTOPT_DEFAULTS "defaults" /* Use all default options. */ +#define MNTOPT_RO "ro" /* Read only. */ +#define MNTOPT_RW "rw" /* Read/write. */ +#define MNTOPT_SUID "suid" /* Set uid allowed. */ +#define MNTOPT_NOSUID "nosuid" /* No set uid allowed. */ +#define MNTOPT_NOAUTO "noauto" /* Do not auto mount. */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct mntent { + char *mnt_fsname; + char *mnt_dir; + char *mnt_type; + char *mnt_opts; + int mnt_freq; + int mnt_passno; +}; + +#ifndef __MLIBC_ABI_ONLY + +FILE *setmntent(const char *, const char *); + +struct mntent *getmntent(FILE *); + +int addmntent(FILE *, const struct mntent *); + +int endmntent(FILE *); + +char *hasmntopt(const struct mntent *, const char *); + +struct mntent *getmntent_r(FILE *, struct mntent *, char *, int); + +#endif /* !__MLIBC_ABI_ONLY */ + +#ifdef __cplusplus +} +#endif + +#endif // _MNTENT_H diff --git a/lib/mlibc/sysdeps/lyre/include/sys/mount.h b/lib/mlibc/sysdeps/lyre/include/sys/mount.h new file mode 100644 index 0000000..b19f3d7 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/sys/mount.h @@ -0,0 +1,54 @@ +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MS_RDONLY 1 +#define MS_NOSUID 2 +#define MS_NODEV 4 +#define MS_NOEXEC 8 +#define MS_SYNCHRONOUS 16 +#define MS_REMOUNT 32 +#define MS_MANDLOCK 64 +#define MS_DIRSYNC 128 +#define MS_NOSYMFOLLOW 256 +#define MS_NOATIME 1024 +#define MS_NODIRATIME 2048 +#define MS_BIND 4096 +#define MS_MOVE 8192 +#define MS_REC 16384 +#define MS_SILENT 32768 +#define MS_POSIXACL (1 << 16) +#define MS_UNBINDABLE (1 << 17) +#define MS_PRIVATE (1 << 18) +#define MS_SLAVE (1 << 19) +#define MS_SHARED (1 << 20) +#define MS_RELATIME (1 << 21) +#define MS_KERNMOUNT (1 << 22) +#define MS_I_VERSION (1 << 23) +#define MS_STRICTATIME (1 << 24) +#define MS_LAZYTIME (1 << 25) +#define MS_NOREMOTELOCK (1 << 27) +#define MS_NOSEC (1 << 28) +#define MS_BORN (1 << 29) +#define MS_ACTIVE (1 << 30) +#define MS_NOUSER (1 << 31) + +#define MNT_FORCE 1 + +#ifndef __MLIBC_ABI_ONLY + +int mount(const char *source, const char *target, + const char *fstype, unsigned long flags, const void *data); +int umount(const char *target); +int umount2(const char *target, int flags); + +#endif /* !__MLIBC_ABI_ONLY */ + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_MOUNT_H diff --git a/lib/mlibc/sysdeps/lyre/include/sys/reboot.h b/lib/mlibc/sysdeps/lyre/include/sys/reboot.h new file mode 100644 index 0000000..6c4e495 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/sys/reboot.h @@ -0,0 +1,20 @@ +#ifndef MLIBC_SYS_REBOOT_H +#define MLIBC_SYS_REBOOT_H + +#include <abi-bits/reboot.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __MLIBC_ABI_ONLY + +int reboot(int arg); + +#endif /* !__MLIBC_ABI_ONLY */ + +#ifdef __cplusplus +} +#endif + +#endif // MLIBC_SYS_REBOOT_H diff --git a/lib/mlibc/sysdeps/lyre/include/sys/sysmacros.h b/lib/mlibc/sysdeps/lyre/include/sys/sysmacros.h new file mode 100644 index 0000000..2d696e3 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/include/sys/sysmacros.h @@ -0,0 +1,33 @@ +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H + +#ifdef __cplusplus +extern "C" { +#endif + +static unsigned int __mlibc_dev_major( + unsigned long long int __dev) { + return ((__dev >> 8) & 0xfff) | ((unsigned int)(__dev >> 32) & ~0xfff); +} + +static unsigned int __mlibc_dev_minor( + unsigned long long int __dev) { + return (__dev & 0xff) | ((unsigned int)(__dev >> 12) & ~0xff); +} + +static unsigned long long int __mlibc_dev_makedev( + unsigned int __major, unsigned int __minor) { + return ((__minor & 0xff) | ((__major & 0xfff) << 8) + | (((unsigned long long int)(__minor & ~0xff)) << 12) + | (((unsigned long long int)(__major & ~0xfff)) << 32)); +} + +#define major(dev) __mlibc_dev_major(dev) +#define minor(dev) __mlibc_dev_minor(dev) +#define makedev(major, minor) __mlibc_dev_makedev(major, minor) + +#ifdef __cplusplus +} +#endif + +#endif // _SYS_SYSMACROS_H diff --git a/lib/mlibc/sysdeps/lyre/meson.build b/lib/mlibc/sysdeps/lyre/meson.build new file mode 100644 index 0000000..56ed19a --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/meson.build @@ -0,0 +1,122 @@ + +rtdl_sources += files( + 'generic/generic.cpp' +) + +libc_sources += files( + 'generic/entry.cpp', + 'generic/generic.cpp', + 'generic/mntent.cpp', + 'generic/mount.cpp', + 'generic/reboot.cpp', + 'generic/thread.cpp', + 'generic/thread.S' +) + +if not no_headers + install_headers( + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/reboot.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/access.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + subdir: 'abi-bits', + follow_symlinks: true + ) + + install_headers( + 'include/asm/ioctl.h', + 'include/asm/ioctls.h', + subdir: 'asm', + ) + + install_headers( + 'include/linux/fb.h', + subdir: 'linux', + ) + + install_headers( + 'include/sys/reboot.h', + 'include/sys/mount.h', + 'include/sys/sysmacros.h', + subdir: 'sys', + ) + + install_headers( + 'include/lyre/syscall.h', + 'include/lyre/sockios.h', + subdir: 'lyre', + ) + + install_headers( + 'include/mntent.h', + ) +endif + +if not headers_only + crt = custom_target('crt0', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crt0.S', + output: 'crt0.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crti', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crti.S', + output: 'crti.o', + install: true, + install_dir: get_option('libdir') + ) + + custom_target('crtn', + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: host_machine.cpu_family() / 'crt-src/crtn.S', + output: 'crtn.o', + install: true, + install_dir: get_option('libdir') + ) +endif + diff --git a/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crt0.S b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crt0.S new file mode 100644 index 0000000..d16a46f --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crt0.S @@ -0,0 +1,7 @@ +.section .text +.global _start +_start: + mov $main, %rdi + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crti.S b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crti.S new file mode 100644 index 0000000..911b078 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crti.S @@ -0,0 +1,11 @@ +.section .init +.global _init +_init: + push %rax + +.section .fini +.global _fini +_fini: + push %rax +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crtn.S b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crtn.S new file mode 100644 index 0000000..0187e50 --- /dev/null +++ b/lib/mlibc/sysdeps/lyre/x86_64/crt-src/crtn.S @@ -0,0 +1,9 @@ +.section .init + pop %rax + ret + +.section .fini + pop %rax + ret +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/aarch64/crt-src/Scrt1.S b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/Scrt1.S new file mode 100644 index 0000000..3e56608 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/Scrt1.S @@ -0,0 +1,10 @@ +.section .text +.global _start +_start: + mov x0, sp + adr x1, main + + bl __mlibc_entry + brk #0 + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crt0.S b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crt0.S new file mode 100644 index 0000000..5e59593 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crt0.S @@ -0,0 +1,11 @@ + +.section .text +.global _start +_start: + mov x0, sp + adrp x1, main + add x1, x1, :lo12:main + bl __mlibc_entry + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crti.S b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crti.S new file mode 100644 index 0000000..4307dfb --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crti.S @@ -0,0 +1,15 @@ + .ident "aarch64-managarm-mlibc crti" + + .section .init + .global _init +_init: + stp x29, x30, [sp, -16]! + mov x29, sp + + .section .fini + .global _fini +_fini: + stp x29, x30, [sp, -16]! + mov x29, sp + + .section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crtn.S b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crtn.S new file mode 100644 index 0000000..005d870 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/crt-src/crtn.S @@ -0,0 +1,11 @@ + .ident "aarch64-managarm-mlibc crtn" + + .section .init + ldp x29, x30, [sp], #16 + ret + + .section .fini + ldp x29, x30, [sp], #16 + ret + + .section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/managarm/aarch64/signals.S b/lib/mlibc/sysdeps/managarm/aarch64/signals.S new file mode 100644 index 0000000..044767d --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/signals.S @@ -0,0 +1,10 @@ + +.section .text +.global __mlibc_signal_restore +__mlibc_signal_restore: + ldr x0, =0x80000006 + svc 0 + brk #1 + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/aarch64/thread.cpp b/lib/mlibc/sysdeps/managarm/aarch64/thread.cpp new file mode 100644 index 0000000..88f1bf3 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/thread.cpp @@ -0,0 +1,56 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/tcb.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <errno.h> +#include <stdint.h> +#include <stddef.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if(mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(*stack_base == MAP_FAILED) { + return errno; + } + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/aarch64/thread_entry.S b/lib/mlibc/sysdeps/managarm/aarch64/thread_entry.S new file mode 100644 index 0000000..4cfcb4c --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/aarch64/thread_entry.S @@ -0,0 +1,11 @@ + +.section .text +.global __mlibc_start_thread +__mlibc_start_thread: + ldp x0, x1, [sp] + ldr x2, [sp, #16] + add sp, sp, #24 + bl __mlibc_enter_thread + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/generic/drm.cpp b/lib/mlibc/sysdeps/managarm/generic/drm.cpp new file mode 100644 index 0000000..805c366 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/drm.cpp @@ -0,0 +1,1176 @@ +#include <drm/drm_fourcc.h> +#include <drm/drm.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-pipe.hpp> + +#include <fs.frigg_bragi.hpp> + +namespace mlibc { + +int ioctl_drm(int fd, unsigned long request, void *arg, int *result, HelHandle handle) { + managarm::fs::IoctlRequest<MemoryAllocator> ioctl_req(getSysdepsAllocator()); + + switch(request) { + case DRM_IOCTL_VERSION: { + auto param = reinterpret_cast<drm_version*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->version_major = resp.drm_version_major(); + param->version_minor = resp.drm_version_minor(); + param->version_patchlevel = resp.drm_version_patchlevel(); + + if(param->name) + memcpy(param->name, resp.drm_driver_name().data(), frg::min(param->name_len, + resp.drm_driver_name().size())); + if(param->date) + memcpy(param->date, resp.drm_driver_date().data(), frg::min(param->date_len, + resp.drm_driver_date().size())); + if(param->desc) + memcpy(param->desc, resp.drm_driver_desc().data(), frg::min(param->desc_len, + resp.drm_driver_desc().size())); + + param->name_len = resp.drm_driver_name().size(); + param->date_len = resp.drm_driver_date().size(); + param->desc_len = resp.drm_driver_desc().size(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_GET_CAP: { + auto param = reinterpret_cast<drm_get_cap*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_capability(param->capability); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->value = resp.drm_value(); + *result = resp.result(); + return 0; + } + } + case DRM_IOCTL_SET_CLIENT_CAP: { + auto param = reinterpret_cast<drm_set_client_cap *>(arg); + mlibc::infoLogger() << "\e[35mmlibc: DRM_IOCTL_SET_CLIENT_CAP(" << param->capability << ") ignores its value\e[39m" << frg::endlog; + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_capability(param->capability); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->value = resp.drm_value(); + *result = resp.result(); + return 0; + } + } + case DRM_IOCTL_GET_MAGIC: { + auto param = reinterpret_cast<drm_auth *>(arg); + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_GET_MAGIC is not implemented correctly\e[39m" + << frg::endlog; + param->magic = 1; + *result = 0; + return 0; + } + case DRM_IOCTL_AUTH_MAGIC: { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_AUTH_MAGIC is not implemented correctly\e[39m" + << frg::endlog; + *result = 0; + return 0; + } + case DRM_IOCTL_SET_MASTER: { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_SET_MASTER is not implemented correctly\e[39m" + << frg::endlog; + *result = 0; + return 0; + } + case DRM_IOCTL_DROP_MASTER: { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_DROP_MASTER is not implemented correctly\e[39m" + << frg::endlog; + *result = 0; + return 0; + } + case DRM_IOCTL_MODE_GETRESOURCES: { + auto param = reinterpret_cast<drm_mode_card_res *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + if(recv_resp.error() == kHelErrDismissed) { + return EINVAL; + } + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + for(size_t i = 0; i < resp.drm_fb_ids_size(); i++) { + if(i >= param->count_fbs) + break; + auto dest = reinterpret_cast<uint32_t *>(param->fb_id_ptr); + dest[i] = resp.drm_fb_ids(i); + } + param->count_fbs = resp.drm_fb_ids_size(); + + for(size_t i = 0; i < resp.drm_crtc_ids_size(); i++) { + if(i >= param->count_crtcs) + break; + auto dest = reinterpret_cast<uint32_t *>(param->crtc_id_ptr); + dest[i] = resp.drm_crtc_ids(i); + } + param->count_crtcs = resp.drm_crtc_ids_size(); + + for(size_t i = 0; i < resp.drm_connector_ids_size(); i++) { + if(i >= param->count_connectors) + break; + auto dest = reinterpret_cast<uint32_t *>(param->connector_id_ptr); + dest[i] = resp.drm_connector_ids(i); + } + param->count_connectors = resp.drm_connector_ids_size(); + + for(size_t i = 0; i < resp.drm_encoder_ids_size(); i++) { + if(i >= param->count_encoders) + continue; + auto dest = reinterpret_cast<uint32_t *>(param->encoder_id_ptr); + dest[i] = resp.drm_encoder_ids(i); + } + param->count_encoders = resp.drm_encoder_ids_size(); + + param->min_width = resp.drm_min_width(); + param->max_width = resp.drm_max_width(); + param->min_height = resp.drm_min_height(); + param->max_height = resp.drm_max_height(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETCONNECTOR: { + auto param = reinterpret_cast<drm_mode_get_connector*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_connector_id(param->connector_id); + req.set_drm_max_modes(param->count_modes); + + auto [offer, send_ioctl_req, send_req, recv_resp, recv_list] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(reinterpret_cast<void *>(param->modes_ptr), param->count_modes * sizeof(drm_mode_modeinfo)) + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + if(recv_resp.error() == kHelErrDismissed) + return EINVAL; + + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_list.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + for(size_t i = 0; i < resp.drm_encoders_size(); i++) { + if(i >= param->count_encoders) + continue; + auto dest = reinterpret_cast<uint32_t *>(param->encoders_ptr); + dest[i] = resp.drm_encoders(i); + } + + param->encoder_id = resp.drm_encoder_id(); + param->connector_type = resp.drm_connector_type(); + param->connector_type_id = resp.drm_connector_type_id(); + param->connection = resp.drm_connection(); + param->mm_width = resp.drm_mm_width(); + param->mm_height = resp.drm_mm_height(); + param->subpixel = resp.drm_subpixel(); + param->pad = 0; + param->count_encoders = resp.drm_encoders_size(); + param->count_modes = resp.drm_num_modes(); + + if(param->props_ptr) { + auto id_ptr = reinterpret_cast<uint32_t *>(param->props_ptr); + auto val_ptr = reinterpret_cast<uint64_t *>(param->prop_values_ptr); + + for(size_t i = 0; i < frg::min(static_cast<size_t>(param->count_props), resp.drm_obj_property_ids_size()); i++) { + id_ptr[i] = resp.drm_obj_property_ids(i); + val_ptr[i] = resp.drm_obj_property_values(i); + } + } + + param->count_props = resp.drm_obj_property_ids_size(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETPROPERTY: { + auto param = reinterpret_cast<drm_mode_get_property*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_property_id(param->prop_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() != managarm::fs::Errors::SUCCESS) { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_MODE_GETPROPERTY(" << param->prop_id << ") error " << (int) resp.error() << "\e[39m" + << frg::endlog; + *result = 0; + return EINVAL; + } + + memcpy(param->name, resp.drm_property_name().data(), resp.drm_property_name().size()); + param->count_values = resp.drm_property_vals_size(); + param->flags = resp.drm_property_flags(); + + for(size_t i = 0; i < param->count_values && i < resp.drm_property_vals_size() && param->values_ptr; i++) { + auto dest = reinterpret_cast<uint64_t *>(param->values_ptr); + dest[i] = resp.drm_property_vals(i); + } + + __ensure(resp.drm_enum_name_size() == resp.drm_enum_value_size()); + + for(size_t i = 0; i < param->count_enum_blobs && i < resp.drm_enum_name_size() && i < resp.drm_enum_value_size(); i++) { + auto dest = reinterpret_cast<drm_mode_property_enum *>(param->enum_blob_ptr); + dest[i].value = resp.drm_enum_value(i); + strncpy(dest[i].name, resp.drm_enum_name(i).data(), DRM_PROP_NAME_LEN); + } + + param->count_enum_blobs = resp.drm_enum_name_size(); + + *result = 0; + return 0; + } + case DRM_IOCTL_MODE_SETPROPERTY: { + auto param = reinterpret_cast<drm_mode_connector_set_property *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_property_id(param->prop_id); + req.set_drm_property_value(param->value); + req.set_drm_obj_id(param->connector_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() != managarm::fs::Errors::SUCCESS) { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_MODE_SETPROPERTY(" << param->prop_id << ") error " << (int) resp.error() << "\e[39m" + << frg::endlog; + *result = 0; + return EINVAL; + } + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETPROPBLOB: { + auto param = reinterpret_cast<drm_mode_get_blob *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_blob_id(param->blob_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() != managarm::fs::Errors::SUCCESS) { + mlibc::infoLogger() << "\e[31mmlibc: DRM_IOCTL_MODE_GETPROPBLOB(" << param->blob_id << ") error " << (int) resp.error() << "\e[39m" + << frg::endlog; + *result = 0; + return EINVAL; + } + + uint8_t *dest = reinterpret_cast<uint8_t *>(param->data); + for(size_t i = 0; i < resp.drm_property_blob_size(); i++) { + if(i >= param->length) { + continue; + } + + dest[i] = resp.drm_property_blob(i); + } + + param->length = resp.drm_property_blob_size(); + + *result = 0; + return 0; + } + case DRM_IOCTL_MODE_GETPLANE: { + auto param = reinterpret_cast<drm_mode_get_plane*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_plane_id(param->plane_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->crtc_id = resp.drm_crtc_id(); + param->fb_id = resp.drm_fb_id(); + param->possible_crtcs = resp.drm_possible_crtcs(); + param->gamma_size = resp.drm_gamma_size(); + + // FIXME: this should be passed as a buffer with helix, but this has no bounded max size? + for(size_t i = 0; i < resp.drm_format_type_size(); i++) { + if(i >= param->count_format_types) { + break; + } + auto dest = reinterpret_cast<uint32_t *>(param->format_type_ptr); + dest[i] = resp.drm_format_type(i); + } + + param->count_format_types = resp.drm_format_type_size(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETPLANERESOURCES: { + auto param = reinterpret_cast<drm_mode_get_plane_res *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + // FIXME: send this via a helix_ng buffer + for(size_t i = 0; i < resp.drm_plane_res_size(); i++) { + if(i >= param->count_planes) { + continue; + } + auto dest = reinterpret_cast<uint32_t *>(param->plane_id_ptr); + dest[i] = resp.drm_plane_res(i); + } + + param->count_planes = resp.drm_plane_res_size(); + + *result = resp.result(); + + return 0; + } + case DRM_IOCTL_MODE_GETENCODER: { + auto param = reinterpret_cast<drm_mode_get_encoder*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_encoder_id(param->encoder_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->encoder_type = resp.drm_encoder_type(); + param->crtc_id = resp.drm_crtc_id(); + param->possible_crtcs = resp.drm_possible_crtcs(); + param->possible_clones = resp.drm_possible_clones(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_CREATE_DUMB: { + auto param = reinterpret_cast<drm_mode_create_dumb*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_width(param->width); + req.set_drm_height(param->height); + req.set_drm_bpp(param->bpp); + req.set_drm_flags(param->flags); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->handle = resp.drm_handle(); + param->pitch = resp.drm_pitch(); + param->size = resp.drm_size(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_ADDFB: { + auto param = reinterpret_cast<drm_mode_fb_cmd *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_width(param->width); + req.set_drm_height(param->height); + req.set_drm_pitch(param->pitch); + req.set_drm_bpp(param->bpp); + req.set_drm_depth(param->depth); + req.set_drm_handle(param->handle); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->fb_id = resp.drm_fb_id(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETFB2: { + auto param = reinterpret_cast<drm_mode_fb_cmd2 *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(DRM_IOCTL_MODE_GETFB2); + req.set_drm_fb_id(param->fb_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->width = resp.drm_width(); + param->height = resp.drm_height(); + param->pixel_format = resp.pixel_format(); + param->modifier[0] = resp.modifier(); + memcpy(param->handles, resp.drm_handles().data(), sizeof(uint32_t) * resp.drm_handles_size()); + memcpy(param->pitches, resp.drm_pitches().data(), sizeof(uint32_t) * resp.drm_pitches_size()); + memcpy(param->offsets, resp.drm_offsets().data(), sizeof(uint32_t) * resp.drm_offsets_size()); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_ADDFB2: { + auto param = reinterpret_cast<drm_mode_fb_cmd2 *>(arg); + + __ensure(!param->flags || param->flags == DRM_MODE_FB_MODIFIERS); + __ensure(!param->modifier[0] || param->modifier[0] == DRM_FORMAT_MOD_INVALID); + __ensure(!param->offsets[0]); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(DRM_IOCTL_MODE_ADDFB2); + + req.set_drm_width(param->width); + req.set_drm_height(param->height); + req.set_drm_pitch(param->pitches[0]); + req.set_drm_fourcc(param->pixel_format); + req.set_drm_handle(param->handles[0]); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->fb_id = resp.drm_fb_id(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_RMFB: { + auto param = reinterpret_cast<int *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_fb_id(*param); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_MAP_DUMB: { + auto param = reinterpret_cast<drm_mode_map_dumb*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_handle(param->handle); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->offset = resp.drm_offset(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_GETCRTC: { + auto param = reinterpret_cast<drm_mode_crtc*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_crtc_id(param->crtc_id); + + auto [offer, send_ioctl_req, send_req, recv_resp, recv_data] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(¶m->mode, sizeof(drm_mode_modeinfo))) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_data.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->fb_id = resp.drm_fb_id(); + param->x = resp.drm_x(); + param->y = resp.drm_y(); + param->gamma_size = resp.drm_gamma_size(); + param->mode_valid = resp.drm_mode_valid(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_SETCRTC: { + auto param = reinterpret_cast<drm_mode_crtc*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + for(size_t i = 0; i < param->count_connectors; i++) { + auto dest = reinterpret_cast<uint32_t *>(param->set_connectors_ptr); + req.add_drm_connector_ids(dest[i]); + } + req.set_drm_x(param->x); + req.set_drm_y(param->y); + req.set_drm_crtc_id(param->crtc_id); + req.set_drm_fb_id(param->fb_id); + req.set_drm_mode_valid(param->mode_valid); + + auto [offer, send_ioctl_req, send_req, send_mode, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::sendBuffer(¶m->mode, sizeof(drm_mode_modeinfo)), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(send_mode.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_OBJ_GETPROPERTIES: { + auto param = reinterpret_cast<drm_mode_obj_get_properties *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_count_props(param->count_props); + req.set_drm_obj_id(param->obj_id); + req.set_drm_obj_type(param->obj_type); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + auto props = reinterpret_cast<uint32_t *>(param->props_ptr); + auto prop_vals = reinterpret_cast<uint64_t *>(param->prop_values_ptr); + + for(size_t i = 0; i < resp.drm_obj_property_ids_size(); i++) { + if(i >= param->count_props) { + break; + } + props[i] = resp.drm_obj_property_ids(i); + prop_vals[i] = resp.drm_obj_property_values(i); + } + + param->count_props = resp.drm_obj_property_ids_size(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_PAGE_FLIP: { + auto param = reinterpret_cast<drm_mode_crtc_page_flip *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + __ensure(!(param->flags & ~DRM_MODE_PAGE_FLIP_EVENT)); + req.set_drm_crtc_id(param->crtc_id); + req.set_drm_fb_id(param->fb_id); + req.set_drm_cookie(param->user_data); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_DIRTYFB: { + auto param = reinterpret_cast<drm_mode_fb_dirty_cmd*>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_fb_id(param->fb_id); + req.set_drm_flags(param->flags); + req.set_drm_color(param->color); + for(size_t i = 0; i < param->num_clips; i++) { + auto dest = reinterpret_cast<drm_clip_rect *>(param->clips_ptr); + managarm::fs::Rect<MemoryAllocator> clip(getSysdepsAllocator()); + clip.set_x1(dest->x1); + clip.set_y1(dest->y1); + clip.set_x2(dest->x2); + clip.set_y2(dest->y2); + req.add_drm_clips(std::move(clip)); + } + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + return 0; + } + } + case DRM_IOCTL_MODE_CURSOR: { + auto param = reinterpret_cast<drm_mode_cursor *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_flags(param->flags); + req.set_drm_crtc_id(param->crtc_id); + + if (param->flags == DRM_MODE_CURSOR_MOVE) { + req.set_drm_x(param->x); + req.set_drm_y(param->y); + } else if (param->flags == DRM_MODE_CURSOR_BO) { + req.set_drm_width(param->width); + req.set_drm_height(param->height); + req.set_drm_handle(param->handle); + } else { + mlibc::infoLogger() << "\e[35mmlibc: invalid flags in DRM_IOCTL_MODE_CURSOR\e[39m" << frg::endlog; + return EINVAL; + } + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if (resp.error() == managarm::fs::Errors::NO_BACKING_DEVICE) { + return ENXIO; + }else if (resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else{ + *result = resp.result(); + return 0; + } + } + case DRM_IOCTL_MODE_DESTROY_DUMB: { + auto param = reinterpret_cast<drm_mode_destroy_dumb *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + req.set_drm_handle(param->handle); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_CREATEPROPBLOB: { + auto param = reinterpret_cast<drm_mode_create_blob *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_blob_size(param->length); + + auto [offer, send_ioctl_req, send_req, blob_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::sendBuffer(reinterpret_cast<void *>(param->data), param->length), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(blob_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->blob_id = resp.drm_blob_id(); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_DESTROYPROPBLOB: { + auto param = reinterpret_cast<drm_mode_destroy_blob *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_blob_id(param->blob_id); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_ATOMIC: { + auto param = reinterpret_cast<drm_mode_atomic *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_flags(param->flags); + req.set_drm_cookie(param->user_data); + + size_t prop_count = 0; + auto objs_ptr = reinterpret_cast<uint32_t *>(param->objs_ptr); + auto count_props_ptr = reinterpret_cast<uint32_t *>(param->count_props_ptr); + auto props_ptr = reinterpret_cast<uint32_t *>(param->props_ptr); + auto prop_values_ptr = reinterpret_cast<uint64_t *>(param->prop_values_ptr); + + for(size_t i = 0; i < param->count_objs; i++) { + /* list of modeobjs and their property count */ + req.add_drm_obj_ids(objs_ptr[i]); + req.add_drm_prop_counts(count_props_ptr[i]); + prop_count += count_props_ptr[i]; + } + + for(size_t i = 0; i < prop_count; i++) { + /* array of property IDs */ + req.add_drm_props(props_ptr[i]); + /* array of property values */ + req.add_drm_prop_values(prop_values_ptr[i]); + } + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + *result = resp.result(); + return 0; + } + case DRM_IOCTL_MODE_LIST_LESSEES: { + mlibc::infoLogger() << "\e[35mmlibc: DRM_IOCTL_MODE_LIST_LESSEES" + " is not implemented correctly\e[39m" << frg::endlog; + return EINVAL; + } + case DRM_IOCTL_MODE_SETGAMMA: { + mlibc::infoLogger() << "\e[35mmlibc: DRM_IOCTL_MODE_SETGAMMA" + " is not implemented correctly\e[39m" << frg::endlog; + return 0; + } + case DRM_IOCTL_MODE_CREATE_LEASE: { + auto param = reinterpret_cast<drm_mode_create_lease *>(arg); + + mlibc::infoLogger() << "\e[35mmlibc: DRM_IOCTL_MODE_CREATE_LEASE" + " is a noop\e[39m" << frg::endlog; + param->lessee_id = 1; + param->fd = fd; + *result = 0; + return 0; + } + case DRM_IOCTL_GEM_CLOSE: { + mlibc::infoLogger() << "\e[35mmlibc: DRM_IOCTL_GEM_CLOSE" + " is a noop\e[39m" << frg::endlog; + return 0; + } + case DRM_IOCTL_PRIME_HANDLE_TO_FD: { + auto param = reinterpret_cast<drm_prime_handle *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_prime_handle(param->handle); + req.set_drm_flags(param->flags); + + auto [offer, send_ioctl_req, send_req, send_creds, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(send_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->fd = resp.drm_prime_fd(); + *result = resp.result(); + return 0; + } + case DRM_IOCTL_PRIME_FD_TO_HANDLE: { + auto param = reinterpret_cast<drm_prime_handle *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_drm_flags(param->flags); + + auto [offer, send_ioctl_req, send_req, send_creds, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(getHandleForFd(param->fd)), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(send_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::FILE_NOT_FOUND) { + return EBADF; + } else { + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + } + + param->handle = resp.drm_prime_handle(); + *result = resp.result(); + return 0; + } + } + + mlibc::infoLogger() << "mlibc: Unexpected DRM ioctl with" + << ", number: 0x" << frg::hex_fmt(_IOC_NR(request)) + << " (raw request: " << frg::hex_fmt(request) << ")" << frg::endlog; + __ensure(!"Illegal ioctl request"); + __builtin_unreachable(); +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/ensure.cpp b/lib/mlibc/sysdeps/managarm/generic/ensure.cpp new file mode 100644 index 0000000..ab0d84f --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/ensure.cpp @@ -0,0 +1,38 @@ + +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> + +#include <hel.h> +#include <hel-syscalls.h> + +void __frigg_assert_fail(const char *assertion, const char *file, unsigned int line, + const char *function) { + mlibc::panicLogger() << "In function " << function + << ", file " << file << ":" << line << "\n" + << "__ensure(" << assertion << ") failed" << frg::endlog; +} + +namespace mlibc { + void sys_libc_log(const char *message) { + // This implementation is inherently signal-safe. + size_t n = 0; + while(message[n]) + n++; + HEL_CHECK(helLog(message, n)); + } + + void sys_libc_panic() { + // This implementation is inherently signal-safe. + const char *message = "mlibc: Panic!"; + size_t n = 0; + while(message[n]) + n++; + helPanic(message, n); + } +} + diff --git a/lib/mlibc/sysdeps/managarm/generic/entry.cpp b/lib/mlibc/sysdeps/managarm/generic/entry.cpp new file mode 100644 index 0000000..3ff28d2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/entry.cpp @@ -0,0 +1,132 @@ +#include <pthread.h> +#include <stdlib.h> +#include <sys/auxv.h> + +#include <frg/eternal.hpp> + +#include <bits/ensure.h> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/elf/startup.h> + +#include <protocols/posix/data.hpp> +#include <protocols/posix/supercalls.hpp> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); +extern "C" void __dlapi_enter(uintptr_t *); + +// declared in posix-pipe.hpp +thread_local Queue globalQueue; + +// TODO: clock tracker page and file table don't need to be thread-local! +thread_local HelHandle __mlibc_posix_lane; +thread_local void *__mlibc_clk_tracker_page; + +namespace { + thread_local unsigned __mlibc_gsf_nesting; + thread_local void *__mlibc_cached_thread_page; + thread_local HelHandle *cachedFileTable; + + // This construction is a bit weird: Even though the variables above + // are thread_local we still protect their initialization with a pthread_once_t + // (instead of using a C++ constructor). + // We do this in order to able to clear the pthread_once_t after a fork. + thread_local pthread_once_t has_cached_infos = PTHREAD_ONCE_INIT; + + void actuallyCacheInfos() { + posix::ManagarmProcessData data; + HEL_CHECK(helSyscall1(kHelCallSuper + posix::superGetProcessData, reinterpret_cast<HelWord>(&data))); + + __mlibc_posix_lane = data.posixLane; + __mlibc_cached_thread_page = data.threadPage; + cachedFileTable = data.fileTable; + __mlibc_clk_tracker_page = data.clockTrackerPage; + } +} + +SignalGuard::SignalGuard() { + pthread_once(&has_cached_infos, &actuallyCacheInfos); + if(!__mlibc_cached_thread_page) + return; + auto p = reinterpret_cast<unsigned int *>(__mlibc_cached_thread_page); + if(!__mlibc_gsf_nesting) + __atomic_store_n(p, 1, __ATOMIC_RELAXED); + __mlibc_gsf_nesting++; +} + +SignalGuard::~SignalGuard() { + pthread_once(&has_cached_infos, &actuallyCacheInfos); + if(!__mlibc_cached_thread_page) + return; + auto p = reinterpret_cast<unsigned int *>(__mlibc_cached_thread_page); + __ensure(__mlibc_gsf_nesting > 0); + __mlibc_gsf_nesting--; + if(!__mlibc_gsf_nesting) { + unsigned int result = __atomic_exchange_n(p, 0, __ATOMIC_RELAXED); + if(result == 2) { + HEL_CHECK(helSyscall0(kHelCallSuper + posix::superSigRaise)); + }else{ + __ensure(result == 1); + } + } +} + +MemoryAllocator &getSysdepsAllocator() { + // use frg::eternal to prevent a call to __cxa_atexit(). + // this is necessary because __cxa_atexit() call this function. + static frg::eternal<VirtualAllocator> virtualAllocator; + static frg::eternal<MemoryPool> heap{virtualAllocator.get()}; + static frg::eternal<MemoryAllocator> singleton{&heap.get()}; + return singleton.get(); +} + +HelHandle getPosixLane() { + cacheFileTable(); + return __mlibc_posix_lane; +} + +HelHandle *cacheFileTable() { + // TODO: Make sure that this is signal-safe (it is called e.g. by sys_clock_get()). + pthread_once(&has_cached_infos, &actuallyCacheInfos); + return cachedFileTable; +} + +HelHandle getHandleForFd(int fd) { + if (fd >= 512) + return 0; + + return cacheFileTable()[fd]; +} + +void clearCachedInfos() { + has_cached_infos = PTHREAD_ONCE_INIT; +} + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(uintptr_t *entry_stack, int (*main_fn)(int argc, char *argv[], char *env[])) { + __dlapi_enter(entry_stack); + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/managarm/generic/file.cpp b/lib/mlibc/sysdeps/managarm/generic/file.cpp new file mode 100644 index 0000000..1f5cba6 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/file.cpp @@ -0,0 +1,2526 @@ +#include <asm/ioctls.h> +#include <dirent.h> +#include <errno.h> +#include <stdio.h> +#include <sys/eventfd.h> +#include <sys/inotify.h> +#include <sys/signalfd.h> +#include <unistd.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/posix-pipe.hpp> + +#include <fs.frigg_bragi.hpp> +#include <posix.frigg_bragi.hpp> + +HelHandle __mlibc_getPassthrough(int fd) { + auto handle = getHandleForFd(fd); + __ensure(handle); + return handle; +} + +namespace mlibc { + +int sys_chdir(const char *path) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::CHDIR); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync(getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_fchdir(int fd) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::FCHDIR); + req.set_fd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_chroot(const char *path) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::CHROOT); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_mkdir(const char *path, mode_t mode) { + return sys_mkdirat(AT_FDCWD, path, mode); +} + +int sys_mkdirat(int dirfd, const char *path, mode_t mode) { + (void)mode; + SignalGuard sguard; + + managarm::posix::MkdirAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(dirfd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + } else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { + return ENOTDIR; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_symlink(const char *target_path, const char *link_path) { + return sys_symlinkat(target_path, AT_FDCWD, link_path); +} + +int sys_symlinkat(const char *target_path, int dirfd, const char *link_path) { + SignalGuard sguard; + + managarm::posix::SymlinkAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(dirfd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), link_path)); + req.set_target_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), target_path)); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { + return ENOTDIR; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_link(const char *old_path, const char *new_path) { + return sys_linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0); +} + +int sys_linkat(int olddirfd, const char *old_path, int newdirfd, const char *new_path, int flags) { + SignalGuard sguard; + + managarm::posix::LinkAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), old_path)); + req.set_target_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), new_path)); + req.set_fd(olddirfd); + req.set_newfd(newdirfd); + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_rename(const char *path, const char *new_path) { + return sys_renameat(AT_FDCWD, path, AT_FDCWD, new_path); +} + +int sys_renameat(int olddirfd, const char *old_path, int newdirfd, const char *new_path) { + SignalGuard sguard; + + managarm::posix::RenameAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), old_path)); + req.set_target_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), new_path)); + req.set_fd(olddirfd); + req.set_newfd(newdirfd); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +} //namespace mlibc + +namespace mlibc { + +int sys_fcntl(int fd, int request, va_list args, int *result) { + SignalGuard sguard; + if(request == F_DUPFD) { + int newfd; + if(int e = sys_dup(fd, 0, &newfd); e) + return e; + *result = newfd; + return 0; + }else if(request == F_DUPFD_CLOEXEC) { + int newfd; + if(int e = sys_dup(fd, O_CLOEXEC, &newfd); e) + return e; + *result = newfd; + return 0; + }else if(request == F_GETFD) { + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::FD_GET_FLAGS); + req.set_fd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) + return EBADF; + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *result = resp.flags(); + return 0; + }else if(request == F_SETFD) { + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::FD_SET_FLAGS); + req.set_fd(fd); + req.set_flags(va_arg(args, int)); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) + return EBADF; + else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) + return EINVAL; + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *result = static_cast<int>(resp.error()); + return 0; + }else if(request == F_GETFL) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_GET_FILE_FLAGS); + req.set_fd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_GETFL) unimplemented for this file\e[39m" << frg::endlog; + return EINVAL; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.flags(); + return 0; + }else if(request == F_SETFL) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_SET_FILE_FLAGS); + req.set_fd(fd); + req.set_flags(va_arg(args, int)); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_SETFL) unimplemented for this file\e[39m" << frg::endlog; + return EINVAL; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = 0; + return 0; + }else if(request == F_SETLK) { + mlibc::infoLogger() << "\e[31mmlibc: F_SETLK\e[39m" << frg::endlog; + return 0; + }else if(request == F_SETLKW) { + mlibc::infoLogger() << "\e[31mmlibc: F_SETLKW\e[39m" << frg::endlog; + return 0; + }else if(request == F_GETLK) { + struct flock *lock = va_arg(args, struct flock *); + lock->l_type = F_UNLCK; + mlibc::infoLogger() << "\e[31mmlibc: F_GETLK is stubbed!\e[39m" << frg::endlog; + return 0; + }else if(request == F_ADD_SEALS) { + auto seals = va_arg(args, int); + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_ADD_SEALS); + req.set_fd(fd); + req.set_seals(seals); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::RecvInline() + )); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_ADD_SEALS) unimplemented for this file\e[39m" << frg::endlog; + return EINVAL; + } else if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { + return EPERM; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.seals(); + return 0; + }else if(request == F_GET_SEALS) { + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_GET_SEALS); + req.set_fd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::RecvInline() + )); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_GET_SEALS) unimplemented for this file\e[39m" << frg::endlog; + return EINVAL; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.seals(); + return 0; + }else{ + mlibc::infoLogger() << "\e[31mmlibc: Unexpected fcntl() request: " + << request << "\e[39m" << frg::endlog; + return EINVAL; + } +} + +int sys_open_dir(const char *path, int *handle) { + return sys_open(path, 0, 0, handle); +} + +int sys_read_entries(int fd, void *buffer, size_t max_size, size_t *bytes_read) { + SignalGuard sguard; + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_READ_ENTRIES); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::END_OF_FILE) { + *bytes_read = 0; + return 0; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + __ensure(max_size > sizeof(struct dirent)); + auto ent = new (buffer) struct dirent; + memset(ent, 0, sizeof(struct dirent)); + memcpy(ent->d_name, resp.path().data(), resp.path().size()); + ent->d_reclen = sizeof(struct dirent); + *bytes_read = sizeof(struct dirent); + return 0; + } +} + +int sys_ttyname(int fd, char *buf, size_t size) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::TTY_NAME); + req.set_fd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::NOT_A_TTY) { + return ENOTTY; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + __ensure(size >= resp.path().size() + 1); + memcpy(buf, resp.path().data(), size); + buf[resp.path().size()] = '\0'; + return 0; + } +} + +int sys_fdatasync(int) { + mlibc::infoLogger() << "\e[35mmlibc: fdatasync() is a no-op\e[39m" + << frg::endlog; + return 0; +} + +int sys_getcwd(char *buffer, size_t size) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::GETCWD); + req.set_size(size); + + auto [offer, send_req, recv_resp, recv_path] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(buffer, size)) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_path.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + if(static_cast<size_t>(resp.size()) >= size) + return ERANGE; + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { + SignalGuard sguard; + + managarm::posix::VmMapRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_address_hint(reinterpret_cast<uintptr_t>(hint)); + req.set_size(size); + req.set_mode(prot); + req.set_flags(flags); + req.set_fd(fd); + req.set_rel_offset(offset); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + }else if(resp.error() == managarm::posix::Errors::NO_MEMORY) { + return EFAULT; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *window = reinterpret_cast<void *>(resp.offset()); + } + + return 0; +} + +int sys_vm_remap(void *pointer, size_t size, size_t new_size, void **window) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::VM_REMAP); + req.set_address(reinterpret_cast<uintptr_t>(pointer)); + req.set_size(size); + req.set_new_size(new_size); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *window = reinterpret_cast<void *>(resp.offset()); + return 0; +} + +int sys_vm_protect(void *pointer, size_t size, int prot) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::VM_PROTECT); + req.set_address(reinterpret_cast<uintptr_t>(pointer)); + req.set_size(size); + req.set_mode(prot); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_vm_unmap(void *pointer, size_t size) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::VM_UNMAP); + req.set_address(reinterpret_cast<uintptr_t>(pointer)); + req.set_size(size); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_setsid(pid_t *sid) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::SETSID); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + *sid = -1; + return EPERM; + } + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *sid = resp.sid(); + return 0; +} + +int sys_tcgetattr(int fd, struct termios *attr) { + int result; + if(int e = sys_ioctl(fd, TCGETS, attr, &result); e) + return e; + return 0; +} + +int sys_tcsetattr(int fd, int when, const struct termios *attr) { + if(when < TCSANOW || when > TCSAFLUSH) + return EINVAL; + + if(int e = sys_ioctl(fd, TCSETS, const_cast<struct termios *>(attr), nullptr); e) + return e; + return 0; +} + +int sys_tcdrain(int) { + mlibc::infoLogger() << "\e[35mmlibc: tcdrain() is a stub\e[39m" << frg::endlog; + return 0; +} + +int sys_socket(int domain, int type_and_flags, int proto, int *fd) { + constexpr int type_mask = int(0xF); + constexpr int flags_mask = ~int(0xF); + __ensure(!((type_and_flags & flags_mask) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))); + + SignalGuard sguard; + + managarm::posix::SocketRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_domain(domain); + req.set_socktype(type_and_flags & type_mask); + req.set_protocol(proto); + req.set_flags(type_and_flags & flags_mask); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EAFNOSUPPORT; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; + } +} + +int sys_pipe(int *fds, int flags) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::PIPE_CREATE); + req.set_flags(flags); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + __ensure(resp.fds_size() == 2); + fds[0] = resp.fds(0); + fds[1] = resp.fds(1); + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { + constexpr int type_mask = int(0xF); + constexpr int flags_mask = ~int(0xF); + __ensure(!((type_and_flags & flags_mask) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))); + + SignalGuard sguard; + + managarm::posix::SockpairRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_domain(domain); + req.set_socktype(type_and_flags & type_mask); + req.set_protocol(proto); + req.set_flags(type_and_flags & flags_mask); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::PROTOCOL_NOT_SUPPORTED) { + return EPROTONOSUPPORT; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + } + __ensure(resp.fds_size() == 2); + fds[0] = resp.fds(0); + fds[1] = resp.fds(1); + return 0; +} + +int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length) { + frg::vector<HelSgItem, MemoryAllocator> sglist{getSysdepsAllocator()}; + auto handle = getHandleForFd(sockfd); + if (!handle) + return EBADF; + + size_t overall_size = 0; + for(int i = 0; i < hdr->msg_iovlen; i++) { + HelSgItem item{ + .buffer = hdr->msg_iov[i].iov_base, + .length = hdr->msg_iov[i].iov_len, + }; + sglist.push_back(item); + overall_size += hdr->msg_iov[i].iov_len; + } + + SignalGuard sguard; + + managarm::fs::SendMsgRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_flags(flags); + req.set_size(overall_size); + + for(auto cmsg = CMSG_FIRSTHDR(hdr); cmsg; cmsg = CMSG_NXTHDR(hdr, cmsg)) { + __ensure(cmsg->cmsg_level == SOL_SOCKET); + if(cmsg->cmsg_type == SCM_CREDENTIALS) { + mlibc::infoLogger() << "mlibc: SCM_CREDENTIALS requested but we don't handle that yet!" << frg::endlog; + return EINVAL; + } + __ensure(cmsg->cmsg_type == SCM_RIGHTS); + __ensure(cmsg->cmsg_len >= sizeof(struct cmsghdr)); + + size_t size = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); + __ensure(!(size % sizeof(int))); + for(size_t off = 0; off < size; off += sizeof(int)) { + int fd; + memcpy(&fd, CMSG_DATA(cmsg) + off, sizeof(int)); + req.add_fds(fd); + } + } + + auto [offer, send_head, send_tail, send_data, imbue_creds, send_addr, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::sendBufferSg(sglist.data(), hdr->msg_iovlen), + helix_ng::imbueCredentials(), + helix_ng::sendBuffer(hdr->msg_name, hdr->msg_namelen), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(send_data.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(send_addr.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SendMsgReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::BROKEN_PIPE) { + return EPIPE; + }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { + return ENOTCONN; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::HOST_UNREACHABLE) { + return EHOSTUNREACH; + }else if(resp.error() == managarm::fs::Errors::ACCESS_DENIED) { + return EACCES; + }else if(resp.error() == managarm::fs::Errors::NETWORK_UNREACHABLE) { + return ENETUNREACH; + }else if(resp.error() == managarm::fs::Errors::DESTINATION_ADDRESS_REQUIRED) { + return EDESTADDRREQ; + }else if(resp.error() == managarm::fs::Errors::ADDRESS_NOT_AVAILABLE) { + return EADDRNOTAVAIL; + }else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::AF_NOT_SUPPORTED) { + return EAFNOSUPPORT; + }else if(resp.error() == managarm::fs::Errors::MESSAGE_TOO_LARGE) { + return EMSGSIZE; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *length = resp.size(); + return 0; + } +} + +int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length) { + if(!hdr->msg_iovlen) { + return EMSGSIZE; + } + + auto handle = getHandleForFd(sockfd); + if (!handle) + return EBADF; + + SignalGuard sguard; + + managarm::fs::RecvMsgRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_flags(flags); + req.set_size(hdr->msg_iov[0].iov_len); + req.set_addr_size(hdr->msg_namelen); + req.set_ctrl_size(hdr->msg_controllen); + + auto [offer, send_req, imbue_creds, recv_resp, recv_addr, recv_data, recv_ctrl] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::recvInline(), + helix_ng::recvBuffer(hdr->msg_name, hdr->msg_namelen), + helix_ng::recvBuffer(hdr->msg_iov[0].iov_base, hdr->msg_iov[0].iov_len), + helix_ng::recvBuffer(hdr->msg_control, hdr->msg_controllen)) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::RecvMsgReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + HEL_CHECK(recv_addr.error()); + HEL_CHECK(recv_data.error()); + HEL_CHECK(recv_ctrl.error()); + + hdr->msg_namelen = resp.addr_size(); + hdr->msg_controllen = recv_ctrl.actualLength(); + hdr->msg_flags = resp.flags(); + *length = resp.ret_val(); + return 0; + } +} + +int sys_pselect(int, fd_set *read_set, fd_set *write_set, + fd_set *except_set, const struct timespec *timeout, + const sigset_t *sigmask, int *num_events) { + // TODO: Do not keep errors from epoll (?). + int fd = epoll_create1(0); + if(fd == -1) + return -1; + + for(int k = 0; k < FD_SETSIZE; k++) { + struct epoll_event ev; + memset(&ev, 0, sizeof(struct epoll_event)); + + if(read_set && FD_ISSET(k, read_set)) + ev.events |= EPOLLIN; // TODO: Additional events. + if(write_set && FD_ISSET(k, write_set)) + ev.events |= EPOLLOUT; // TODO: Additional events. + if(except_set && FD_ISSET(k, except_set)) + ev.events |= EPOLLPRI; + + if(!ev.events) + continue; + ev.data.u32 = k; + + if(epoll_ctl(fd, EPOLL_CTL_ADD, k, &ev)) + return -1; + } + + struct epoll_event evnts[16]; + int n = epoll_pwait(fd, evnts, 16, + timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 100) : -1, sigmask); + if(n == -1) + return -1; + + fd_set res_read_set; + fd_set res_write_set; + fd_set res_except_set; + FD_ZERO(&res_read_set); + FD_ZERO(&res_write_set); + FD_ZERO(&res_except_set); + int m = 0; + + for(int i = 0; i < n; i++) { + int k = evnts[i].data.u32; + + if(read_set && FD_ISSET(k, read_set) + && evnts[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) { + FD_SET(k, &res_read_set); + m++; + } + + if(write_set && FD_ISSET(k, write_set) + && evnts[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) { + FD_SET(k, &res_write_set); + m++; + } + + if(except_set && FD_ISSET(k, except_set) + && evnts[i].events & EPOLLPRI) { + FD_SET(k, &res_except_set); + m++; + } + } + + if(close(fd)) + __ensure("close() failed on epoll file"); + + if(read_set) + memcpy(read_set, &res_read_set, sizeof(fd_set)); + if(write_set) + memcpy(write_set, &res_write_set, sizeof(fd_set)); + if(except_set) + memcpy(except_set, &res_except_set, sizeof(fd_set)); + + *num_events = m; + return 0; +} + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { + __ensure(timeout >= 0 || timeout == -1); // TODO: Report errors correctly. + + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::EPOLL_CALL); + req.set_timeout(timeout > 0 ? int64_t{timeout} * 1000000 : timeout); + + for(nfds_t i = 0; i < count; i++) { + req.add_fds(fds[i].fd); + req.add_events(fds[i].events); + } + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + __ensure(resp.events_size() == count); + + int m = 0; + for(nfds_t i = 0; i < count; i++) { + if(resp.events(i)) + m++; + fds[i].revents = resp.events(i); + } + + *num_events = m; + return 0; + } +} + +int sys_epoll_create(int flags, int *fd) { + // Some applications assume EPOLL_CLOEXEC and O_CLOEXEC to be the same. + // They are on linux, but not yet on managarm. + __ensure(!(flags & ~(EPOLL_CLOEXEC | O_CLOEXEC))); + + SignalGuard sguard; + + uint32_t proto_flags = 0; + if(flags & EPOLL_CLOEXEC || flags & O_CLOEXEC) + proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::EPOLL_CREATE); + req.set_flags(proto_flags); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + if(mode == EPOLL_CTL_ADD) { + __ensure(ev); + req.set_request_type(managarm::posix::CntReqType::EPOLL_ADD); + req.set_flags(ev->events); + req.set_cookie(ev->data.u64); + }else if(mode == EPOLL_CTL_MOD) { + __ensure(ev); + req.set_request_type(managarm::posix::CntReqType::EPOLL_MODIFY); + req.set_flags(ev->events); + req.set_cookie(ev->data.u64); + }else if(mode == EPOLL_CTL_DEL) { + req.set_request_type(managarm::posix::CntReqType::EPOLL_DELETE); + }else{ + mlibc::panicLogger() << "\e[31mmlibc: Illegal epoll_ctl() mode\e[39m" << frg::endlog; + } + req.set_fd(epfd); + req.set_newfd(fd); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + } else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + } else if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } + return 0; +} + +int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, + int timeout, const sigset_t *sigmask, int *raised) { + __ensure(timeout >= 0 || timeout == -1); // TODO: Report errors correctly. + + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::EPOLL_WAIT); + req.set_fd(epfd); + req.set_size(n); + req.set_timeout(timeout > 0 ? int64_t{timeout} * 1000000 : timeout); + if(sigmask != NULL) { + req.set_sigmask((long int)*sigmask); + req.set_sigmask_needed(true); + } else { + req.set_sigmask_needed(false); + } + + auto [offer, send_req, recv_resp, recv_data] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(ev, n * sizeof(struct epoll_event))) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_data.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + } + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + __ensure(!(recv_data.actualLength() % sizeof(struct epoll_event))); + *raised = recv_data.actualLength() / sizeof(struct epoll_event); + return 0; +} + +int sys_timerfd_create(int clockid, int flags, int *fd) { + (void) clockid; + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::TIMERFD_CREATE); + req.set_flags(flags); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_timerfd_settime(int fd, int, + const struct itimerspec *value, struct itimerspec *oldvalue) { + __ensure(!oldvalue); + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::TIMERFD_SETTIME); + req.set_fd(fd); + req.set_time_secs(value->it_value.tv_sec); + req.set_time_nanos(value->it_value.tv_nsec); + req.set_interval_secs(value->it_interval.tv_sec); + req.set_interval_nanos(value->it_interval.tv_nsec); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_signalfd_create(const sigset_t *masks, int flags, int *fd) { + __ensure(!(flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))); + + uint32_t proto_flags = 0; + if(flags & SFD_CLOEXEC) + proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + if(flags & SFD_NONBLOCK) + proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; + + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::SIGNALFD_CREATE); + req.set_flags(proto_flags); + req.set_sigset(*masks); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_inotify_create(int flags, int *fd) { + __ensure(!(flags & ~(IN_CLOEXEC | IN_NONBLOCK))); + + SignalGuard sguard; + + uint32_t proto_flags = 0; + if(flags & IN_CLOEXEC) + proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + if(flags & IN_NONBLOCK) + proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; + + managarm::posix::InotifyCreateRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_flags(proto_flags); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_inotify_add_watch(int ifd, const char *path, uint32_t mask, int *wd) { + SignalGuard sguard; + + managarm::posix::InotifyAddRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(ifd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + req.set_flags(mask); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *wd = resp.wd(); + return 0; + } +} + +int sys_eventfd_create(unsigned int initval, int flags, int *fd) { + SignalGuard sguard; + + uint32_t proto_flags = 0; + if (flags & EFD_NONBLOCK) proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; + if (flags & EFD_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + if (flags & EFD_SEMAPHORE) + return ENOSYS; + + managarm::posix::EventfdCreateRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_flags(proto_flags); + req.set_initval(initval); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + return sys_openat(AT_FDCWD, path, flags, mode, fd); +} + +int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) { + SignalGuard sguard; + + // We do not support O_TMPFILE. + if(flags & O_TMPFILE) + return EOPNOTSUPP; + + uint32_t proto_flags = 0; + if(flags & O_APPEND) + proto_flags |= managarm::posix::OpenFlags::OF_APPEND; + if(flags & O_CREAT) + proto_flags |= managarm::posix::OpenFlags::OF_CREATE; + if(flags & O_EXCL) + proto_flags |= managarm::posix::OpenFlags::OF_EXCLUSIVE; + if(flags & O_NONBLOCK) + proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; + if(flags & O_TRUNC) + proto_flags |= managarm::posix::OpenFlags::OF_TRUNC; + + if(flags & O_CLOEXEC) + proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + if(flags & O_NOCTTY) + proto_flags |= managarm::posix::OpenFlags::OF_NOCTTY; + + if(flags & O_RDONLY) + proto_flags |= managarm::posix::OpenFlags::OF_RDONLY; + else if(flags & O_WRONLY) + proto_flags |= managarm::posix::OpenFlags::OF_WRONLY; + else if(flags & O_RDWR) + proto_flags |= managarm::posix::OpenFlags::OF_RDWR; + else if(flags & O_PATH) + proto_flags |= managarm::posix::OpenFlags::OF_PATH; + + managarm::posix::OpenAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(dirfd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + req.set_flags(proto_flags); + req.set_mode(mode); + + auto [offer, sendHead, sendTail, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendHead.error()); + HEL_CHECK(sendTail.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { + return ENOTDIR; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_OPERATION_TARGET) { + mlibc::infoLogger() << "\e[31mmlibc: openat unimplemented for this file " << path << "\e[39m" << frg::endlog; + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::NO_BACKING_DEVICE) { + return ENXIO; + }else if(resp.error() == managarm::posix::Errors::IS_DIRECTORY) { + return EISDIR; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; + } +} + +int sys_mkfifoat(int dirfd, const char *path, mode_t mode) { + SignalGuard sguard; + + managarm::posix::MkfifoAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(dirfd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + req.set_mode(mode); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::INTERNAL_ERROR) { + return EIEIO; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_mknodat(int dirfd, const char *path, int mode, int dev) { + SignalGuard sguard; + + managarm::posix::MknodAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_dirfd(dirfd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + req.set_mode(mode); + req.set_device(dev); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + return EEXIST; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_read(int fd, void *data, size_t max_size, ssize_t *bytes_read) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::READ); + req.set_fd(fd); + req.set_size(max_size); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_req, imbue_creds, recv_resp, recv_data] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::imbueCredentials(), + helix_ng::recvInline(), + helix_ng::recvBuffer(data, max_size) + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); +/* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { + return EBADF; + }else*/ + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::END_OF_FILE) { + *bytes_read = 0; + return 0; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + HEL_CHECK(recv_data.error()); + *bytes_read = recv_data.actualLength(); + return 0; + } +} + +int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { + for(int i = 0; i < iovc; i++) { + ssize_t intermed = 0; + + if(int e = sys_read(fd, iovs[i].iov_base, iovs[i].iov_len, &intermed); e) + return e; + else if(intermed == 0) + break; + + *bytes_read += intermed; + } + + return 0; +} + +int sys_write(int fd, const void *data, size_t size, ssize_t *bytes_written) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::WRITE); + req.set_fd(fd); + req.set_size(size); + + auto [offer, send_req, imbue_creds, send_data, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::sendBuffer(data, size), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(send_data.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + // TODO: implement NO_SUCH_FD +/* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { + return EBADF; + }else*/ if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; // FD does not support writes. + }else if(resp.error() == managarm::fs::Errors::NO_SPACE_LEFT) { + return ENOSPC; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { + return ENOTCONN; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + if(bytes_written) { + *bytes_written = resp.size(); + } + return 0; + } +} + +int sys_pread(int fd, void *buf, size_t n, off_t off, ssize_t *bytes_read) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_PREAD); + req.set_fd(fd); + req.set_size(n); + req.set_offset(off); + + auto [offer, send_req, imbue_creds, recv_resp, recv_data] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::recvInline(), + helix_ng::recvBuffer(buf, n)) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); +/* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { + return EBADF; + }else*/ + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::END_OF_FILE) { + *bytes_read = 0; + return 0; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + HEL_CHECK(recv_data.error()); + *bytes_read = recv_data.actualLength(); + return 0; + } +} + +int sys_pwrite(int fd, const void *buf, size_t n, off_t off, ssize_t *bytes_written) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_PWRITE); + req.set_fd(fd); + req.set_size(n); + req.set_offset(off); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_head, imbue_creds, to_write, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::sendBuffer(buf, n), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(to_write.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::NO_SPACE_LEFT) { + return ENOSPC; + }else if(resp.error() == managarm::fs::Errors::SEEK_ON_PIPE) { + return ESPIPE; + }else if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *bytes_written = n; + return 0; + } +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if(!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + req.set_rel_offset(offset); + + if(whence == SEEK_SET) { + req.set_req_type(managarm::fs::CntReqType::SEEK_ABS); + }else if(whence == SEEK_CUR) { + req.set_req_type(managarm::fs::CntReqType::SEEK_REL); + }else if(whence == SEEK_END) { + req.set_req_type(managarm::fs::CntReqType::SEEK_EOF); + }else{ + return EINVAL; + } + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::SEEK_ON_PIPE) { + return ESPIPE; + } else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *new_offset = resp.offset(); + return 0; + } +} + + +int sys_close(int fd) { + SignalGuard sguard; + + managarm::posix::CloseRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + + if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::SUCCESS) { + return 0; + }else{ + __ensure(!"Unexpected error"); + __builtin_unreachable(); + } +} + +int sys_dup(int fd, int flags, int *newfd) { + SignalGuard sguard; + + __ensure(!(flags & ~(O_CLOEXEC))); + + uint32_t proto_flags = 0; + if(flags & O_CLOEXEC) + proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::DUP); + req.set_fd(fd); + req.set_flags(proto_flags); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if (resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + } else if (resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + } + + *newfd = resp.fd(); + return 0; +} + +int sys_dup2(int fd, int flags, int newfd) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::DUP2); + req.set_fd(fd); + req.set_newfd(newfd); + req.set_flags(flags); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if (resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + } else if (resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + } + + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *result) { + SignalGuard sguard; + + managarm::posix::FstatAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + if (fsfdt == fsfd_target::path) { + req.set_fd(AT_FDCWD); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + } else if (fsfdt == fsfd_target::fd) { + flags |= AT_EMPTY_PATH; + req.set_fd(fd); + } else { + __ensure(fsfdt == fsfd_target::fd_path); + req.set_fd(fd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + } + + if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) { + return EINVAL; + } + + if (!(flags & AT_EMPTY_PATH) && (!path || !strlen(path))) { + return ENOENT; + } + + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::BAD_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { + return ENOTDIR; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + memset(result, 0, sizeof(struct stat)); + + switch(resp.file_type()) { + case managarm::posix::FileType::FT_REGULAR: + result->st_mode = S_IFREG; break; + case managarm::posix::FileType::FT_DIRECTORY: + result->st_mode = S_IFDIR; break; + case managarm::posix::FileType::FT_SYMLINK: + result->st_mode = S_IFLNK; break; + case managarm::posix::FileType::FT_CHAR_DEVICE: + result->st_mode = S_IFCHR; break; + case managarm::posix::FileType::FT_BLOCK_DEVICE: + result->st_mode = S_IFBLK; break; + case managarm::posix::FileType::FT_SOCKET: + result->st_mode = S_IFSOCK; break; + case managarm::posix::FileType::FT_FIFO: + result->st_mode = S_IFIFO; break; + default: + __ensure(!resp.file_type()); + } + + result->st_dev = 1; + result->st_ino = resp.fs_inode(); + result->st_mode |= resp.mode(); + result->st_nlink = resp.num_links(); + result->st_uid = resp.uid(); + result->st_gid = resp.gid(); + result->st_rdev = resp.ref_devnum(); + result->st_size = resp.file_size(); + result->st_atim.tv_sec = resp.atime_secs(); + result->st_atim.tv_nsec = resp.atime_nanos(); + result->st_mtim.tv_sec = resp.mtime_secs(); + result->st_mtim.tv_nsec = resp.mtime_nanos(); + result->st_ctim.tv_sec = resp.ctime_secs(); + result->st_ctim.tv_nsec = resp.ctime_nanos(); + result->st_blksize = 4096; + result->st_blocks = resp.file_size() / 512 + 1; + return 0; + } +} + +int sys_readlink(const char *path, void *data, size_t max_size, ssize_t *length) { + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::READLINK); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + + auto [offer, send_req, recv_resp, recv_data] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(data, max_size)) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *length = recv_data.actualLength(); + return 0; + } +} + +int sys_rmdir(const char *path) { + SignalGuard sguard; + + managarm::posix::RmdirRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_ftruncate(int fd, size_t size) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_TRUNCATE); + req.set_size(size); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; + } +} + +int sys_fallocate(int fd, off_t offset, size_t size) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_FALLOCATE); + req.set_rel_offset(offset); + req.set_size(size); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { + return EPERM; + }else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; + } + return 0; +} + +int sys_unlinkat(int fd, const char *path, int flags) { + SignalGuard sguard; + + managarm::posix::UnlinkAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), path)); + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::RESOURCE_IN_USE) { + return EBUSY; + }else if(resp.error() == managarm::posix::Errors::IS_DIRECTORY) { + return EISDIR; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_access(const char *path, int mode) { + return sys_faccessat(AT_FDCWD, path, mode, 0); +} + +int sys_faccessat(int dirfd, const char *pathname, int, int flags) { + SignalGuard sguard; + + managarm::posix::AccessAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), pathname)); + req.set_fd(dirfd); + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_flock(int fd, int opts) { + SignalGuard sguard; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::FLOCK); + req.set_fd(fd); + req.set_flock_flags(opts); + auto handle = getHandleForFd(fd); + if(!handle) { + return EBADF; + } + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::WOULD_BLOCK) { + return EWOULDBLOCK; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_isatty(int fd) { + SignalGuard sguard; + + managarm::posix::IsTtyRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { + return EBADF; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + if(resp.mode()) + return 0; + return ENOTTY; + } +} + +int sys_chmod(const char *pathname, mode_t mode) { + return sys_fchmodat(AT_FDCWD, pathname, mode, 0); +} + +int sys_fchmod(int fd, mode_t mode) { + return sys_fchmodat(fd, "", mode, AT_EMPTY_PATH); +} + +int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { + SignalGuard sguard; + + managarm::posix::FchmodAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), pathname)); + req.set_mode(mode); + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::NOT_SUPPORTED) { + return ENOTSUP; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) { + (void)dirfd; + (void)pathname; + (void)owner; + (void)group; + (void)flags; + mlibc::infoLogger() << "mlibc: sys_fchownat is a stub!" << frg::endlog; + return 0; +} + +int sys_umask(mode_t mode, mode_t *old) { + (void)mode; + mlibc::infoLogger() << "mlibc: sys_umask is a stub, hardcoding 022!" << frg::endlog; + *old = 022; + return 0; +} + +int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { + SignalGuard sguard; + + managarm::posix::UtimensAtRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(dirfd); + if(pathname != nullptr) + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), pathname)); + if(times) { + req.set_atimeSec(times[0].tv_sec); + req.set_atimeNsec(times[0].tv_nsec); + req.set_mtimeSec(times[1].tv_sec); + req.set_mtimeNsec(times[1].tv_nsec); + } else { + req.set_atimeSec(UTIME_NOW); + req.set_atimeNsec(UTIME_NOW); + req.set_mtimeSec(UTIME_NOW); + req.set_mtimeNsec(UTIME_NOW); + } + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { + return ENOENT; + }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { + return EBADF; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else if(resp.error() == managarm::posix::Errors::NOT_SUPPORTED) { + return ENOTSUP; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_getentropy(void *buffer, size_t length) { + SignalGuard sguard; + auto p = reinterpret_cast<char *>(buffer); + size_t n = 0; + + while(n < length) { + size_t chunk; + HEL_CHECK(helGetRandomBytes(p + n, length - n, &chunk)); + n+= chunk; + } + + return 0; +} + +int sys_gethostname(char *buffer, size_t bufsize) { + SignalGuard sguard; + mlibc::infoLogger() << "mlibc: gethostname always returns managarm" << frg::endlog; + char name[10] = "managarm\0"; + if(bufsize < 10) + return ENAMETOOLONG; + strncpy(buffer, name, 10); + return 0; +} + +int sys_fsync(int) { + mlibc::infoLogger() << "mlibc: fsync is a stub" << frg::endlog; + return 0; +} + +int sys_memfd_create(const char *name, int flags, int *fd) { + SignalGuard sguard; + + managarm::posix::MemFdCreateRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_name(frg::string<MemoryAllocator>(getSysdepsAllocator(), name)); + req.set_flags(flags); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } + + *fd = resp.fd(); + + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_uname(struct utsname *buf) { + __ensure(buf); + mlibc::infoLogger() << "\e[31mmlibc: uname() returns static information\e[39m" << frg::endlog; + strcpy(buf->sysname, "Managarm"); + strcpy(buf->nodename, "managarm"); + strcpy(buf->release, "0.0.1-rolling"); + strcpy(buf->version, "Managarm is not Managram"); +#if defined(__x86_64__) + strcpy(buf->machine, "x86_64"); +#elif defined (__aarch64__) + strcpy(buf->machine, "aarch64"); +#else +# error Unknown architecture +#endif + + return 0; +} + +int sys_madvise(void *, size_t, int) { + mlibc::infoLogger() << "mlibc: sys_madvise is a stub!" << frg::endlog; + return 0; +} + +int sys_ptsname(int fd, char *buffer, size_t length) { + int index; + if(int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) + return e; + if((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { + return ERANGE; + } + return 0; +} + +int sys_unlockpt(int fd) { + int unlock = 0; + + if(int e = sys_ioctl(fd, TIOCSPTLCK, &unlock, NULL); e) + return e; + + return 0; +} + +} //namespace mlibc + diff --git a/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp b/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp new file mode 100644 index 0000000..8da0e1e --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp @@ -0,0 +1,744 @@ + +// for _Exit() +#include <stdlib.h> + +#include <string.h> +#include <errno.h> + +// for fork() and execve() +#include <unistd.h> +// for sched_yield() +#include <sched.h> +#include <stdio.h> +// for getrusage() +#include <sys/resource.h> +// for waitpid() +#include <sys/wait.h> +#include <pthread.h> + +#include <bits/ensure.h> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <posix.frigg_bragi.hpp> +#include <protocols/posix/supercalls.hpp> + +namespace mlibc { + +int sys_futex_tid() { + HelWord tid = 0; + HEL_CHECK(helSyscall0_1(kHelCallSuper + posix::superGetTid, + &tid)); + + return tid; +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + // This implementation is inherently signal-safe. + if(time) { + if(helFutexWait(pointer, expected, time->tv_nsec + time->tv_sec * 1000000000)) + return -1; + return 0; + } + if(helFutexWait(pointer, expected, -1)) + return -1; + return 0; +} + +int sys_futex_wake(int *pointer) { + // This implementation is inherently signal-safe. + if(helFutexWake(pointer)) + return -1; + return 0; +} + +int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { + if(ru) { + mlibc::infoLogger() << "mlibc: struct rusage in sys_waitpid is unsupported" << frg::endlog; + return ENOSYS; + } + + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::WAIT); + req.set_pid(pid); + req.set_flags(flags); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + if(status) + *status = resp.mode(); + *ret_pid = resp.pid(); + return 0; +} + +int sys_waitid(idtype_t idtype, id_t id, siginfo_t *info, int options) { + SignalGuard sguard; + + managarm::posix::WaitIdRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_idtype(idtype); + req.set_id(id); + req.set_flags(options); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::WaitIdResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + info->si_pid = resp.pid(); + info->si_uid = resp.uid(); + info->si_signo = SIGCHLD; + info->si_status = resp.sig_status(); + info->si_code = resp.sig_code(); + return 0; +} + +void sys_exit(int status) { + // This implementation is inherently signal-safe. + HEL_CHECK(helSyscall1(kHelCallSuper + posix::superExit, status)); + __builtin_trap(); +} + +void sys_yield() { + // This implementation is inherently signal-safe. + HEL_CHECK(helYield()); +} + +int sys_sleep(time_t *secs, long *nanos) { + SignalGuard sguard; + globalQueue.trim(); + + uint64_t now; + HEL_CHECK(helGetClock(&now)); + + uint64_t async_id; + HEL_CHECK(helSubmitAwaitClock(now + uint64_t(*secs) * 1000000000 + uint64_t(*nanos), + globalQueue.getQueue(), 0, &async_id)); + + auto element = globalQueue.dequeueSingle(); + auto result = parseSimple(element); + HEL_CHECK(result->error); + + *secs = 0; + *nanos = 0; + + return 0; +} + +int sys_fork(pid_t *child) { + // This implementation is inherently signal-safe. + int res; + + sigset_t full_sigset; + res = sigfillset(&full_sigset); + __ensure(!res); + + sigset_t former_sigset; + res = sigprocmask(SIG_SETMASK, &full_sigset, &former_sigset); + __ensure(!res); + + HelWord out; + HEL_CHECK(helSyscall0_1(kHelCallSuper + posix::superFork, &out)); + *child = out; + + if(!out) { + clearCachedInfos(); + globalQueue.recreateQueue(); + } + + res = sigprocmask(SIG_SETMASK, &former_sigset, nullptr); + __ensure(!res); + + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]) { + // TODO: Make this function signal-safe! + frg::string<MemoryAllocator> args_area(getSysdepsAllocator()); + for(auto it = argv; *it; ++it) + args_area += frg::string_view{*it, strlen(*it) + 1}; + + frg::string<MemoryAllocator> env_area(getSysdepsAllocator()); + for(auto it = envp; *it; ++it) + env_area += frg::string_view{*it, strlen(*it) + 1}; + + uintptr_t out; + + HEL_CHECK(helSyscall6_1(kHelCallSuper + posix::superExecve, + reinterpret_cast<uintptr_t>(path), + strlen(path), + reinterpret_cast<uintptr_t>(args_area.data()), + args_area.size(), + reinterpret_cast<uintptr_t>(env_area.data()), + env_area.size(), + &out)); + + return out; +} + +gid_t sys_getgid() { + SignalGuard sguard; + + managarm::posix::GetGidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.uid(); +} + +int sys_setgid(gid_t gid) { + SignalGuard sguard; + + managarm::posix::SetGidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_uid(gid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + return EPERM; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +gid_t sys_getegid() { + SignalGuard sguard; + + managarm::posix::GetEgidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.uid(); +} + +int sys_setegid(gid_t egid) { + SignalGuard sguard; + + managarm::posix::SetEgidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_uid(egid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + return EPERM; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +uid_t sys_getuid() { + SignalGuard sguard; + + managarm::posix::GetUidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.uid(); +} + +int sys_setuid(uid_t uid) { + SignalGuard sguard; + + managarm::posix::SetUidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_uid(uid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + return EPERM; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +uid_t sys_geteuid() { + SignalGuard sguard; + + managarm::posix::GetEuidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.uid(); +} + +int sys_seteuid(uid_t euid) { + SignalGuard sguard; + + managarm::posix::SetEuidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_uid(euid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + return EPERM; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +pid_t sys_gettid() { + // TODO: use an actual gettid syscall. + return sys_getpid(); +} + +pid_t sys_getpid() { + SignalGuard sguard; + + managarm::posix::GetPidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.pid(); +} + +pid_t sys_getppid() { + SignalGuard sguard; + + managarm::posix::GetPpidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return resp.pid(); +} + +int sys_getsid(pid_t pid, pid_t *sid) { + SignalGuard sguard; + + managarm::posix::GetSidRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_pid(pid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::NO_SUCH_RESOURCE) { + *sid = 0; + return ESRCH; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *sid = resp.pid(); + return 0; + } +} + +int sys_getpgid(pid_t pid, pid_t *pgid) { + SignalGuard sguard; + + managarm::posix::GetPgidRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_pid(pid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::NO_SUCH_RESOURCE) { + *pgid = 0; + return ESRCH; + } else { + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *pgid = resp.pid(); + return 0; + } +} + +int sys_setpgid(pid_t pid, pid_t pgid) { + SignalGuard sguard; + + managarm::posix::SetPgidRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_pid(pid); + req.set_pgid(pgid); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::posix::Errors::INSUFFICIENT_PERMISSION) { + return EPERM; + }else if(resp.error() == managarm::posix::Errors::NO_SUCH_RESOURCE) { + return ESRCH; + }else if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { + return EACCES; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } +} + +int sys_getrusage(int scope, struct rusage *usage) { + memset(usage, 0, sizeof(struct rusage)); + + SignalGuard sguard; + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::GET_RESOURCE_USAGE); + req.set_mode(scope); + + auto [offer, send_head, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + + usage->ru_utime.tv_sec = resp.ru_user_time() / 1'000'000'000; + usage->ru_utime.tv_usec = (resp.ru_user_time() % 1'000'000'000) / 1'000; + + return 0; +} + +int sys_getschedparam(void *tcb, int *policy, struct sched_param *param) { + if(tcb != mlibc::get_current_tcb()) { + return ESRCH; + } + + *policy = SCHED_OTHER; + int prio = 0; + // TODO(no92): use helGetPriority(kHelThisThread) here + mlibc::infoLogger() << "\e[31mlibc: sys_getschedparam always returns priority 0\e[39m" << frg::endlog; + param->sched_priority = prio; + + return 0; +} + +int sys_setschedparam(void *tcb, int policy, const struct sched_param *param) { + if(tcb != mlibc::get_current_tcb()) { + return ESRCH; + } + + if(policy != SCHED_OTHER) { + return EINVAL; + } + + HEL_CHECK(helSetPriority(kHelThisThread, param->sched_priority)); + + return 0; +} + +int sys_clone(void *tcb, pid_t *pid_out, void *stack) { + HelWord pid = 0; + HEL_CHECK(helSyscall2_1(kHelCallSuper + posix::superClone, + reinterpret_cast<HelWord>(__mlibc_start_thread), + reinterpret_cast<HelWord>(stack), + &pid)); + + if (pid_out) + *pid_out = pid; + + return 0; +} + +int sys_tcb_set(void *pointer) { +#if defined(__aarch64__) + uintptr_t addr = reinterpret_cast<uintptr_t>(pointer); + addr += sizeof(Tcb) - 0x10; + asm volatile ("msr tpidr_el0, %0" :: "r"(addr)); +#else + HEL_CHECK(helWriteFsBase(pointer)); +#endif + return 0; +} + +void sys_thread_exit() { + // This implementation is inherently signal-safe. + HEL_CHECK(helSyscall1(kHelCallSuper + posix::superExit, 0)); + __builtin_trap(); +} + +int sys_thread_setname(void *tcb, const char *name) { + if(strlen(name) > 15) { + return ERANGE; + } + + auto t = reinterpret_cast<Tcb *>(tcb); + char *path; + int cs = 0; + + if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { + return ENOMEM; + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + int fd; + if(int e = sys_open(path, O_WRONLY, 0, &fd); e) { + return e; + } + + if(int e = sys_write(fd, name, strlen(name) + 1, NULL)) { + return e; + } + + sys_close(fd); + + pthread_setcancelstate(cs, 0); + + return 0; +} + +int sys_thread_getname(void *tcb, char *name, size_t size) { + auto t = reinterpret_cast<Tcb *>(tcb); + char *path; + int cs = 0; + ssize_t real_size = 0; + + if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { + return ENOMEM; + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + int fd; + if(int e = sys_open(path, O_RDONLY | O_CLOEXEC, 0, &fd); e) { + return e; + } + + if(int e = sys_read(fd, name, size, &real_size)) { + return e; + } + + name[real_size - 1] = 0; + sys_close(fd); + + pthread_setcancelstate(cs, 0); + + if(static_cast<ssize_t>(size) <= real_size) { + return ERANGE; + } + + return 0; +} + + +} //namespace mlibc + diff --git a/lib/mlibc/sysdeps/managarm/generic/ioctl.cpp b/lib/mlibc/sysdeps/managarm/generic/ioctl.cpp new file mode 100644 index 0000000..384c09e --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/ioctl.cpp @@ -0,0 +1,708 @@ +#include <errno.h> +#include <fcntl.h> +#include <linux/cdrom.h> +#include <linux/input.h> +#include <linux/kd.h> +#include <linux/vt.h> +#include <sys/ioctl.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-pipe.hpp> + +#include <fs.frigg_bragi.hpp> +#include <posix.frigg_bragi.hpp> + +namespace mlibc { + +static constexpr bool logIoctls = false; + +int ioctl_drm(int fd, unsigned long request, void *arg, int *result, HelHandle handle); + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { + if(logIoctls) + mlibc::infoLogger() << "mlibc: ioctl with" + << " type: 0x" << frg::hex_fmt(_IOC_TYPE(request)) + << ", number: 0x" << frg::hex_fmt(_IOC_NR(request)) + << " (raw request: " << frg::hex_fmt(request) << ")" + << " on fd " << fd << frg::endlog; + + SignalGuard sguard; + auto handle = getHandleForFd(fd); + if(!handle) + return EBADF; + + if(_IOC_TYPE(request) == 'd') { + return ioctl_drm(fd, request, arg, result, handle); + } + + managarm::fs::IoctlRequest<MemoryAllocator> ioctl_req(getSysdepsAllocator()); + + switch(request) { + case FIONBIO: { + auto mode = reinterpret_cast<int *>(arg); + int flags = fcntl(fd, F_GETFL, 0); + if(*mode) { + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + }else{ + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } + return 0; + } + case FIONREAD: { + auto argp = reinterpret_cast<int *>(arg); + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + if(!argp) + return EINVAL; + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(FIONREAD); + + auto [offer, send_ioctl_req, send_req, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { + return ENOTCONN; + } else { + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *argp = resp.fionread_count(); + + return 0; + } + } + case FIOCLEX: { + managarm::posix::IoctlFioclexRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + if(recvResp.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; + } + case TCGETS: { + auto param = reinterpret_cast<struct termios *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, recv_resp, recv_attrs] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(param, sizeof(struct termios)) + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_attrs.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + __ensure(recv_attrs.actualLength() == sizeof(struct termios)); + *result = resp.result(); + return 0; + } + case TCSETS: { + auto param = reinterpret_cast<struct termios *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, send_attrs, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::sendBuffer(param, sizeof(struct termios)), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(send_attrs.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + if(result) + *result = resp.result(); + return 0; + } + case TIOCSCTTY: { + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, imbue_creds, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::recvInline()) + ); + + HEL_CHECK(offer.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + }else if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { + return EPERM; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + return 0; + } + case TIOCGWINSZ: { + auto param = reinterpret_cast<struct winsize *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) + return EINVAL; + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + param->ws_col = resp.pts_width(); + param->ws_row = resp.pts_height(); + param->ws_xpixel = resp.pts_pixel_width(); + param->ws_ypixel = resp.pts_pixel_height(); + return 0; + } + case TIOCSWINSZ: { + auto param = reinterpret_cast<const struct winsize *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_pts_width(param->ws_col); + req.set_pts_height(param->ws_row); + req.set_pts_pixel_width(param->ws_xpixel); + req.set_pts_pixel_height(param->ws_ypixel); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + *result = resp.result(); + return 0; + } + case TIOCGPTN: { + auto param = reinterpret_cast<int *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *param = resp.pts_index(); + if(result) + *result = resp.result(); + return 0; + } + case TIOCGPGRP: { + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_ioctl_req, send_req, imbue_creds, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::imbueCredentials(), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error()) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::NOT_A_TERMINAL) { + return ENOTTY; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + *static_cast<int *>(arg) = resp.pid(); + return 0; + } + case TIOCSPGRP: { + auto param = reinterpret_cast<int *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_pgid(*param); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_ioctl_req, send_req, imbue_creds, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::imbueCredentials(), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { + return EPERM; + } else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + return 0; + } + case TIOCGSID: { + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_ioctl_req, send_req, imbue_creds, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::imbueCredentials(), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + if(send_ioctl_req.error()) + return EINVAL; + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error()) + return EINVAL; + HEL_CHECK(send_req.error()); + if(imbue_creds.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::NOT_A_TERMINAL) { + return ENOTTY; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + *static_cast<int *>(arg) = resp.pid(); + return 0; + } + case CDROM_GET_CAPABILITY: { + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_ioctl_req, send_req, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + if(send_ioctl_req.error()) + return EINVAL; + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error()) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::NOT_A_TERMINAL) { + return ENOTTY; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + return 0; + } + } // end of switch() + + + if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGVERSION)) { + *reinterpret_cast<int *>(arg) = 0x010001; // should be EV_VERSION + *result = 0; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGID)) { + memset(arg, 0, sizeof(struct input_id)); + *result = 0; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGNAME(0))) { + const char *s = "Managarm generic evdev"; + auto chunk = frg::min(_IOC_SIZE(request), strlen(s) + 1); + memcpy(arg, s, chunk); + *result = chunk; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGPHYS(0))) { + // Returns the sysfs path of the device. + const char *s = "input0"; + auto chunk = frg::min(_IOC_SIZE(request), strlen(s) + 1); + memcpy(arg, s, chunk); + *result = chunk; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGUNIQ(0))) { + // Returns a unique ID for the device. + const char *s = "0"; + auto chunk = frg::min(_IOC_SIZE(request), strlen(s) + 1); + memcpy(arg, s, chunk); + *result = chunk; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGPROP(0))) { + // Returns a bitmask of properties of the device. + auto size = _IOC_SIZE(request); + memset(arg, 0, size); + *result = size; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGKEY(0))) { + // Returns the current key state. + auto size = _IOC_SIZE(request); + memset(arg, 0, size); + *result = size; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGLED(0))) { + // Returns the current LED state. + auto size = _IOC_SIZE(request); + memset(arg, 0, size); + *result = size; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGSW(0))) { + auto size = _IOC_SIZE(request); + memset(arg, 0, size); + *result = size; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) >= _IOC_NR(EVIOCGBIT(0, 0)) + && _IOC_NR(request) <= _IOC_NR(EVIOCGBIT(EV_MAX, 0))) { + // Returns a bitmask of capabilities of the device. + // If type is zero, return a mask of supported types. + // As EV_SYN is zero, this implies that it is impossible + // to get the mask of supported synthetic events. + auto type = _IOC_NR(request) - _IOC_NR(EVIOCGBIT(0, 0)); + if(!type) { + // TODO: Check with the Linux ABI if we have to do this. + memset(arg, 0, _IOC_SIZE(request)); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(EVIOCGBIT(0, 0)); + req.set_size(_IOC_SIZE(request)); + + auto [offer, send_ioctl_req, send_req, recv_resp, recv_data] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(arg, _IOC_SIZE(request))) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_data.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = recv_data.actualLength(); + return 0; + }else{ + // TODO: Check with the Linux ABI if we have to do this. + memset(arg, 0, _IOC_SIZE(request)); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(EVIOCGBIT(1, 0)); + req.set_input_type(type); + req.set_size(_IOC_SIZE(request)); + + auto [offer, send_ioctl_req, send_req, recv_resp, recv_data] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(arg, _IOC_SIZE(request))) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + HEL_CHECK(recv_data.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = recv_data.actualLength(); + return 0; + } + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCSCLOCKID)) { + auto param = reinterpret_cast<int *>(arg); + + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(request); + req.set_input_clock(*param); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *result = resp.result(); + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) >= _IOC_NR(EVIOCGABS(0)) + && _IOC_NR(request) <= _IOC_NR(EVIOCGABS(ABS_MAX))) { + auto param = reinterpret_cast<struct input_absinfo *>(arg); + + auto type = _IOC_NR(request) - _IOC_NR(EVIOCGABS(0)); + managarm::fs::GenericIoctlRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_command(EVIOCGABS(0)); + req.set_input_type(type); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync(handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_ioctl_req.error()); + if(send_req.error() == kHelErrDismissed) + return EINVAL; + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::GenericIoctlReply<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + param->value = resp.input_value(); + param->minimum = resp.input_min(); + param->maximum = resp.input_max(); + param->fuzz = resp.input_fuzz(); + param->flat = resp.input_flat(); + param->resolution = resp.input_resolution(); + + *result = resp.result(); + return 0; + }else if(request == KDSETMODE) { + auto param = reinterpret_cast<unsigned int *>(arg); + mlibc::infoLogger() << "\e[35mmlibc: KD_SETMODE(" << frg::hex_fmt(param) << ") is a no-op" << frg::endlog; + + *result = 0; + return 0; + }else if(request == KDGETMODE) { + auto param = reinterpret_cast<unsigned int *>(arg); + mlibc::infoLogger() << "\e[35mmlibc: KD_GETMODE is a no-op" << frg::endlog; + *param = 0; + + *result = 0; + return 0; + }else if(request == KDSKBMODE) { + auto param = reinterpret_cast<long>(arg); + mlibc::infoLogger() << "\e[35mmlibc: KD_SKBMODE(" << frg::hex_fmt(param) << ") is a no-op" << frg::endlog; + + *result = 0; + return 0; + }else if(request == VT_SETMODE) { + // auto param = reinterpret_cast<struct vt_mode *>(arg); + mlibc::infoLogger() << "\e[35mmlibc: VT_SETMODE is a no-op" << frg::endlog; + + *result = 0; + return 0; + }else if(request == VT_GETSTATE) { + auto param = reinterpret_cast<struct vt_stat *>(arg); + + param->v_active = 0; + param->v_signal = 0; + param->v_state = 0; + + mlibc::infoLogger() << "\e[35mmlibc: VT_GETSTATE is a no-op" << frg::endlog; + + *result = 0; + return 0; + }else if(request == VT_ACTIVATE || request == VT_WAITACTIVE) { + mlibc::infoLogger() << "\e[35mmlibc: VT_ACTIVATE/VT_WAITACTIVE are no-ops" << frg::endlog; + *result = 0; + return 0; + }else if(request == TIOCSPTLCK) { + mlibc::infoLogger() << "\e[35mmlibc: TIOCSPTLCK is a no-op" << frg::endlog; + if(result) + *result = 0; + return 0; + } + + mlibc::infoLogger() << "mlibc: Unexpected ioctl with" + << " type: 0x" << frg::hex_fmt(_IOC_TYPE(request)) + << ", number: 0x" << frg::hex_fmt(_IOC_NR(request)) + << " (raw request: " << frg::hex_fmt(request) << ")" << frg::endlog; + __ensure(!"Illegal ioctl request"); + __builtin_unreachable(); +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/memory.cpp b/lib/mlibc/sysdeps/managarm/generic/memory.cpp new file mode 100644 index 0000000..91e47af --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/memory.cpp @@ -0,0 +1,30 @@ + +#include <string.h> + +#include <bits/ensure.h> +#include <mlibc/allocator.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <protocols/posix/supercalls.hpp> + +#include <hel.h> +#include <hel-syscalls.h> + +namespace mlibc { + +int sys_anon_allocate(size_t size, void **pointer) { + // This implementation is inherently signal-safe. + __ensure(!(size & 0xFFF)); + HelWord out; + HEL_CHECK(helSyscall1_1(kHelCallSuper + posix::superAnonAllocate, size, &out)); + *pointer = reinterpret_cast<void *>(out); + return 0; +} + +int sys_anon_free(void *pointer, size_t size) { + // This implementation is inherently signal-safe. + HEL_CHECK(helSyscall2(kHelCallSuper + posix::superAnonDeallocate, (HelWord)pointer, size)); + return 0; +} + +} //namespace mlibc + diff --git a/lib/mlibc/sysdeps/managarm/generic/mount.cpp b/lib/mlibc/sysdeps/managarm/generic/mount.cpp new file mode 100644 index 0000000..5677b20 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/mount.cpp @@ -0,0 +1,44 @@ +#include <errno.h> +#include <string.h> +#include <sys/mount.h> + +#include <bits/ensure.h> +#include <mlibc/allocator.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <posix.frigg_bragi.hpp> +#include <bragi/helpers-frigg.hpp> + +namespace mlibc { + +int sys_mount(const char *source, const char *target, + const char *fstype, unsigned long, const void *) { + SignalGuard sguard; + + managarm::posix::MountRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), source)); + req.set_target_path(frg::string<MemoryAllocator>(getSysdepsAllocator(), target)); + req.set_fs_type(frg::string<MemoryAllocator>(getSysdepsAllocator(), fstype)); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + auto resp = *bragi::parse_head_only<managarm::posix::SvrResponse>(recv_resp, getSysdepsAllocator()); + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) + return ENOENT; + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/net.cpp b/lib/mlibc/sysdeps/managarm/generic/net.cpp new file mode 100644 index 0000000..63f2d0c --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/net.cpp @@ -0,0 +1,57 @@ +#include <mlibc/all-sysdeps.hpp> +#include <sys/ioctl.h> +#include <net/if.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +namespace mlibc { + +int sys_if_indextoname(unsigned int index, char *name) { + int fd = 0; + int r = sys_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, &fd); + + if(r) + return r; + + struct ifreq ifr; + ifr.ifr_ifindex = index; + + int res = 0; + int ret = sys_ioctl(fd, SIOCGIFNAME, &ifr, &res); + close(fd); + + if(ret) { + if(ret == ENODEV) + return ENXIO; + return ret; + } + + strncpy(name, ifr.ifr_name, IF_NAMESIZE); + + return 0; +} + +int sys_if_nametoindex(const char *name, unsigned int *ret) { + int fd = 0; + int r = sys_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, &fd); + + if(r) + return r; + + struct ifreq ifr; + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + + int res = 0; + r = sys_ioctl(fd, SIOCGIFINDEX, &ifr, &res); + close(fd); + + if(r) + return r; + + *ret = ifr.ifr_ifindex; + + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/sched.cpp b/lib/mlibc/sysdeps/managarm/generic/sched.cpp new file mode 100644 index 0000000..bce8db8 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/sched.cpp @@ -0,0 +1,102 @@ +#include <bits/ensure.h> +#include <unistd.h> + +#include <hel.h> +#include <hel-syscalls.h> +#include <mlibc/debug.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/posix-sysdeps.hpp> + +#include <posix.frigg_bragi.hpp> + +namespace mlibc { + +int sys_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { + return sys_getthreadaffinity(pid, cpusetsize, mask); +} + +int sys_getthreadaffinity(pid_t tid, size_t cpusetsize, cpu_set_t *mask) { + SignalGuard sguard; + + managarm::posix::GetAffinityRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_pid(tid); + req.set_size(cpusetsize); + + auto [offer, send_head, recv_resp, recv_data] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(mask, cpusetsize) + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else if(resp.error() != managarm::posix::Errors::SUCCESS) { + mlibc::infoLogger() << "mlibc: got unexpected error from posix in sys_getaffinity!" << frg::endlog; + return EIEIO; + } + HEL_CHECK(recv_data.error()); + + return 0; +} + +int sys_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask) { + return sys_setthreadaffinity(pid, cpusetsize, mask); +} + +int sys_setthreadaffinity(pid_t tid, size_t cpusetsize, const cpu_set_t *mask) { + SignalGuard sguard; + + frg::vector<uint8_t, MemoryAllocator> affinity_mask(getSysdepsAllocator()); + affinity_mask.resize(cpusetsize); + memcpy(affinity_mask.data(), mask, cpusetsize); + managarm::posix::SetAffinityRequest<MemoryAllocator> req(getSysdepsAllocator()); + + req.set_pid(tid); + req.set_mask(affinity_mask); + + auto [offer, send_head, send_tail, recv_resp] = + exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_head.error()); + HEL_CHECK(send_tail.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } else if(resp.error() != managarm::posix::Errors::SUCCESS) { + mlibc::infoLogger() << "mlibc: got unexpected error from posix in sys_getaffinity!" << frg::endlog; + return EIEIO; + } + + return 0; +} + +int sys_getcpu(int *cpu) { + HEL_CHECK(helGetCurrentCpu(cpu)); + return 0; +} + +} diff --git a/lib/mlibc/sysdeps/managarm/generic/signals.cpp b/lib/mlibc/sysdeps/managarm/generic/signals.cpp new file mode 100644 index 0000000..486f3d4 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/signals.cpp @@ -0,0 +1,139 @@ +#include <bits/ensure.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> + +#include <hel.h> +#include <hel-syscalls.h> + +#include <mlibc/debug.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <posix.frigg_bragi.hpp> + +#include <bragi/helpers-frigg.hpp> +#include <helix/ipc-structs.hpp> + +#include <protocols/posix/supercalls.hpp> + +extern "C" void __mlibc_signal_restore(); + +namespace mlibc { + +int sys_sigprocmask(int how, const sigset_t *set, sigset_t *retrieve) { + // This implementation is inherently signal-safe. + uint64_t former, unused; + if(set) { + HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, how, *set, &former, &unused)); + }else{ + HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, 0, 0, &former, &unused)); + } + if(retrieve) + *retrieve = former; + return 0; +} + +int sys_sigaction(int number, const struct sigaction *__restrict action, + struct sigaction *__restrict saved_action) { + SignalGuard sguard; + + // TODO: Respect restorer. __ensure(!(action->sa_flags & SA_RESTORER)); + + managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_request_type(managarm::posix::CntReqType::SIG_ACTION); + req.set_sig_number(number); + if(action) { + req.set_mode(1); + req.set_flags(action->sa_flags); + req.set_sig_mask(action->sa_mask); + if(action->sa_flags & SA_SIGINFO) { + req.set_sig_handler(reinterpret_cast<uintptr_t>(action->sa_sigaction)); + }else{ + req.set_sig_handler(reinterpret_cast<uintptr_t>(action->sa_handler)); + } + req.set_sig_restorer(reinterpret_cast<uintptr_t>(&__mlibc_signal_restore)); + } else { + req.set_mode(0); + } + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::posix::Errors::ILLEGAL_REQUEST) { + // This is only returned for servers, not for normal userspace. + return ENOSYS; + }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { + return EINVAL; + } + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + + if(saved_action) { + saved_action->sa_flags = resp.flags(); + saved_action->sa_mask = resp.sig_mask(); + if(resp.flags() & SA_SIGINFO) { + saved_action->sa_sigaction = + reinterpret_cast<void (*)(int, siginfo_t *, void *)>(resp.sig_handler()); + }else{ + saved_action->sa_handler = reinterpret_cast<void (*)(int)>(resp.sig_handler()); + } + // TODO: saved_action->sa_restorer = resp.sig_restorer; + } + return 0; +} + +int sys_kill(int pid, int number) { + // This implementation is inherently signal-safe. + HEL_CHECK(helSyscall2(kHelObserveSuperCall + posix::superSigKill, pid, number)); + return 0; +} + +int sys_tgkill(int, int tid, int number) { + return sys_kill(tid, number); +} + +int sys_sigaltstack(const stack_t *ss, stack_t *oss) { + HelWord out; + + // This implementation is inherently signal-safe. + HEL_CHECK(helSyscall2_1(kHelObserveSuperCall + posix::superSigAltStack, + reinterpret_cast<HelWord>(ss), + reinterpret_cast<HelWord>(oss), + &out)); + + return out; +} + +int sys_sigsuspend(const sigset_t *set) { + //SignalGuard sguard; + uint64_t former, seq, unused; + + HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, SIG_SETMASK, *set, &former, &seq)); + HEL_CHECK(helSyscall1(kHelObserveSuperCall + posix::superSigSuspend, seq)); + HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, SIG_SETMASK, former, &unused, &unused)); + + return EINTR; +} + +int sys_sigpending(sigset_t *set) { + uint64_t pendingMask; + + HEL_CHECK(helSyscall0_1(kHelObserveSuperCall + posix::superSigGetPending, &pendingMask)); + *set = pendingMask; + + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/socket.cpp b/lib/mlibc/sysdeps/managarm/generic/socket.cpp new file mode 100644 index 0000000..5bdc1fc --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/socket.cpp @@ -0,0 +1,423 @@ + +#include <bits/ensure.h> +#include <errno.h> +#include <sys/socket.h> +#include <linux/netlink.h> +#include <netinet/tcp.h> +#include <netinet/in.h> + +#include <mlibc/allocator.hpp> +#include <mlibc/debug.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <fs.frigg_bragi.hpp> +#include <posix.frigg_bragi.hpp> + +namespace { + +int fcntl_helper(int fd, int request, int *result, ...) { + va_list args; + va_start(args, result); + if(!mlibc::sys_fcntl) { + return ENOSYS; + } + int ret = mlibc::sys_fcntl(fd, request, args, result); + va_end(args); + return ret; +} + +} + +namespace mlibc { + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags) { + SignalGuard sguard; + + managarm::posix::AcceptRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_fd(fd); + + auto [offer, sendReq, recvResp] = exchangeMsgsSync( + getPosixLane(), + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + HEL_CHECK(recvResp.error()); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::posix::Errors::WOULD_BLOCK) { + return EWOULDBLOCK; + }else{ + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *newfd = resp.fd(); + } + + if(addr_ptr && addr_length) { + if(int e = mlibc::sys_peername(*newfd, addr_ptr, *addr_length, addr_length); e) { + errno = e; + return -1; + } + } + + if(flags & SOCK_NONBLOCK) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFL, &fcntl_ret); + fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK); + } + + if(flags & SOCK_CLOEXEC) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFD, &fcntl_ret); + fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC); + } + + return 0; +} + +int sys_bind(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + SignalGuard sguard; + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_BIND); + + auto [offer, send_req, send_creds, send_buf, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::sendBuffer(addr_ptr, addr_length), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(send_creds.error()); + HEL_CHECK(send_buf.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::FILE_NOT_FOUND) { + return ENOENT; + } else if(resp.error() == managarm::fs::Errors::ADDRESS_IN_USE) { + return EADDRINUSE; + } else if(resp.error() == managarm::fs::Errors::ALREADY_EXISTS) { + return EINVAL; + } else if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; + } else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + } else if(resp.error() == managarm::fs::Errors::ACCESS_DENIED) { + return EACCES; + } else if(resp.error() == managarm::fs::Errors::ADDRESS_NOT_AVAILABLE) { + return EADDRNOTAVAIL; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; +} + +int sys_connect(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_CONNECT); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_req, imbue_creds, send_addr, recv_resp] = + exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::imbueCredentials(), + helix_ng::sendBuffer(const_cast<struct sockaddr *>(addr_ptr), addr_length), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(send_addr.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::FILE_NOT_FOUND) { + return ENOENT; + } else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { + return EINVAL; + } + + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; +} + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_SOCKNAME); + req.set_fd(fd); + req.set_size(max_addr_length); + + auto [offer, send_req, recv_resp, recv_addr] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline(), + helix_ng::recvBuffer(addr_ptr, max_addr_length)) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return ENOTSOCK; + } + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + HEL_CHECK(recv_addr.error()); + *actual_length = resp.file_size(); + return 0; +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_PEERNAME); + req.set_fd(fd); + req.set_size(max_addr_length); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, sendReq, recvResp, recvData] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::recvInline(), + helix_ng::recvBuffer(addr_ptr, max_addr_length) + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(sendReq.error()); + if(recvResp.error() == kHelErrDismissed) + return ENOTSOCK; + HEL_CHECK(recvResp.error()); + HEL_CHECK(recvData.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recvResp.data(), recvResp.length()); + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return ENOTSOCK; + }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { + return ENOTCONN; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *actual_length = resp.file_size(); + return 0; + } +} + +int sys_getsockopt(int fd, int layer, int number, + void *__restrict buffer, socklen_t *__restrict size) { + SignalGuard sguard; + + if(layer == SOL_SOCKET && number == SO_PEERCRED) { + if(*size != sizeof(struct ucred)) + return EINVAL; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_GET_OPTION); + req.set_command(SO_PEERCRED); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + struct ucred creds; + creds.pid = resp.pid(); + creds.uid = resp.uid(); + creds.gid = resp.gid(); + memcpy(buffer, &creds, sizeof(struct ucred)); + return 0; + }else if(layer == SOL_SOCKET && number == SO_SNDBUF) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_SNDBUF is unimplemented\e[39m" << frg::endlog; + *(int *)buffer = 4096; + return 0; + }else if(layer == SOL_SOCKET && number == SO_TYPE) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_TYPE is unimplemented, hardcoding SOCK_STREAM\e[39m" << frg::endlog; + *(int *)buffer = SOCK_STREAM; + return 0; + }else if(layer == SOL_SOCKET && number == SO_ERROR) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_ERROR is unimplemented, hardcoding 0\e[39m" << frg::endlog; + *(int *)buffer = 0; + return 0; + }else if(layer == SOL_SOCKET && number == SO_KEEPALIVE) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_KEEPALIVE is unimplemented, hardcoding 0\e[39m" << frg::endlog; + *(int *)buffer = 0; + return 0; + }else if(layer == SOL_SOCKET && number == SO_LINGER) { + mlibc::infoLogger() << "\e[31mmlibc: getsockopt() call with SOL_SOCKET and SO_LINGER is unimplemented, hardcoding 0\e[39m" << frg::endlog; + *(int *)buffer = 0; + return 0; + }else{ + mlibc::panicLogger() << "\e[31mmlibc: Unexpected getsockopt() call, layer: " << layer << " number: " << number << "\e[39m" << frg::endlog; + __builtin_unreachable(); + } +} + +int sys_setsockopt(int fd, int layer, int number, + const void *buffer, socklen_t size) { + SignalGuard sguard; + + if(layer == SOL_SOCKET && number == SO_PASSCRED) { + int value; + __ensure(size == sizeof(int)); + memcpy(&value, buffer, sizeof(int)); + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_SET_OPTION); + req.set_command(SO_PASSCRED); + req.set_value(value); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; + }else if(layer == SOL_SOCKET && number == SO_ATTACH_FILTER) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_ATTACH_FILTER) is not implemented" + " correctly\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_RCVBUFFORCE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_RCVBUFFORCE) is not implemented" + " correctly\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_SNDBUF) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_SNDBUF is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_KEEPALIVE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_KEEPALIVE is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_REUSEADDR) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_REUSEADDR is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_REUSEPORT) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_REUSEPORT is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_RCVBUF) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_RCVBUF is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == IPPROTO_TCP && number == TCP_NODELAY) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with IPPROTO_TCP and TCP_NODELAY is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_SOCKET && number == SO_ACCEPTCONN) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET and SO_ACCEPTCONN is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == IPPROTO_TCP && number == TCP_KEEPIDLE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with IPPROTO_TCP and TCP_KEEPIDLE is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_NETLINK && number == NETLINK_EXT_ACK) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_NETLINK and NETLINK_EXT_ACK is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == SOL_NETLINK && number == NETLINK_GET_STRICT_CHK) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_NETLINK and NETLINK_EXT_ACK is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == IPPROTO_TCP && number == TCP_KEEPINTVL) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with IPPROTO_TCP and TCP_KEEPINTVL is unimplemented\e[39m" << frg::endlog; + return 0; + }else if(layer == IPPROTO_TCP && number == TCP_KEEPCNT) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with IPPROTO_TCP and TCP_KEEPCNT is unimplemented\e[39m" << frg::endlog; + return 0; + }else{ + mlibc::panicLogger() << "\e[31mmlibc: Unexpected setsockopt() call, layer: " << layer << " number: " << number << "\e[39m" << frg::endlog; + __builtin_unreachable(); + } +} + +int sys_listen(int fd, int) { + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::PT_LISTEN); + + frg::string<MemoryAllocator> ser(getSysdepsAllocator()); + req.SerializeToString(&ser); + + auto [offer, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBuffer(ser.data(), ser.size()), + helix_ng::recvInline() + ) + ); + + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/generic/time.cpp b/lib/mlibc/sysdeps/managarm/generic/time.cpp new file mode 100644 index 0000000..468a738 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/generic/time.cpp @@ -0,0 +1,81 @@ + +#include <bits/ensure.h> +#include <time.h> +#include <string.h> +#include <sys/time.h> + +#include <hel.h> +#include <hel-syscalls.h> +#include <mlibc/debug.hpp> +#include <mlibc/allocator.hpp> +#include <mlibc/posix-pipe.hpp> +#include <mlibc/all-sysdeps.hpp> + +struct TrackerPage { + uint64_t seqlock; + int32_t state; + int32_t padding; + int64_t refClock; + int64_t baseRealtime; +}; + +extern thread_local TrackerPage *__mlibc_clk_tracker_page; + +namespace mlibc { + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + // This implementation is inherently signal-safe. + if(clock == CLOCK_MONOTONIC || clock == CLOCK_MONOTONIC_RAW || clock == CLOCK_MONOTONIC_COARSE) { + uint64_t tick; + HEL_CHECK(helGetClock(&tick)); + *secs = tick / 1000000000; + *nanos = tick % 1000000000; + }else if(clock == CLOCK_REALTIME) { + cacheFileTable(); + + // Start the seqlock read. + auto seqlock = __atomic_load_n(&__mlibc_clk_tracker_page->seqlock, __ATOMIC_ACQUIRE); + __ensure(!(seqlock & 1)); + + // Perform the actual loads. + auto ref = __atomic_load_n(&__mlibc_clk_tracker_page->refClock, __ATOMIC_RELAXED); + auto base = __atomic_load_n(&__mlibc_clk_tracker_page->baseRealtime, __ATOMIC_RELAXED); + + // Finish the seqlock read. + __atomic_thread_fence(__ATOMIC_ACQUIRE); + __ensure(__atomic_load_n(&__mlibc_clk_tracker_page->seqlock, __ATOMIC_RELAXED) == seqlock); + + // Calculate the current time. + uint64_t tick; + HEL_CHECK(helGetClock(&tick)); + __ensure(tick >= (uint64_t)__mlibc_clk_tracker_page->refClock); // TODO: Respect the seqlock! + tick -= ref; + tick += base; + *secs = tick / 1000000000; + *nanos = tick % 1000000000; + }else if(clock == CLOCK_PROCESS_CPUTIME_ID) { + mlibc::infoLogger() << "\e[31mmlibc: clock_gettime does not support the CPU time clocks" + "\e[39m" << frg::endlog; + *secs = 0; + *nanos = 0; + }else if(clock == CLOCK_BOOTTIME) { + mlibc::infoLogger() << "\e[31mmlibc: clock_gettime does not support CLOCK_BOOTTIME" + "\e[39m" << frg::endlog; + *secs = 0; + *nanos = 0; + }else{ + mlibc::panicLogger() << "mlibc: Unexpected clock " << clock << frg::endlog; + } + return 0; +} + +int sys_clock_getres(int clock, time_t *secs, long *nanos) { + (void)clock; + (void)secs; + (void)nanos; + mlibc::infoLogger() << "mlibc: clock_getres is a stub" << frg::endlog; + return 0; +} + +} //namespace mlibc + diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/access.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/access.h new file mode 120000 index 0000000..cb83931 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/access.h @@ -0,0 +1 @@ +../../../../abis/linux/access.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/auxv.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/auxv.h new file mode 120000 index 0000000..e760d62 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/auxv.h @@ -0,0 +1 @@ +../../../../abis/managarm/auxv.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/blkcnt_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/blkcnt_t.h new file mode 120000 index 0000000..0b0ec27 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/blkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/blksize_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/blksize_t.h new file mode 120000 index 0000000..7dc8d7c --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/blksize_t.h @@ -0,0 +1 @@ +../../../../abis/linux/blksize_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/clockid_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/clockid_t.h new file mode 120000 index 0000000..6a42da5 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/clockid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/clockid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/dev_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/dev_t.h new file mode 120000 index 0000000..bca881e --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/dev_t.h @@ -0,0 +1 @@ +../../../../abis/linux/dev_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/epoll.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/epoll.h new file mode 120000 index 0000000..eb4b76d --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/epoll.h @@ -0,0 +1 @@ +../../../../abis/linux/epoll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/errno.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/errno.h new file mode 120000 index 0000000..6e507de --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/errno.h @@ -0,0 +1 @@ +../../../../abis/linux/errno.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/fcntl.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/fcntl.h new file mode 120000 index 0000000..463e2c9 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/fcntl.h @@ -0,0 +1 @@ +../../../../abis/linux/fcntl.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/fsblkcnt_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/fsblkcnt_t.h new file mode 120000 index 0000000..898dfb2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/fsblkcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsblkcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/fsfilcnt_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/fsfilcnt_t.h new file mode 120000 index 0000000..791755c --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/fsfilcnt_t.h @@ -0,0 +1 @@ +../../../../abis/linux/fsfilcnt_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/gid_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/gid_t.h new file mode 120000 index 0000000..abce6d6 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/gid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/gid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/in.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/in.h new file mode 120000 index 0000000..418d1d5 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/in.h @@ -0,0 +1 @@ +../../../../abis/linux/in.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/ino_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/ino_t.h new file mode 120000 index 0000000..4c20aca --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/ino_t.h @@ -0,0 +1 @@ +../../../../abis/linux/ino_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/inotify.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/inotify.h new file mode 120000 index 0000000..b5cb282 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/inotify.h @@ -0,0 +1 @@ +../../../../abis/linux/inotify.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/ioctls.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/ioctls.h new file mode 120000 index 0000000..595106b --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/ioctls.h @@ -0,0 +1 @@ +../../../../abis/linux/ioctls.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/limits.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/limits.h new file mode 120000 index 0000000..6c88db2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/limits.h @@ -0,0 +1 @@ +../../../../abis/linux/limits.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/mode_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/mode_t.h new file mode 120000 index 0000000..5d78fdf --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/mode_t.h @@ -0,0 +1 @@ +../../../../abis/linux/mode_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/mqueue.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/mqueue.h new file mode 120000 index 0000000..fa87b07 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/mqueue.h @@ -0,0 +1 @@ +../../../../abis/linux/mqueue.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/msg.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/msg.h new file mode 120000 index 0000000..f402b49 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/msg.h @@ -0,0 +1 @@ +../../../../abis/linux/msg.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/nlink_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/nlink_t.h new file mode 120000 index 0000000..bb3b625 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/nlink_t.h @@ -0,0 +1 @@ +../../../../abis/linux/nlink_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/packet.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/packet.h new file mode 120000 index 0000000..998ef1a --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/packet.h @@ -0,0 +1 @@ +../../../../abis/linux/packet.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/pid_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/pid_t.h new file mode 120000 index 0000000..baa90f6 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/pid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/pid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/poll.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/poll.h new file mode 120000 index 0000000..8ea6a0a --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/poll.h @@ -0,0 +1 @@ +../../../../abis/linux/poll.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/ptrace.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/ptrace.h new file mode 120000 index 0000000..b2517b2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/ptrace.h @@ -0,0 +1 @@ +../../../../abis/linux/ptrace.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/reboot.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/reboot.h new file mode 120000 index 0000000..77013a4 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/reboot.h @@ -0,0 +1 @@ +../../../../abis/linux/reboot.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/resource.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/resource.h new file mode 120000 index 0000000..88d7402 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/resource.h @@ -0,0 +1 @@ +../../../../abis/linux/resource.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/seek-whence.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/seek-whence.h new file mode 120000 index 0000000..df7bccf --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/seek-whence.h @@ -0,0 +1 @@ +../../../../abis/linux/seek-whence.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/shm.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/shm.h new file mode 120000 index 0000000..067d8c4 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/shm.h @@ -0,0 +1 @@ +../../../../abis/linux/shm.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/signal.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/signal.h new file mode 120000 index 0000000..4dcb0b7 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/signal.h @@ -0,0 +1 @@ +../../../../abis/linux/signal.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/socket.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/socket.h new file mode 120000 index 0000000..f1dc016 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/socket.h @@ -0,0 +1 @@ +../../../../abis/linux/socket.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/socklen_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/socklen_t.h new file mode 120000 index 0000000..41f3b11 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/socklen_t.h @@ -0,0 +1 @@ +../../../../abis/linux/socklen_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/stat.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/stat.h new file mode 120000 index 0000000..1f63b41 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/stat.h @@ -0,0 +1 @@ +../../../../abis/linux/stat.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/statfs.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/statfs.h new file mode 120000 index 0000000..e3d202f --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/statfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/statvfs.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/statvfs.h new file mode 120000 index 0000000..1fc80c2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/statvfs.h @@ -0,0 +1 @@ +../../../../abis/linux/statvfs.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/suseconds_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/suseconds_t.h new file mode 120000 index 0000000..9ed6597 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/suseconds_t.h @@ -0,0 +1 @@ +../../../../abis/linux/suseconds_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/termios.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/termios.h new file mode 120000 index 0000000..ee8f0b0 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/termios.h @@ -0,0 +1 @@ +../../../../abis/linux/termios.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/time.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/time.h new file mode 120000 index 0000000..2a02625 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/time.h @@ -0,0 +1 @@ +../../../../abis/linux/time.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/uid_t.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/uid_t.h new file mode 120000 index 0000000..b306777 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/uid_t.h @@ -0,0 +1 @@ +../../../../abis/linux/uid_t.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/utsname.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/utsname.h new file mode 120000 index 0000000..b285754 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/utsname.h @@ -0,0 +1 @@ +../../../../abis/linux/utsname.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/vm-flags.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/vm-flags.h new file mode 120000 index 0000000..bbe258c --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/vm-flags.h @@ -0,0 +1 @@ +../../../../abis/linux/vm-flags.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/vt.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/vt.h new file mode 120000 index 0000000..5798a4a --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/vt.h @@ -0,0 +1 @@ +../../../../abis/linux/vt.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/wait.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/wait.h new file mode 120000 index 0000000..feb2840 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/wait.h @@ -0,0 +1 @@ +../../../../abis/linux/wait.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/abi-bits/xattr.h b/lib/mlibc/sysdeps/managarm/include/abi-bits/xattr.h new file mode 120000 index 0000000..66412d7 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/abi-bits/xattr.h @@ -0,0 +1 @@ +../../../../abis/linux/xattr.h
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/managarm/include/mlibc/posix-pipe.hpp b/lib/mlibc/sysdeps/managarm/include/mlibc/posix-pipe.hpp new file mode 100644 index 0000000..4bcf1cb --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/mlibc/posix-pipe.hpp @@ -0,0 +1,300 @@ +#ifndef MLIBC_POSIX_PIPE +#define MLIBC_POSIX_PIPE + +#include <signal.h> +#include <stdint.h> +#include <string.h> +#include <cstddef> + +#include <hel.h> +#include <hel-syscalls.h> + +struct SignalGuard { + SignalGuard(); + + SignalGuard(const SignalGuard &) = delete; + + ~SignalGuard(); + + SignalGuard &operator= (const SignalGuard &) = delete; +}; + +// We need an allocator for message structs in sysdeps functions; the "normal" mlibc +// allocator cannot be used, as the sysdeps function might be called from a signal. +MemoryAllocator &getSysdepsAllocator(); + +struct Queue; + +struct ElementHandle { + friend void swap(ElementHandle &u, ElementHandle &v) { + using std::swap; + swap(u._queue, v._queue); + swap(u._n, v._n); + swap(u._data, v._data); + } + + ElementHandle() + : _queue{nullptr}, _n{-1}, _data{nullptr} { } + + ElementHandle(Queue *queue, int n, void *data) + : _queue{queue}, _n{n}, _data{data} { } + + ElementHandle(const ElementHandle &other); + + ElementHandle(ElementHandle &&other) + : ElementHandle{} { + swap(*this, other); + } + + ~ElementHandle(); + + ElementHandle &operator= (ElementHandle other) { + swap(*this, other); + return *this; + } + + void *data() { + return _data; + } + + void advance(size_t size) { + _data = reinterpret_cast<char *>(_data) + size; + } + +private: + Queue *_queue; + int _n; + void *_data; +}; + +struct Queue { + Queue() + : _handle{kHelNullHandle} { + // We do not need to protect those allocations against signals as this constructor + // is only called during library initialization. + _chunks[0] = reinterpret_cast<HelChunk *>(getSysdepsAllocator().allocate(sizeof(HelChunk) + 4096)); + _chunks[1] = reinterpret_cast<HelChunk *>(getSysdepsAllocator().allocate(sizeof(HelChunk) + 4096)); + + recreateQueue(); + } + + Queue(const Queue &) = delete; + + Queue &operator= (const Queue &) = delete; + + void recreateQueue() { + // Reset the internal queue state. + _retrieveIndex = 0; + _nextIndex = 0; + _lastProgress = 0; + + // Setup the queue header. + HelQueueParameters params { + .flags = 0, + .ringShift = 1, + .numChunks = 2, + .chunkSize = 4096 + }; + HEL_CHECK(helCreateQueue(¶ms, &_handle)); + + auto chunksOffset = (sizeof(HelQueue) + (sizeof(int) << 1) + 63) & ~size_t(63); + auto reservedPerChunk = (sizeof(HelChunk) + params.chunkSize + 63) & ~size_t(63); + auto overallSize = chunksOffset + params.numChunks * reservedPerChunk; + + void *mapping; + HEL_CHECK(helMapMemory(_handle, kHelNullHandle, nullptr, + 0, (overallSize + 0xFFF) & ~size_t(0xFFF), + kHelMapProtRead | kHelMapProtWrite, &mapping)); + + _queue = reinterpret_cast<HelQueue *>(mapping); + auto chunksPtr = reinterpret_cast<std::byte *>(mapping) + chunksOffset; + for(unsigned int i = 0; i < 2; ++i) + _chunks[i] = reinterpret_cast<HelChunk *>(chunksPtr + i * reservedPerChunk); + + // Reset and enqueue the chunks. + _chunks[0]->progressFutex = 0; + _chunks[1]->progressFutex = 0; + _refCount[0] = 1; + _refCount[1] = 1; + + _queue->indexQueue[0] = 0; + _queue->indexQueue[1] = 1; + _queue->headFutex = 0; + _nextIndex = 2; + _wakeHeadFutex(); + } + + HelHandle getQueue() { + return _handle; + } + + void trim() { } + + ElementHandle dequeueSingle() { + while(true) { + __ensure(_retrieveIndex != _nextIndex); + + bool done; + _waitProgressFutex(&done); + + auto n = _numberOf(_retrieveIndex); + __ensure(_refCount[n]); + + if(done) { + retire(n); + + _lastProgress = 0; + _retrieveIndex = ((_retrieveIndex + 1) & kHelHeadMask); + continue; + } + + // Dequeue the next element. + auto ptr = (char *)_chunks[n] + sizeof(HelChunk) + _lastProgress; + auto element = reinterpret_cast<HelElement *>(ptr); + _lastProgress += sizeof(HelElement) + element->length; + _refCount[n]++; + return ElementHandle{this, n, ptr + sizeof(HelElement)}; + } + } + + void retire(int n) { + __ensure(_refCount[n]); + if(_refCount[n]-- > 1) + return; + + // Reset and enqueue the chunk again. + _chunks[n]->progressFutex = 0; + _refCount[n] = 1; + + _queue->indexQueue[_nextIndex & 1] = n; + _nextIndex = ((_nextIndex + 1) & kHelHeadMask); + _wakeHeadFutex(); + } + + void reference(int n) { + _refCount[n]++; + } + +private: + int _numberOf(int index) { + return _queue->indexQueue[index & 1]; + } + + HelChunk *_retrieveChunk() { + return _chunks[_numberOf(_retrieveIndex)]; + } + + void _wakeHeadFutex() { + auto futex = __atomic_exchange_n(&_queue->headFutex, _nextIndex, __ATOMIC_RELEASE); + if(futex & kHelHeadWaiters) + HEL_CHECK(helFutexWake(&_queue->headFutex)); + } + + void _waitProgressFutex(bool *done) { + while(true) { + auto futex = __atomic_load_n(&_retrieveChunk()->progressFutex, __ATOMIC_ACQUIRE); + __ensure(!(futex & ~(kHelProgressMask | kHelProgressWaiters | kHelProgressDone))); + do { + if(_lastProgress != (futex & kHelProgressMask)) { + *done = false; + return; + }else if(futex & kHelProgressDone) { + *done = true; + return; + } + + if(futex & kHelProgressWaiters) + break; // Waiters bit is already set (in a previous iteration). + } while(!__atomic_compare_exchange_n(&_retrieveChunk()->progressFutex, &futex, + _lastProgress | kHelProgressWaiters, + false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)); + + HEL_CHECK(helFutexWait(&_retrieveChunk()->progressFutex, + _lastProgress | kHelProgressWaiters, -1)); + } + } + +private: + HelHandle _handle; + HelQueue *_queue; + HelChunk *_chunks[2]; + + // Index of the chunk that we are currently retrieving/inserting next. + int _retrieveIndex; + int _nextIndex; + + // Progress into the current chunk. + int _lastProgress; + + // Number of ElementHandle objects alive. + int _refCount[2]; +}; + +inline ElementHandle::~ElementHandle() { + if(_queue) + _queue->retire(_n); +} + +inline ElementHandle::ElementHandle(const ElementHandle &other) { + _queue = other._queue; + _n = other._n; + _data = other._data; + + _queue->reference(_n); +} + + +inline HelSimpleResult *parseSimple(ElementHandle &element) { + auto result = reinterpret_cast<HelSimpleResult *>(element.data()); + element.advance(sizeof(HelSimpleResult)); + return result; +} + +inline HelInlineResult *parseInline(ElementHandle &element) { + auto result = reinterpret_cast<HelInlineResult *>(element.data()); + element.advance(sizeof(HelInlineResult) + ((result->length + 7) & ~size_t(7))); + return result; +} + +inline HelLengthResult *parseLength(ElementHandle &element) { + auto result = reinterpret_cast<HelLengthResult *>(element.data()); + element.advance(sizeof(HelLengthResult)); + return result; +} + +inline HelHandleResult *parseHandle(ElementHandle &element) { + auto result = reinterpret_cast<HelHandleResult *>(element.data()); + element.advance(sizeof(HelHandleResult)); + return result; +} + +HelHandle getPosixLane(); +HelHandle *cacheFileTable(); +HelHandle getHandleForFd(int fd); +void clearCachedInfos(); + +extern thread_local Queue globalQueue; + +// This include is here because it needs ElementHandle to be declared +#include <helix/ipc-structs.hpp> + +template <typename ...Args> +auto exchangeMsgsSync(HelHandle descriptor, Args &&...args) { + auto results = helix_ng::createResultsTuple(args...); + auto actions = helix_ng::chainActionArrays(args...); + + HEL_CHECK(helSubmitAsync(descriptor, actions.data(), + actions.size(), globalQueue.getQueue(), 0, 0)); + + auto element = globalQueue.dequeueSingle(); + void *ptr = element.data(); + + [&]<size_t ...p>(std::index_sequence<p...>) { + (results.template get<p>().parse(ptr, element), ...); + } (std::make_index_sequence<std::tuple_size_v<decltype(results)>>{}); + + return results; +} + + +#endif // MLIBC_POSIX_PIPE diff --git a/lib/mlibc/sysdeps/managarm/include/mlibc/thread-entry.hpp b/lib/mlibc/sysdeps/managarm/include/mlibc/thread-entry.hpp new file mode 100644 index 0000000..2dd88a6 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/include/mlibc/thread-entry.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include <mlibc/tcb.hpp> + +extern "C" void __mlibc_start_thread(void); +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb); + +namespace mlibc { + void *prepare_stack(void *entry, void *user_arg, void *tcb); +} diff --git a/lib/mlibc/sysdeps/managarm/meson.build b/lib/mlibc/sysdeps/managarm/meson.build new file mode 100644 index 0000000..3b85e30 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/meson.build @@ -0,0 +1,145 @@ + +bragi = find_program('bragi') + +bragi_gen = generator(bragi, arguments: [ + '-l', 'frigg', + '--protobuf', + '@INPUT@', + '@OUTPUT@' + ], + output: '@BASENAME@.frigg_bragi.hpp') + +fs_bragi = bragi_gen.process('../../subprojects/managarm/protocols/fs/fs.bragi') +posix_bragi = bragi_gen.process('../../subprojects/managarm/protocols/posix/posix.bragi') + +managarm_incl = include_directories( + '../../subprojects/managarm/protocols/posix/include', + '../../subprojects/managarm/hel/include', + '../../subprojects/bragi/include') + +rtdl_include_dirs += managarm_incl +rtdl_sources += files( + 'generic/ensure.cpp', + 'generic/memory.cpp', + 'rtdl-generic/support.cpp', +) +rtdl_sources += [ + fs_bragi, + posix_bragi, +] + +libc_include_dirs += include_directories('../../../ports/libdrm/include') +libc_include_dirs += managarm_incl + +libc_sources += files( + 'generic/drm.cpp', + 'generic/ensure.cpp', + 'generic/entry.cpp', + 'generic/file.cpp', + 'generic/fork-exec.cpp', + 'generic/ioctl.cpp', + 'generic/memory.cpp', + 'generic/mount.cpp', + 'generic/net.cpp', + 'generic/sched.cpp', + 'generic/signals.cpp', + 'generic/socket.cpp', + 'generic/time.cpp' +) +libc_sources += [ + fs_bragi, + posix_bragi, +] + +if host_machine.cpu_family() == 'aarch64' + libc_sources += files( + 'aarch64/signals.S', + 'aarch64/thread_entry.S', + 'aarch64/thread.cpp' + ) +elif host_machine.cpu_family() == 'x86_64' + libc_sources += files( + 'x86_64/signals.S', + 'x86_64/thread_entry.S', + 'x86_64/thread.cpp' + ) +else + error('Unknown architecture') +endif + +if not no_headers + install_headers( + 'include/abi-bits/access.h', + 'include/abi-bits/auxv.h', + 'include/abi-bits/seek-whence.h', + 'include/abi-bits/vm-flags.h', + 'include/abi-bits/errno.h', + 'include/abi-bits/fcntl.h', + 'include/abi-bits/in.h', + 'include/abi-bits/stat.h', + 'include/abi-bits/signal.h', + 'include/abi-bits/reboot.h', + 'include/abi-bits/resource.h', + 'include/abi-bits/socket.h', + 'include/abi-bits/termios.h', + 'include/abi-bits/time.h', + 'include/abi-bits/blkcnt_t.h', + 'include/abi-bits/blksize_t.h', + 'include/abi-bits/dev_t.h', + 'include/abi-bits/gid_t.h', + 'include/abi-bits/ino_t.h', + 'include/abi-bits/mode_t.h', + 'include/abi-bits/nlink_t.h', + 'include/abi-bits/pid_t.h', + 'include/abi-bits/uid_t.h', + 'include/abi-bits/wait.h', + 'include/abi-bits/limits.h', + 'include/abi-bits/utsname.h', + 'include/abi-bits/ptrace.h', + 'include/abi-bits/poll.h', + 'include/abi-bits/epoll.h', + 'include/abi-bits/packet.h', + 'include/abi-bits/inotify.h', + 'include/abi-bits/clockid_t.h', + 'include/abi-bits/shm.h', + 'include/abi-bits/mqueue.h', + 'include/abi-bits/suseconds_t.h', + 'include/abi-bits/fsfilcnt_t.h', + 'include/abi-bits/fsblkcnt_t.h', + 'include/abi-bits/socklen_t.h', + 'include/abi-bits/statfs.h', + 'include/abi-bits/statvfs.h', + 'include/abi-bits/ioctls.h', + 'include/abi-bits/xattr.h', + 'include/abi-bits/msg.h', + 'include/abi-bits/vt.h', + subdir: 'abi-bits', + follow_symlinks: true + ) +endif + +if not headers_only + crtstuff = ['crt0'] + if host_machine.cpu_family() in ['x86_64', 'aarch64'] + crtstuff += [ + 'Scrt1', + 'crti', + 'crtn' + ] + endif + foreach crtthing : crtstuff + crtf = crtthing + '.S' + crt_src = files(host_machine.cpu_family() / 'crt-src' / crtf) + crt = custom_target( + crtthing, + build_by_default: true, + command: c_compiler.cmd_array() + ['-c', '-o', '@OUTPUT@', '@INPUT@'], + input: crt_src, + output: crtthing + '.o', + install: true, + install_dir: get_option('libdir') + ) + endforeach + +endif + diff --git a/lib/mlibc/sysdeps/managarm/rtdl-generic/support.cpp b/lib/mlibc/sysdeps/managarm/rtdl-generic/support.cpp new file mode 100644 index 0000000..ee8ecbb --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/rtdl-generic/support.cpp @@ -0,0 +1,444 @@ +#include <fcntl.h> +#include <stdint.h> +#include <string.h> +#include <cstddef> + +#include <frg/manual_box.hpp> +#include <frg/string.hpp> +#include <hel.h> +#include <hel-syscalls.h> + +#include <mlibc/allocator.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <posix.frigg_bragi.hpp> +#include <fs.frigg_bragi.hpp> + +#include <protocols/posix/data.hpp> +#include <protocols/posix/supercalls.hpp> + +// -------------------------------------------------------- +// POSIX I/O functions. +// -------------------------------------------------------- + +HelHandle posixLane; +HelHandle *fileTable; + +void cacheFileTable() { + if(fileTable) + return; + + posix::ManagarmProcessData data; + HEL_CHECK(helSyscall1(kHelCallSuper + posix::superGetProcessData, reinterpret_cast<HelWord>(&data))); + posixLane = data.posixLane; + fileTable = data.fileTable; +} + +template<typename T> +T load(void *ptr) { + T result; + memcpy(&result, ptr, sizeof(T)); + return result; +} + +// This Queue implementation is more simplistic than the ones in mlibc and helix. +// In fact, we only manage a single chunk; this minimizes the memory usage of the queue. +struct Queue { + Queue() + : _handle{kHelNullHandle}, _lastProgress(0) { + HelQueueParameters params { + .flags = 0, + .ringShift = 0, + .numChunks = 1, + .chunkSize = 4096 + }; + HEL_CHECK(helCreateQueue(¶ms, &_handle)); + + auto chunksOffset = (sizeof(HelQueue) + (sizeof(int) << 0) + 63) & ~size_t(63); + auto reservedPerChunk = (sizeof(HelChunk) + params.chunkSize + 63) & ~size_t(63); + auto overallSize = chunksOffset + params.numChunks * reservedPerChunk; + + void *mapping; + HEL_CHECK(helMapMemory(_handle, kHelNullHandle, nullptr, + 0, (overallSize + 0xFFF) & ~size_t(0xFFF), + kHelMapProtRead | kHelMapProtWrite, &mapping)); + + _queue = reinterpret_cast<HelQueue *>(mapping); + _chunk = reinterpret_cast<HelChunk *>( + reinterpret_cast<std::byte *>(mapping) + chunksOffset); + + // Reset and enqueue the first chunk. + _chunk->progressFutex = 0; + + _queue->indexQueue[0] = 0; + _queue->headFutex = 1; + _nextIndex = 1; + _wakeHeadFutex(); + } + + Queue(const Queue &) = delete; + + Queue &operator= (const Queue &) = delete; + + HelHandle getHandle() { + return _handle; + } + + void *dequeueSingle() { + while(true) { + bool done; + _waitProgressFutex(&done); + if(done) { + // Reset and enqueue the chunk again. + _chunk->progressFutex = 0; + + _queue->indexQueue[0] = 0; + _nextIndex = ((_nextIndex + 1) & kHelHeadMask); + _wakeHeadFutex(); + + _lastProgress = 0; + continue; + } + + // Dequeue the next element. + auto ptr = (char *)_chunk + sizeof(HelChunk) + _lastProgress; + auto element = load<HelElement>(ptr); + _lastProgress += sizeof(HelElement) + element.length; + return ptr + sizeof(HelElement); + } + } + +private: + void _wakeHeadFutex() { + auto futex = __atomic_exchange_n(&_queue->headFutex, _nextIndex, __ATOMIC_RELEASE); + if(futex & kHelHeadWaiters) + HEL_CHECK(helFutexWake(&_queue->headFutex)); + } + + void _waitProgressFutex(bool *done) { + while(true) { + auto futex = __atomic_load_n(&_chunk->progressFutex, __ATOMIC_ACQUIRE); + __ensure(!(futex & ~(kHelProgressMask | kHelProgressWaiters | kHelProgressDone))); + do { + if(_lastProgress != (futex & kHelProgressMask)) { + *done = false; + return; + }else if(futex & kHelProgressDone) { + *done = true; + return; + } + + if(futex & kHelProgressWaiters) + break; // Waiters bit is already set (in a previous iteration). + } while(!__atomic_compare_exchange_n(&_chunk->progressFutex, &futex, + _lastProgress | kHelProgressWaiters, + false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)); + + HEL_CHECK(helFutexWait(&_chunk->progressFutex, + _lastProgress | kHelProgressWaiters, -1)); + } + } + +private: + HelHandle _handle; + HelQueue *_queue; + HelChunk *_chunk; + int _nextIndex; + int _lastProgress; +}; + +frg::manual_box<Queue> globalQueue; + +HelSimpleResult *parseSimple(void *&element) { + auto result = reinterpret_cast<HelSimpleResult *>(element); + element = (char *)element + sizeof(HelSimpleResult); + return result; +} + +HelInlineResult *parseInline(void *&element) { + auto result = reinterpret_cast<HelInlineResult *>(element); + element = (char *)element + sizeof(HelInlineResult) + + ((result->length + 7) & ~size_t(7)); + return result; +} + +HelLengthResult *parseLength(void *&element) { + auto result = reinterpret_cast<HelLengthResult *>(element); + element = (char *)element + sizeof(HelLengthResult); + return result; +} + +HelHandleResult *parseHandle(void *&element) { + auto result = reinterpret_cast<HelHandleResult *>(element); + element = (char *)element + sizeof(HelHandleResult); + return result; +} + +namespace mlibc { + +int sys_tcb_set(void *pointer) { +#if defined(__aarch64__) + asm volatile ("msr tpidr_el0, %0" :: "r"(pointer)); +#else + HEL_CHECK(helWriteFsBase(pointer)); +#endif + return 0; +} + +int sys_open(const char *path, int flags, mode_t mode, int *fd) { + cacheFileTable(); + HelAction actions[4]; + + managarm::posix::OpenAtRequest<MemoryAllocator> req(getAllocator()); + req.set_fd(AT_FDCWD); + req.set_flags(flags); + req.set_mode(mode); + req.set_path(frg::string<MemoryAllocator>(getAllocator(), path)); + + if(!globalQueue.valid()) + globalQueue.initialize(); + + frg::string<MemoryAllocator> head(getAllocator()); + frg::string<MemoryAllocator> tail(getAllocator()); + head.resize(req.size_of_head()); + tail.resize(req.size_of_tail()); + bragi::limited_writer headWriter{head.data(), head.size()}; + bragi::limited_writer tailWriter{tail.data(), tail.size()}; + auto headOk = req.encode_head(headWriter); + auto tailOk = req.encode_tail(tailWriter); + __ensure(headOk); + __ensure(tailOk); + + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = head.data(); + actions[1].length = head.size(); + actions[2].type = kHelActionSendFromBuffer; + actions[2].flags = kHelItemChain; + actions[2].buffer = tail.data(); + actions[2].length = tail.size(); + actions[3].type = kHelActionRecvInline; + actions[3].flags = 0; + HEL_CHECK(helSubmitAsync(posixLane, actions, 4, globalQueue->getHandle(), 0, 0)); + + auto element = globalQueue->dequeueSingle(); + auto offer = parseHandle(element); + auto send_head = parseSimple(element); + auto send_tail = parseSimple(element); + auto recv_resp = parseInline(element); + HEL_CHECK(offer->error); + HEL_CHECK(send_head->error); + HEL_CHECK(send_tail->error); + HEL_CHECK(recv_resp->error); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + + if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) + return -1; + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *fd = resp.fd(); + return 0; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + __ensure(whence == SEEK_SET); + + cacheFileTable(); + auto lane = fileTable[fd]; + HelAction actions[3]; + + managarm::fs::CntRequest<MemoryAllocator> req(getAllocator()); + req.set_req_type(managarm::fs::CntReqType::SEEK_ABS); + req.set_rel_offset(offset); + + if(!globalQueue.valid()) + globalQueue.initialize(); + + frg::string<MemoryAllocator> ser(getAllocator()); + req.SerializeToString(&ser); + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = ser.data(); + actions[1].length = ser.size(); + actions[2].type = kHelActionRecvInline; + actions[2].flags = 0; + HEL_CHECK(helSubmitAsync(lane, actions, 3, globalQueue->getHandle(), 0, 0)); + + auto element = globalQueue->dequeueSingle(); + auto offer = parseHandle(element); + auto send_req = parseSimple(element); + auto recv_resp = parseInline(element); + HEL_CHECK(offer->error); + HEL_CHECK(send_req->error); + HEL_CHECK(recv_resp->error); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *new_offset = offset; + return 0; +} + +int sys_read(int fd, void *data, size_t length, ssize_t *bytes_read) { + cacheFileTable(); + auto lane = fileTable[fd]; + HelAction actions[5]; + + managarm::fs::CntRequest<MemoryAllocator> req(getAllocator()); + req.set_req_type(managarm::fs::CntReqType::READ); + req.set_size(length); + + if(!globalQueue.valid()) + globalQueue.initialize(); + + frg::string<MemoryAllocator> ser(getAllocator()); + req.SerializeToString(&ser); + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = ser.data(); + actions[1].length = ser.size(); + actions[2].type = kHelActionImbueCredentials; + actions[2].handle = kHelThisThread; + actions[2].flags = kHelItemChain; + actions[3].type = kHelActionRecvInline; + actions[3].flags = kHelItemChain; + actions[4].type = kHelActionRecvToBuffer; + actions[4].flags = 0; + actions[4].buffer = data; + actions[4].length = length; + HEL_CHECK(helSubmitAsync(lane, actions, 5, globalQueue->getHandle(), 0, 0)); + + auto element = globalQueue->dequeueSingle(); + auto offer = parseHandle(element); + auto send_req = parseSimple(element); + auto imbue_creds = parseSimple(element); + auto recv_resp = parseInline(element); + auto recv_data = parseLength(element); + HEL_CHECK(offer->error); + HEL_CHECK(send_req->error); + HEL_CHECK(imbue_creds->error); + HEL_CHECK(recv_resp->error); + HEL_CHECK(recv_data->error); + + managarm::fs::SvrResponse<MemoryAllocator> resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + *bytes_read = recv_data->length; + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { + cacheFileTable(); + HelAction actions[3]; + + managarm::posix::VmMapRequest<MemoryAllocator> req(getAllocator()); + req.set_address_hint(reinterpret_cast<uintptr_t>(hint)); + req.set_size(size); + req.set_mode(prot); + req.set_flags(flags); + req.set_fd(fd); + req.set_rel_offset(offset); + + if(!globalQueue.valid()) + globalQueue.initialize(); + + frg::string<MemoryAllocator> ser(getAllocator()); + req.SerializeToString(&ser); + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = ser.data(); + actions[1].length = ser.size(); + actions[2].type = kHelActionRecvInline; + actions[2].flags = 0; + HEL_CHECK(helSubmitAsync(posixLane, actions, 3, + globalQueue->getHandle(), 0, 0)); + + auto element = globalQueue->dequeueSingle(); + auto offer = parseHandle(element); + auto send_req = parseSimple(element); + auto recv_resp = parseInline(element); + + HEL_CHECK(offer->error); + HEL_CHECK(send_req->error); + HEL_CHECK(recv_resp->error); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + *window = reinterpret_cast<void *>(resp.offset()); + return 0; +} + +int sys_close(int fd) { + cacheFileTable(); + HelAction actions[3]; + + managarm::posix::CloseRequest<MemoryAllocator> req(getAllocator()); + req.set_fd(fd); + + if(!globalQueue.valid()) + globalQueue.initialize(); + + frg::string<MemoryAllocator> ser(getAllocator()); + req.SerializeToString(&ser); + actions[0].type = kHelActionOffer; + actions[0].flags = kHelItemAncillary; + actions[1].type = kHelActionSendFromBuffer; + actions[1].flags = kHelItemChain; + actions[1].buffer = ser.data(); + actions[1].length = ser.size(); + actions[2].type = kHelActionRecvInline; + actions[2].flags = 0; + HEL_CHECK(helSubmitAsync(posixLane, actions, 3, globalQueue->getHandle(), 0, 0)); + + auto element = globalQueue->dequeueSingle(); + auto offer = parseHandle(element); + auto send_req = parseSimple(element); + auto recv_resp = parseInline(element); + HEL_CHECK(offer->error); + HEL_CHECK(send_req->error); + HEL_CHECK(recv_resp->error); + + managarm::posix::SvrResponse<MemoryAllocator> resp(getAllocator()); + resp.ParseFromArray(recv_resp->data, recv_resp->length); + __ensure(resp.error() == managarm::posix::Errors::SUCCESS); + return 0; +} + +int sys_futex_tid() { + HelWord tid = 0; + HEL_CHECK(helSyscall0_1(kHelCallSuper + posix::superGetTid, + &tid)); + + return tid; +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { + // This implementation is inherently signal-safe. + if(time) { + if(helFutexWait(pointer, expected, time->tv_nsec + time->tv_sec * 1000000000)) + return -1; + return 0; + } + if(helFutexWait(pointer, expected, -1)) + return -1; + return 0; +} + +int sys_futex_wake(int *pointer) { + // This implementation is inherently signal-safe. + if(helFutexWake(pointer)) + return -1; + return 0; +} + + +} // namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/x86_64/crt-src/Scrt1.S b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/Scrt1.S new file mode 100644 index 0000000..d0e8213 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/Scrt1.S @@ -0,0 +1,8 @@ +.section .text +.global _start +_start: + mov %rsp, %rdi + lea main(%rip), %rsi + call __mlibc_entry +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crt0.S b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crt0.S new file mode 100644 index 0000000..6afb421 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crt0.S @@ -0,0 +1,10 @@ + +.section .text +.global _start +_start: + mov %rsp, %rdi + mov $main, %rsi + call __mlibc_entry + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crti.S b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crti.S new file mode 100644 index 0000000..1ca20f2 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crti.S @@ -0,0 +1,15 @@ + .ident "x86_64-managarm-mlibc crti" + + .section .init + .globl _init + .type _init,@function +_init: + push %rax + + .section .fini + .globl _fini + .type _fini,@function +_fini: + push %rax + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crtn.S b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crtn.S new file mode 100644 index 0000000..fdb309e --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/crt-src/crtn.S @@ -0,0 +1,11 @@ +.ident "x86_64-managarm-mlibc crtn" + +.section .init + pop %rax + ret + +.section .fini + pop %rax + ret + +.section .note.GNU-stack,"",%progbits diff --git a/lib/mlibc/sysdeps/managarm/x86_64/signals.S b/lib/mlibc/sysdeps/managarm/x86_64/signals.S new file mode 100644 index 0000000..33ac4a3 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/signals.S @@ -0,0 +1,10 @@ + +.section .text +.global __mlibc_signal_restore +__mlibc_signal_restore: + mov $0x80000006, %rdi + syscall + ud2 + +.section .note.GNU-stack,"",%progbits + diff --git a/lib/mlibc/sysdeps/managarm/x86_64/thread.cpp b/lib/mlibc/sysdeps/managarm/x86_64/thread.cpp new file mode 100644 index 0000000..88f1bf3 --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/thread.cpp @@ -0,0 +1,56 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/tcb.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <errno.h> +#include <stdint.h> +#include <stddef.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if(mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(*stack_base == MAP_FAILED) { + return errno; + } + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/managarm/x86_64/thread_entry.S b/lib/mlibc/sysdeps/managarm/x86_64/thread_entry.S new file mode 100644 index 0000000..51e703b --- /dev/null +++ b/lib/mlibc/sysdeps/managarm/x86_64/thread_entry.S @@ -0,0 +1,11 @@ + +.section .text +.global __mlibc_start_thread +__mlibc_start_thread: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_enter_thread + +.section .note.GNU-stack,"",%progbits + |