mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
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:
parent
c95c9d9508
commit
f684e348d4
76 changed files with 1844 additions and 1121 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
/**
|
||||
* Changes process group for process.
|
||||
* @vforksafe
|
||||
*/
|
||||
int setpgid(int pid, int pgid) {
|
||||
int rc, me;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
39
libc/calls/struct/siginfo-freebsd.internal.h
Normal file
39
libc/calls/struct/siginfo-freebsd.internal.h
Normal 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_ */
|
53
libc/calls/struct/siginfo-netbsd.internal.h
Normal file
53
libc/calls/struct/siginfo-netbsd.internal.h
Normal 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_ */
|
36
libc/calls/struct/siginfo-openbsd.internal.h
Normal file
36
libc/calls/struct/siginfo-openbsd.internal.h
Normal 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_ */
|
22
libc/calls/struct/siginfo-xnu.internal.h
Normal file
22
libc/calls/struct/siginfo-xnu.internal.h
Normal 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_ */
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
42
libc/calls/struct/ucontext-openbsd.internal.h
Normal file
42
libc/calls/struct/ucontext-openbsd.internal.h
Normal 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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue