Improve signal handling and math

- Polyfill ucontext_t on FreeBSD/OpenBSD/NetBSD
- Add tests confirming signals can edit CPU state
- Work towards supporting ZIP filesystem on bare metal
- Add more tinymath unit tests for POSIX conformance
- Add X87 and SSE status flags to crash report
- Fix some bugs in blinkenlights
- Fix llvm build breakage
This commit is contained in:
Justine Tunney 2021-02-25 18:30:17 -08:00
parent cdc54ea1fd
commit 40291c9db3
109 changed files with 2316 additions and 520 deletions

View file

@ -245,9 +245,9 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
void _init_onntconsoleevent(void);
void _init_wincrash(void);
#ifndef __SIGACTION
#define __SIGACTION(FN, SIG, ...) \
({ \
#ifndef __SIGACTION_YOINK
#define __SIGACTION_YOINK(SIG) \
do { \
if (SupportsWindows()) { \
if (__builtin_constant_p(SIG)) { \
switch (SIG) { \
@ -272,14 +272,23 @@ void _init_wincrash(void);
YOINK(_init_wincrash); \
} \
} \
(FN)(SIG, __VA_ARGS__); \
})
} while (0)
#endif
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
#define sigaction(SIG, ACT, OLD) __SIGACTION(sigaction, SIG, ACT, OLD)
#define signal(SIG, HAND) __SIGACTION(signal, SIG, HAND)
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
#define sigaction(SIG, ACT, OLD) \
({ \
__SIGACTION_YOINK(SIG); \
sigaction(SIG, (ACT), OLD); \
})
#define signal(SIG, HAND) \
({ \
__SIGACTION_YOINK(SIG); \
signal(SIG, HAND); \
})
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
#endif /* GNU && !ANSI */
COSMOPOLITAN_C_END_

View file

@ -40,8 +40,10 @@ int close(int fd) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = weaken(__zipos_close)(fd);
} else {
if (!IsWindows()) {
if (!IsWindows() && !IsMetal()) {
rc = sys_close(fd);
} else if (IsMetal()) {
rc = 0;
} else {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
rc = weaken(sys_close_epoll_nt)(fd);

View file

@ -22,7 +22,7 @@
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
int fstat_metal(int fd, struct stat *st) {
int sys_fstat_metal(int fd, struct stat *st) {
if (fd < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
memset(st, 0, sizeof(*st));

View file

@ -34,7 +34,7 @@ int fstat(int fd, struct stat *st) {
} else if (!IsWindows() && !IsMetal()) {
return sys_fstat(fd, st);
} else if (IsMetal()) {
return fstat_metal(fd, st);
return sys_fstat_metal(fd, st);
} else {
if (!__isfdkind(fd, kFdFile)) return ebadf();
return sys_fstat_nt(g_fds.p[fd].handle, st);

View file

@ -35,7 +35,7 @@
*/
int gettimeofday(struct timeval *tv, struct timezone *tz) {
axdx_t ad;
if (!IsWindows()) {
if (!IsWindows() && !IsMetal()) {
ad = sys_gettimeofday(tv, tz, NULL);
assert(ad.ax != -1);
if (SupportsXnu() && ad.ax && tv) {
@ -43,6 +43,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
tv->tv_usec = ad.dx;
}
return 0;
} else if (IsMetal()) {
return enosys();
} else {
return sys_gettimeofday_nt(tv, tz);
}

View file

@ -206,17 +206,15 @@ void sys_exit(int) hidden;
*/
void __onfork(void) hidden;
bool32 __sigenter(i32, struct siginfo *, struct ucontext *) hidden;
i32 __fixupnewfd(i32, i32) hidden;
u32 __prot2nt(i32, i32) privileged;
void __restore_rt() hidden;
void __sigenter_xnu(void *, i32, i32, void *, void *) hidden wontreturn;
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
void __stat2linux(void *) hidden;
void __restore_rt_netbsd(void) hidden;
void __xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *,
const struct __darwin_ucontext *) hidden wontreturn;
void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
struct __darwin_ucontext *) hidden;
int gethostname_linux(char *, size_t) hidden;
int gethostname_bsd(char *, size_t) hidden;
int gethostname_nt(char *, size_t) hidden;
@ -288,19 +286,24 @@ int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
unsigned __wincrash_nt(struct NtExceptionPointers *);
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_nt(struct Fd *, const struct iovec *, int) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » metal
*/
int fstat_metal(int, struct stat *);
int sys_fstat_metal(int, struct stat *);
int sys_openat_metal(int, const char *, int, unsigned);
ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_metal(struct Fd *, const struct iovec *, int) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » drivers
*/
ssize_t readv_serial(struct Fd *, const struct iovec *, int) hidden;
ssize_t writev_serial(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_readv_serial(struct Fd *, const struct iovec *, int) hidden;
ssize_t sys_writev_serial(struct Fd *, const struct iovec *, int) hidden;
#undef sigset
#undef i32

View file

@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MetalFile {
char *base;
size_t size;
size_t pos;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_ */

40
libc/calls/openat-metal.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) {
int fd;
struct MetalFile *state;
if (strcmp(file, "ape.com")) return enoent();
if (!weaken(calloc)) return enomem();
if ((fd = __reservefd()) == -1) return -1;
state = weaken(calloc)(1, sizeof(struct MetalFile));
state->base = (char *)_base;
state->size = _end - _base;
g_fds.p[fd].kind = kFdFile;
g_fds.p[fd].flags = flags;
g_fds.p[fd].handle = (intptr_t)state;
return fd;
}

View file

@ -51,8 +51,10 @@ int openat(int dirfd, const char *file, int flags, ...) {
if (__vforked) return einval();
if (dirfd != AT_FDCWD) return einval();
return weaken(__zipos_open)(&zipname, flags, mode);
} else if (!IsWindows()) {
} else if (!IsWindows() && !IsMetal()) {
return sys_openat(dirfd, file, flags, mode);
} else if (IsMetal()) {
return sys_openat_metal(dirfd, file, flags, mode);
} else {
return sys_open_nt(dirfd, file, flags, mode);
}

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -17,32 +17,27 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/macros.h"
.source __FILE__
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
// BSD signal handler.
//
// This is needed because (1) a signal is allowed to trigger at
// just about any time, and leaf functions (e.g. memcpy) aren't
// required to leave Cosmopolitan's image base register alone.
//
// @param %edi is the signal number
// @param %rsi will be passed for sigactions
// @param %rdx will be passed for sigactions
// @return true if handler was invoked
__sigenter:
push %rbp
mov %rsp,%rbp
.profilable
and $NSIG-1,%edi
mov __sighandrvas(,%rdi,4),%eax
cmp $kSigactionMinRva,%eax
jl 2f
lea _base(%rax),%eax
call *%rax
mov $1,%eax
1: leave
ret
2: xor %eax,%eax
jmp 1b
.endfn __sigenter,globl,hidden
ssize_t sys_readv_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
int i;
size_t got, toto;
struct MetalFile *file;
switch (fd->kind) {
case kFdSerial:
return sys_readv_serial(fd, iov, iovlen);
case kFdFile:
file = (struct MetalFile *)fd->handle;
for (toto = i = 0; i < iovlen && file->pos < file->size; ++i) {
got = MIN(iov[i].iov_len, file->size - file->pos);
memcpy(iov[i].iov_base, file->base, got);
toto += got;
}
return toto;
default:
return ebadf();
}
}

35
libc/calls/readv-nt.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
textwindows ssize_t sys_readv_nt(struct Fd *fd, const struct iovec *iov,
int iovlen) {
switch (fd->kind) {
case kFdFile:
case kFdConsole:
return sys_read_nt(fd, iov, iovlen, -1);
case kFdSocket:
return weaken(sys_recvfrom_nt)(fd, iov, iovlen, 0, NULL, 0);
default:
return ebadf();
}
}

View file

@ -34,7 +34,7 @@ static int GetFirstIov(struct iovec *iov, int iovlen) {
return -1;
}
ssize_t readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
ssize_t sys_readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
size_t i, j, got = 0;
if ((i = GetFirstIov(iov, iovlen)) != -1) {
while (!IsDataAvailable(fd)) asm("pause");

View file

@ -36,16 +36,13 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
return readv_serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) {
} else if (!IsWindows() && !IsMetal()) {
return sys_readv(fd, iov, iovlen);
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
return sys_read_nt(&g_fds.p[fd], iov, iovlen, -1);
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdSocket)) {
return weaken(sys_recvfrom_nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
} else {
} else if (fd >= g_fds.n) {
return ebadf();
} else if (IsMetal()) {
return sys_readv_metal(g_fds.p + fd, iov, iovlen);
} else {
return sys_readv_nt(g_fds.p + fd, iov, iovlen);
}
}

View file

@ -39,16 +39,6 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
union metasigaction {
struct sigaction cosmo;
struct sigaction_linux linux;
struct sigaction_freebsd freebsd;
struct sigaction_openbsd openbsd;
struct sigaction_netbsd netbsd;
struct sigaction_xnu_in xnu_in;
struct sigaction_xnu_out xnu_out;
};
#ifndef SWITCHEROO
#define SWITCHEROO(S1, S2, A, B, C, D) \
do { \
@ -66,6 +56,20 @@ union metasigaction {
} while (0);
#endif
union metasigaction {
struct sigaction cosmo;
struct sigaction_linux linux;
struct sigaction_freebsd freebsd;
struct sigaction_openbsd openbsd;
struct sigaction_netbsd netbsd;
struct sigaction_xnu_in xnu_in;
struct sigaction_xnu_out xnu_out;
};
void __sigenter_netbsd(int, void *, void *);
void __sigenter_freebsd(int, void *, void *);
void __sigenter_openbsd(int, void *, void *);
static void sigaction_cosmo2native(union metasigaction *sa) {
if (!sa) return;
switch (__hostos) {
@ -165,17 +169,21 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
memcpy(&copy, act, sizeof(copy));
ap = &copy;
if (IsXnu()) {
ap->sa_restorer = (void *)&__xnutrampoline;
ap->sa_handler = (void *)&__xnutrampoline;
ap->sa_restorer = (void *)&__sigenter_xnu;
ap->sa_handler = (void *)&__sigenter_xnu;
} else if (IsLinux()) {
if (!(ap->sa_flags & SA_RESTORER)) {
ap->sa_flags |= SA_RESTORER;
ap->sa_restorer = &__restore_rt;
}
} else if (IsNetbsd()) {
ap->sa_sigaction = act->sa_sigaction;
} else if (rva >= kSigactionMinRva) {
ap->sa_sigaction = (sigaction_f)__sigenter;
ap->sa_sigaction = (sigaction_f)__sigenter_netbsd;
} else if (IsFreebsd()) {
ap->sa_sigaction = (sigaction_f)__sigenter_freebsd;
} else if (IsOpenbsd()) {
ap->sa_sigaction = (sigaction_f)__sigenter_openbsd;
} else {
return enosys();
}
sigaction_cosmo2native((union metasigaction *)ap);
} else {

View file

@ -0,0 +1,196 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/macros.h"
#include "libc/str/str.h"
union sigval_freebsd {
int32_t sival_int;
void *sival_ptr;
int32_t sigval_int;
void *sigval_ptr;
};
struct siginfo_freebsd {
int32_t si_signo;
int32_t si_errno;
int32_t si_code;
int32_t si_pid;
uint32_t si_uid;
int32_t si_status;
void *si_addr;
union sigval_freebsd si_value;
union {
struct {
int _trapno;
} _fault;
struct {
int _timerid;
int _overrun;
} _timer;
struct {
int _mqd;
} _mesgq;
struct {
long _band;
} _poll;
struct {
long __spare1__;
int __spare2__[7];
} __spare__;
} _reason;
};
struct stack_freebsd {
void *ss_sp;
uint64_t ss_size;
int32_t ss_flags;
};
struct mcontext_freebsd {
int64_t mc_onstack;
int64_t mc_rdi;
int64_t mc_rsi;
int64_t mc_rdx;
int64_t mc_rcx;
int64_t mc_r8;
int64_t mc_r9;
int64_t mc_rax;
int64_t mc_rbx;
int64_t mc_rbp;
int64_t mc_r10;
int64_t mc_r11;
int64_t mc_r12;
int64_t mc_r13;
int64_t mc_r14;
int64_t mc_r15;
uint32_t mc_trapno;
uint16_t mc_fs;
uint16_t mc_gs;
int64_t mc_addr;
uint32_t mc_flags;
uint16_t mc_es;
uint16_t mc_ds;
int64_t mc_err;
int64_t mc_rip;
int64_t mc_cs;
int64_t mc_rflags;
int64_t mc_rsp;
int64_t mc_ss;
int64_t mc_len;
int64_t mc_fpformat;
int64_t mc_ownedfp;
int64_t mc_fpstate[64];
int64_t mc_fsbase;
int64_t mc_gsbase;
int64_t mc_xfpustate;
int64_t mc_xfpustate_len;
long mc_spare[4];
};
struct ucontext_freebsd {
struct sigset_freebsd uc_sigmask;
struct mcontext_freebsd uc_mcontext;
struct ucontext_freebsd *uc_link;
struct stack_freebsd uc_stack;
int32_t uc_flags;
int32_t __spare__[4];
};
hidden void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
struct ucontext_freebsd *ctx) {
int rva;
ucontext_t uc;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
if (ctx) {
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
uc.uc_flags = ctx->uc_flags;
memcpy(&uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
uc.uc_mcontext.rdi = ctx->uc_mcontext.mc_rdi;
uc.uc_mcontext.rsi = ctx->uc_mcontext.mc_rsi;
uc.uc_mcontext.rdx = ctx->uc_mcontext.mc_rdx;
uc.uc_mcontext.rcx = ctx->uc_mcontext.mc_rcx;
uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
uc.uc_mcontext.rax = ctx->uc_mcontext.mc_rax;
uc.uc_mcontext.rbx = ctx->uc_mcontext.mc_rbx;
uc.uc_mcontext.rbp = ctx->uc_mcontext.mc_rbp;
uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10;
uc.uc_mcontext.r11 = ctx->uc_mcontext.mc_r11;
uc.uc_mcontext.r12 = ctx->uc_mcontext.mc_r12;
uc.uc_mcontext.r13 = ctx->uc_mcontext.mc_r13;
uc.uc_mcontext.r14 = ctx->uc_mcontext.mc_r14;
uc.uc_mcontext.r15 = ctx->uc_mcontext.mc_r15;
uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
uc.uc_mcontext.fs = ctx->uc_mcontext.mc_fs;
uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
uc.uc_mcontext.eflags = ctx->uc_mcontext.mc_flags;
uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
uc.uc_mcontext.rip = ctx->uc_mcontext.mc_rip;
uc.uc_mcontext.rsp = ctx->uc_mcontext.mc_rsp;
}
((sigaction_f)(_base + rva))(sig, (void *)si, &uc);
if (ctx) {
ctx->uc_stack.ss_sp = uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = uc.uc_stack.ss_flags;
ctx->uc_flags = uc.uc_flags;
memcpy(&ctx->uc_sigmask, &uc.uc_sigmask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
ctx->uc_mcontext.mc_rdi = uc.uc_mcontext.rdi;
ctx->uc_mcontext.mc_rsi = uc.uc_mcontext.rsi;
ctx->uc_mcontext.mc_rdx = uc.uc_mcontext.rdx;
ctx->uc_mcontext.mc_rcx = uc.uc_mcontext.rcx;
ctx->uc_mcontext.mc_r8 = uc.uc_mcontext.r8;
ctx->uc_mcontext.mc_r9 = uc.uc_mcontext.r9;
ctx->uc_mcontext.mc_rax = uc.uc_mcontext.rax;
ctx->uc_mcontext.mc_rbx = uc.uc_mcontext.rbx;
ctx->uc_mcontext.mc_rbp = uc.uc_mcontext.rbp;
ctx->uc_mcontext.mc_r10 = uc.uc_mcontext.r10;
ctx->uc_mcontext.mc_r11 = uc.uc_mcontext.r11;
ctx->uc_mcontext.mc_r12 = uc.uc_mcontext.r12;
ctx->uc_mcontext.mc_r13 = uc.uc_mcontext.r13;
ctx->uc_mcontext.mc_r14 = uc.uc_mcontext.r14;
ctx->uc_mcontext.mc_r15 = uc.uc_mcontext.r15;
ctx->uc_mcontext.mc_trapno = uc.uc_mcontext.trapno;
ctx->uc_mcontext.mc_fs = uc.uc_mcontext.fs;
ctx->uc_mcontext.mc_gs = uc.uc_mcontext.gs;
ctx->uc_mcontext.mc_flags = uc.uc_mcontext.eflags;
ctx->uc_mcontext.mc_err = uc.uc_mcontext.err;
ctx->uc_mcontext.mc_rip = uc.uc_mcontext.rip;
ctx->uc_mcontext.mc_rsp = uc.uc_mcontext.rsp;
}
}
/*
* When the FreeBSD kernel invokes this signal handler it pushes a
* trampoline on the stack which does two things: 1) it calls this
* function, and 2) calls sys_sigreturn() once this returns.
*/
}

View file

@ -0,0 +1,204 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/macros.h"
#include "libc/str/str.h"
#define RDI 0
#define RSI 1
#define RDX 2
#define R10 6
#define R8 4
#define R9 5
#define RCX 3
#define R11 7
#define R12 8
#define R13 9
#define R14 10
#define R15 11
#define RBP 12
#define RBX 13
#define RAX 14
#define GS 15
#define FS 16
#define ES 17
#define DS 18
#define TRAP 19
#define ERR 20
#define RIP 21
#define CS 22
#define RFLAGS 23
#define RSP 24
#define SS 25
union sigval_netbsd {
int32_t sival_int;
void *sival_ptr;
};
struct siginfo_netbsd {
int32_t _signo;
int32_t _code;
int32_t _errno;
int32_t _pad;
union {
struct {
int32_t _pid;
uint32_t _uid;
union sigval_netbsd _value;
} _rt;
struct {
int32_t _pid;
uint32_t _uid;
int32_t _status;
int64_t _utime;
int64_t _stime;
} _child;
struct {
void *_addr;
int32_t _trap;
int32_t _trap2;
int32_t _trap3;
} _fault;
struct {
int64_t _band;
int32_t _fd;
} _poll;
struct {
int32_t _sysnum;
int32_t _retval[2];
int32_t _error;
uint64_t _args[8];
} _syscall;
struct {
int32_t _pe_report_event;
union {
int32_t _pe_other_pid;
int32_t _pe_lwp;
} _option;
} _ptrace_state;
} _reason;
};
struct sigset_netbsd {
uint32_t __bits[4];
};
struct stack_netbsd {
void *ss_sp;
size_t ss_size;
int32_t ss_flags;
};
struct mcontext_netbsd {
int64_t __gregs[26];
int64_t _mc_tlsbase;
struct FpuState __fpregs;
};
struct ucontext_netbsd {
uint32_t uc_flags;
struct ucontext_netbsd *uc_link;
struct sigset_netbsd uc_sigmask;
struct stack_netbsd uc_stack;
struct mcontext_netbsd uc_mcontext;
};
hidden void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
struct ucontext_netbsd *ctx) {
int rva;
ucontext_t uc;
struct siginfo si2;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
memset(&si2, 0, sizeof(si2));
if (si) {
si2.si_signo = si->_signo;
si2.si_code = si->_code;
si2.si_errno = si->_errno;
}
if (ctx) {
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_flags = ctx->uc_flags;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
memcpy(&uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
uc.uc_mcontext.rdi = ctx->uc_mcontext.__gregs[RDI];
uc.uc_mcontext.rsi = ctx->uc_mcontext.__gregs[RSI];
uc.uc_mcontext.rdx = ctx->uc_mcontext.__gregs[RDX];
uc.uc_mcontext.rcx = ctx->uc_mcontext.__gregs[RCX];
uc.uc_mcontext.r8 = ctx->uc_mcontext.__gregs[R8];
uc.uc_mcontext.r9 = ctx->uc_mcontext.__gregs[R9];
uc.uc_mcontext.rax = ctx->uc_mcontext.__gregs[RAX];
uc.uc_mcontext.rbx = ctx->uc_mcontext.__gregs[RBX];
uc.uc_mcontext.rbp = ctx->uc_mcontext.__gregs[RBP];
uc.uc_mcontext.r10 = ctx->uc_mcontext.__gregs[R10];
uc.uc_mcontext.r11 = ctx->uc_mcontext.__gregs[R11];
uc.uc_mcontext.r12 = ctx->uc_mcontext.__gregs[R12];
uc.uc_mcontext.r13 = ctx->uc_mcontext.__gregs[R13];
uc.uc_mcontext.r14 = ctx->uc_mcontext.__gregs[R14];
uc.uc_mcontext.r15 = ctx->uc_mcontext.__gregs[R15];
uc.uc_mcontext.trapno = ctx->uc_mcontext.__gregs[TRAP];
uc.uc_mcontext.fs = ctx->uc_mcontext.__gregs[FS];
uc.uc_mcontext.gs = ctx->uc_mcontext.__gregs[GS];
uc.uc_mcontext.err = ctx->uc_mcontext.__gregs[ERR];
uc.uc_mcontext.rip = ctx->uc_mcontext.__gregs[RIP];
uc.uc_mcontext.rsp = ctx->uc_mcontext.__gregs[RSP];
*uc.uc_mcontext.fpregs = ctx->uc_mcontext.__fpregs;
}
((sigaction_f)(_base + rva))(sig, &si2, &uc);
if (ctx) {
ctx->uc_mcontext.__gregs[RDI] = uc.uc_mcontext.rdi;
ctx->uc_mcontext.__gregs[RSI] = uc.uc_mcontext.rsi;
ctx->uc_mcontext.__gregs[RDX] = uc.uc_mcontext.rdx;
ctx->uc_mcontext.__gregs[RCX] = uc.uc_mcontext.rcx;
ctx->uc_mcontext.__gregs[R8] = uc.uc_mcontext.r8;
ctx->uc_mcontext.__gregs[R9] = uc.uc_mcontext.r9;
ctx->uc_mcontext.__gregs[RAX] = uc.uc_mcontext.rax;
ctx->uc_mcontext.__gregs[RBX] = uc.uc_mcontext.rbx;
ctx->uc_mcontext.__gregs[RBP] = uc.uc_mcontext.rbp;
ctx->uc_mcontext.__gregs[R10] = uc.uc_mcontext.r10;
ctx->uc_mcontext.__gregs[R11] = uc.uc_mcontext.r11;
ctx->uc_mcontext.__gregs[R12] = uc.uc_mcontext.r12;
ctx->uc_mcontext.__gregs[R13] = uc.uc_mcontext.r13;
ctx->uc_mcontext.__gregs[R14] = uc.uc_mcontext.r14;
ctx->uc_mcontext.__gregs[R15] = uc.uc_mcontext.r15;
ctx->uc_mcontext.__gregs[TRAP] = uc.uc_mcontext.trapno;
ctx->uc_mcontext.__gregs[FS] = uc.uc_mcontext.fs;
ctx->uc_mcontext.__gregs[GS] = uc.uc_mcontext.gs;
ctx->uc_mcontext.__gregs[ERR] = uc.uc_mcontext.err;
ctx->uc_mcontext.__gregs[RIP] = uc.uc_mcontext.rip;
ctx->uc_mcontext.__gregs[RSP] = uc.uc_mcontext.rsp;
ctx->uc_mcontext.__fpregs = *uc.uc_mcontext.fpregs;
}
}
/*
* When the NetBSD kernel invokes this signal handler it pushes a
* trampoline on the stack which does two things: 1) it calls this
* function, and 2) calls sys_sigreturn() once this returns.
*/
}

View file

@ -0,0 +1,169 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/macros.h"
#include "libc/str/str.h"
union sigval_openbsd {
int32_t sival_int;
void *sival_ptr;
};
struct siginfo_openbsd {
int32_t si_signo;
int32_t si_code;
int32_t si_errno;
union {
int _pad[29];
struct {
int32_t _pid;
union {
struct {
uint32_t _uid;
union sigval_openbsd _value;
} _kill;
struct {
int64_t _utime;
int64_t _stime;
int32_t _status;
} _cld;
} _pdata;
} _proc;
struct {
void *_addr;
int32_t _trapno;
} _fault;
} _data;
};
struct ucontext_openbsd {
int64_t sc_rdi;
int64_t sc_rsi;
int64_t sc_rdx;
int64_t sc_rcx;
int64_t sc_r8;
int64_t sc_r9;
int64_t sc_r10;
int64_t sc_r11;
int64_t sc_r12;
int64_t sc_r13;
int64_t sc_r14;
int64_t sc_r15;
int64_t sc_rbp;
int64_t sc_rbx;
int64_t sc_rax;
int64_t sc_gs;
int64_t sc_fs;
int64_t sc_es;
int64_t sc_ds;
int64_t sc_trapno;
int64_t sc_err;
int64_t sc_rip;
int64_t sc_cs;
int64_t sc_rflags;
int64_t sc_rsp;
int64_t sc_ss;
struct FpuState *sc_fpstate;
int32_t __sc_unused;
int32_t sc_mask;
int64_t sc_cookie;
};
hidden void __sigenter_openbsd(int sig, struct siginfo_openbsd *si,
struct ucontext_openbsd *ctx) {
int rva;
ucontext_t uc;
struct siginfo si2;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&uc, 0, sizeof(uc));
memset(&si2, 0, sizeof(si2));
if (si) {
si2.si_signo = si->si_signo;
si2.si_code = si->si_code;
si2.si_errno = si->si_errno;
}
if (ctx) {
uc.uc_mcontext.fpregs = &uc.__fpustate;
memcpy(&uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->sc_mask)));
uc.uc_mcontext.rdi = ctx->sc_rdi;
uc.uc_mcontext.rsi = ctx->sc_rsi;
uc.uc_mcontext.rdx = ctx->sc_rdx;
uc.uc_mcontext.rcx = ctx->sc_rcx;
uc.uc_mcontext.r8 = ctx->sc_r8;
uc.uc_mcontext.r9 = ctx->sc_r9;
uc.uc_mcontext.rax = ctx->sc_rax;
uc.uc_mcontext.rbx = ctx->sc_rbx;
uc.uc_mcontext.rbp = ctx->sc_rbp;
uc.uc_mcontext.r10 = ctx->sc_r10;
uc.uc_mcontext.r11 = ctx->sc_r11;
uc.uc_mcontext.r12 = ctx->sc_r12;
uc.uc_mcontext.r13 = ctx->sc_r13;
uc.uc_mcontext.r14 = ctx->sc_r14;
uc.uc_mcontext.r15 = ctx->sc_r15;
uc.uc_mcontext.trapno = ctx->sc_trapno;
uc.uc_mcontext.fs = ctx->sc_fs;
uc.uc_mcontext.gs = ctx->sc_gs;
uc.uc_mcontext.err = ctx->sc_err;
uc.uc_mcontext.rip = ctx->sc_rip;
uc.uc_mcontext.rsp = ctx->sc_rsp;
if (ctx->sc_fpstate) {
*uc.uc_mcontext.fpregs = *ctx->sc_fpstate;
}
}
((sigaction_f)(_base + rva))(sig, &si2, &uc);
if (ctx) {
ctx->sc_rdi = uc.uc_mcontext.rdi;
ctx->sc_rsi = uc.uc_mcontext.rsi;
ctx->sc_rdx = uc.uc_mcontext.rdx;
ctx->sc_rcx = uc.uc_mcontext.rcx;
ctx->sc_r8 = uc.uc_mcontext.r8;
ctx->sc_r9 = uc.uc_mcontext.r9;
ctx->sc_rax = uc.uc_mcontext.rax;
ctx->sc_rbx = uc.uc_mcontext.rbx;
ctx->sc_rbp = uc.uc_mcontext.rbp;
ctx->sc_r10 = uc.uc_mcontext.r10;
ctx->sc_r11 = uc.uc_mcontext.r11;
ctx->sc_r12 = uc.uc_mcontext.r12;
ctx->sc_r13 = uc.uc_mcontext.r13;
ctx->sc_r14 = uc.uc_mcontext.r14;
ctx->sc_r15 = uc.uc_mcontext.r15;
ctx->sc_trapno = uc.uc_mcontext.trapno;
ctx->sc_fs = uc.uc_mcontext.fs;
ctx->sc_gs = uc.uc_mcontext.gs;
ctx->sc_err = uc.uc_mcontext.err;
ctx->sc_rip = uc.uc_mcontext.rip;
ctx->sc_rsp = uc.uc_mcontext.rsp;
if (ctx->sc_fpstate) {
*ctx->sc_fpstate = *uc.uc_mcontext.fpregs;
}
}
}
/*
* When the OpenBSD kernel invokes this signal handler it pushes a
* trampoline on the stack which does two things: 1) it calls this
* function, and 2) calls sys_sigreturn() once this returns.
*/
}

View file

@ -49,7 +49,7 @@ struct siginfo {
};
char __ignoreme[128 - 2 * sizeof(int32_t) - sizeof(int64_t)];
};
} forcealign(8);
};
typedef struct siginfo siginfo_t;

View file

@ -65,7 +65,7 @@ struct FpuStackEntry {
uint16_t padding[3];
};
struct FpuState {
struct thatispacked FpuState {
uint16_t cwd;
uint16_t swd;
uint16_t ftw;
@ -122,26 +122,7 @@ struct MachineContext {
typedef struct MachineContext mcontext_t;
struct ucontext {
union {
uint64_t uc_flags;
struct {
unsigned cf : 1; /* bit 0: carry flag */
unsigned vf : 1; /* bit 1: V flag: was 8085 signed-number overflow */
unsigned pf : 1; /* bit 2: parity flag */
unsigned rf : 1; /* bit 3: always zero [undoc] */
unsigned af : 1; /* bit 4: auxiliary flag */
unsigned kf : 1; /* bit 5: K flag = V flag ⊕ sgn(result) [undoc] */
unsigned zf : 1; /* bit 6: zero flag */
unsigned sf : 1; /* bit 7: sign flag */
unsigned tf : 1; /* bit 8: trap flag */
unsigned if_ : 1; /* bit 9: interrupt enable flag */
unsigned df : 1; /* bit 10: direction flag */
unsigned of : 1; /* bit 11: overflow flag */
unsigned pl : 2; /* b12-13: i/o privilege level (80286+) */
unsigned nt : 1; /* bit 14: nested task flag (80286+) */
unsigned pc : 1; /* bit 15: oldskool flag */
};
};
uint64_t uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext; /* use this */

View file

@ -23,8 +23,12 @@
void __winalarm(void *lpArgToCompletionRoutine, uint32_t dwTimerLowValue,
uint32_t dwTimerHighValue) {
int rva;
siginfo_t info;
memset(&info, 0, sizeof(info));
info.si_signo = SIGALRM;
__sigenter(info.si_signo, &info, NULL);
rva = __sighandrvas[SIGALRM];
if (rva >= kSigactionMinRva) {
((sigaction_f)(_base + rva))(SIGALRM, &info, NULL);
}
}

View file

@ -24,7 +24,7 @@
#include "libc/str/str.h"
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
int sig;
int sig, rva;
struct Goodies {
ucontext_t ctx;
struct siginfo si;
@ -69,7 +69,10 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
return kNtExceptionContinueSearch;
}
memset(&g, 0, sizeof(g));
ntcontext2linux(&g.ctx, ep->ContextRecord);
return __sigenter(sig, &g.si, &g.ctx) ? kNtExceptionContinueExecution
: kNtExceptionContinueSearch;
rva = __sighandrvas[sig];
if (rva >= kSigactionMinRva) {
ntcontext2linux(&g.ctx, ep->ContextRecord);
((sigaction_f)(_base + rva))(sig, &g.si, &g.ctx);
}
return kNtExceptionContinueExecution;
}

29
libc/calls/writev-metal.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/sysv/errfuns.h"
ssize_t sys_writev_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
switch (fd->kind) {
case kFdSerial:
return sys_writev_serial(fd, iov, iovlen);
default:
return ebadf();
}
}

35
libc/calls/writev-nt.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
textwindows ssize_t sys_writev_nt(struct Fd *fd, const struct iovec *iov,
int iovlen) {
switch (fd->kind) {
case kFdFile:
case kFdConsole:
return sys_write_nt(fd, iov, iovlen, -1);
case kFdSocket:
return weaken(sys_sendto_nt)(fd, iov, iovlen, 0, NULL, 0);
default:
return ebadf();
}
}

View file

@ -20,7 +20,7 @@
#include "libc/nexgen32e/uart.internal.h"
#include "libc/runtime/pc.internal.h"
ssize_t writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
ssize_t sys_writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
size_t i, j, wrote = 0;
for (i = 0; i < iovlen; ++i) {
for (j = 0; j < iov[i].iov_len; ++j) {

View file

@ -39,16 +39,13 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
return writev_serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) {
} else if (!IsWindows() && !IsMetal()) {
return sys_writev(fd, iov, iovlen);
} else if (fd < g_fds.n &&
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
return sys_write_nt(&g_fds.p[fd], iov, iovlen, -1);
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
return weaken(sys_sendto_nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
} else {
} else if (fd >= g_fds.n) {
return ebadf();
} else if (IsMetal()) {
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
} else {
return sys_writev_nt(g_fds.p + fd, iov, iovlen);
}
}

View file

@ -50,17 +50,6 @@ struct __darwin_sigaltstack {
int32_t ss_flags;
};
struct __darwin_fp_control {
uint16_t __invalid : 1, __denorm : 1, __zdiv : 1, __ovrfl : 1, __undfl : 1,
__precis : 1, : 2, __pc : 2, __rc : 2, : 1, : 3;
};
struct __darwin_fp_status {
uint16_t __invalid : 1, __denorm : 1, __zdiv : 1, __ovrfl : 1, __undfl : 1,
__precis : 1, __stkflt : 1, __errsumm : 1, __c0 : 1, __c1 : 1, __c2 : 1,
__tos : 3, __c3 : 1, __busy : 1;
};
struct __darwin_mmst_reg {
char __mmst_reg[10];
char __mmst_rsrv[6];
@ -116,8 +105,8 @@ struct __darwin_x86_thread_full_state64 {
struct __darwin_x86_float_state64 {
int32_t __fpu_reserved[2];
struct __darwin_fp_control __fpu_fcw;
struct __darwin_fp_status __fpu_fsw;
uint16_t __fpu_fcw;
uint16_t __fpu_fsw;
uint8_t __fpu_ftw;
uint8_t __fpu_rsrv1;
uint16_t __fpu_fop;
@ -153,14 +142,14 @@ struct __darwin_x86_float_state64 {
struct __darwin_xmm_reg __fpu_xmm13;
struct __darwin_xmm_reg __fpu_xmm14;
struct __darwin_xmm_reg __fpu_xmm15;
char __fpu_rsrv4[6 * 16];
char __fpu_rsrv4[96];
int32_t __fpu_reserved1;
};
struct __darwin_x86_avx_state64 {
int32_t __fpu_reserved[2];
struct __darwin_fp_control __fpu_fcw;
struct __darwin_fp_status __fpu_fsw;
uint16_t __fpu_fcw;
uint16_t __fpu_fsw;
uint8_t __fpu_ftw;
uint8_t __fpu_rsrv1;
uint16_t __fpu_fop;
@ -219,8 +208,8 @@ struct __darwin_x86_avx_state64 {
struct __darwin_x86_avx512_state64 {
int32_t __fpu_reserved[2];
struct __darwin_fp_control __fpu_fcw;
struct __darwin_fp_status __fpu_fsw;
uint16_t __fpu_fcw;
uint16_t __fpu_fsw;
uint8_t __fpu_ftw;
uint8_t __fpu_rsrv1;
uint16_t __fpu_fop;
@ -390,6 +379,12 @@ static void xnuexceptionstate2linux(
mc->err = xnues->__err;
}
static void linuxexceptionstate2xnu(
struct __darwin_x86_exception_state64 *xnues, mcontext_t *mc) {
xnues->__trapno = mc->trapno;
xnues->__err = mc->err;
}
static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
struct __darwin_x86_thread_state64 *xnuss) {
mc->rdi = xnuss->__rdi;
@ -401,7 +396,6 @@ static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
mc->rcx = xnuss->__rcx;
mc->rsp = xnuss->__rsp;
mc->rip = xnuss->__rip;
/* g.uc.uc_mcontext.rip = xnuctx->uc_mcontext->__es.__faultvaddr; */
mc->cs = xnuss->__cs;
mc->gs = xnuss->__gs;
mc->fs = xnuss->__fs;
@ -410,10 +404,29 @@ static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
memcpy(&mc->r8, &xnuss->__r8, 8 * sizeof(int64_t));
}
static void linuxthreadstate2xnu(struct __darwin_x86_thread_state64 *xnuss,
ucontext_t *uc, mcontext_t *mc) {
xnuss->__rdi = mc->rdi;
xnuss->__rsi = mc->rsi;
xnuss->__rbp = mc->rbp;
xnuss->__rbx = mc->rbx;
xnuss->__rdx = mc->rdx;
xnuss->__rax = mc->rax;
xnuss->__rcx = mc->rcx;
xnuss->__rsp = mc->rsp;
xnuss->__rip = mc->rip;
xnuss->__cs = mc->cs;
xnuss->__gs = mc->gs;
xnuss->__fs = mc->fs;
xnuss->__rflags = mc->eflags;
xnuss->__rflags = uc->uc_flags;
memcpy(&xnuss->__r8, &mc->r8, 8 * sizeof(int64_t));
}
static void xnussefpustate2linux(struct FpuState *fs,
struct __darwin_x86_float_state64 *xnufs) {
memcpy(&fs->cwd, &xnufs->__fpu_fcw, 2);
memcpy(&fs->swd, &xnufs->__fpu_fsw, 2);
fs->cwd = xnufs->__fpu_fcw;
fs->swd = xnufs->__fpu_fsw;
fs->ftw = xnufs->__fpu_ftw;
fs->fop = xnufs->__fpu_fop;
fs->rip = xnufs->__fpu_ip;
@ -424,49 +437,91 @@ static void xnussefpustate2linux(struct FpuState *fs,
memcpy(fs->st, &xnufs->__fpu_stmm0, (8 + 16) * sizeof(uint128_t));
}
wontreturn void __xnutrampoline(void *fn, int infostyle, int sig,
const struct __darwin_siginfo *xnuinfo,
const struct __darwin_ucontext *xnuctx) {
/* note: this function impl can't access static memory */
static void linuxssefpustate2xnu(struct __darwin_x86_float_state64 *xnufs,
struct FpuState *fs) {
xnufs->__fpu_fcw = fs->cwd;
xnufs->__fpu_fsw = fs->swd;
xnufs->__fpu_ftw = fs->ftw;
xnufs->__fpu_fop = fs->fop;
xnufs->__fpu_ip = fs->rip;
xnufs->__fpu_dp = fs->rdp;
xnufs->__fpu_mxcsr = fs->mxcsr;
xnufs->__fpu_mxcsrmask = fs->mxcr_mask;
/* copy st0-st7 as well as xmm0-xmm15 */
memcpy(&xnufs->__fpu_stmm0, fs->st, (8 + 16) * sizeof(uint128_t));
}
void __sigenter_xnu(void *fn, int infostyle, int sig,
struct __darwin_siginfo *xnuinfo,
struct __darwin_ucontext *xnuctx) {
int rva;
intptr_t ax;
struct Goodies {
ucontext_t uc;
siginfo_t si;
} g;
memset(&g, 0, sizeof(g));
if (xnuctx) {
/* g.uc.uc_sigmask = xnuctx->uc_sigmask; */
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
if (xnuctx->uc_mcontext) {
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_x86_exception_state64)) {
xnuexceptionstate2linux(&g.uc.uc_mcontext, &xnuctx->uc_mcontext->__es);
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
memset(&g, 0, sizeof(g));
if (xnuctx) {
memcpy(&g.uc.uc_sigmask, &xnuctx->uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(xnuctx->uc_sigmask)));
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
if (xnuctx->uc_mcontext) {
if (xnuctx->uc_mcsize >=
sizeof(struct __darwin_x86_exception_state64)) {
xnuexceptionstate2linux(&g.uc.uc_mcontext,
&xnuctx->uc_mcontext->__es);
}
if (xnuctx->uc_mcsize >=
(sizeof(struct __darwin_x86_exception_state64) +
sizeof(struct __darwin_x86_thread_state64))) {
xnuthreadstate2linux(&g.uc, &g.uc.uc_mcontext,
&xnuctx->uc_mcontext->__ss);
}
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
}
}
if (xnuctx->uc_mcsize >= (sizeof(struct __darwin_x86_exception_state64) +
sizeof(struct __darwin_x86_thread_state64))) {
xnuthreadstate2linux(&g.uc, &g.uc.uc_mcontext,
&xnuctx->uc_mcontext->__ss);
}
if (xnuinfo) {
g.si.si_signo = xnuinfo->si_signo;
g.si.si_errno = xnuinfo->si_errno;
g.si.si_code = xnuinfo->si_code;
if (xnuinfo->si_pid) {
g.si.si_pid = xnuinfo->si_pid;
g.si.si_uid = xnuinfo->si_uid;
g.si.si_status = xnuinfo->si_status;
} else {
g.si.si_addr = (void *)xnuinfo->si_addr;
}
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
}
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
if (xnuctx) {
xnuctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
xnuctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
xnuctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
if (xnuctx->uc_mcontext) {
if (xnuctx->uc_mcsize >=
sizeof(struct __darwin_x86_exception_state64)) {
linuxexceptionstate2xnu(&xnuctx->uc_mcontext->__es,
&g.uc.uc_mcontext);
}
if (xnuctx->uc_mcsize >=
(sizeof(struct __darwin_x86_exception_state64) +
sizeof(struct __darwin_x86_thread_state64))) {
linuxthreadstate2xnu(&xnuctx->uc_mcontext->__ss, &g.uc,
&g.uc.uc_mcontext);
}
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
linuxssefpustate2xnu(&xnuctx->uc_mcontext->__fs, &g.uc.__fpustate);
}
}
}
}
if (xnuinfo) {
g.si.si_signo = xnuinfo->si_signo;
g.si.si_errno = xnuinfo->si_errno;
g.si.si_code = xnuinfo->si_code;
if (xnuinfo->si_pid) {
g.si.si_pid = xnuinfo->si_pid;
g.si.si_uid = xnuinfo->si_uid;
g.si.si_status = xnuinfo->si_status;
} else {
g.si.si_addr = (void *)xnuinfo->si_addr;
}
}
__sigenter(sig, &g.si, &g.uc);
asm volatile("syscall"
: "=a"(ax)
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)