From 46a9b989a720c6641c2219fa2aac1dcdf6c76e62 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Tue, 22 Aug 2023 04:13:55 +0300 Subject: [PATCH 01/45] options/internal: return 1 from setjmp if longjmp was called with 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This behavior was previously incorrect on aarch64 and x86. Co-authored-by: Kacper Słomiński Co-authored-by: no92 --- options/internal/aarch64/setjmp.S | 5 +++-- options/internal/x86/setjmp.S | 23 ++++++++++++----------- options/internal/x86_64/setjmp.S | 2 +- tests/ansi/longjmp.c | 13 +++++++++++-- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/options/internal/aarch64/setjmp.S b/options/internal/aarch64/setjmp.S index 3ede7b3ab8..9dddaa8b53 100644 --- a/options/internal/aarch64/setjmp.S +++ b/options/internal/aarch64/setjmp.S @@ -56,7 +56,8 @@ longjmp: ldp d12, d13, [x0, #144] ldp d14, d15, [x0, #160] - mov x0, x1 - ret + cmp w1, 0 + csinc w0, w1, wzr, ne + br x30 .section .note.GNU-stack,"",%progbits diff --git a/options/internal/x86/setjmp.S b/options/internal/x86/setjmp.S index 2894a29df4..fa6644c7b5 100644 --- a/options/internal/x86/setjmp.S +++ b/options/internal/x86/setjmp.S @@ -1,11 +1,11 @@ .type __setjmp, "function" __setjmp: - mov 4(%esp), %eax # Save argument (buffer) in edi - mov %ebx, 0x00(%eax) - mov %ebp, 0x04(%eax) - mov %esi, 0x08(%eax) - mov %edi, 0x0c(%eax) + mov 4(%esp), %eax # Save argument (buffer) in edi + mov %ebx, 0x00(%eax) + mov %ebp, 0x04(%eax) + mov %esi, 0x08(%eax) + mov %edi, 0x0c(%eax) lea 4(%esp), %ecx # esp before return eip is pushed mov %ecx, 0x10(%eax) @@ -17,8 +17,8 @@ __setjmp: xor %eax, %eax ret - 1: - jmp __sigsetjmp +1: + jmp __sigsetjmp@PLT .global setjmp .type setjmp, "function" @@ -35,16 +35,17 @@ sigsetjmp: .global longjmp .type longjmp, "function" longjmp: - mov 4(%esp), %ecx + mov 4(%esp), %ecx mov 0x00(%ecx), %ebx mov 0x04(%ecx), %ebp mov 0x08(%ecx), %esi mov 0x0c(%ecx), %edi mov 8(%esp), %eax - test %eax, %eax - setz %al - + test %eax, %eax + jnz 1f + inc %eax +1: mov 0x10(%ecx), %esp jmp *0x14(%ecx) diff --git a/options/internal/x86_64/setjmp.S b/options/internal/x86_64/setjmp.S index cf7ff9ebe6..aa8a13433b 100644 --- a/options/internal/x86_64/setjmp.S +++ b/options/internal/x86_64/setjmp.S @@ -46,7 +46,7 @@ longjmp: mov %rsi, %rax test %rax, %rax jnz 1f - xor %rax, %rax + inc %rax 1: mov 0x30(%rdi), %rsp jmp *0x38(%rdi) diff --git a/tests/ansi/longjmp.c b/tests/ansi/longjmp.c index fa6f82d9c0..9f9c1ed414 100644 --- a/tests/ansi/longjmp.c +++ b/tests/ansi/longjmp.c @@ -4,11 +4,11 @@ #include jmp_buf buf; - + noreturn void do_jump(int arg) { longjmp(buf, 2 * arg); } - + int main(void) { volatile int times_called = 0; @@ -17,4 +17,13 @@ int main(void) { } assert(times_called == 4); + + times_called = 0; + int ret = setjmp(buf); + assert(ret == times_called); + + if (!ret) { + times_called = 1; + longjmp(buf, 0); + } } From c373402e55d49fe6baa78e17dfe7fcb771406307 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 05:04:27 +0200 Subject: [PATCH 02/45] options/ansi: silence warnings from musl math --- options/ansi/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/ansi/meson.build b/options/ansi/meson.build index fa1efd1fc2..04e88f4d0e 100644 --- a/options/ansi/meson.build +++ b/options/ansi/meson.build @@ -321,5 +321,5 @@ if not headers_only 'musl-generic-math/truncl.c', pic: true, include_directories: libc_include_dirs, - c_args: ['-Wno-unused', '-Wno-implicit', '-Wno-parentheses', '-Wno-sign-compare', '-Wno-attributes', '-Wno-unknown-pragmas']) + c_args: ['-Wno-unused', '-Wno-implicit', '-Wno-parentheses', '-Wno-sign-compare', '-Wno-attributes', '-Wno-unknown-pragmas', '-Wno-maybe-uninitialized']) endif From bba0a462710dd55deb9eab9770a311f562e43c06 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 05:04:58 +0200 Subject: [PATCH 03/45] options/internal: correctly define ssize_t --- options/internal/include/bits/ssize_t.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/options/internal/include/bits/ssize_t.h b/options/internal/include/bits/ssize_t.h index 357d3dc313..c450233dc2 100644 --- a/options/internal/include/bits/ssize_t.h +++ b/options/internal/include/bits/ssize_t.h @@ -3,7 +3,13 @@ #define MLIBC_SSIZE_T_H // TODO: use ptrdiff_t instead? +#if __UINTPTR_MAX__ == __UINT64_MAX__ typedef long ssize_t; +#elif __UINTPTR_MAX__ == __UINT32_MAX__ +typedef int ssize_t; +#else +#error "unsupported architecture" +#endif #endif // MLIBC_SSIZE_T_H From 43c9623402233ae81b8f4913dab604c61af9b2f3 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 05:05:45 +0200 Subject: [PATCH 04/45] options/rtdl: correctly check for frigg error return --- options/rtdl/generic/linker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/rtdl/generic/linker.cpp b/options/rtdl/generic/linker.cpp index 8fefa701e0..8b45f992e0 100644 --- a/options/rtdl/generic/linker.cpp +++ b/options/rtdl/generic/linker.cpp @@ -179,7 +179,7 @@ SharedObject *ObjectRepository::requestObjectWithName(frg::string_view name, if (path.starts_with("$ORIGIN")) { frg::string_view dirname = origin->path; auto lastsl = dirname.find_last('/'); - if (lastsl != (uint64_t)-1) { + if (lastsl != size_t(-1)) { dirname = dirname.sub_string(0, lastsl); } else { dirname = "."; From 0365c9f568a4ca2455660529b1e98f036d7dfacb Mon Sep 17 00:00:00 2001 From: FedorLap2006 Date: Thu, 21 Jul 2022 19:51:09 +0300 Subject: [PATCH 05/45] options/internal: implement x86-specific headers Co-authored-by: no92 --- .../internal/x86-include/mlibc/arch-defs.hpp | 13 ++++++++++++ options/internal/x86-include/mlibc/thread.hpp | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100755 options/internal/x86-include/mlibc/arch-defs.hpp create mode 100755 options/internal/x86-include/mlibc/thread.hpp diff --git a/options/internal/x86-include/mlibc/arch-defs.hpp b/options/internal/x86-include/mlibc/arch-defs.hpp new file mode 100755 index 0000000000..aa8fe38507 --- /dev/null +++ b/options/internal/x86-include/mlibc/arch-defs.hpp @@ -0,0 +1,13 @@ +#ifndef MLIBC_ARCH_DEFS_HPP +#define MLIBC_ARCH_DEFS_HPP + +#include + +namespace mlibc { + +inline constexpr size_t page_size = 0x1000; + +} // namespace mlibc + +#endif // MLIBC_ARCH_DEFS_HPP + diff --git a/options/internal/x86-include/mlibc/thread.hpp b/options/internal/x86-include/mlibc/thread.hpp new file mode 100755 index 0000000000..3475fb4968 --- /dev/null +++ b/options/internal/x86-include/mlibc/thread.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace mlibc { + +inline Tcb *get_current_tcb() { + uintptr_t ptr; + asm ("movl %%gs:0, %0" : "=r"(ptr)); + return reinterpret_cast(ptr); +} + +inline uintptr_t get_sp() { + uintptr_t esp; + asm ("mov %%esp, %0" : "=r"(esp)); + return esp; +} + +} // namespace mlibc + From 9ed1fad746b08f7ced2204313a429178abf0e67b Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 14 Aug 2023 23:47:40 +0200 Subject: [PATCH 06/45] sysdeps/linux: update riscv64 syscall numbers --- sysdeps/linux/include/bits/syscall_aliases.h | 3 +++ sysdeps/linux/riscv64/syscallnos.h | 1 + 2 files changed, 4 insertions(+) diff --git a/sysdeps/linux/include/bits/syscall_aliases.h b/sysdeps/linux/include/bits/syscall_aliases.h index aa56b6c496..b929efc7c2 100644 --- a/sysdeps/linux/include/bits/syscall_aliases.h +++ b/sysdeps/linux/include/bits/syscall_aliases.h @@ -1295,6 +1295,9 @@ #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 diff --git a/sysdeps/linux/riscv64/syscallnos.h b/sysdeps/linux/riscv64/syscallnos.h index 14422f04ba..a5a11bb15b 100644 --- a/sysdeps/linux/riscv64/syscallnos.h +++ b/sysdeps/linux/riscv64/syscallnos.h @@ -246,6 +246,7 @@ #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 From c78c7ad36542d84a20becc5c5f69769d7e88c747 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 14 Aug 2023 23:48:17 +0200 Subject: [PATCH 07/45] sysdeps/linux: generate x86 syscall numbers Co-authored-by: FedorLap2006 --- sysdeps/linux/update-syscall-list.py | 9 +- sysdeps/linux/x86/syscallnos.h | 433 +++++++++++++++++++++++++++ 2 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 sysdeps/linux/x86/syscallnos.h diff --git a/sysdeps/linux/update-syscall-list.py b/sysdeps/linux/update-syscall-list.py index 6821276c32..58825f7522 100755 --- a/sysdeps/linux/update-syscall-list.py +++ b/sysdeps/linux/update-syscall-list.py @@ -22,10 +22,11 @@ # 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"] +WANTED_ARCHES = ["riscv64", "x86_64", "arm64", "i386"] # How to translate from Linux arch directory names to gnutools architecture fields LINUX_GNU_TRANSLATION = { - "arm64": "aarch64" + "arm64": "aarch64", + "i386": "x86", } argp = argparse.ArgumentParser() @@ -268,7 +269,7 @@ def main(ctx: Context): ("tile64", ["__LP64__", "__tilegx__"]), ], "x86": [ - ("i386", []), + ("i386", ["__i386__"]), ("x32", ["__ILP32__"]), ("x86_64", ["__LP64__"]), ], @@ -287,6 +288,8 @@ def main(ctx: Context): 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) diff --git a/sysdeps/linux/x86/syscallnos.h b/sysdeps/linux/x86/syscallnos.h new file mode 100644 index 0000000000..f75eb0ad49 --- /dev/null +++ b/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 */ From ae3c63d7857cad81d8ff8d6d2f880ca91060603f Mon Sep 17 00:00:00 2001 From: no92 Date: Sun, 20 Aug 2023 23:58:35 +0200 Subject: [PATCH 08/45] options/internal: add operator delete for use on 32-bit platforms --- options/internal/gcc-extra/cxxabi.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/options/internal/gcc-extra/cxxabi.cpp b/options/internal/gcc-extra/cxxabi.cpp index aa222a8353..c5bd92f5eb 100644 --- a/options/internal/gcc-extra/cxxabi.cpp +++ b/options/internal/gcc-extra/cxxabi.cpp @@ -10,6 +10,10 @@ __ensure(!"operator delete called! delete expressions cannot be used in mlibc."); } #else + extern "C" [[gnu::visibility("hidden")]] void _ZdlPvj() { // operator delete (void *, unsigned int) + __ensure(!"operator delete called! delete expressions cannot be used in mlibc."); + } + extern "C" [[gnu::visibility("hidden")]] void _ZdlPvm() { // operator delete (void *, size_t) __ensure(!"operator delete called! delete expressions cannot be used in mlibc."); } From c8408d0d31e468020017f6b7961fc3f4a9aaade1 Mon Sep 17 00:00:00 2001 From: FedorLap2006 Date: Thu, 21 Jul 2022 19:53:47 +0300 Subject: [PATCH 09/45] options/rtdl: x86 entry and relocation stub --- options/rtdl/x86/entry.S | 10 ++++++++++ options/rtdl/x86/runtime.S | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 options/rtdl/x86/entry.S create mode 100755 options/rtdl/x86/runtime.S diff --git a/options/rtdl/x86/entry.S b/options/rtdl/x86/entry.S new file mode 100644 index 0000000000..963185b3f7 --- /dev/null +++ b/options/rtdl/x86/entry.S @@ -0,0 +1,10 @@ +.global _start +_start: + call relocateSelf + + push %esp + call interpreterMain + + jmp *%eax + +.section .note.GNU-stack,"",%progbits diff --git a/options/rtdl/x86/runtime.S b/options/rtdl/x86/runtime.S new file mode 100755 index 0000000000..40a175f243 --- /dev/null +++ b/options/rtdl/x86/runtime.S @@ -0,0 +1,9 @@ +.global pltRelocateStub +# save / restore all registers that can hold function parameters +pltRelocateStub: + # we need to save / restore all registers than can hold function arguments + # we do not need to save callee-saved registers as they will not be trashed by lazyRelocate + # TODO: save floating point argument registers + ud2 + +.section .note.GNU-stack,"",%progbits From acdb3778f08937c9df3936cdc50706e571a5d82b Mon Sep 17 00:00:00 2001 From: FedorLap2006 Date: Thu, 21 Jul 2022 23:00:51 +0300 Subject: [PATCH 10/45] options/rtdl: set TLS parameters on x86 --- options/rtdl/generic/linker.cpp | 2 +- options/rtdl/include/mlibc/rtdl-abi.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/options/rtdl/generic/linker.cpp b/options/rtdl/generic/linker.cpp index 8b45f992e0..211acc8f7f 100644 --- a/options/rtdl/generic/linker.cpp +++ b/options/rtdl/generic/linker.cpp @@ -29,7 +29,7 @@ constexpr bool logBaseAddresses = false; constexpr bool logRpath = false; constexpr bool eagerBinding = true; -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__i386__) constexpr inline bool tlsAboveTp = false; #elif defined(__aarch64__) constexpr inline bool tlsAboveTp = true; diff --git a/options/rtdl/include/mlibc/rtdl-abi.hpp b/options/rtdl/include/mlibc/rtdl-abi.hpp index 9060b04cd8..135b46193c 100644 --- a/options/rtdl/include/mlibc/rtdl-abi.hpp +++ b/options/rtdl/include/mlibc/rtdl-abi.hpp @@ -3,13 +3,13 @@ #include -#if defined(__x86_64__) || defined(__aarch64__) || defined(__riscv) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__i386__) || defined(__riscv) struct __abi_tls_entry { struct SharedObject *object; - uint64_t offset; + size_t offset; }; -static_assert(sizeof(__abi_tls_entry) == 16, "Bad __abi_tls_entry size"); +static_assert(sizeof(__abi_tls_entry) == sizeof(size_t) * 2, "Bad __abi_tls_entry size"); extern "C" void *__dlapi_get_tls(struct __abi_tls_entry *); @@ -19,7 +19,7 @@ extern "C" void *__dlapi_get_tls(struct __abi_tls_entry *); #if defined(__riscv) constexpr inline unsigned long TLS_DTV_OFFSET = 0x800; -#elif defined(__x86_64__) || defined(__aarch64__) +#elif defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) constexpr inline unsigned long TLS_DTV_OFFSET = 0; #else #error "Missing architecture specific code." From 488577bb64edd76c0c7d1c0868989a127ff0733e Mon Sep 17 00:00:00 2001 From: FedorLap2006 Date: Thu, 21 Jul 2022 23:04:39 +0300 Subject: [PATCH 11/45] options/rtdl: implement getLdsoBase for x86 --- options/rtdl/generic/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/rtdl/generic/main.cpp b/options/rtdl/generic/main.cpp index a1b646409e..faba3910d1 100644 --- a/options/rtdl/generic/main.cpp +++ b/options/rtdl/generic/main.cpp @@ -57,7 +57,7 @@ DebugInterface globalDebugInterface; // Use a PC-relative instruction sequence to find our runtime load address. uintptr_t getLdsoBase() { -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) // On x86_64, the first GOT entry holds the link-time address of _DYNAMIC. // TODO: This isn't guaranteed on AArch64, so this might fail with some linkers. auto linktime_dynamic = reinterpret_cast(_GLOBAL_OFFSET_TABLE_[0]); From c1d3668b035a9030c454d1850ad26bc74db8be2f Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 26 Dec 2023 12:07:20 +0100 Subject: [PATCH 12/45] options/rtdl: implement copy relocations for DT_REL --- options/rtdl/generic/linker.cpp | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/options/rtdl/generic/linker.cpp b/options/rtdl/generic/linker.cpp index 211acc8f7f..d6e91180a5 100644 --- a/options/rtdl/generic/linker.cpp +++ b/options/rtdl/generic/linker.cpp @@ -793,7 +793,28 @@ void processCopyRela(SharedObject *object, elf_rela *reloc) { memcpy((void *)rel_addr, (void *)p->virtualAddress(), symbol->st_size); } +void processCopyRel(SharedObject *object, elf_rel *reloc) { + auto type = ELF_R_TYPE(reloc->r_info); + auto symbol_index = ELF_R_SYM(reloc->r_info); + + if(type != R_COPY) + return; + + uintptr_t rel_addr = object->baseAddress + reloc->r_offset; + + auto symbol = (elf_sym *)(object->baseAddress + object->symbolTableOffset + + symbol_index * sizeof(elf_sym)); + ObjectSymbol r(object, symbol); + frg::optional p = Scope::resolveGlobalOrLocal(*globalScope, object->localScope, r.getString(), object->objectRts, Scope::resolveCopy); + __ensure(p); + + memcpy((void *)rel_addr, (void *)p->virtualAddress(), symbol->st_size); +} + void processCopyRelocations(SharedObject *object) { + frg::optional rel_offset; + frg::optional rel_length; + frg::optional rela_offset; frg::optional rela_length; @@ -801,6 +822,15 @@ void processCopyRelocations(SharedObject *object) { elf_dyn *dynamic = &object->dynamic[i]; switch(dynamic->d_tag) { + case DT_REL: + rel_offset = dynamic->d_un.d_ptr; + break; + case DT_RELSZ: + rel_length = dynamic->d_un.d_val; + break; + case DT_RELENT: + __ensure(dynamic->d_un.d_val == sizeof(elf_rel)); + break; case DT_RELA: rela_offset = dynamic->d_un.d_ptr; break; @@ -818,8 +848,14 @@ void processCopyRelocations(SharedObject *object) { auto reloc = (elf_rela *)(object->baseAddress + *rela_offset + offset); processCopyRela(object, reloc); } + } else if(rel_offset && rel_length) { + for(size_t offset = 0; offset < *rel_length; offset += sizeof(elf_rel)) { + auto reloc = (elf_rel *)(object->baseAddress + *rel_offset + offset); + processCopyRel(object, reloc); + } }else{ __ensure(!rela_offset && !rela_length); + __ensure(!rel_offset && !rel_length); } } From 7c13ffe79c09697619d1da7c3ca662336fb6365b Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Tue, 15 Aug 2023 19:51:19 +0300 Subject: [PATCH 13/45] options/internal: change `struct Tcb` layout for x86 * Move `returnValue` to be after `cancelBits`, since GCC requires `stackCanary` to be located at 0x14. * Add asserts for fields with assumed offsets. * Add padding before `stackCanary` to keep current offsets for non-x86 architectures Co-authored-by: no92 --- options/internal/include/mlibc/tcb.hpp | 27 +++++++++++++++++++------- options/rtdl/aarch64/runtime.S | 2 +- sysdeps/linux/aarch64/cp_syscall.S | 2 +- sysdeps/linux/riscv64/cp_syscall.S | 2 +- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/options/internal/include/mlibc/tcb.hpp b/options/internal/include/mlibc/tcb.hpp index aba795b85e..92aad7af88 100644 --- a/options/internal/include/mlibc/tcb.hpp +++ b/options/internal/include/mlibc/tcb.hpp @@ -92,13 +92,18 @@ struct Tcb { void **dtvPointers; int tid; int didExit; +#if defined(__x86_64__) + uint8_t padding[8]; +#endif + uintptr_t stackCanary; + int cancelBits; + union { void *voidPtr; int intVal; } returnValue; - uintptr_t stackCanary; - int cancelBits; TcbThreadReturnValue returnValueType; + struct AtforkHandler { void (*prepare)(void); void (*parent)(void); @@ -146,22 +151,30 @@ struct Tcb { // There are a few places where we assume the layout of the TCB: #if defined(__x86_64__) -// sysdeps/linux/x86_64/cp_syscall.S uses the offset of cancelBits. -// GCC also expects the stack canary to be at fs:0x28. +// GCC expects the stack canary to be at fs:0x28. static_assert(offsetof(Tcb, stackCanary) == 0x28); +// sysdeps/linux/x86_64/cp_syscall.S uses the offset of cancelBits. static_assert(offsetof(Tcb, cancelBits) == 0x30); +#elif defined(__i386__) +// GCC expects the stack canary to be at gs:0x14. +// The offset differs from x86_64 due to the change in the pointer size +// and removed padding before the stack canary. +static_assert(offsetof(Tcb, stackCanary) == 0x14); +// sysdeps/linux/x86/cp_syscall.S uses the offset of cancelBits. +// It differs from x86_64 for the same reasons as the stack canary. +static_assert(offsetof(Tcb, cancelBits) == 0x18); #elif defined(__aarch64__) // The thread pointer on AArch64 points to 16 bytes before the end of the TCB. // options/linker/aarch64/runtime.S uses the offset of dtvPointers. -static_assert(sizeof(Tcb) - offsetof(Tcb, dtvPointers) - TP_TCB_OFFSET == 96); +static_assert(sizeof(Tcb) - offsetof(Tcb, dtvPointers) - TP_TCB_OFFSET == 104); // sysdeps/linux/aarch64/cp_syscall.S uses the offset of cancelBits. -static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) - TP_TCB_OFFSET == 64); +static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) - TP_TCB_OFFSET == 80); #elif defined(__riscv) && __riscv_xlen == 64 // The thread pointer on RISC-V points to *after* the TCB, and since // we need to access specific fields that means that the value in // sysdeps/linux/riscv64/cp_syscall.S needs to be updated whenever // the struct is expanded. -static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) == 80); +static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) == 96); #else #error "Missing architecture specific code." #endif diff --git a/options/rtdl/aarch64/runtime.S b/options/rtdl/aarch64/runtime.S index f02baba00c..c3e2cffa76 100644 --- a/options/rtdl/aarch64/runtime.S +++ b/options/rtdl/aarch64/runtime.S @@ -16,7 +16,7 @@ __mlibcTlsdescDynamic: ldr x0, [x0, #8] ldp x1, x2, [x0] // tlsIndex, addend mrs x0, tpidr_el0 // tp - ldr x0, [x0, #-96] // tp->dtvPointers + ldr x0, [x0, #-104] // tp->dtvPointers ldr x0, [x0, x1, lsl 3] // [tlsIndex] add x0, x0, x2 // + addend mrs x1, tpidr_el0 // tp diff --git a/sysdeps/linux/aarch64/cp_syscall.S b/sysdeps/linux/aarch64/cp_syscall.S index edfc3e61a3..98690c7371 100644 --- a/sysdeps/linux/aarch64/cp_syscall.S +++ b/sysdeps/linux/aarch64/cp_syscall.S @@ -13,7 +13,7 @@ __mlibc_do_asm_cp_syscall: mov x5, x6 mrs x7, tpidr_el0 - ldr w7, [x7, #-64] // Tcb::cancelBits. See asserts in tcb.hpp. + ldr w7, [x7, #-80] // Tcb::cancelBits. See asserts in tcb.hpp. __mlibc_syscall_begin: // tcbCancelEnableBit && tcbCancelTriggerBit mov x9, #((1 << 0) | (1 << 2)) diff --git a/sysdeps/linux/riscv64/cp_syscall.S b/sysdeps/linux/riscv64/cp_syscall.S index 63230a2bf2..8d3175ded1 100644 --- a/sysdeps/linux/riscv64/cp_syscall.S +++ b/sysdeps/linux/riscv64/cp_syscall.S @@ -13,7 +13,7 @@ __mlibc_do_asm_cp_syscall: mv a4, a5 mv a5, a6 ld a6, -8(sp) // a7 - lw t0, -80(tp) // Tcb::cancelBits. See asserts in tcb.hpp. + lw t0, -96(tp) // Tcb::cancelBits. See asserts in tcb.hpp. __mlibc_syscall_begin: // tcbCancelEnableBit && tcbCancelTriggerBit li t1, (1 << 0) | (1 << 2) From 03c08490b716583d26193987c6c2a17f41afe16f Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sat, 19 Aug 2023 14:34:37 +0300 Subject: [PATCH 14/45] options/internal: make mlibc_crtbegin.S architecture specific --- meson.build | 2 +- .../{gcc-extra => aarch64}/mlibc_crtbegin.S | 0 options/internal/riscv64/mlibc_crtbegin.S | 29 +++++++++++++++++++ options/internal/x86/mlibc_crtbegin.S | 29 +++++++++++++++++++ options/internal/x86_64/mlibc_crtbegin.S | 29 +++++++++++++++++++ tests/meson.build | 2 +- 6 files changed, 89 insertions(+), 2 deletions(-) rename options/internal/{gcc-extra => aarch64}/mlibc_crtbegin.S (100%) create mode 100644 options/internal/riscv64/mlibc_crtbegin.S create mode 100644 options/internal/x86/mlibc_crtbegin.S create mode 100644 options/internal/x86_64/mlibc_crtbegin.S diff --git a/meson.build b/meson.build index 524350cebe..dc894e2671 100644 --- a/meson.build +++ b/meson.build @@ -326,7 +326,7 @@ internal_sources = [ ] internal_dso_sources = [ - 'options/internal/gcc-extra/mlibc_crtbegin.S', + 'options/internal' / host_machine.cpu_family() / 'mlibc_crtbegin.S', 'options/internal' / host_machine.cpu_family() / 'mlibc_crtend.S', ] diff --git a/options/internal/gcc-extra/mlibc_crtbegin.S b/options/internal/aarch64/mlibc_crtbegin.S similarity index 100% rename from options/internal/gcc-extra/mlibc_crtbegin.S rename to options/internal/aarch64/mlibc_crtbegin.S diff --git a/options/internal/riscv64/mlibc_crtbegin.S b/options/internal/riscv64/mlibc_crtbegin.S new file mode 100644 index 0000000000..b99748bcc7 --- /dev/null +++ b/options/internal/riscv64/mlibc_crtbegin.S @@ -0,0 +1,29 @@ + +.section .data +.hidden __dso_handle +.global __dso_handle +__dso_handle: + .quad __dso_handle + +.section .init +.hidden _init +.global _init +_init: + +.section .fini +.hidden _fini +.global _fini +_fini: + +.section .ctors +.hidden __CTOR_LIST__ +.global __CTOR_LIST__ +__CTOR_LIST__: + +.section .dtors +.hidden __DTOR_LIST__ +.global __DTOR_LIST__ +__DTOR_LIST__: + +.section .note.GNU-stack,"",%progbits + diff --git a/options/internal/x86/mlibc_crtbegin.S b/options/internal/x86/mlibc_crtbegin.S new file mode 100644 index 0000000000..d317451820 --- /dev/null +++ b/options/internal/x86/mlibc_crtbegin.S @@ -0,0 +1,29 @@ + +.section .data +.hidden __dso_handle +.global __dso_handle +__dso_handle: + .long __dso_handle + +.section .init +.hidden _init +.global _init +_init: + +.section .fini +.hidden _fini +.global _fini +_fini: + +.section .ctors +.hidden __CTOR_LIST__ +.global __CTOR_LIST__ +__CTOR_LIST__: + +.section .dtors +.hidden __DTOR_LIST__ +.global __DTOR_LIST__ +__DTOR_LIST__: + +.section .note.GNU-stack,"",%progbits + diff --git a/options/internal/x86_64/mlibc_crtbegin.S b/options/internal/x86_64/mlibc_crtbegin.S new file mode 100644 index 0000000000..b99748bcc7 --- /dev/null +++ b/options/internal/x86_64/mlibc_crtbegin.S @@ -0,0 +1,29 @@ + +.section .data +.hidden __dso_handle +.global __dso_handle +__dso_handle: + .quad __dso_handle + +.section .init +.hidden _init +.global _init +_init: + +.section .fini +.hidden _fini +.global _fini +_fini: + +.section .ctors +.hidden __CTOR_LIST__ +.global __CTOR_LIST__ +__CTOR_LIST__: + +.section .dtors +.hidden __DTOR_LIST__ +.global __DTOR_LIST__ +__DTOR_LIST__: + +.section .note.GNU-stack,"",%progbits + diff --git a/tests/meson.build b/tests/meson.build index e1d747b128..feebfaf146 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -152,7 +152,7 @@ if library_type == 'static' test_c_args += '-no-pie' test_link_args += ['-no-pie', '-static'] test_sources += [ - '../options/internal/gcc-extra/mlibc_crtbegin.S', + '../options/internal' / host_machine.cpu_family() / 'mlibc_crtbegin.S', '../options/internal' / host_machine.cpu_family() / 'mlibc_crtend.S', crt, ] From e7bf93f607d3219c1b01c4b4950960c1c0ecd156 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 02:41:56 +0200 Subject: [PATCH 15/45] sysdeps/linux: additional checking before mmap'ing --- sysdeps/linux/generic/sysdeps.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index 2fc9db3697..c17988818b 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -175,6 +175,10 @@ int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2 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; auto ret = do_syscall(SYS_mmap, hint, size, prot, flags, fd, offset); // TODO: musl fixes up EPERM errors from the kernel. if(int e = sc_error(ret); e) From 0d4fb631e7121eca44084dc1d2e9d9ad60df3427 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 02:43:02 +0200 Subject: [PATCH 16/45] sysdeps/linux: prefer SYS_mmap2 over SYS_mmap if possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kacper Słomiński --- sysdeps/linux/generic/sysdeps.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index c17988818b..aad9fb71c7 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -179,7 +179,11 @@ int sys_vm_map(void *hint, size_t size, int prot, int flags, 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; From 9f13f8cd4e7ab816e43da13e84c086956b291086 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 02:52:26 +0200 Subject: [PATCH 17/45] sysdeps/linux: implement sys_{tcb_set,clone} for x86 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kacper Słomiński Co-authored-by: FedorLap2006 --- sysdeps/linux/generic/sysdeps.cpp | 52 ++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index aad9fb71c7..9a4f5d16d3 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -43,11 +44,42 @@ 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(-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(pointer) + sizeof(Tcb); asm volatile ("mv tp, %0" :: "r"(thread_data)); @@ -542,13 +574,31 @@ int sys_clone(void *tcb, pid_t *pid_out, void *stack) { // TODO: We should change the sysdep so that we don't need to do this. auto tp = reinterpret_cast(tcb) + sizeof(Tcb) - 0x10; tcb = reinterpret_cast(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(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(user_desc); #endif auto ret = __mlibc_spawn_thread(flags, stack, pid_out, NULL, tcb); if (ret < 0) return ret; - return 0; + return 0; } extern "C" const char __mlibc_syscall_begin[1]; From 8505b8b6d48ac4a627157716ea1b27f7e12767c5 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:30:08 +0200 Subject: [PATCH 18/45] sysdeps/linux: implement crt stubs for x86 Co-authored-by: FedorLap2006 --- sysdeps/linux/x86/crt-src/Scrt1.S | 23 +++++++++++++++++++++++ sysdeps/linux/x86/crt-src/crt1.S | 18 ++++++++++++++++++ sysdeps/linux/x86/crt-src/crti.S | 9 +++++++++ sysdeps/linux/x86/crt-src/crtn.S | 7 +++++++ 4 files changed, 57 insertions(+) create mode 100644 sysdeps/linux/x86/crt-src/Scrt1.S create mode 100644 sysdeps/linux/x86/crt-src/crt1.S create mode 100644 sysdeps/linux/x86/crt-src/crti.S create mode 100644 sysdeps/linux/x86/crt-src/crtn.S diff --git a/sysdeps/linux/x86/crt-src/Scrt1.S b/sysdeps/linux/x86/crt-src/Scrt1.S new file mode 100644 index 0000000000..0332497406 --- /dev/null +++ b/sysdeps/linux/x86/crt-src/Scrt1.S @@ -0,0 +1,23 @@ +.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, %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/sysdeps/linux/x86/crt-src/crt1.S b/sysdeps/linux/x86/crt-src/crt1.S new file mode 100644 index 0000000000..ed45da3d2e --- /dev/null +++ b/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/sysdeps/linux/x86/crt-src/crti.S b/sysdeps/linux/x86/crt-src/crti.S new file mode 100644 index 0000000000..d794ff637c --- /dev/null +++ b/sysdeps/linux/x86/crt-src/crti.S @@ -0,0 +1,9 @@ +.section .init +.global _init +_init: + pushl %eax + +.section .fini +.global _fini +_fini: + pushl %eax diff --git a/sysdeps/linux/x86/crt-src/crtn.S b/sysdeps/linux/x86/crt-src/crtn.S new file mode 100644 index 0000000000..93ddf88372 --- /dev/null +++ b/sysdeps/linux/x86/crt-src/crtn.S @@ -0,0 +1,7 @@ +.section .init + popl %eax + ret + +.section .fini + popl %eax + ret From 25bbd1e21e64dbccd0aefe18c6a1763dc5d35dbf Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 02:53:31 +0200 Subject: [PATCH 19/45] sysdeps/linux: remove duplicate flag from sys_clone --- sysdeps/linux/generic/sysdeps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index 9a4f5d16d3..a43e67df6f 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -561,7 +561,7 @@ void sys_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_SETTLS + | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID; #if defined(__riscv) From 08cfab044eb1d93d78c4d9df6c59d23e44cd6152 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:03:05 +0200 Subject: [PATCH 20/45] sysdeps/linux: fall back on SYS_fstatat64 when SYS_newfstatat is not defined Co-authored-by: FedorLap2006 --- sysdeps/linux/generic/sysdeps.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index a43e67df6f..a38fc200f3 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -261,7 +261,11 @@ int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat 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; From f0a6036be4dbef6151e7b404a0e8baf4881b6f68 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:28:19 +0200 Subject: [PATCH 21/45] sysdeps/linux: implement `__mlibc_spawn_thread` for x86 --- sysdeps/linux/x86/thread_entry.S | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 sysdeps/linux/x86/thread_entry.S diff --git a/sysdeps/linux/x86/thread_entry.S b/sysdeps/linux/x86/thread_entry.S new file mode 100644 index 0000000000..031a6aaa14 --- /dev/null +++ b/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 From ba4a838395793b793c780efaa541484c6bd0d224 Mon Sep 17 00:00:00 2001 From: FedorLap2006 Date: Thu, 21 Jul 2022 23:02:26 +0300 Subject: [PATCH 22/45] abis: support signals on x86 --- abis/linux/signal.h | 51 +++++++++++++++++++++++++++++-- abis/mlibc/signal.h | 6 ++-- sysdeps/linux/generic/sysdeps.cpp | 3 ++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/abis/linux/signal.h b/abis/linux/signal.h index 24811c2839..a089ac3e03 100644 --- a/abis/linux/signal.h +++ b/abis/linux/signal.h @@ -194,6 +194,28 @@ typedef struct __stack { #define SI_USER 0 #define SI_KERNEL 128 +#if defined(__i386__) +#define REG_GS 0 +#define REG_FS 1 +#define REG_ES 2 +#define REG_DS 3 +#define REG_EDI 4 +#define REG_ESI 5 +#define REG_EBP 6 +#define REG_ESP 7 +#define REG_EBX 8 +#define REG_EDX 9 +#define REG_ECX 10 +#define REG_EAX 11 +#define REG_TRAPNO 12 +#define REG_ERR 13 +#define REG_EIP 14 +#define REG_CS 15 +#define REG_EFL 16 +#define REG_UESP 17 +#define REG_SS 18 +#define NGREG 19 +#elif defined(__x86_64__) #define REG_R8 0 #define REG_R9 1 #define REG_R10 2 @@ -217,6 +239,8 @@ typedef struct __stack { #define REG_TRAPNO 20 #define REG_OLDMASK 21 #define REG_CR2 22 +#define NGREG 23 +#endif struct sigevent { union sigval sigev_value; @@ -240,9 +264,7 @@ struct sigaction { // Taken from the linux kernel headers -#if defined(__x86_64__) - -#define NGREG 23 +#if defined(__x86_64__) || defined(__i386__) struct _fpreg { unsigned short significand[4]; @@ -260,6 +282,7 @@ struct _xmmreg { }; struct _fpstate { +#if defined(__x86_64__) uint16_t cwd; uint16_t swd; uint16_t ftw; @@ -271,6 +294,28 @@ struct _fpstate { struct _fpxreg _st[8]; struct _xmmreg _xmm[16]; uint32_t padding[24]; +#elif defined(__i386__) + uint32_t cw; + uint32_t sw; + uint32_t tag; + uint32_t ipoff; + uint32_t cssel; + uint32_t dataoff; + uint32_t datasel; + struct _fpreg _st[8]; + uint16_t status; + uint16_t magic; + + // FXSR FPU + + uint32_t _fxsr_env[6]; + uint32_t mxscr; + uint32_t reserved; + struct _fpxreg _fxsr_st[8]; + struct _xmmreg _xmm[8]; + + uint32_t padding2[56]; +#endif }; typedef struct { diff --git a/abis/mlibc/signal.h b/abis/mlibc/signal.h index 29663c2b7d..320bea7422 100644 --- a/abis/mlibc/signal.h +++ b/abis/mlibc/signal.h @@ -8,6 +8,7 @@ #include #include +#include #include union sigval { @@ -94,8 +95,7 @@ typedef void (*__sighandler) (int); #define SEGV_MAPERR 1 #define SEGV_ACCERR 2 -// TODO: replace this by uint64_t -typedef long sigset_t; +typedef __mlibc_uint64 sigset_t; #define SIGUNUSED SIGSYS @@ -163,7 +163,7 @@ struct sigaction { void (*sa_sigaction)(int, siginfo_t *, void *); }; -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) // TODO: This is wrong for AArch64. typedef struct { diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index a38fc200f3..3f3db48130 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -303,6 +303,9 @@ int sys_sigaction(int signum, const struct sigaction *act, kernel_act.restorer = __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)); From dd5df92cbb5af53506e3583eb5883f61848bd818 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Tue, 22 Aug 2023 03:34:48 +0200 Subject: [PATCH 23/45] sysdeps/linux: implement __mlibc_do_asm_cp_syscall for x86 Co-authored-by: no92 --- sysdeps/linux/x86/cp_syscall.S | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sysdeps/linux/x86/cp_syscall.S diff --git a/sysdeps/linux/x86/cp_syscall.S b/sysdeps/linux/x86/cp_syscall.S new file mode 100644 index 0000000000..b89e1f4c21 --- /dev/null +++ b/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 From 650e1a873eb0959a48955c0dd42c9545f7a2a57e Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:41:46 +0200 Subject: [PATCH 24/45] sysdeps/linux: implement __do_syscallN for x86 Co-authored-by: FedorLap2006 --- sysdeps/linux/x86/arch-syscall.cpp | 90 ++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 sysdeps/linux/x86/arch-syscall.cpp diff --git a/sysdeps/linux/x86/arch-syscall.cpp b/sysdeps/linux/x86/arch-syscall.cpp new file mode 100644 index 0000000000..35fc8aacaa --- /dev/null +++ b/sysdeps/linux/x86/arch-syscall.cpp @@ -0,0 +1,90 @@ +#include +#include + +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; +} From 83ddafc038af44e1873b780b66b7aeb093e7a4f6 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:42:40 +0200 Subject: [PATCH 25/45] sysdeps/linux: implement __mlibc_signal_restore for x86 Co-authored-by: FedorLap2006 --- sysdeps/linux/aarch64/signals.S | 4 ++++ sysdeps/linux/generic/sysdeps.cpp | 3 ++- sysdeps/linux/riscv64/signals.S | 8 ++++++-- sysdeps/linux/x86/signals.S | 18 ++++++++++++++++++ sysdeps/linux/x86_64/signals.S | 5 ++++- 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 sysdeps/linux/x86/signals.S diff --git a/sysdeps/linux/aarch64/signals.S b/sysdeps/linux/aarch64/signals.S index 4e7e8380ff..923d8d775d 100644 --- a/sysdeps/linux/aarch64/signals.S +++ b/sysdeps/linux/aarch64/signals.S @@ -1,7 +1,11 @@ .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/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index 3f3db48130..f73d7e7326 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -286,6 +286,7 @@ int sys_fstatfs(int fd, struct statfs *buf) { } 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) { @@ -300,7 +301,7 @@ int sys_sigaction(int signum, const struct sigaction *act, if (act) { kernel_act.handler = act->sa_handler; kernel_act.flags = act->sa_flags | SA_RESTORER; - kernel_act.restorer = __mlibc_signal_restore; + kernel_act.restorer = (act->sa_flags & SA_SIGINFO) ? __mlibc_signal_restore_rt : __mlibc_signal_restore; kernel_act.mask = act->sa_mask; } diff --git a/sysdeps/linux/riscv64/signals.S b/sysdeps/linux/riscv64/signals.S index af95724215..77690430d0 100644 --- a/sysdeps/linux/riscv64/signals.S +++ b/sysdeps/linux/riscv64/signals.S @@ -1,8 +1,12 @@ .section .text - nop // TODO: why is this needed? + .global __mlibc_signal_restore .type __mlibc_signal_restore, @function __mlibc_signal_restore: - unimp // TODO +.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/sysdeps/linux/x86/signals.S b/sysdeps/linux/x86/signals.S new file mode 100644 index 0000000000..8127ee4934 --- /dev/null +++ b/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/sysdeps/linux/x86_64/signals.S b/sysdeps/linux/x86_64/signals.S index 1c518efef1..09b4387d86 100644 --- a/sysdeps/linux/x86_64/signals.S +++ b/sysdeps/linux/x86_64/signals.S @@ -1,9 +1,12 @@ .section .text - nop + .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 From dc64c5f245a1a213c3a19e5982c18d78fc6d6d25 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sun, 27 Aug 2023 18:18:02 +0300 Subject: [PATCH 26/45] sysdeps/linux: port sys_before_cancellable_syscall to x86 --- sysdeps/linux/generic/sysdeps.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index f73d7e7326..447ec75b7e 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -620,6 +620,8 @@ extern "C" const char __mlibc_syscall_end[1]; int sys_before_cancellable_syscall(ucontext_t *uct) { #if defined(__x86_64__) auto pc = reinterpret_cast(uct->uc_mcontext.gregs[REG_RIP]); +#elif defined(__i386__) + auto pc = reinterpret_cast(uct->uc_mcontext.gregs[REG_EIP]); #elif defined(__riscv) auto pc = reinterpret_cast(uct->uc_mcontext.gregs[REG_PC]); #elif defined(__aarch64__) From 2e5f2cba9402fcdf752be0c860a57ec49c7a2de0 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 28 Aug 2023 16:32:07 +0300 Subject: [PATCH 27/45] sysdeps/linux: read `__hwcap` from auxv in `__mlibc_entry` --- options/rtdl/generic/main.cpp | 2 +- sysdeps/linux/generic/entry.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/options/rtdl/generic/main.cpp b/options/rtdl/generic/main.cpp index faba3910d1..463a3e329b 100644 --- a/options/rtdl/generic/main.cpp +++ b/options/rtdl/generic/main.cpp @@ -740,7 +740,7 @@ void __dlapi_enter(uintptr_t *entry_stack) { // using the host toolchain. // __gnu_linux__ is the define checked by libgcc -#if defined(__aarch64__) && defined(__gnu_linux__) +#if defined(__aarch64__) && defined(__gnu_linux__) && !defined(MLIBC_STATIC_BUILD) extern "C" unsigned long __getauxval(unsigned long type) { // Find the auxiliary vector by skipping args and environment. diff --git a/sysdeps/linux/generic/entry.cpp b/sysdeps/linux/generic/entry.cpp index 9b376c0c23..aa049ce375 100644 --- a/sysdeps/linux/generic/entry.cpp +++ b/sysdeps/linux/generic/entry.cpp @@ -2,6 +2,7 @@ #include #include #include +#include // defined by the POSIX library void __mlibc_initLocale(); @@ -12,6 +13,8 @@ extern "C" void __dlapi_enter(uintptr_t *); extern char **environ; static mlibc::exec_stack_data __mlibc_stack_data; +size_t __hwcap; + struct LibraryGuard { LibraryGuard(); }; @@ -29,6 +32,7 @@ LibraryGuard::LibraryGuard() { 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); } From 9404ec0fd4bb63e6a290dadf82f7c0d3558dbd27 Mon Sep 17 00:00:00 2001 From: no92 Date: Fri, 25 Aug 2023 00:02:03 +0200 Subject: [PATCH 28/45] options/lsb: implement ___tls_get_addr for x86 This function is not the same as the else below, as it has three leading underscores instead of two. I didn't find a definitive explanation for this online, but it seems to have been some glibc meme. --- options/lsb/generic/tls.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/options/lsb/generic/tls.cpp b/options/lsb/generic/tls.cpp index 09b25aca5b..1d7cc30dca 100644 --- a/options/lsb/generic/tls.cpp +++ b/options/lsb/generic/tls.cpp @@ -11,6 +11,10 @@ auto dtvPtr = reinterpret_cast(tcbPtr->dtvPointers[0]); return reinterpret_cast(dtvPtr + entry->offset + TLS_DTV_OFFSET); } +#elif defined(__i386__) + extern "C" __attribute__((regparm(1))) void *___tls_get_addr(struct __abi_tls_entry *entry) { + return __dlapi_get_tls(entry); + } #else extern "C" void *__tls_get_addr(struct __abi_tls_entry *entry) { return __dlapi_get_tls(entry); From d949c41dc862348b3661f83421cff38190d2c7eb Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sat, 26 Aug 2023 23:17:12 +0300 Subject: [PATCH 29/45] options/internal: add __stack_chk_fail_local alias for __stack_chk_fail Co-authored-by: no92 --- options/internal/gcc/stack_protector.cpp | 8 +++++++- sysdeps/linux/x86/crt-src/Scrt1.S | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/options/internal/gcc/stack_protector.cpp b/options/internal/gcc/stack_protector.cpp index e6e7c5f489..e5e50f0914 100644 --- a/options/internal/gcc/stack_protector.cpp +++ b/options/internal/gcc/stack_protector.cpp @@ -20,6 +20,12 @@ void initStackGuard(void *entropy) { } // namespace mlibc -extern "C" void __stack_chk_fail() { +extern "C" [[noreturn]] void __stack_chk_fail() { mlibc::panicLogger() << "Stack smashing detected!" << frg::endlog; + __builtin_unreachable(); } + +extern "C" [[noreturn, gnu::visibility("hidden")]] void __stack_chk_fail_local() { + __stack_chk_fail(); +}; + diff --git a/sysdeps/linux/x86/crt-src/Scrt1.S b/sysdeps/linux/x86/crt-src/Scrt1.S index 0332497406..a62b127ac2 100644 --- a/sysdeps/linux/x86/crt-src/Scrt1.S +++ b/sysdeps/linux/x86/crt-src/Scrt1.S @@ -1,4 +1,10 @@ .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 From 4742c72e2f217c33f830446175682d4763796bcf Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Tue, 15 Aug 2023 18:09:33 +0300 Subject: [PATCH 30/45] abis/linux: define `struct stat` for x86 --- abis/linux/stat.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/abis/linux/stat.h b/abis/linux/stat.h index 3e9c981329..4e567a83f2 100644 --- a/abis/linux/stat.h +++ b/abis/linux/stat.h @@ -85,6 +85,31 @@ struct stat { unsigned int __unused5; }; +#elif defined(__i386__) + +struct stat { + dev_t st_dev; + int __st_dev_padding; + long __st_ino_truncated; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + int __st_rdev_padding; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + struct { + long tv_sec; + long tv_nsec; + } __st_atim32, __st_mtim32, __st_ctim32; + ino_t st_ino; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +}; + #endif #ifdef __cplusplus From a32a2f99a6e4ba190d0ef27bed0f56d6e1a3af62 Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 03:02:06 +0200 Subject: [PATCH 31/45] options/posix: define IPC_64 for x86 --- options/posix/include/sys/ipc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/posix/include/sys/ipc.h b/options/posix/include/sys/ipc.h index 6083478b07..8318ddef15 100644 --- a/options/posix/include/sys/ipc.h +++ b/options/posix/include/sys/ipc.h @@ -20,7 +20,7 @@ extern "C" { #define IPC_PRIVATE ((key_t) 0) -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(__i386__) #define IPC_64 0x100 #elif defined(__x86_64__) || (defined(__riscv) && __riscv_xlen == 64) #define IPC_64 0 From b8d1ed4a4c20e13499a929c9e1fdc6d532995b4b Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sat, 26 Aug 2023 03:39:30 +0300 Subject: [PATCH 32/45] abis/linux: use correct size of suseconds_t on x86 --- abis/linux/suseconds_t.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abis/linux/suseconds_t.h b/abis/linux/suseconds_t.h index 723ddfaeb0..1de1a7cbc1 100644 --- a/abis/linux/suseconds_t.h +++ b/abis/linux/suseconds_t.h @@ -3,6 +3,6 @@ #include -typedef __mlibc_int64 suseconds_t; +typedef long suseconds_t; #endif /* _ABIBITS_SUSECONDS_T_H */ From 77d8406ed79022c28da5b083c15d6275514823d4 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sat, 26 Aug 2023 03:42:58 +0300 Subject: [PATCH 33/45] options/posix: use correct size of useconds_t on x86 --- options/posix/include/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/posix/include/unistd.h b/options/posix/include/unistd.h index f9d7de8e24..26f407d8f5 100644 --- a/options/posix/include/unistd.h +++ b/options/posix/include/unistd.h @@ -305,7 +305,7 @@ extern int optopt; #endif /* !__MLIBC_ABI_ONLY */ // Non-POSIX functions supported by Linux. -typedef __mlibc_uint64 useconds_t; +typedef unsigned useconds_t; #ifndef __MLIBC_ABI_ONLY From ef373808d8432ba44f114c6d8c0c7e2d37bf0a17 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 00:52:20 +0200 Subject: [PATCH 34/45] options/ansi: correctly define SCN* and PRI* macros on 32-bit platforms --- options/ansi/include/inttypes.h | 82 ++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/options/ansi/include/inttypes.h b/options/ansi/include/inttypes.h index bf0066156f..549544057a 100644 --- a/options/ansi/include/inttypes.h +++ b/options/ansi/include/inttypes.h @@ -7,6 +7,14 @@ /* gate behind !__MLIBC_ABI_ONLY */ #ifndef __MLIBC_ABI_ONLY +#if UINTPTR_MAX == UINT64_MAX +# define __PRI64 "l" +# define __PRIPTR "l" +#else +# define __PRI64 "ll" +# define __PRIPTR "" +#endif + // TODO: This is extremly unelegant and fragile. #define PRId8 "d" #define PRIi8 "i" @@ -26,16 +34,16 @@ #define PRIiLEAST32 "i" #define PRIdFAST32 "ld" #define PRIiFAST32 "li" -#define PRId64 "ld" -#define PRIi64 "li" -#define PRIdLEAST64 "ld" -#define PRIiLEAST64 "li" -#define PRIdFAST64 "ld" -#define PRIiFAST64 "li" -#define PRIdMAX "ld" -#define PRIiMAX "li" -#define PRIdPTR "ld" -#define PRIiPTR "li" +#define PRId64 __PRI64 "d" +#define PRIi64 __PRI64 "i" +#define PRIdLEAST64 __PRI64 "d" +#define PRIiLEAST64 __PRI64 "i" +#define PRIdFAST64 __PRI64 "d" +#define PRIiFAST64 __PRI64 "i" +#define PRIdMAX __PRI64 "d" +#define PRIiMAX __PRI64 "i" +#define PRIdPTR __PRIPTR "d" +#define PRIiPTR __PRIPTR "i" #define PRIo8 "o" #define PRIu8 "u" #define PRIx8 "x" @@ -72,42 +80,42 @@ #define PRIuFAST32 "lu" #define PRIxFAST32 "lx" #define PRIXFAST32 "lX" -#define PRIo64 "lo" -#define PRIu64 "lu" -#define PRIx64 "lx" -#define PRIX64 "lX" -#define PRIoLEAST64 "lo" -#define PRIuLEAST64 "lu" -#define PRIxLEAST64 "lx" -#define PRIXLEAST64 "lX" -#define PRIoFAST64 "lo" -#define PRIuFAST64 "lu" -#define PRIxFAST64 "lx" -#define PRIXFAST64 "lX" -#define PRIoMAX "lo" -#define PRIuMAX "lu" -#define PRIxMAX "lx" -#define PRIXMAX "lX" -#define PRIoPTR "lo" -#define PRIuPTR "lu" -#define PRIxPTR "lx" -#define PRIXPTR "lX" +#define PRIo64 __PRI64 "o" +#define PRIu64 __PRI64 "u" +#define PRIx64 __PRI64 "x" +#define PRIX64 __PRI64 "X" +#define PRIoLEAST64 __PRI64 "o" +#define PRIuLEAST64 __PRI64 "u" +#define PRIxLEAST64 __PRI64 "x" +#define PRIXLEAST64 __PRI64 "X" +#define PRIoFAST64 __PRI64 "o" +#define PRIuFAST64 __PRI64 "u" +#define PRIxFAST64 __PRI64 "x" +#define PRIXFAST64 __PRI64 "X" +#define PRIoMAX __PRI64 "o" +#define PRIuMAX __PRI64 "u" +#define PRIxMAX __PRI64 "x" +#define PRIXMAX __PRI64 "X" +#define PRIoPTR __PRIPTR "o" +#define PRIuPTR __PRIPTR "u" +#define PRIxPTR __PRIPTR "x" +#define PRIXPTR __PRIPTR "X" #define SCNu32 "u" -#define SCNu64 "lu" -#define SCNuMAX "lu" +#define SCNu64 __PRI64 "u" +#define SCNuMAX __PRI64 "u" #define SCNx16 "hx" #define SCNx32 "x" -#define SCNx64 "lx" -#define SCNxMAX "lx" +#define SCNx64 __PRI64 "x" +#define SCNxMAX __PRI64 "x" #define SCNi8 "hhi" -#define SCNxPTR "lx" +#define SCNxPTR __PRIPTR "x" #define SCNi8 "hhi" -#define SCNi64 "li" +#define SCNi64 __PRI64 "i" #define SCNd32 "d" -#define SCNd64 "ld" +#define SCNd64 __PRI64 "d" #endif /* !__MLIBC_ABI_ONLY */ From 1e2014aa9e424004b455a0dc69f38fc866b78c73 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 00:53:31 +0200 Subject: [PATCH 35/45] options/posix: use SCNxPTR when scanning /proc/self/maps --- options/posix/generic/pthread-stubs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/posix/generic/pthread-stubs.cpp b/options/posix/generic/pthread-stubs.cpp index 7c60cc2900..f9eed3b366 100644 --- a/options/posix/generic/pthread-stubs.cpp +++ b/options/posix/generic/pthread-stubs.cpp @@ -277,7 +277,7 @@ namespace { auto sp = mlibc::get_sp(); while (fgets(line, 256, fp)) { uintptr_t from, to; - if(sscanf(line, "%lx-%lx", &from, &to) != 2) + if(sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) continue; if (sp < to && sp > from) { // We need to return the lowest byte of the stack. From 562fd1c9c3d5e95ed7659d93f31001cef1a6057e Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Mon, 21 Aug 2023 00:01:43 +0200 Subject: [PATCH 36/45] options/ansi: implement fenv for x86 Co-authored-by: no92 --- options/ansi/include/bits/ansi/fenv.h | 5 +- options/internal/x86/fenv.S | 168 ++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 options/internal/x86/fenv.S diff --git a/options/ansi/include/bits/ansi/fenv.h b/options/ansi/include/bits/ansi/fenv.h index 8935dd8030..677ddaa091 100644 --- a/options/ansi/include/bits/ansi/fenv.h +++ b/options/ansi/include/bits/ansi/fenv.h @@ -1,15 +1,16 @@ #ifndef MLIBC_FENV_H #define MLIBC_FENV_H -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__i386__) +#define FE_DENORMAL 2 #define FE_DIVBYZERO 4 #define FE_INEXACT 32 #define FE_INVALID 1 #define FE_OVERFLOW 8 #define FE_UNDERFLOW 16 -#define FE_ALL_EXCEPT 63 +#define FE_ALL_EXCEPT (FE_DENORMAL | FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) #define FE_TONEAREST 0 #define FE_DOWNWARD 0x400 diff --git a/options/internal/x86/fenv.S b/options/internal/x86/fenv.S new file mode 100644 index 0000000000..a46b5fa041 --- /dev/null +++ b/options/internal/x86/fenv.S @@ -0,0 +1,168 @@ +# The functions below are taken from musl. + +.hidden __hwcap + +.global feclearexcept +.type feclearexcept,@function +feclearexcept: + mov 4(%esp),%ecx + and $0x3f,%ecx + fnstsw %ax + # consider sse fenv as well if the cpu has XMM capability + call 1f +1: addl $__hwcap-1b,(%esp) + pop %edx + testl $0x02000000,(%edx) + jz 2f + # maintain exceptions in the sse mxcsr, clear x87 exceptions + test %eax,%ecx + jz 1f + fnclex +1: push %edx + stmxcsr (%esp) + pop %edx + and $0x3f,%eax + or %eax,%edx + test %edx,%ecx + jz 1f + not %ecx + and %ecx,%edx + push %edx + ldmxcsr (%esp) + pop %edx +1: xor %eax,%eax + ret + # only do the expensive x87 fenv load/store when needed +2: test %eax,%ecx + jz 1b + not %ecx + and %ecx,%eax + test $0x3f,%eax + jz 1f + fnclex + jmp 1b +1: sub $32,%esp + fnstenv (%esp) + mov %al,4(%esp) + fldenv (%esp) + add $32,%esp + xor %eax,%eax + ret + +.global feraiseexcept +.type feraiseexcept,@function +feraiseexcept: + mov 4(%esp),%eax + and $0x3f,%eax + sub $32,%esp + fnstenv (%esp) + or %al,4(%esp) + fldenv (%esp) + add $32,%esp + xor %eax,%eax + ret + +.global __fesetround +.hidden __fesetround +.type __fesetround,@function +__fesetround: + mov 4(%esp),%ecx + push %eax + xor %eax,%eax + fnstcw (%esp) + andb $0xf3,1(%esp) + or %ch,1(%esp) + fldcw (%esp) + # consider sse fenv as well if the cpu has XMM capability + call 1f +1: addl $__hwcap-1b,(%esp) + pop %edx + testl $0x02000000,(%edx) + jz 1f + stmxcsr (%esp) + shl $3,%ch + andb $0x9f,1(%esp) + or %ch,1(%esp) + ldmxcsr (%esp) +1: pop %ecx + ret + +.global fegetround +.type fegetround,@function +fegetround: + push %eax + fnstcw (%esp) + pop %eax + and $0xc00,%eax + ret + +.global fegetenv +.type fegetenv,@function +fegetenv: + mov 4(%esp),%ecx + xor %eax,%eax + fnstenv (%ecx) + # consider sse fenv as well if the cpu has XMM capability + call 1f +1: addl $__hwcap-1b,(%esp) + pop %edx + testl $0x02000000,(%edx) + jz 1f + push %eax + stmxcsr (%esp) + pop %edx + and $0x3f,%edx + or %edx,4(%ecx) +1: ret + +.global fesetenv +.type fesetenv,@function +fesetenv: + mov 4(%esp),%ecx + xor %eax,%eax + inc %ecx + jz 1f + fldenv -1(%ecx) + movl -1(%ecx),%ecx + jmp 2f +1: push %eax + push %eax + push %eax + push %eax + pushl $0xffff + push %eax + pushl $0x37f + fldenv (%esp) + add $28,%esp + # consider sse fenv as well if the cpu has XMM capability +2: call 1f +1: addl $__hwcap-1b,(%esp) + pop %edx + testl $0x02000000,(%edx) + jz 1f + # mxcsr := same rounding mode, cleared exceptions, default mask + and $0xc00,%ecx + shl $3,%ecx + or $0x1f80,%ecx + mov %ecx,4(%esp) + ldmxcsr 4(%esp) +1: ret + +.global fetestexcept +.type fetestexcept,@function +fetestexcept: + mov 4(%esp),%ecx + and $0x3f,%ecx + fnstsw %ax + # consider sse fenv as well if the cpu has XMM capability + call 1f +1: addl $__hwcap-1b,(%esp) + pop %edx + testl $0x02000000,(%edx) + jz 1f + stmxcsr 4(%esp) + or 4(%esp),%eax +1: and %ecx,%eax + ret + +.section .note.GNU-stack,"",%progbits From bf763e47afb1aad54050cc38ec415bdc3b26b663 Mon Sep 17 00:00:00 2001 From: no92 Date: Wed, 30 Aug 2023 03:28:27 +0200 Subject: [PATCH 37/45] tests/ansi: fix float compare function in fenv test --- tests/ansi/fenv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ansi/fenv.c b/tests/ansi/fenv.c index 701a20fef3..629a5cb65d 100644 --- a/tests/ansi/fenv.c +++ b/tests/ansi/fenv.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #define NO_OPTIMIZE(x) asm volatile("" :: "r,m" (x) : "memory") @@ -11,7 +12,7 @@ static void div_by_zero() { } static bool float_cmp(float a, float b) { - return fabs(a - b) < .000000000001; + return a == b || fabs(a - b) < (fabs(a) + fabs(b)) * FLT_EPSILON; } static void test_rounding(float expectation1, float expectation2) { From a100f1a2d8fbc368aa2a21de2c7b4874fa116ed5 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 21 Aug 2023 00:00:05 +0200 Subject: [PATCH 38/45] tests/posix: fix sigaltstack and pthread_attr tests for x86 --- tests/posix/pthread_attr.c | 2 ++ tests/posix/sigaltstack.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/tests/posix/pthread_attr.c b/tests/posix/pthread_attr.c index 33960b8a69..c901a908e8 100644 --- a/tests/posix/pthread_attr.c +++ b/tests/posix/pthread_attr.c @@ -90,6 +90,8 @@ static void *stackaddr_worker(void *arg) { void *sp; #if defined(__x86_64__) asm volatile ("mov %%rsp, %0" : "=r"(sp)); +#elif defined(__i386__) + asm volatile ("mov %%esp, %0" : "=r"(sp)); #elif defined(__aarch64__) asm volatile ("mov %0, sp" : "=r"(sp)); #elif defined (__riscv) diff --git a/tests/posix/sigaltstack.c b/tests/posix/sigaltstack.c index f3725a093e..bebcc30794 100644 --- a/tests/posix/sigaltstack.c +++ b/tests/posix/sigaltstack.c @@ -40,6 +40,9 @@ int main() { #if defined(__x86_64__) asm volatile ("mov $0, %rsp\n" "\t" "push $0"); +#elif defined(__i386__) + asm volatile ("mov $0, %esp\n" + "\t" "push $0"); #elif defined(__aarch64__) asm volatile ("mov sp, %0\n" "\t" "stp x0, x1, [sp, #-16]!" :: "r"((uint64_t)0)); From 4b8ede60c615ecb21a3f1910a7d7850be55c92ba Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sat, 26 Aug 2023 23:30:10 +0300 Subject: [PATCH 39/45] tests/ansi: fix strtol test on x86 --- tests/ansi/strtol.c | 60 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/tests/ansi/strtol.c b/tests/ansi/strtol.c index 37c0ed5515..823cb4a09f 100644 --- a/tests/ansi/strtol.c +++ b/tests/ansi/strtol.c @@ -57,52 +57,84 @@ int main () { DO_ERR_TEST("-999999999999999999999999999", LONG_MIN, ERANGE, strtol, 10); // strtol +#if defined(__i386__) + DO_TEST("-2147483648", LONG_MIN, -1, strtol, 10); + DO_TEST("2147483647", LONG_MAX, -1, strtol, 10); + DO_ERR_TEST("-2147483649", LONG_MIN, ERANGE, strtol, 10); + DO_ERR_TEST("2147483648", LONG_MAX, ERANGE, strtol, 10); +#else DO_TEST("-9223372036854775808", LONG_MIN, -1, strtol, 10); DO_TEST("9223372036854775807", LONG_MAX, -1, strtol, 10); DO_ERR_TEST("9223372036854775808", LONG_MAX, ERANGE, strtol, 10); DO_ERR_TEST("-9223372036854775809", LONG_MIN, ERANGE, strtol, 10); +#endif + // wcstol +#if defined(__i386__) + DO_TESTL(L"-2147483648", LONG_MIN, -1, wcstol, 10); + DO_TESTL(L"2147483647", LONG_MAX, -1, wcstol, 10); + DO_ERR_TESTL(L"2147483648", LONG_MAX, ERANGE, wcstol, 10); + DO_ERR_TESTL(L"-2147483649", LONG_MIN, ERANGE, wcstol, 10); +#else DO_TESTL(L"-9223372036854775808", LONG_MIN, -1, wcstol, 10); DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstol, 10); DO_ERR_TESTL(L"9223372036854775808", LONG_MAX, ERANGE, wcstol, 10); DO_ERR_TESTL(L"-9223372036854775809", LONG_MIN, ERANGE, wcstol, 10); +#endif // strtoll - DO_TEST("-9223372036854775808", LONG_MIN, -1, strtoll, 10); - DO_TEST("9223372036854775807", LONG_MAX, -1, strtoll, 10); + DO_TEST("-9223372036854775808", LLONG_MIN, -1, strtoll, 10); + DO_TEST("9223372036854775807", LLONG_MAX, -1, strtoll, 10); DO_ERR_TEST("9223372036854775808", LLONG_MAX, ERANGE, strtoll, 10); DO_ERR_TEST("-9223372036854775809", LLONG_MIN, ERANGE, strtoll, 10); // wcstoll - DO_TESTL(L"-9223372036854775808", LONG_MIN, -1, wcstoll, 10); - DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstoll, 10); + DO_TESTL(L"-9223372036854775808", LLONG_MIN, -1, wcstoll, 10); + DO_TESTL(L"9223372036854775807", LLONG_MAX, -1, wcstoll, 10); DO_ERR_TESTL(L"9223372036854775808", LLONG_MAX, ERANGE, wcstoll, 10); DO_ERR_TESTL(L"-9223372036854775809", LLONG_MIN, ERANGE, wcstoll, 10); // strtoul +#if defined(__i386__) + DO_TEST("-1", -(1UL), -1, strtoul, 10); + DO_TEST("2147483647", LONG_MAX, -1, strtoul, 10); + DO_TEST("4294967295", ULONG_MAX, -1, strtoul, 10); + DO_TEST("-4294967295", 1UL, -1, strtoul, 10); + DO_ERR_TEST("4294967296", ULONG_MAX, ERANGE, strtoul, 10); +#else DO_TEST("-1", -(1UL), -1, strtoul, 10); DO_TEST("9223372036854775807", LONG_MAX, -1, strtoul, 10); DO_TEST("18446744073709551615", ULONG_MAX, -1, strtoul, 10); DO_TEST("-18446744073709551615", 1UL, -1, strtoul, 10); DO_ERR_TEST("18446744073709551616", ULONG_MAX, ERANGE, strtoul, 10); +#endif + // wcstoul +#if defined(__i386__) + DO_TESTL(L"-1", -(1UL), -1, wcstoul, 10); + DO_TESTL(L"2147483647", LONG_MAX, -1, wcstoul, 10); + DO_TESTL(L"4294967295", ULONG_MAX, -1, wcstoul, 10); + DO_TESTL(L"-4294967295", 1UL, -1, wcstoul, 10); + DO_ERR_TESTL(L"4294967296", ULONG_MAX, ERANGE, wcstoul, 10); +#else DO_TESTL(L"-1", -(1UL), -1, wcstoul, 10); DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstoul, 10); DO_TESTL(L"18446744073709551615", ULONG_MAX, -1, wcstoul, 10); DO_TESTL(L"-18446744073709551615", 1UL, -1, wcstoul, 10); DO_ERR_TESTL(L"18446744073709551616", ULONG_MAX, ERANGE, wcstoul, 10); +#endif // strtoull - DO_TEST("-1", -(1UL), -1, strtoull, 10); - DO_TEST("9223372036854775807", LONG_MAX, -1, strtoull, 10); - DO_TEST("18446744073709551615", ULONG_MAX, -1, strtoull, 10); - DO_TEST("-18446744073709551615", 1UL, -1, strtoull, 10); - DO_ERR_TEST("18446744073709551616", ULONG_MAX, ERANGE, strtoull, 10); + DO_TEST("-1", -(1ULL), -1, strtoull, 10); + DO_TEST("9223372036854775807", LLONG_MAX, -1, strtoull, 10); + DO_TEST("18446744073709551615", ULLONG_MAX, -1, strtoull, 10); + DO_TEST("-18446744073709551615", 1ULL, -1, strtoull, 10); + DO_ERR_TEST("18446744073709551616", ULLONG_MAX, ERANGE, strtoull, 10); // wcstoull - DO_TESTL(L"-1", -(1UL), -1, wcstoull, 10); - DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstoull, 10); - DO_TESTL(L"18446744073709551615", ULONG_MAX, -1, wcstoull, 10); - DO_TESTL(L"-18446744073709551615", 1UL, -1, wcstoull, 10); - DO_ERR_TESTL(L"18446744073709551616", ULONG_MAX, ERANGE, wcstoull, 10); + DO_TESTL(L"-1", -(1ULL), -1, wcstoull, 10); + DO_TESTL(L"9223372036854775807", LLONG_MAX, -1, wcstoull, 10); + DO_TESTL(L"18446744073709551615", ULLONG_MAX, -1, wcstoull, 10); + DO_TESTL(L"-18446744073709551615", 1ULL, -1, wcstoull, 10); + DO_ERR_TESTL(L"18446744073709551616", ULLONG_MAX, ERANGE, wcstoull, 10); return 0; } From 7742f432120d946552511c4449139cea907969f9 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Mon, 28 Aug 2023 16:25:50 +0300 Subject: [PATCH 40/45] tests/ansi: guard 64-bit sscanf test on x86 --- tests/ansi/sscanf.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/ansi/sscanf.c b/tests/ansi/sscanf.c index 9767c67cdd..f3a881fceb 100644 --- a/tests/ansi/sscanf.c +++ b/tests/ansi/sscanf.c @@ -96,12 +96,21 @@ int main() { assert(!strcmp(strparm, "0")); } + { + char buf[] = "fffff100"; + unsigned long y = 0; + sscanf(buf, "%lx", &y); + assert(y == 0xfffff100); + } + +#if !defined(__i386__) { char buf[] = "fffffffff100"; unsigned long y = 0; sscanf(buf, "%lx", &y); assert(y == 0xfffffffff100); } +#endif { char buf[] = "410dc000"; From 486e6f4df71c1ba6a629dbad781bf35410232509 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 00:53:05 +0200 Subject: [PATCH 41/45] tests/posix: fix warnings about wrong format specifier for ssize_t --- tests/posix/getdelim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/posix/getdelim.c b/tests/posix/getdelim.c index 92318dc976..bc43ef6164 100644 --- a/tests/posix/getdelim.c +++ b/tests/posix/getdelim.c @@ -26,7 +26,7 @@ int main(void) { fp = fopen(TEST_FILE, "r"); assert(fp); while ((read = getline(&line, &len, fp)) != -1) { - printf("read line of length %zu, capacity %zu\n", read, len); + printf("read line of length %zd, capacity %zu\n", read, len); } assert(!ferror(fp)); free(line); @@ -45,7 +45,7 @@ int main(void) { fp = fopen(TEST_FILE, "r"); assert(fp); while ((read = getdelim(&line, &len, 'b', fp)) != -1) { - printf("read line of length %zu, capacity %zu\n", read, len); + printf("read line of length %zd, capacity %zu\n", read, len); assert((size_t)read == nchars + 1); } From af6d925cd19bcb3bdbf77119989df018bb544447 Mon Sep 17 00:00:00 2001 From: no92 Date: Thu, 31 Aug 2023 05:06:24 +0200 Subject: [PATCH 42/45] tests: fix implicit assumptions of 64-bit behavior --- tests/ansi/utf8.c | 9 ++++++++- tests/glibc/ffsl-ffsll.c | 5 +++++ tests/posix/wcwidth.c | 9 ++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/ansi/utf8.c b/tests/ansi/utf8.c index 35dd867745..18b0d5a102 100644 --- a/tests/ansi/utf8.c +++ b/tests/ansi/utf8.c @@ -1,10 +1,17 @@ #include +#include #include #include #include #include #include +#if UINTPTR_MAX == UINT64_MAX +#define WCHAR_SPEC "" +#else +#define WCHAR_SPEC "l" +#endif + #define EXPECT(func) ({ \ if(res != expected_ret) { \ printf(#func " decoded %d bytes (expected %d bytes), at %s:%d\n", \ @@ -13,7 +20,7 @@ abort(); \ } \ if(wc != expected) { \ - printf(#func " output cp %x (expected cp %x), at %s:%d\n", wc, \ + printf(#func " output cp %" WCHAR_SPEC "x (expected cp %" WCHAR_SPEC "x), at %s:%d\n", wc, \ expected, __FILE__, line); \ fflush(stdout); \ abort(); \ diff --git a/tests/glibc/ffsl-ffsll.c b/tests/glibc/ffsl-ffsll.c index 543eb93ad2..ed70ad687f 100644 --- a/tests/glibc/ffsl-ffsll.c +++ b/tests/glibc/ffsl-ffsll.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -6,8 +7,10 @@ int main(void){ // ffsl assert(ffsl(0x8000) == 16); assert(ffsl(0) == 0); +#if UINTPTR_MAX == UINT64_MAX assert(ffsl(LLONG_MAX - 1) == 2); assert(ffsl(LLONG_MAX) == 1); +#endif assert(ffsl(LONG_MIN) == (long)(sizeof(long) * CHAR_BIT)); assert(ffsl(LONG_MIN + 1) == 1); @@ -18,8 +21,10 @@ int main(void){ // ffsll assert(ffsll(0x8000) == 16); assert(ffsll(0) == 0); +#if UINTPTR_MAX == UINT64_MAX assert(ffsll(LLONG_MAX - 1) == 2); assert(ffsll(LLONG_MAX) == 1); +#endif assert(ffsll(LLONG_MIN) == (long long)(sizeof(long long) * CHAR_BIT)); assert(ffsll(LLONG_MIN + 1) == 1); diff --git a/tests/posix/wcwidth.c b/tests/posix/wcwidth.c index a433d3e2d9..2e6fc8cd13 100644 --- a/tests/posix/wcwidth.c +++ b/tests/posix/wcwidth.c @@ -1,10 +1,17 @@ #include #include +#include #include #include #include #include +#if UINTPTR_MAX == UINT64_MAX +#define WCHAR_SPEC "" +#else +#define WCHAR_SPEC "l" +#endif + /* * The code in this test is taken from https://github.com/termux/wcwidth/, * under the following license: @@ -26,7 +33,7 @@ void assertWidthIs(int expected_width, wchar_t c) { tests_run++; int actual_width = wcwidth(c); if (actual_width != expected_width) { - fprintf(stderr, "ERROR: wcwidth(U+%04x, '%lc') returned %d, expected %d\n", c, c, actual_width, expected_width); + fprintf(stderr, "ERROR: wcwidth(U+%04" WCHAR_SPEC "x, '%lc') returned %d, expected %d\n", c, (wint_t) c, actual_width, expected_width); test_failures++; } } From 9f3cd7113103e04a8b2d67d16153f16bbbdec93c Mon Sep 17 00:00:00 2001 From: no92 Date: Tue, 22 Aug 2023 02:49:53 +0200 Subject: [PATCH 43/45] tests: set shorter timeout --- tests/meson.build | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/meson.build b/tests/meson.build index feebfaf146..daa11c8467 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,3 +1,5 @@ +timeout_sec = 10 + all_test_cases = [ 'ansi/alloc', 'ansi/sscanf', @@ -216,10 +218,11 @@ foreach test_name : all_test_cases args: [ meson.source_root() + '/tests/' + test_name + '.py', exec - ] + ], + timeout: timeout_sec, ) else - test(test_short_name, exec, suite: test_subdir, should_fail: should_fail) + test(test_short_name, exec, suite: test_subdir, should_fail: should_fail, timeout: timeout_sec) endif if build_tests_host_libc and not host_libc_excluded_test_cases.contains(test_name) @@ -242,6 +245,6 @@ foreach test_name : all_test_cases link_args: ['-lresolv', '-ldl', '-pthread', '-lm', '-lrt'], native: true, ) - test(test_short_name, exec, suite: ['host-libc', test_subdir], should_fail: should_fail) + test(test_short_name, exec, suite: ['host-libc', test_subdir], should_fail: should_fail, timeout: timeout_sec) endif endforeach From 2c71beeaa37aa17e04610ebef30d1cce3ce19593 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 21 Aug 2023 20:34:21 +0200 Subject: [PATCH 44/45] ci: use `meson setup` --- ci/bootstrap.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci/bootstrap.yml b/ci/bootstrap.yml index 88db3b8b0b..0a1f94f29e 100644 --- a/ci/bootstrap.yml +++ b/ci/bootstrap.yml @@ -24,6 +24,7 @@ packages: configure: - args: - 'meson' + - 'setup' - '--prefix=/usr' - '--libdir=lib' - '--buildtype=debugoptimized' @@ -54,6 +55,7 @@ packages: configure: - args: - 'meson' + - 'setup' - '--prefix=/usr' - '--libdir=lib' - '--buildtype=debugoptimized' @@ -80,6 +82,7 @@ packages: configure: - args: - 'meson' + - 'setup' - '--prefix=/usr' - '--libdir=lib' - '--buildtype=debugoptimized' @@ -107,6 +110,7 @@ packages: configure: - args: - 'meson' + - 'setup' - '--prefix=/usr' - '--libdir=lib' - '--buildtype=debugoptimized' @@ -138,6 +142,7 @@ packages: configure: - args: - 'meson' + - 'setup' - '--prefix=/usr' - '--libdir=lib' - '--buildtype=debugoptimized' From a30b3c1db0152372cb787aaa435072313df674e9 Mon Sep 17 00:00:00 2001 From: no92 Date: Mon, 21 Aug 2023 20:34:40 +0200 Subject: [PATCH 45/45] ci: correctly copy linux-headers Adding the `/` at the end allows for symlinking the directory and avoiding a cp error. --- ci/bootstrap.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/bootstrap.yml b/ci/bootstrap.yml index 0a1f94f29e..f166bcc44c 100644 --- a/ci/bootstrap.yml +++ b/ci/bootstrap.yml @@ -166,7 +166,7 @@ packages: from_source: linux configure: # custom build system requires in tree-ish builds - - args: ['cp', '-Tr', '@THIS_SOURCE_DIR@', '.'] + - args: ['cp', '-Tr', '@THIS_SOURCE_DIR@/', '.'] build: - args: | LINUX_ARCH="@OPTION:arch@"