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/internal/generic/global-config.cpp mlibc-workdir/options/internal/generic/global-config.cpp index 3b7b862..3d86e7a 100644 --- mlibc-clean/options/internal/generic/global-config.cpp +++ mlibc-workdir/options/internal/generic/global-config.cpp @@ -1,9 +1,15 @@ #include -#include +#include #include namespace mlibc { +namespace { + +constinit mlibc::lazy_eternal globalConfigInstance; + +} // namespace + struct GlobalConfigGuard { GlobalConfigGuard(); }; @@ -12,7 +18,7 @@ GlobalConfigGuard guard; GlobalConfigGuard::GlobalConfigGuard() { // Force the config to be created during initialization of libc.so. - mlibc::globalConfig(); + globalConfigInstance.get(); } static bool envEnabled(const char *env) { @@ -29,4 +35,8 @@ GlobalConfig::GlobalConfig() { debugMonetaryLengths = envEnabled("MLIBC_DEBUG_MONETARY_LENGTHS"); } +const GlobalConfig &globalConfig() { + return globalConfigInstance.get(); +} + } // namespace mlibc diff --git mlibc-clean/options/internal/include/mlibc/allocator.hpp mlibc-workdir/options/internal/include/mlibc/allocator.hpp index 852620a..a1bfb0a 100644 --- mlibc-clean/options/internal/include/mlibc/allocator.hpp +++ mlibc-workdir/options/internal/include/mlibc/allocator.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -35,4 +36,34 @@ MemoryAllocator &getAllocator(); #endif // !MLIBC_DEBUG_ALLOCATOR +namespace mlibc { + +template +struct lazy_eternal { + constexpr lazy_eternal() = default; + + template + auto &get(this Self &&self) { + if (__atomic_load_n(&self.initialized_, __ATOMIC_ACQUIRE)) + return *self.box_.get(); + + { + frg::unique_lock lock{self.lock_}; + if (!__atomic_load_n(&self.initialized_, __ATOMIC_RELAXED)) { + self.box_.initialize(); + __atomic_store_n(&self.initialized_, 1, __ATOMIC_RELEASE); + } + } + + return *self.box_.get(); + } + +private: + mutable uint32_t initialized_ = 0; + mutable FutexLock lock_; + mutable frg::manual_box box_; +}; + +} // namespace mlibc + #endif // MLIBC_FRIGG_ALLOC diff --git mlibc-clean/options/internal/include/mlibc/global-config.hpp mlibc-workdir/options/internal/include/mlibc/global-config.hpp index 0235c54..3fad411 100644 --- mlibc-clean/options/internal/include/mlibc/global-config.hpp +++ mlibc-workdir/options/internal/include/mlibc/global-config.hpp @@ -14,11 +14,8 @@ struct GlobalConfig { bool debugMonetaryLengths; }; -inline const GlobalConfig &globalConfig() { - static GlobalConfig cached; - return cached; -} +const GlobalConfig &globalConfig(); -} +} // namespace mlibc #endif // MLIBC_GLOBAL_CONFIG diff --git mlibc-clean/options/internal/include/mlibc/lock.hpp mlibc-workdir/options/internal/include/mlibc/lock.hpp index f447741..ab44667 100644 --- mlibc-clean/options/internal/include/mlibc/lock.hpp +++ mlibc-workdir/options/internal/include/mlibc/lock.hpp @@ -14,7 +14,7 @@ template struct alignas(4) FutexLockImpl { - FutexLockImpl() : _state{0}, _recursion{0} { } + constexpr FutexLockImpl() : _state{0}, _recursion{0} { } FutexLockImpl(const FutexLockImpl &) = delete; diff --git mlibc-clean/options/internal/include/mlibc/sysdep-signatures.hpp mlibc-workdir/options/internal/include/mlibc/sysdep-signatures.hpp index d639e43..bff59a5 100644 --- mlibc-clean/options/internal/include/mlibc/sysdep-signatures.hpp +++ mlibc-workdir/options/internal/include/mlibc/sysdep-signatures.hpp @@ -23,6 +23,10 @@ #include +#if __MLIBC_POSIX_OPTION +#include +#endif + namespace mlibc { template @@ -235,6 +239,7 @@ SYSDEP_FUNC(SetRegid, gid_t rgid, gid_t egid); SYSDEP_FUNC(GetLoginR, char *name, size_t name_len); SYSDEP_FUNC(IfIndextoname, unsigned int index, char *name); SYSDEP_FUNC(IfNametoindex, const char *name, unsigned int *ret); +SYSDEP_FUNC(IfNameindex, struct if_nameindex **ret); SYSDEP_FUNC(Ptsname, int fd, char *buffer, size_t length); SYSDEP_FUNC(Unlockpt, int fd); SYSDEP_FUNC(ThreadSetname, void *tcb, const char *name); diff --git mlibc-clean/options/internal/include/mlibc/sysdep-tags.hpp mlibc-workdir/options/internal/include/mlibc/sysdep-tags.hpp index 17cf422..b90d201 100644 --- mlibc-clean/options/internal/include/mlibc/sysdep-tags.hpp +++ mlibc-workdir/options/internal/include/mlibc/sysdep-tags.hpp @@ -476,6 +476,8 @@ struct GetLoginR {}; struct IfIndextoname {}; // int sys_if_nametoindex(const char *name, unsigned int *ret); struct IfNametoindex {}; +// int sys_if_nameindex(struct if_nameindex **ret); +struct IfNameindex {}; // int sys_ptsname(int fd, char *buffer, size_t length); struct Ptsname {}; // int sys_unlockpt(int fd); diff --git mlibc-clean/options/posix/generic/net-if.cpp mlibc-workdir/options/posix/generic/net-if.cpp index ed0c463..8df2580 100644 --- mlibc-clean/options/posix/generic/net-if.cpp +++ mlibc-workdir/options/posix/generic/net-if.cpp @@ -6,8 +6,13 @@ #include #include -void if_freenameindex(struct if_nameindex *) { - mlibc::infoLogger() << "mlibc: if_freenameindex is a no-op" << frg::endlog; +void if_freenameindex(struct if_nameindex *index) { + if(!index) + return; + + for(struct if_nameindex *it = index; it->if_index || it->if_name; ++it) + free(it->if_name); + free(index); } char *if_indextoname(unsigned int index, char *name) { @@ -20,9 +25,13 @@ 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; + struct if_nameindex *ret = nullptr; + if(int e = mlibc::sysdep_or_enosys(&ret); e) { + errno = e; + return nullptr; + } + + return ret; } unsigned int if_nametoindex(const char *name) { diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp index 3b04372..a4b934a 100644 --- mlibc-clean/sysdeps/astral/generic/generic.cpp +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include #include #include @@ -11,8 +13,20 @@ #include #include #include +#include +#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 Sysdeps::operator()(size_t size, const gid_t *list) { @@ -31,14 +45,214 @@ namespace mlibc { return 0; } - int Sysdeps::operator()(int fd, int layer, int number, - void *__restrict buffer, socklen_t *__restrict size) { + int Sysdeps::operator()(const char *path, const char *name, + const void *val, size_t size, int flags) { + (void)path; + (void)name; + (void)val; (void)size; - (void)buffer; - // TODO unstub - mlibc::infoLogger() << "getsockopt: " << fd << " " << layer << " " << number << frg::endlog; + (void)flags; + return ENOTSUP; + } + + int Sysdeps::operator()(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 Sysdeps::operator()(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 Sysdeps::operator()(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 Sysdeps::operator()(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 Sysdeps::operator()(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 Sysdeps::operator()(const char *path, char *list, size_t size, + ssize_t *nread) { + (void)path; + (void)list; + (void)size; + (void)nread; + return ENOTSUP; + } + + int Sysdeps::operator()(const char *path, char *list, size_t size, + ssize_t *nread) { + (void)path; + (void)list; + (void)size; + (void)nread; + return ENOTSUP; + } + + int Sysdeps::operator()(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 Sysdeps::operator()(struct ifaddrs **out) { + struct ifaddrs *list = nullptr; + + int dirfd; + int error = sysdep("/dev/", O_DIRECTORY | O_RDONLY, 0, &dirfd); + if(error) + return error; + + struct dirent dent; + size_t bytes_read; + for(;;) { + error = sysdep(dirfd, &dent, sizeof(dent), &bytes_read); + if(error) + goto leave; + + if(bytes_read == 0) + break; + + struct stat st; + if(sysdep(fsfd_target::fd_path, dirfd, dent.d_name, AT_SYMLINK_NOFOLLOW, &st)) + continue; + + if(!S_ISCHR(st.st_mode) || major(st.st_rdev) != 10) + continue; + + int fd; + error = sysdep(dirfd, dent.d_name, 0, 0, &fd); + if(error) + continue; + + astral_net_info_t net_info = {}; + int r; + error = sysdep(fd, 0x1337631, &net_info, &r); + if(error) { + sysdep(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; + sysdep(fd); + } + + *out = list; + +leave: + sysdep(dirfd); + return error; + } + + // XXX extremely leaky. + int Sysdeps::operator()(struct if_nameindex **out) { + struct ifaddrs *ifaddrs; + if(int e = sysdep(&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 Sysdeps::operator()(int fd, int layer, int number, + void *__restrict buffer, socklen_t *__restrict size) { + long ret; + return syscall(SYSCALL_GETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, (uint64_t)size); + } int Sysdeps::operator()(bool *ipv4, bool *ipv6) { // there is no ipv6 support in the kernel currently and no way of checking for configured interfaces @@ -47,6 +261,71 @@ namespace mlibc { return 0; } + int Sysdeps::operator()(int fd) { + int r; + // unlockpt is a no-op kernel side, so use this to check for an invalid pty + return sysdep(fd, 0x13376167, nullptr, &r); + } + + int Sysdeps::operator()(const char *path, struct statfs *buf) { + struct statvfs stvfs; + int ret = sysdep(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 Sysdeps::operator()(int fd, struct statfs *buf) { + struct statvfs stvfs; + int ret = sysdep(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 Sysdeps::operator()(const char *path, struct statvfs *out) { + long r; + return syscall(SYSCALL_FSTATVFSAT, &r, AT_FDCWD, (uint64_t)path, (uint64_t)out, 0); + } + + int Sysdeps::operator()(int fd, struct statvfs *out) { + long r; + return syscall(SYSCALL_FSTATVFS, &r, fd, (uint64_t)out); + } + + void Sysdeps::operator()() { + long r; + syscall(SYSCALL_YIELD, &r); + } + int Sysdeps::operator()(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 Sysdeps::operator()(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); } @@ -562,6 +842,16 @@ namespace mlibc { return sysdep(fd, TCSETS, (void *)attr, &res); } + int Sysdeps::operator()(int fd, struct winsize *winsz) { + int res; + return sysdep(fd, TIOCGWINSZ, (void *)winsz, &res); + } + + int Sysdeps::operator()(int fd, const struct winsize *winsz) { + int res; + return sysdep(fd, TIOCSWINSZ, (void *)winsz, &res); + } + int Sysdeps::operator()(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { long ret; long error = syscall(SYSCALL_POLL, &ret, (uint64_t)fds, count, timeout); @@ -932,4 +1222,13 @@ namespace mlibc { *nanos = ts.tv_nsec; return err; } + + int Sysdeps::operator()(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 diff --git mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp index ce91084..e7e9b6d 100644 --- mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp +++ mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp @@ -7,8 +7,25 @@ namespace mlibc { struct AstralSysdepTags : SetGroups, GetGroups, + Setxattr, + Lsetxattr, + Fsetxattr, + Getxattr, + Lgetxattr, + Fgetxattr, + Listxattr, + Llistxattr, + Flistxattr, + Getifaddrs, + IfNameindex, GetSockopt, InetConfigured, + Unlockpt, + Statfs, + Fstatfs, + Statvfs, + Fstatvfs, + Yield, Readv, Writev, Sysinfo, @@ -85,6 +102,8 @@ struct AstralSysdepTags : Sleep, Tcgetattr, Tcsetattr, + Tcgetwinsize, + Tcsetwinsize, Poll, Ppoll, Pselect, @@ -135,6 +154,7 @@ struct AstralSysdepTags : VmUnmap, Isatty, ClockGet, + ClockGetres, PrepareStack {};