Improve signals and memory protection

- Document sigaction()
- Simplify New Technology fork() code
- Testing and many bug fixes for mprotect()
- Distribute Intel Xed ILD in the amalgamation
- Turn Xed enums into defines to avoid DWARF bloat
- Improve polyfilling of SA_SIGINFO on BSDs and fix bugs
- setpgid(getpid(), getpid()) on Windows will ignore CTRL-C
- Work around issues relating to NT mappings being executable
- Permit automatic executable stack override via `ape_stack_pf`
This commit is contained in:
Justine Tunney 2022-04-12 22:11:00 -07:00
parent c95c9d9508
commit f684e348d4
76 changed files with 1844 additions and 1121 deletions

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
@ -27,7 +28,7 @@
textwindows int sys_chdir_nt(const char *path) {
uint32_t n;
int e, ms, len;
int e, ms, err, len;
char16_t path16[PATH_MAX], var[4];
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (len && path16[len - 1] != u'\\') {
@ -39,7 +40,7 @@ textwindows int sys_chdir_nt(const char *path) {
* chdir() seems flaky on windows 7
* in a similar way to rmdir() sigh
*/
for (ms = 1;; ms *= 2) {
for (err = errno, ms = 1;; ms *= 2) {
if (SetCurrentDirectory(path16)) {
/*
* Now we need to set a magic environment variable.
@ -68,12 +69,12 @@ textwindows int sys_chdir_nt(const char *path) {
if (ms <= 512 &&
(e == kNtErrorFileNotFound || e == kNtErrorAccessDenied)) {
Sleep(ms);
errno = err;
continue;
} else {
break;
}
}
}
errno = e;
return -1;
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
@ -23,39 +24,70 @@
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
int prot, int flags,
int64_t handle, int64_t off) {
int prot, int flags, int fd,
int64_t off) {
size_t i;
bool iscow;
int64_t handle;
uint32_t oldprot;
struct DirectMap dm;
struct ProtectNt fl;
const struct NtSecurityAttributes *sec;
if (fd != -1) {
handle = g_fds.p[fd].handle;
} else {
handle = kNtInvalidHandleValue;
}
if (flags & MAP_PRIVATE) {
sec = 0; // MAP_PRIVATE isn't inherited across fork()
} else {
sec = &kNtIsInheritable; // MAP_SHARED gives us zero-copy fork()
}
if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE) && handle != -1) {
// windows has cow pages but they can't propagate across fork()
if (prot & PROT_EXEC) {
// nt will whine under many circumstances if we change the execute bit
// later using mprotect(). the workaround is to always request execute
// and then virtualprotect() it away until we actually need it. please
// note that open-nt.c always requests an kNtGenericExecute accessmask
iscow = false;
if (handle != -1) {
if (flags & MAP_PRIVATE) {
// windows has cow pages but they can't propagate across fork()
// that means we only get copy-on-write for the root process :(
fl = (struct ProtectNt){kNtPageExecuteWritecopy,
kNtFileMapCopy | kNtFileMapExecute};
iscow = true;
} else {
fl = (struct ProtectNt){kNtPageWritecopy, kNtFileMapCopy};
assert(flags & MAP_SHARED);
if ((g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY) {
fl = (struct ProtectNt){kNtPageExecuteRead,
kNtFileMapRead | kNtFileMapExecute};
} else {
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
kNtFileMapWrite | kNtFileMapExecute};
}
}
} else {
fl = __nt2prot(prot);
assert(flags & MAP_ANONYMOUS);
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
kNtFileMapWrite | kNtFileMapExecute};
}
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
(size + off) >> 32, (size + off), 0))) {
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
size, addr))) {
return dm;
if (VirtualProtect(addr, size, __prot2nt(prot, iscow), &oldprot)) {
return dm;
} else {
return dm;
UnmapViewOfFile(dm.addr);
}
}
CloseHandle(dm.maphandle);
}

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
@ -35,7 +36,6 @@
noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags,
int fd, int64_t off) {
/* asan runtime depends on this function */
char mode[8];
struct DirectMap d;
if (!IsWindows() && !IsMetal()) {
d.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
@ -43,11 +43,10 @@ noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags,
} else if (IsMetal()) {
d = sys_mmap_metal(addr, size, prot, flags, fd, off);
} else {
d = sys_mmap_nt(addr, size, prot, flags,
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, off);
d = sys_mmap_nt(addr, size, prot, flags, fd, off);
}
STRACE("sys_mmap(%.12p%s, %'zu, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size,
DescribeMapping(prot, flags, mode), fd, off, d.addr, d.maphandle);
STRACE("sys_mmap(%.12p%s, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size, DescribeProtFlags(prot),
DescribeMapFlags(flags), fd, off, d.addr, d.maphandle);
return d;
}

View file

@ -7,6 +7,7 @@
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction-xnu.internal.h"
#include "libc/calls/struct/siginfo-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigval.h"
#include "libc/calls/struct/stat.h"
@ -234,7 +235,7 @@ int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
void __stat2cosmo(struct stat *restrict, const union metastat *) hidden;
void __restore_rt_netbsd(void) hidden;
void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
void __sigenter_xnu(void *, i32, i32, struct siginfo_xnu *,
struct __darwin_ucontext *) hidden;
int gethostname_linux(char *, size_t) hidden;
int gethostname_bsd(char *, size_t) hidden;

View file

@ -1,64 +0,0 @@
/*-*- 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
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/asmflag.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/memory.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/nr.h"
/**
* Modifies restrictions on virtual memory address range.
*
* @param prot can have PROT_{NONE,READ,WRITE,EXEC,GROWSDOWN}
* @return 0 on success, or -1 w/ errno
* @see mmap()
*/
noasan noubsan privileged int mprotect(void *addr, size_t len, int prot) {
bool cf;
int64_t rc;
uint32_t oldprot;
char protbuf[4];
if (!IsWindows()) {
asm volatile(CFLAG_ASM("clc\n\tsyscall")
: CFLAG_CONSTRAINT(cf), "=a"(rc)
: "1"(__NR_mprotect), "D"(addr), "S"(len), "d"(prot)
: "rcx", "r11", "memory", "cc");
if (cf) {
errno = rc;
rc = -1;
} else if (rc > -4096ul) {
errno = -rc;
rc = -1;
}
} else {
if (VirtualProtect(addr, len, __prot2nt(prot, 0), &oldprot)) {
rc = 0;
} else {
rc = __winerr();
}
}
STRACE("mprotect(%p, %'zu, %s[%#x]) → %d% m", addr, len,
DescribeProt(prot, protbuf), prot, rc);
return rc;
}

View file

@ -25,6 +25,7 @@
/**
* Changes process group for process.
* @vforksafe
*/
int setpgid(int pid, int pgid) {
int rc, me;

View file

@ -100,7 +100,7 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
cthread_spinlock(&__sig_lock);
rva = __sighandrvas[sig];
flags = __sighandflags[sig];
if (~flags & SA_NODEFER) {
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
// by default we try to avoid reentering a signal handler. for
// example, if a sigsegv handler segfaults, then we'd want the
// second signal to just kill the process. doing this means we
@ -125,16 +125,15 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
// handover control to user
((sigaction_f)(_base + rva))(sig, infop, ctx);
// leave the signal
cthread_spinlock(&__sig_lock);
if (~flags & SA_NODEFER) {
if ((~flags & SA_NODEFER) && (~flags & SA_RESETHAND)) {
// it's now safe to reenter the signal so we need to restore it.
// since sigaction() is @asyncsignalsafe we only restore it if the
// user didn't change it during the signal handler. we also don't
// need to do anything if this was a oneshot signal or nodefer.
cthread_spinlock(&__sig_lock);
_cmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
cthread_spunlock(&__sig_lock);
}
if (flags & SA_RESETHAND) {
STRACE("resetting oneshot signal handler");
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
}
cthread_spunlock(&__sig_lock);
if (!restartable) {
return true; // always send EINTR for wait4(), poll(), etc.

View file

@ -236,15 +236,64 @@ static int __sigaction(int sig, const struct sigaction *act,
* .sa_flags = SA_RESETHAND|SA_RESTART|SA_SIGINFO};
* CHECK_NE(-1, sigaction(SIGINT, &sa, NULL));
*
* Here's an example of the most professional way to handle signals.
* It's generally a best practice to have signal handlers do the fewest
* number of things possible. The trick is to have your signals work
* hand-in-glove with the EINTR errno returned by i/o.
* The following flags are supported across platforms:
*
* - `SA_SIGINFO`: Causes the `siginfo_t` and `ucontext_t` parameters to
* be passed. This not only gives you more information about the
* signal, but also allows your signal handler to change the CPU
* registers. That's useful for recovering from crashes. If you don't
* use this attribute, then signal delivery will go a little faster.
*
* - `SA_RESTART`: Enables BSD signal handling semantics. Normally i/o
* entrypoints check for pending signals to deliver. If one gets
* delivered during an i/o call, the normal behavior is to cancel the
* i/o operation and return -1 with EINTR in errno. If you use the
* `SA_RESTART` flag then that behavior changes, so that any function
* that's been annotated with @restartable will not return `EINTR` and
* will instead resume the i/o operation. This makes coding easier but
* it can be an anti-pattern if not used carefully, since poor usage
* can easily result in latency issues. It also requires one to do
* more work in signal handlers, so special care needs to be given to
* which C library functions are @asyncsignalsafe.
*
* - `SA_RESETHAND`: Causes signal handler to be single-shot. This means
* that, upon entry of delivery to a signal handler, it's reset to the
* `SIG_DFL` handler automatically. You may use the alias `SA_ONESHOT`
* for this flag, which means the same thing.
*
* - `SA_NODEFER`: Disables the reentrancy safety check on your signal
* handler. Normally that's a good thing, since for instance if your
* `SIGSEGV` signal handler happens to segfault, you're going to want
* your process to just crash rather than looping endlessly. But in
* some cases it's desirable to use `SA_NODEFER` instead, such as at
* times when you wish to `longjmp()` out of your signal handler and
* back into your program. This is only safe to do across platforms
* for non-crashing signals such as `SIGCHLD` and `SIGINT`. Crash
* handlers should use Xed instead to recover execution, because on
* Windows a `SIGSEGV` or `SIGTRAP` crash handler might happen on a
* separate stack and/or a separate thread. You may use the alias
* `SA_NOMASK` for this flag, which means the same thing.
*
* - `SA_NOCLDWAIT`: Changes `SIGCHLD` so the zombie is gone and you
* can't call `wait()` anymore; similar to SIGCHLD + SIG_IGN but may
* still deliver the SIGCHLD.
*
* - `SA_NOCLDSTOP`: Lets you set `SIGCHLD` handler that's only notified
* on exit/termination and not notified on `SIGSTOP`, `SIGTSTP`,
* `SIGTTIN`, `SIGTTOU`, or `SIGCONT`.
*
* Here's an example of the most professional way to handle signals in
* an i/o event loop. It's generally a best practice to have signal
* handlers do the fewest number of things possible. The trick is to
* have your signals work hand-in-glove with the EINTR errno. This
* obfuscates the need for having to worry about @asyncsignalsafe.
*
* static volatile bool gotctrlc;
*
* void OnCtrlC(int sig) {
* gotctrlc = true;
* }
*
* int main() {
* size_t got;
* ssize_t rc;
@ -286,7 +335,96 @@ static int __sigaction(int sig, const struct sigaction *act,
*
* Please note that you can't do the above if you use SA_RESTART. Since
* the purpose of SA_RESTART is to restart i/o operations whose docs say
* that they're @restartable and read() is one such function.
* that they're @restartable and read() is one such function. Here's
* some even better news: if you don't install any signal handlers at
* all, then your i/o calls will never be interrupted!
*
* Here's an example of the most professional way to recover from
* `SIGSEGV`, `SIGFPE`, and `SIGILL`.
*
* void ContinueOnCrash(void);
*
* void SkipOverFaultingInstruction(struct ucontext *ctx) {
* struct XedDecodedInst xedd;
* xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
* xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
* ctx->uc_mcontext.rip += xedd.length;
* }
*
* void OnCrash(int sig, struct siginfo *si, struct ucontext *ctx) {
* SkipOverFaultingInstruction(ctx);
* ContinueOnCrash(); // reinstall here in case *rip faults
* }
*
* void ContinueOnCrash(void) {
* struct sigaction sa = {.sa_handler = OnSigSegv,
* .sa_flags = SA_SIGINFO | SA_RESETHAND};
* sigaction(SIGSEGV, &sa, 0);
* sigaction(SIGFPE, &sa, 0);
* sigaction(SIGILL, &sa, 0);
* }
*
* int main() {
* ContinueOnCrash();
* // ...
* }
*
* You may also edit any other CPU registers during the handler. For
* example, you can use the above technique so that division by zero
* becomes defined to a specific value of your choosing!
*
* Please note that Xed isn't needed to recover from `SIGTRAP` which can
* be raised at any time by embedding `DebugBreak()` or `asm("int3")` in
* your program code. Your signal handler will automatically skip over
* the interrupt instruction, assuming your signal handler returns.
*
* The important signals supported across all platforms are:
*
* - `SIGINT`: When you press Ctrl-C this signal gets broadcasted to
* your process session group. This is the normal way to terminate
* console applications.
*
* - `SIGQUIT`: When you press CTRL-\ this signal gets broadcasted to
* your process session group. This is the irregular way to kill an
* application in cases where maybe your `SIGINT` handler is broken
* although, Cosmopolitan Libc ShowCrashReports() should program it
* such as to attach a debugger to the process if possible, or else
* show a crash report. Also note that in New Technology you should
* press CTRL+BREAK rather than CTRL+\ to get this signal.
*
* - `SIGHUP`: This gets sent to your non-daemon processes when you
* close your terminal session.
*
* - `SIGTERM` is what the `kill` command sends by default. It's the
* choice signal for terminating daemons.
*
* - `SIGUSR1` and `SIGUSR2` can be anything you want. Their default
* action is to kill the process. By convention `SIGUSR1` is usually
* used by daemons to reload the config file.
*
* - `SIGCHLD` is sent when a process terminates and it takes a certain
* degree of UNIX mastery to address sanely.
*
* - `SIGALRM` is invoked by `setitimer()` and `alarm()`. It can be
* useful for interrupting i/o operations like `connect()`.
*
* - `SIGTRAP`: This happens when an INT3 instruction is encountered.
*
* - `SIGILL` happens on illegal instructions, e.g. `UD2`.
*
* - `SIGABRT` happens when you call `abort()`.
*
* - `SIGFPE` happens when you divide ints by zero, among other things.
*
* - `SIGSEGV` and `SIGBUS` indicate memory access errors and they have
* inconsistent semantics across platforms like FreeBSD.
*
* - `SIGWINCH` is sent when your terminal window is resized.
*
* - `SIGXCPU` and `SIGXFSZ` may be raised if you run out of resources,
* which can happen if your process, or the parent process that
* spawned your process, happened to call `setrlimit()`. Doing this is
* a wonderful idea.
*
* @return 0 on success or -1 w/ errno
* @see xsigaction() for a much better api

View file

@ -19,83 +19,101 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo-freebsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext-freebsd.internal.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/repstosb.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
struct ucontext_freebsd *ctx) {
int rva;
ucontext_t uc;
int rva, flags;
struct Goodies {
ucontext_t uc;
siginfo_t si;
} g;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
bzero(&uc, 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.r8 = ctx->uc_mcontext.mc_r8;
uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
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.rdi = ctx->uc_mcontext.mc_rdi;
uc.uc_mcontext.rsi = ctx->uc_mcontext.mc_rsi;
uc.uc_mcontext.rbp = ctx->uc_mcontext.mc_rbp;
uc.uc_mcontext.rbx = ctx->uc_mcontext.mc_rbx;
uc.uc_mcontext.rdx = ctx->uc_mcontext.mc_rdx;
uc.uc_mcontext.rax = ctx->uc_mcontext.mc_rax;
uc.uc_mcontext.rcx = ctx->uc_mcontext.mc_rcx;
uc.uc_mcontext.rsp = ctx->uc_mcontext.mc_rsp;
uc.uc_mcontext.rip = ctx->uc_mcontext.mc_rip;
uc.uc_mcontext.eflags = ctx->uc_mcontext.mc_flags;
uc.uc_mcontext.fs = ctx->uc_mcontext.mc_fs;
uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
memcpy(&uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
}
((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;
memcpy(&ctx->uc_mcontext.mc_fpstate, &uc.__fpustate, 512);
flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
g.uc.uc_flags = ctx->uc_flags;
memcpy(&g.uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
g.uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10;
g.uc.uc_mcontext.r11 = ctx->uc_mcontext.mc_r11;
g.uc.uc_mcontext.r12 = ctx->uc_mcontext.mc_r12;
g.uc.uc_mcontext.r13 = ctx->uc_mcontext.mc_r13;
g.uc.uc_mcontext.r14 = ctx->uc_mcontext.mc_r14;
g.uc.uc_mcontext.r15 = ctx->uc_mcontext.mc_r15;
g.uc.uc_mcontext.rdi = ctx->uc_mcontext.mc_rdi;
g.uc.uc_mcontext.rsi = ctx->uc_mcontext.mc_rsi;
g.uc.uc_mcontext.rbp = ctx->uc_mcontext.mc_rbp;
g.uc.uc_mcontext.rbx = ctx->uc_mcontext.mc_rbx;
g.uc.uc_mcontext.rdx = ctx->uc_mcontext.mc_rdx;
g.uc.uc_mcontext.rax = ctx->uc_mcontext.mc_rax;
g.uc.uc_mcontext.rcx = ctx->uc_mcontext.mc_rcx;
g.uc.uc_mcontext.rsp = ctx->uc_mcontext.mc_rsp;
g.uc.uc_mcontext.rip = ctx->uc_mcontext.mc_rip;
g.uc.uc_mcontext.eflags = ctx->uc_mcontext.mc_flags;
g.uc.uc_mcontext.fs = ctx->uc_mcontext.mc_fs;
g.uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
memcpy(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
g.si.si_signo = freebsdinfo->si_signo;
g.si.si_errno = freebsdinfo->si_errno;
g.si.si_code = freebsdinfo->si_code;
if (freebsdinfo->si_pid) {
g.si.si_pid = freebsdinfo->si_pid;
g.si.si_uid = freebsdinfo->si_uid;
} else {
g.si.si_addr = (void *)freebsdinfo->si_addr;
}
g.si.si_value = freebsdinfo->si_value;
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
ctx->uc_flags = g.uc.uc_flags;
memcpy(&ctx->uc_sigmask, &g.uc.uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi;
ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi;
ctx->uc_mcontext.mc_rdx = g.uc.uc_mcontext.rdx;
ctx->uc_mcontext.mc_rcx = g.uc.uc_mcontext.rcx;
ctx->uc_mcontext.mc_r8 = g.uc.uc_mcontext.r8;
ctx->uc_mcontext.mc_r9 = g.uc.uc_mcontext.r9;
ctx->uc_mcontext.mc_rax = g.uc.uc_mcontext.rax;
ctx->uc_mcontext.mc_rbx = g.uc.uc_mcontext.rbx;
ctx->uc_mcontext.mc_rbp = g.uc.uc_mcontext.rbp;
ctx->uc_mcontext.mc_r10 = g.uc.uc_mcontext.r10;
ctx->uc_mcontext.mc_r11 = g.uc.uc_mcontext.r11;
ctx->uc_mcontext.mc_r12 = g.uc.uc_mcontext.r12;
ctx->uc_mcontext.mc_r13 = g.uc.uc_mcontext.r13;
ctx->uc_mcontext.mc_r14 = g.uc.uc_mcontext.r14;
ctx->uc_mcontext.mc_r15 = g.uc.uc_mcontext.r15;
ctx->uc_mcontext.mc_trapno = g.uc.uc_mcontext.trapno;
ctx->uc_mcontext.mc_fs = g.uc.uc_mcontext.fs;
ctx->uc_mcontext.mc_gs = g.uc.uc_mcontext.gs;
ctx->uc_mcontext.mc_flags = g.uc.uc_mcontext.eflags;
ctx->uc_mcontext.mc_err = g.uc.uc_mcontext.err;
ctx->uc_mcontext.mc_rip = g.uc.uc_mcontext.rip;
ctx->uc_mcontext.mc_rsp = g.uc.uc_mcontext.rsp;
memcpy(&ctx->uc_mcontext.mc_fpstate, &g.uc.__fpustate, 512);
}
}
/*

View file

@ -19,11 +19,13 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo-netbsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
#define RDI 0
#define RSI 1
@ -57,50 +59,6 @@ union sigval_netbsd {
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];
};
@ -127,19 +85,23 @@ struct ucontext_netbsd {
void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
struct ucontext_netbsd *ctx) {
int rva;
int rva, flags;
ucontext_t uc;
struct siginfo si2;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
bzero(&uc, sizeof(uc));
bzero(&si2, sizeof(si2));
if (si) {
si2.si_signo = si->_signo;
si2.si_code = si->_code;
si2.si_errno = si->_errno;
}
if (ctx) {
flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
bzero(&uc, sizeof(uc));
bzero(&si2, sizeof(si2));
si2.si_signo = si->si_signo;
si2.si_code = si->si_code;
si2.si_errno = si->si_errno;
si2.si_pid = si->si_pid;
si2.si_uid = si->si_uid;
si2.si_value = si->si_value;
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_flags = ctx->uc_flags;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
@ -169,9 +131,7 @@ void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
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) {
((sigaction_f)(_base + rva))(sig, &si2, &uc);
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;

View file

@ -19,145 +19,91 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/siginfo-openbsd.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/ucontext-openbsd.internal.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/repstosb.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.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;
};
void __sigenter_openbsd(int sig, struct siginfo_openbsd *si,
void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
struct ucontext_openbsd *ctx) {
int rva;
ucontext_t uc;
struct siginfo si2;
int rva, flags;
struct Goodies {
ucontext_t uc;
struct siginfo si;
} g;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
bzero(&uc, sizeof(uc));
bzero(&si2, 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;
flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
g.si.si_signo = openbsdinfo->si_signo;
g.si.si_code = openbsdinfo->si_code;
g.si.si_errno = openbsdinfo->si_errno;
if (openbsdinfo->si_pid) {
g.si.si_pid = openbsdinfo->si_pid;
g.si.si_uid = openbsdinfo->si_uid;
} else {
g.si.si_addr = (void *)openbsdinfo->si_addr;
}
}
((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;
g.si.si_value = openbsdinfo->si_value;
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
memcpy(&g.uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask)));
g.uc.uc_mcontext.rdi = ctx->sc_rdi;
g.uc.uc_mcontext.rsi = ctx->sc_rsi;
g.uc.uc_mcontext.rdx = ctx->sc_rdx;
g.uc.uc_mcontext.rcx = ctx->sc_rcx;
g.uc.uc_mcontext.r8 = ctx->sc_r8;
g.uc.uc_mcontext.r9 = ctx->sc_r9;
g.uc.uc_mcontext.rax = ctx->sc_rax;
g.uc.uc_mcontext.rbx = ctx->sc_rbx;
g.uc.uc_mcontext.rbp = ctx->sc_rbp;
g.uc.uc_mcontext.r10 = ctx->sc_r10;
g.uc.uc_mcontext.r11 = ctx->sc_r11;
g.uc.uc_mcontext.r12 = ctx->sc_r12;
g.uc.uc_mcontext.r13 = ctx->sc_r13;
g.uc.uc_mcontext.r14 = ctx->sc_r14;
g.uc.uc_mcontext.r15 = ctx->sc_r15;
g.uc.uc_mcontext.trapno = ctx->sc_trapno;
g.uc.uc_mcontext.fs = ctx->sc_fs;
g.uc.uc_mcontext.gs = ctx->sc_gs;
g.uc.uc_mcontext.err = ctx->sc_err;
g.uc.uc_mcontext.rip = ctx->sc_rip;
g.uc.uc_mcontext.rsp = ctx->sc_rsp;
if (ctx->sc_fpstate) {
*ctx->sc_fpstate = *uc.uc_mcontext.fpregs;
*g.uc.uc_mcontext.fpregs = *ctx->sc_fpstate;
}
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
ctx->sc_rdi = g.uc.uc_mcontext.rdi;
ctx->sc_rsi = g.uc.uc_mcontext.rsi;
ctx->sc_rdx = g.uc.uc_mcontext.rdx;
ctx->sc_rcx = g.uc.uc_mcontext.rcx;
ctx->sc_r8 = g.uc.uc_mcontext.r8;
ctx->sc_r9 = g.uc.uc_mcontext.r9;
ctx->sc_rax = g.uc.uc_mcontext.rax;
ctx->sc_rbx = g.uc.uc_mcontext.rbx;
ctx->sc_rbp = g.uc.uc_mcontext.rbp;
ctx->sc_r10 = g.uc.uc_mcontext.r10;
ctx->sc_r11 = g.uc.uc_mcontext.r11;
ctx->sc_r12 = g.uc.uc_mcontext.r12;
ctx->sc_r13 = g.uc.uc_mcontext.r13;
ctx->sc_r14 = g.uc.uc_mcontext.r14;
ctx->sc_r15 = g.uc.uc_mcontext.r15;
ctx->sc_trapno = g.uc.uc_mcontext.trapno;
ctx->sc_fs = g.uc.uc_mcontext.fs;
ctx->sc_gs = g.uc.uc_mcontext.gs;
ctx->sc_err = g.uc.uc_mcontext.err;
ctx->sc_rip = g.uc.uc_mcontext.rip;
ctx->sc_rsp = g.uc.uc_mcontext.rsp;
if (ctx->sc_fpstate) {
*ctx->sc_fpstate = *g.uc.uc_mcontext.fpregs;
}
}
}

View file

@ -19,9 +19,11 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/metasigaltstack.h"
#include "libc/calls/struct/siginfo-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/repstosb.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
@ -30,24 +32,6 @@
* @fileoverview XNU kernel callback normalization.
*/
union __darwin_sigval {
int32_t sival_int;
void *sival_ptr;
};
struct __darwin_siginfo {
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 __darwin_sigval si_value;
int64_t si_band;
uint64_t __pad[7];
};
struct __darwin_mmst_reg {
char __mmst_reg[10];
char __mmst_rsrv[6];
@ -467,71 +451,76 @@ noasan static void linuxssefpustate2xnu(
}
noasan void __sigenter_xnu(void *fn, int infostyle, int sig,
struct __darwin_siginfo *xnuinfo,
struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) {
int rva;
intptr_t ax;
int rva, flags;
struct Goodies {
ucontext_t uc;
siginfo_t si;
} g;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
repstosb(&g, 0, sizeof(g));
if (xnuctx) {
g.uc.uc_flags = xnuctx->uc_onstack ? SA_ONSTACK : 0;
g.uc.uc_sigmask.__bits[0] = 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.uc_mcontext, &xnuctx->uc_mcontext->__ss);
}
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
if (xnuctx) {
g.uc.uc_flags = xnuctx->uc_onstack ? SA_ONSTACK : 0;
g.uc.uc_sigmask.__bits[0] = 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.uc_mcontext, &xnuctx->uc_mcontext->__ss);
}
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
}
}
}
}
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 (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;
} else {
g.si.si_addr = (void *)xnuinfo->si_addr;
}
g.si.si_value = xnuinfo->si_value;
}
}
((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);
((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);
}
}
}
}

View file

@ -28,7 +28,7 @@
*
* @return old signal handler on success or SIG_ERR w/ errno
* @note this function has BSD semantics, i.e. SA_RESTART
* @see sigaction() which has more features
* @see sigaction() which has more features and docs
*/
sighandler_t(signal)(int sig, sighandler_t func) {
struct sigaction old, sa = {.sa_handler = func, .sa_flags = SA_RESTART};

View file

@ -0,0 +1,39 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_FREEBSD_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_FREEBSD_H_
#include "libc/calls/struct/sigval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct siginfo_freebsd {
int32_t si_signo;
int32_t si_errno;
int32_t si_code;
int32_t si_pid;
int32_t si_uid;
int32_t si_status;
void *si_addr;
union sigval si_value;
union {
struct {
int32_t si_trapno;
};
struct {
int32_t si_timerid;
int32_t si_overrun;
};
struct {
int32_t si_mqd;
};
struct {
long si_band;
};
struct {
int64_t __pad1;
int32_t __pad2[7];
};
};
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_FREEBSD_H_ */

View file

@ -0,0 +1,53 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_NETBSD_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_NETBSD_H_
#include "libc/calls/struct/sigval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct siginfo_netbsd {
int32_t si_signo;
int32_t si_code;
int32_t si_errno;
int32_t __pad;
union {
struct { /* RT */
int32_t si_pid;
int32_t si_uid;
union sigval si_value;
};
struct { /* chld */
int32_t _pid;
int32_t _uid;
int32_t si_status;
int64_t si_utime;
int64_t si_stime;
};
struct { /* fault */
void *si_addr;
int32_t si_trap;
int32_t si_trap2;
int32_t si_trap3;
};
struct { /* poll */
int64_t si_band;
int32_t si_fd;
};
struct { /* syscall */
int32_t si_sysnum;
int32_t si_retval[2];
int32_t si_error;
uint64_t si_args[8];
};
struct { /* ptrace */
int32_t si_pe_report_event;
union {
int32_t si_pe_other_pid;
int32_t si_pe_lwp;
};
};
};
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_NETBSD_H_ */

View file

@ -0,0 +1,36 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_OPENBSD_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_OPENBSD_H_
#include "libc/calls/struct/sigval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct siginfo_openbsd {
int32_t si_signo;
int32_t si_code;
int32_t si_errno;
union {
int32_t _pad[(128 / 4) - 3];
struct {
int32_t si_pid;
union {
struct {
int32_t si_uid;
union sigval si_value;
};
struct {
int64_t si_utime;
int64_t si_stime;
int32_t si_status;
};
};
};
struct {
void *si_addr;
int32_t si_trapno;
};
};
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_OPENBSD_H_ */

View file

@ -0,0 +1,22 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_XNU_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_XNU_H_
#include "libc/calls/struct/sigval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct siginfo_xnu {
int32_t si_signo;
int32_t si_errno;
int32_t si_code;
int32_t si_pid;
int32_t si_uid;
int32_t si_status;
void *si_addr;
union sigval si_value;
int64_t si_band;
uint64_t __pad[7];
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_XNU_H_ */

View file

@ -15,7 +15,7 @@ struct siginfo {
uint32_t si_uid;
};
struct {
int32_t si_timerid;
int32_t si_timerid; /* SIGALRM */
int32_t si_overrun;
};
};
@ -23,7 +23,8 @@ struct siginfo {
union sigval si_value; /* provided by third arg of sigqueue(2) */
struct {
int32_t si_status;
int64_t si_utime, si_stime;
int64_t si_utime;
int64_t si_stime;
};
};
};
@ -39,7 +40,7 @@ struct siginfo {
};
};
struct {
int64_t si_band;
int64_t si_band; /* SIGPOLL */
int32_t si_fd;
};
struct {

View file

@ -4,43 +4,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
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 {
int32_t _trapno;
} _fault;
struct {
int32_t _timerid;
int32_t _overrun;
} _timer;
struct {
int32_t _mqd;
} _mesgq;
struct {
int64_t _band;
} _poll;
struct {
int64_t __spare1__;
int32_t __spare2__[7];
} __spare__;
} _reason;
};
struct stack_freebsd {
void *ss_sp;
uint64_t ss_size;

View file

@ -0,0 +1,42 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_OPENBSD_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_OPENBSD_INTERNAL_H_
#include "libc/calls/ucontext.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
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;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_OPENBSD_INTERNAL_H_ */

View file

@ -96,7 +96,9 @@ static textwindows bool IsDirectorySymlink(const char16_t *path) {
static textwindows int sys_rmdir_nt(const char16_t *path) {
int e, ms;
for (ms = 1;; ms *= 2) {
if (RemoveDirectory(path)) return 0;
if (RemoveDirectory(path)) {
return 0;
}
/*
* Files can linger, for absolutely no reason.
* Possibly some Windows Defender bug on Win7.
@ -104,14 +106,13 @@ static textwindows int sys_rmdir_nt(const char16_t *path) {
* Alternative is use Microsoft internal APIs.
* Never could have imagined it'd be this bad.
*/
if ((e = GetLastError()) == kNtErrorDirNotEmpty && ms <= 512) {
if (GetLastError() == kNtErrorDirNotEmpty && ms <= 2048) {
Sleep(ms);
continue;
} else {
break;
}
}
errno = e;
return -1;
}
@ -121,7 +122,7 @@ static textwindows int sys_unlink_nt(const char16_t *path) {
} else if (DeleteFile(path)) {
return 0;
} else {
return __winerr();
return -1;
}
}