diff --git mlibc-clean/options/ansi/generic/time.cpp mlibc-workdir/options/ansi/generic/time.cpp index 8edf44b..c13a2c1 100644 --- mlibc-clean/options/ansi/generic/time.cpp +++ mlibc-workdir/options/ansi/generic/time.cpp @@ -598,7 +598,7 @@ int nanosleep(const struct timespec *req, struct timespec *rem) { int e = mlibc::sys_sleep(&tmp.tv_sec, &tmp.tv_nsec); if (!e) return 0; - else if (e == EINTR) + else if (e == EINTR && rem) *rem = tmp; errno = e; diff --git mlibc-clean/options/internal/include/mlibc/strtol.hpp mlibc-workdir/options/internal/include/mlibc/strtol.hpp index a77d9d0..9f3fe08 100644 --- mlibc-clean/options/internal/include/mlibc/strtol.hpp +++ mlibc-workdir/options/internal/include/mlibc/strtol.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace mlibc { diff --git mlibc-clean/options/ansi/generic/inttypes.cpp mlibc-workdir/options/ansi/generic/inttypes.cpp index 6478680..1ca08f4 100644 --- mlibc-clean/options/ansi/generic/inttypes.cpp +++ mlibc-workdir/options/ansi/generic/inttypes.cpp @@ -1,11 +1,7 @@ - -#include #include -#include +#include #include #include - -static const char *__mlibc_digits = "0123456789abcdefghijklmnopqrstuvwxyz"; intmax_t imaxabs(intmax_t num) { @@ -16,83 +14,17 @@ imaxdiv_t imaxdiv(intmax_t number, intmax_t denom) { return r; } -template T strtoxmax(const char *it, char **out, int base) { - T v = 0; - bool negate = false; - const unsigned char *s = (const unsigned char *)it; - int c; - - if(std::is_signed_v) { - if(*s == '+') { - s++; - }else if(*s == '-') { - negate = true; - s++; - } - } - - do { - c = *s++; - } while (isspace(c)); - if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - - if(base == 8) { - if(*it != 0) - goto parse_digits; - it++; - }else if(base == 16) { - if(*it != 0) - goto parse_digits; - it++; - if(*it != 'x' && *it != 'X') - goto parse_digits; - it++; - } - -parse_digits: - while(*it) { - if(isspace(*it)) { - it++; - continue; - } - - __ensure(base <= 10); // TODO: For base > 10 we need to implement tolower(). - //auto c = strchr(__mlibc_digits, tolower(*it)); - auto c = strchr(__mlibc_digits, *it); - if(!c || (c - __mlibc_digits) >= base) - break; - v = v * base + (c - __mlibc_digits); - it++; - } - - if(std::is_signed_v) { - if(negate) - v = -v; - } - - if(out) - *out = const_cast(it); - return v; -} - -intmax_t strtoimax(const char *it, char **out, int base) { - // TODO: This function has to check for overflow! - return strtoxmax(it, out, base); +intmax_t strtoimax(const char *string, char **end, int base) { + return mlibc::stringToInteger(string, end, base); } -uintmax_t strtoumax(const char *it, char **out, int base) { - return strtoxmax(it, out, base); +uintmax_t strtoumax(const char *string, char **end, int base) { + return mlibc::stringToInteger(string, end, base); } intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int) { __ensure(!"Not implemented"); __builtin_unreachable(); } uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int) { __ensure(!"Not implemented"); __builtin_unreachable(); } diff --git mlibc-clean/options/ansi/generic/wchar.cpp mlibc-workdir/options/ansi/generic/wchar.cpp index b44ebc2..9339316 100644 --- mlibc-clean/options/ansi/generic/wchar.cpp +++ mlibc-workdir/options/ansi/generic/wchar.cpp @@ -54,8 +54,13 @@ size_t mbrlen(const char *__restrict mbs, size_t mb_limit, mbstate_t *__restrict mlibc::code_seq nseq{mbs, mbs + mb_limit}; mlibc::code_seq wseq{&wc, &wc + 1}; - if(auto e = cc->decode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) - __ensure(!"decode_wtranscode() errors are not handled"); + if(auto e = cc->decode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) { + if(e == mlibc::charcode_error::input_underflow) + return static_cast(-1); + __ensure(e == mlibc::charcode_error::illegal_input); + errno = EILSEQ; + return static_cast(-1); + } return nseq.it - mbs; } diff --git mlibc-clean/options/glibc/generic/execinfo.cpp mlibc-workdir/options/glibc/generic/execinfo.cpp index 1ed110d..ded9114 100644 --- mlibc-clean/options/glibc/generic/execinfo.cpp +++ mlibc-workdir/options/glibc/generic/execinfo.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -52,29 +53,7 @@ _Unwind_Reason_Code trace(_Unwind_Context *context, void *arg) { } // namespace int backtrace(void **buffer, int size) { - if (size <= 0) - return 0; - - if (!libgccHandle) { - libgccHandle = dlopen("libgcc_s.so.1", RTLD_LAZY | RTLD_LOCAL); - if (!libgccHandle || libgccHandle.value() == nullptr) { - auto error = dlerror(); - mlibc::infoLogger() << "Failed to load libgcc_s.so.1: " << (error ? error : "") << frg::endlog; - return 0; - } - - unwindBacktrace = reinterpret_cast(dlsym(libgccHandle.value(), "_Unwind_Backtrace")); - unwindGetIP = reinterpret_cast(dlsym(libgccHandle.value(), "_Unwind_GetIP")); - - if (!unwindBacktrace || !unwindGetIP) { - mlibc::infoLogger() << "Failed to find unwind functions in libgcc_s.so.1: " << dlerror() << frg::endlog; - return 0; - } - } - - UnwindState state{buffer, size}; - unwindBacktrace(trace, &state); - return state.current_frame; + return ENOSYS; } char **backtrace_symbols(void *const *, int) { @@ -82,25 +61,5 @@ char **backtrace_symbols(void *const *, int) { __builtin_unreachable(); } -void backtrace_symbols_fd(void *const *buffer, int size, int fd) { - if (size <= 0 || fd < 0) - return; - - for (int frame_num = 0; frame_num < size; frame_num++) { - Dl_info info; - if (dladdr(buffer[frame_num], &info) != 0) { - if (info.dli_fname != nullptr) - write(fd, info.dli_fname, strlen(info.dli_fname)); - - if (info.dli_sname != nullptr) - dprintf(fd, "(%s+0x%" PRIxPTR ") ", info.dli_sname, - reinterpret_cast(buffer[frame_num]) - reinterpret_cast(info.dli_saddr)); - else if(info.dli_saddr) - dprintf(fd, "(+%p) ", info.dli_saddr); - else - dprintf(fd, "() "); - } - - dprintf(fd, "[%p]\n", buffer[frame_num]); - } +void backtrace_symbols_fd(void *const *, int, int) { } diff --git mlibc-clean/options/posix/generic/net-if.cpp mlibc-workdir/options/posix/generic/net-if.cpp index 992aef7..e39c499 100644 --- mlibc-clean/options/posix/generic/net-if.cpp +++ mlibc-workdir/options/posix/generic/net-if.cpp @@ -22,11 +22,18 @@ char *if_indextoname(unsigned int index, char *name) { } struct if_nameindex *if_nameindex(void) { - mlibc::infoLogger() << "mlibc: if_nameindex() is a no-op" << frg::endlog; - errno = ENOSYS; - return nullptr; + auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_if_nameindex, 0); + struct if_nameindex *ret = 0; + + if(int e = sysdep(&ret); e) { + errno = e; + return 0; + } + + return ret; } + unsigned int if_nametoindex(const char *name) { auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_if_nametoindex, 0); unsigned int ret = 0; diff --git mlibc-clean/options/posix/generic/netdb.cpp mlibc-workdir/options/posix/generic/netdb.cpp index 299d9d3..d32237c 100644 --- mlibc-clean/options/posix/generic/netdb.cpp +++ mlibc-workdir/options/posix/generic/netdb.cpp @@ -371,8 +371,8 @@ int gethostbyaddr_r(const void *__restrict, socklen_t, int, struct hostent *__re int gethostbyname_r(const char *__restrict, struct hostent *__restrict, char *__restrict, size_t, struct hostent **__restrict, int *__restrict) { - __ensure(!"Not implemented"); - __builtin_unreachable(); + mlibc::infoLogger() << "gethostbyname_r is a stub!" << frg::endlog; + return -1; } struct protoent *getprotobyname(const char *) { diff --git mlibc-clean/options/posix/generic/utmpx.cpp mlibc-workdir/options/posix/generic/utmpx.cpp index 2c6252c..1d9064c 100644 --- mlibc-clean/options/posix/generic/utmpx.cpp +++ mlibc-workdir/options/posix/generic/utmpx.cpp @@ -77,10 +77,10 @@ void setutxent(void) { } struct utmpx *getutxent(void) { - frg::unique_lock lock{utmpxMutex}; - if(!utmpxFd) setutxent(); + frg::unique_lock lock{utmpxMutex}; + if(!utmpxFd) { errno = ENOENT; return nullptr; @@ -95,10 +95,10 @@ struct utmpx *getutxent(void) { } struct utmpx *pututxline(const struct utmpx *ut) { - frg::unique_lock lock{utmpxMutex}; - if(!utmpxFd) setutxent(); + frg::unique_lock lock{utmpxMutex}; + if(!utmpxFd) { errno = ENOENT; return nullptr; @@ -135,10 +135,10 @@ int utmpxname(const char *file) { } struct utmpx *getutxid(const struct utmpx *ut) { - frg::unique_lock lock{utmpxMutex}; - if(!utmpxFd) setutxent(); + + frg::unique_lock lock{utmpxMutex}; if(!utmpxFd) { errno = ENOENT; return nullptr; @@ -153,10 +153,10 @@ struct utmpx *getutxid(const struct utmpx *ut) { } struct utmpx *getutxline(const struct utmpx *ut) { - frg::unique_lock lock{utmpxMutex}; - if(!utmpxFd) setutxent(); + frg::unique_lock lock{utmpxMutex}; + if(!utmpxFd) { errno = ENOENT; return nullptr; diff --git mlibc-clean/options/posix/include/mlibc/posix-sysdeps.hpp mlibc-workdir/options/posix/include/mlibc/posix-sysdeps.hpp index 3666050..ecfc1ae 100644 --- mlibc-clean/options/posix/include/mlibc/posix-sysdeps.hpp +++ mlibc-workdir/options/posix/include/mlibc/posix-sysdeps.hpp @@ -230,6 +230,7 @@ int sys_vm_unmap(void *pointer, size_t size); [[gnu::weak]] int sys_if_indextoname(unsigned int index, char *name); [[gnu::weak]] int sys_if_nametoindex(const char *name, unsigned int *ret); +[[gnu::weak]] int sys_if_nameindex(struct if_nameindex **); [[gnu::weak]] int sys_ptsname(int fd, char *buffer, size_t length); [[gnu::weak]] int sys_unlockpt(int fd); diff --git mlibc-clean/options/rtld/generic/linker.cpp mlibc-workdir/options/rtld/generic/linker.cpp index 07dbe11..3ece6ec 100644 --- mlibc-clean/options/rtld/generic/linker.cpp +++ mlibc-workdir/options/rtld/generic/linker.cpp @@ -29,7 +29,7 @@ uintptr_t libraryBase = 0x41000000; constexpr bool verbose = false; constexpr bool stillSlightlyVerbose = false; -constexpr bool logBaseAddresses = false; +constexpr bool logBaseAddresses = true; constexpr bool logRpath = false; constexpr bool logLdPath = false; constexpr bool logSymbolVersions = false; diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp index 939925e..f8f8c8f 100644 --- mlibc-clean/sysdeps/astral/generic/generic.cpp +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -13,6 +14,16 @@ #include #include #include +#include + +typedef struct { + struct sockaddr addr; + struct sockaddr broadaddr; + struct sockaddr netmask; + struct sockaddr hwaddr; + short flags; + int mtu; +} astral_net_info_t; namespace mlibc { int sys_setgroups(size_t size, const gid_t *list) { @@ -31,13 +42,216 @@ namespace mlibc { return 0; } + int sys_setxattr(const char *path, const char *name, + const void *val, size_t size, int flags) { + (void)path; + (void)name; + (void)val; + (void)size; + (void)flags; + return ENOTSUP; + } + int sys_lsetxattr(const char *path, const char *name, + const void *val, size_t size, int flags) { + (void)path; + (void)name; + (void)val; + (void)size; + (void)flags; + return ENOTSUP; + } + + int sys_fsetxattr(int fd, const char *name, const void *val, + size_t size, int flags) { + (void)fd; + (void)name; + (void)val; + (void)size; + (void)flags; + return ENOTSUP; + } + + int sys_getxattr(const char *path, const char *name, + void *val, size_t size, ssize_t *nread) { + (void)path; + (void)name; + (void)val; + (void)size; + (void)nread; + return ENOTSUP; + } + + int sys_lgetxattr(const char *path, const char *name, + void *val, size_t size, ssize_t *nread) { + (void)path; + (void)name; + (void)val; + (void)size; + (void)nread; + return ENOTSUP; + } + + int sys_fgetxattr(int fd, const char *name, void *val, + size_t size, ssize_t *nread) { + (void)fd; + (void)name; + (void)val; + (void)size; + (void)nread; + return ENOTSUP; + } + + int sys_listxattr(const char *path, char *list, size_t size, + ssize_t *nread) { + (void)path; + (void)list; + (void)size; + (void)nread; + return ENOTSUP; + } + + int sys_llistxattr(const char *path, char *list, size_t size, + ssize_t *nread) { + (void)path; + (void)list; + (void)size; + (void)nread; + return ENOTSUP; + } + + int sys_flistxattr(int fd, char *list, size_t size, + ssize_t *nread) { + (void)fd; + (void)list; + (void)size; + (void)nread; + return ENOTSUP; + } + +#ifndef MLIBC_BUILDING_RTLD + // XXX this might leak memory in case of an error. + int sys_getifaddrs(struct ifaddrs **out) { + struct ifaddrs *list = NULL; + + int dirfd; + int error = sys_open("/dev/", O_DIRECTORY | O_RDONLY, 0, &dirfd); + if (error) + return error; + + + struct dirent dent; + size_t bytes_read; + for (;;) { + error = sys_read_entries(dirfd, &dent, sizeof(dent), &bytes_read); + if (error) + goto leave; + + if (bytes_read == 0) + break; + + struct stat st; + if (sys_stat(fsfd_target::fd_path, dirfd, dent.d_name, AT_SYMLINK_NOFOLLOW, &st)) + continue; + + // check if network device + if (!S_ISCHR(st.st_mode) || major(st.st_rdev) != 10) + continue; + + int fd; + error = sys_openat(dirfd, dent.d_name, 0, 0, &fd); + if (error) + continue; + + astral_net_info_t net_info = {}; + int r; + error = sys_ioctl(fd, 0x1337631, &net_info, &r); + if (error) { + sys_close(fd); + continue; + } + + struct ifaddrs *next = (struct ifaddrs *)calloc(1, sizeof(struct ifaddrs)); + __ensure(next); + + next->ifa_next = list; + + next->ifa_name = strdup(dent.d_name); + __ensure(next->ifa_name); + + next->ifa_flags = net_info.flags; + + next->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr)); + __ensure(next->ifa_addr); + memcpy(next->ifa_addr, &net_info.addr, sizeof(struct sockaddr)); + + if (net_info.netmask.sa_family) { + next->ifa_netmask = (struct sockaddr *)malloc(sizeof(struct sockaddr)); + __ensure(next->ifa_netmask); + memcpy(next->ifa_netmask, &net_info.netmask, sizeof(struct sockaddr)); + } + + if (net_info.broadaddr.sa_family) { + next->ifa_broadaddr = (struct sockaddr *)malloc(sizeof(struct sockaddr)); + __ensure(next->ifa_broadaddr); + memcpy(next->ifa_broadaddr, &net_info.broadaddr, sizeof(struct sockaddr)); + } + + next->ifa_data = nullptr; + + list = next; + sys_close(fd); + } + + *out = list; + + leave: + sys_close(dirfd); + return error; + } + + // XXX extremely leaky. + int sys_if_nameindex(struct if_nameindex **out) { + struct ifaddrs *ifaddrs; + if (int e = sys_getifaddrs(&ifaddrs); e) + return e; + + struct ifaddrs *it = ifaddrs; + int count = 0; + while (it) { + ++count; + it = it->ifa_next; + } + + struct if_nameindex *arr = (struct if_nameindex *)malloc(sizeof(struct if_nameindex) * (count + 1)); + if (!arr) + return ENOMEM; + + int i = 0; + while (ifaddrs) { + arr[i].if_index = i + 1; + arr[i].if_name = strdup(ifaddrs->ifa_name); + __ensure(arr[i].if_name); + + ++i; + + ifaddrs = ifaddrs->ifa_next; + } + + arr[count].if_index = 0; + arr[count].if_name = nullptr; + + *out = arr; + + return 0; + } +#endif + int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size) { (void)size; (void)buffer; - // TODO unstub - mlibc::infoLogger() << "getsockopt: " << fd << " " << layer << " " << number << frg::endlog; - return 0; + long ret; + return syscall(SYSCALL_GETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, (uint64_t)size); } int sys_inet_configured(bool *ipv4, bool *ipv6) { @@ -47,6 +261,71 @@ namespace mlibc { return 0; } + int sys_unlockpt(int fd) { + int r; + // unlockpt is a no-op kernel side, so use this to check for an invalid pty + return sys_ioctl(fd, 0x13376167, NULL, &r); + } + + int sys_statfs(const char *path, struct statfs *buf) { + struct statvfs stvfs; + int ret = sys_statvfs(path, &stvfs); + if (ret) + return ret; + + buf->f_type = 0; /* statvfs has no f_type */ + buf->f_blocks = stvfs.f_blocks; + buf->f_bfree = stvfs.f_bfree; + buf->f_bavail = stvfs.f_bavail; + buf->f_files = stvfs.f_files; + buf->f_ffree = stvfs.f_ffree; + buf->f_fsid.__val[0] = (int)(stvfs.f_fsid & 0xFFFFFFFF); + buf->f_fsid.__val[1] = (int)(stvfs.f_fsid >> 32); + buf->f_namelen = stvfs.f_namemax; + buf->f_flags = stvfs.f_flag; + buf->f_bsize = stvfs.f_frsize; + buf->f_frsize = stvfs.f_bsize; + + return 0; + } + + int sys_fstatfs(int fd, struct statfs *buf) { + struct statvfs stvfs; + int ret = sys_fstatvfs(fd, &stvfs); + if (ret) + return ret; + + buf->f_type = 0; /* statvfs has no f_type */ + buf->f_bsize = stvfs.f_bsize; + buf->f_bfree = stvfs.f_bfree; + buf->f_bavail = stvfs.f_bavail; + buf->f_files = stvfs.f_files; + buf->f_ffree = stvfs.f_ffree; + buf->f_fsid.__val[0] = (int)(stvfs.f_fsid & 0xFFFFFFFF); + buf->f_fsid.__val[1] = (int)(stvfs.f_fsid >> 32); + buf->f_namelen = stvfs.f_namemax; + buf->f_flags = stvfs.f_flag; + buf->f_bsize = stvfs.f_frsize; + buf->f_frsize = stvfs.f_bsize; + + return 0; + } + + int sys_statvfs(const char *path, struct statvfs *out) { + long r; + return syscall(SYSCALL_FSTATVFSAT, &r, AT_FDCWD, (uint64_t)path, (uint64_t)out, 0); + } + + int sys_fstatvfs(int fd, struct statvfs *out) { + long r; + return syscall(SYSCALL_FSTATVFS, &r, fd, (uint64_t)out); + } + + void sys_yield() { + long r; + syscall(SYSCALL_YIELD, &r); + } + int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { long r; int error = syscall(SYSCALL_READV, &r, fd, (uint64_t)iovs, iovc); @@ -489,6 +768,7 @@ namespace mlibc { int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size) { long ret; + mlibc::infoLogger() << "setsockopt: fd " << fd << " layer " << layer << " number " << number << frg::endlog; return syscall(SYSCALL_SETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, size); } @@ -932,4 +1212,13 @@ namespace mlibc { *nanos = ts.tv_nsec; return err; } + + int sys_clock_getres(int clock, time_t *secs, long *nanos) { + struct timespec ts; + long ret; + int err = syscall(SYSCALL_CLOCK_GETRES, &ret, clock, (uint64_t)&ts); + *secs = ts.tv_sec; + *nanos = ts.tv_nsec; + return err; + } } // namespace mlibc diff --git mlibc-clean/sysdeps/astral/include/astral/archctl.h mlibc-workdir/sysdeps/astral/include/astral/archctl.h index 7e4f2a1..ecc2677 100644 --- mlibc-clean/sysdeps/astral/include/astral/archctl.h +++ mlibc-workdir/sysdeps/astral/include/astral/archctl.h @@ -5,6 +5,17 @@ #define ARCH_CTL_SET_FSBASE 1 #define ARCH_CTL_GET_GSBASE 2 #define ARCH_CTL_GET_FSBASE 3 +#define ARCH_CTL_SET_SYSTRACE 4 +#define ARCH_CTL_SET_LDT_ENTRY 5 + +#define ARCH_CTL_SYSTRACE_OFF 0 +#define ARCH_CTL_SYSTRACE_SELF 1 +#define ARCH_CTL_SYSTRACE_ALL 2 + +typedef struct { + uint64_t entry; + uint16_t seg; +} archctl_ldt_request_t; #ifdef __cplusplus extern "C" { diff --git mlibc-clean/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h index a6c4067..f1e0b65 100644 --- mlibc-clean/sysdeps/astral/include/astral/syscall.h +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h @@ -103,6 +103,11 @@ #define SYSCALL_SYSINFO 96 #define SYSCALL_WRITEV 97 #define SYSCALL_READV 98 +#define SYSCALL_YIELD 99 +#define SYSCALL_FSTATVFS 100 +#define SYSCALL_FSTATVFSAT 101 +#define SYSCALL_GETSOCKOPT 102 +#define SYSCALL_CLOCK_GETRES 103 #ifndef __MLIBC_ABI_ONLY