mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-29 14:00:29 +00:00
Improve memory safety
This commit makes numerous refinements to cosmopolitan memory handling. The default stack size has been reduced from 2mb to 128kb. A new macro is now provided so you can easily reconfigure the stack size to be any value you want. Work around the breaking change by adding to your main: STATIC_STACK_SIZE(0x00200000); // 2mb stack If you're not sure how much stack you need, then you can use: STATIC_YOINK("stack_usage_logging"); After which you can `sort -nr o/$MODE/stack.log`. Based on the unit test suite, nothing in the Cosmopolitan repository (except for Python) needs a stack size greater than 30kb. There are also new macros for detecting the size and address of the stack at runtime, e.g. GetStackAddr(). We also now support sigaltstack() so if you want to see nice looking crash reports whenever a stack overflow happens, you can put this in main(): ShowCrashReports(); Under `make MODE=dbg` and `make MODE=asan` the unit testing framework will now automatically print backtraces of memory allocations when things like memory leaks happen. Bugs are now fixed in ASAN global variable overrun detection. The memtrack and asan runtimes also handle edge cases now. The new tools helped to identify a few memory leaks, which are fixed by this change. This change should fix an issue reported in #288 with ARG_MAX limits. Fixing this doubled the performance of MKDEPS.COM and AR.COM yet again.
This commit is contained in:
parent
a0b39f886c
commit
226aaf3547
317 changed files with 6474 additions and 3993 deletions
|
@ -5,13 +5,13 @@
|
|||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigval.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/sysinfo.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/tms.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/typedef/sighandler_t.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/pflink.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
|
@ -178,7 +178,6 @@ int setreuid(uint32_t, uint32_t);
|
|||
int setrlimit(int, const struct rlimit *);
|
||||
int setsid(void);
|
||||
int setuid(uint32_t);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
int sigignore(int);
|
||||
int siginterrupt(int, int);
|
||||
int sigprocmask(int, const struct sigset *, struct sigset *);
|
||||
|
@ -206,7 +205,6 @@ intptr_t syscall(int, ...);
|
|||
long ptrace(int, int, void *, void *);
|
||||
long telldir(DIR *);
|
||||
long times(struct tms *);
|
||||
sighandler_t signal(int, sighandler_t);
|
||||
size_t GetFileSize(const char *);
|
||||
size_t getfiledescriptorsize(int);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
|
@ -247,51 +245,6 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
void _init_onntconsoleevent(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
#ifndef __SIGACTION_YOINK
|
||||
#define __SIGACTION_YOINK(SIG) \
|
||||
do { \
|
||||
if (SupportsWindows()) { \
|
||||
if (__builtin_constant_p(SIG)) { \
|
||||
switch (SIG) { \
|
||||
case SIGINT: \
|
||||
case SIGQUIT: \
|
||||
case SIGHUP: \
|
||||
case SIGTERM: \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
break; \
|
||||
case SIGTRAP: \
|
||||
case SIGILL: \
|
||||
case SIGSEGV: \
|
||||
case SIGABRT: \
|
||||
case SIGFPE: \
|
||||
YOINK(_init_wincrash); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
YOINK(_init_wincrash); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define sigaction(SIG, ACT, OLD) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
sigaction(SIG, (ACT), OLD); \
|
||||
})
|
||||
|
||||
#define signal(SIG, HAND) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
signal(SIG, HAND); \
|
||||
})
|
||||
|
||||
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
|
||||
|
||||
|
|
|
@ -18,39 +18,55 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static noasan bool AccessCommand(char path[hasatleast PATH_MAX],
|
||||
const char *name, size_t namelen,
|
||||
size_t pathlen) {
|
||||
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
static noasan bool EndsWithIgnoreCase(const char *p, size_t n, const char *s) {
|
||||
size_t i, m;
|
||||
m = __strlen(s);
|
||||
if (n >= m) {
|
||||
for (i = n - m; i < n; ++i) {
|
||||
if (kToLower[p[i] & 255] != (*s++ & 255)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
memcpy(path + pathlen, name, namelen + 1);
|
||||
if (isexecutable(path)) return true;
|
||||
memcpy(path + pathlen + namelen, ".com", 5);
|
||||
if (isexecutable(path)) return true;
|
||||
memcpy(path + pathlen + namelen, ".exe", 5);
|
||||
if (isexecutable(path)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static noasan bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
||||
size_t namelen) {
|
||||
static noasan bool AccessCommand(const char *name,
|
||||
char path[hasatleast PATH_MAX], size_t namelen,
|
||||
const char *suffix, size_t pathlen) {
|
||||
size_t suffixlen;
|
||||
suffixlen = __strlen(suffix);
|
||||
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return -1;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: __memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
}
|
||||
__repmovsb(path + pathlen, name, namelen);
|
||||
__repmovsb(path + pathlen + namelen, suffix, suffixlen + 1);
|
||||
return isexecutable(path);
|
||||
}
|
||||
|
||||
static noasan bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
||||
size_t namelen, const char *suffix) {
|
||||
size_t i;
|
||||
const char *p;
|
||||
p = firstnonnull(emptytonull(getenv("PATH")), "/bin:/usr/local/bin:/usr/bin");
|
||||
for (;;) {
|
||||
for (i = 0; p[i] && p[i] != ':' && p[i] != ';'; ++i) {
|
||||
if (i < PATH_MAX) path[i] = p[i];
|
||||
if (i < PATH_MAX) {
|
||||
path[i] = p[i];
|
||||
}
|
||||
}
|
||||
if (AccessCommand(path, name, namelen, i)) {
|
||||
if (AccessCommand(name, path, namelen, suffix, i)) {
|
||||
return true;
|
||||
}
|
||||
if (p[i] == ':' || p[i] == ';') {
|
||||
|
@ -62,6 +78,23 @@ static noasan bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
|||
return false;
|
||||
}
|
||||
|
||||
static noasan bool FindCommand(const char *name,
|
||||
char pathbuf[hasatleast PATH_MAX],
|
||||
size_t namelen, const char *suffix) {
|
||||
if (memchr(name, '/', namelen) || memchr(name, '\\', namelen)) {
|
||||
pathbuf[0] = 0;
|
||||
return AccessCommand(name, pathbuf, namelen, suffix, 0);
|
||||
}
|
||||
return ((IsWindows() &&
|
||||
(AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
|
||||
AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, ".") - pathbuf))) ||
|
||||
SearchPath(name, pathbuf, namelen, suffix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves full pathname of executable.
|
||||
*
|
||||
|
@ -72,40 +105,28 @@ static noasan bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
|||
* @vforksafe
|
||||
*/
|
||||
noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
char *p;
|
||||
int olderr;
|
||||
size_t namelen;
|
||||
int rc, olderr;
|
||||
if (!name) {
|
||||
efault();
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (!(namelen = strlen(name))) {
|
||||
if (!(namelen = __strlen(name))) {
|
||||
enoent();
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (namelen + 1 > PATH_MAX) {
|
||||
enametoolong();
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (strchr(name, '/') || strchr(name, '\\')) {
|
||||
if (AccessCommand(strcpy(pathbuf, ""), name, namelen, 0)) {
|
||||
return pathbuf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
olderr = errno;
|
||||
if ((IsWindows() &&
|
||||
(AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, ".") - pathbuf))) ||
|
||||
SearchPath(pathbuf, name, namelen)) {
|
||||
errno = olderr;
|
||||
if (FindCommand(name, pathbuf, namelen, "") ||
|
||||
(!EndsWithIgnoreCase(name, namelen, ".exe") &&
|
||||
!EndsWithIgnoreCase(name, namelen, ".com") &&
|
||||
!EndsWithIgnoreCase(name, namelen, ".com.dbg") &&
|
||||
(FindCommand(name, pathbuf, namelen, ".com") ||
|
||||
FindCommand(name, pathbuf, namelen, ".exe")))) {
|
||||
return pathbuf;
|
||||
} else {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static void __ensurefds_destroy(void) {
|
||||
weaken(free)(g_fds.p);
|
||||
}
|
||||
|
||||
int __ensurefds(int fd) {
|
||||
size_t n1, n2;
|
||||
struct Fd *p1, *p2;
|
||||
|
@ -36,9 +40,15 @@ int __ensurefds(int fd) {
|
|||
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
|
||||
memcpy(p2, p1, n1 * sizeof(*p1));
|
||||
bzero(p2 + n1, (n2 - n1) * sizeof(*p1));
|
||||
if (p1 != g_fds.__init_p && weaken(free)) weaken(free)(p1);
|
||||
if (cmpxchg(&g_fds.p, p1, p2)) {
|
||||
g_fds.n = n2;
|
||||
if (weaken(free)) {
|
||||
if (p1 == g_fds.__init_p) {
|
||||
atexit(__ensurefds_destroy);
|
||||
} else {
|
||||
weaken(free)(p1);
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
} else if (weaken(free)) {
|
||||
weaken(free)(p2);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -42,15 +43,18 @@ char *getcwd(char *buf, size_t size) {
|
|||
if (buf) {
|
||||
p = buf;
|
||||
if (!size) {
|
||||
SYSDEBUG("getcwd(%p, %x) EINVAL", buf, size);
|
||||
einval();
|
||||
return 0;
|
||||
}
|
||||
} else if (weaken(malloc)) {
|
||||
if (!size) size = PATH_MAX + 1;
|
||||
if (!(p = weaken(malloc)(size))) {
|
||||
SYSDEBUG("getcwd(%p, %x) ENOMEM", buf, size);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
SYSDEBUG("getcwd() EINVAL needs buf≠0 or STATIC_YOINK(\"malloc\")");
|
||||
einval();
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,5 +85,6 @@ char *getcwd(char *buf, size_t size) {
|
|||
}
|
||||
}
|
||||
}
|
||||
SYSDEBUG("getcwd(%p, %x) -> %s", buf, size, r);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -115,6 +116,7 @@ i32 __sys_fcntl(i32, i32, ...) hidden;
|
|||
i32 __sys_fstat(i32, void *) hidden;
|
||||
i32 __sys_fstatat(i32, const char *, void *, i32) hidden;
|
||||
i32 __sys_getrusage(i32, struct rusage *) hidden;
|
||||
i32 __sys_munmap(void *, u64) hidden;
|
||||
i32 __sys_openat(i32, const char *, i32, u32) hidden;
|
||||
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
|
||||
|
@ -177,6 +179,7 @@ i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
|
|||
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
|
||||
i32 sys_setsid(void) hidden;
|
||||
i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden;
|
||||
i32 sys_sigaltstack(const void *, void *) hidden;
|
||||
i32 sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden;
|
||||
i32 sys_sigqueue(i32, i32, const union sigval) hidden;
|
||||
i32 sys_sigqueueinfo(i32, const siginfo_t *) hidden;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/ipadapteraddresses.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -239,6 +241,7 @@ struct HostAdapterInfoNode *appendHostInfo(
|
|||
|
||||
/* Returns -1 in case of failure */
|
||||
static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) {
|
||||
static bool once;
|
||||
struct NtIpAdapterAddresses *aa;
|
||||
struct NtIpAdapterUnicastAddress *ua;
|
||||
struct NtIpAdapterPrefix *ap;
|
||||
|
@ -270,7 +273,12 @@ static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) {
|
|||
(ua != NULL) && (count < MAX_UNICAST_ADDR); ++count) {
|
||||
node = appendHostInfo(node, baseName, aa, &ua, &ap, count);
|
||||
if (!node) goto err;
|
||||
if (!__hostInfo) __hostInfo = node;
|
||||
if (!__hostInfo) {
|
||||
__hostInfo = node;
|
||||
if (cmpxchg(&once, false, true)) {
|
||||
atexit(freeHostInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: do we need to process the remaining adapter prefix?
|
||||
|
|
|
@ -1,66 +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/alg/alg.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
#define kBufSize 1024
|
||||
#define kProcStatus "/proc/self/status"
|
||||
#define kPid "TracerPid:\t"
|
||||
|
||||
static noasan int NtBeingDebugged(void) {
|
||||
return NtGetPeb()->BeingDebugged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if gdb, strace, windbg, etc. is controlling process.
|
||||
* @return non-zero if attached, otherwise 0
|
||||
*/
|
||||
int IsDebuggerPresent(bool force) {
|
||||
int fd, res;
|
||||
ssize_t got;
|
||||
char buf[1024];
|
||||
res = false;
|
||||
if (!force) {
|
||||
if (getenv("HEISENDEBUG")) return false;
|
||||
if (IsGenuineCosmo()) return false;
|
||||
}
|
||||
if (IsWindows()) {
|
||||
res = NtBeingDebugged();
|
||||
} else if (IsLinux()) {
|
||||
if ((fd = sys_openat(AT_FDCWD, kProcStatus, O_RDONLY, 0)) != -1) {
|
||||
if ((got = sys_read(fd, buf, sizeof(buf) - sizeof(kPid))) != -1) {
|
||||
buf[got] = '\0';
|
||||
res = atoi(firstnonnull(strstr(buf, kPid), kPid) + strlen(kPid));
|
||||
}
|
||||
sys_close(fd);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,37 +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/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
bool g_isrunningundermake;
|
||||
|
||||
/**
|
||||
* Returns true if current process was spawned by GNU Make.
|
||||
*/
|
||||
bool IsRunningUnderMake(void) {
|
||||
return g_isrunningundermake;
|
||||
}
|
||||
|
||||
textstartup void g_isrunningundermake_init(void) {
|
||||
g_isrunningundermake = !!getenv("MAKEFLAGS");
|
||||
}
|
||||
|
||||
const void *const g_isrunningundermake_ctor[] initarray = {
|
||||
g_isrunningundermake_init,
|
||||
};
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -94,7 +95,10 @@ textwindows int __mkntpath2(const char *path,
|
|||
m = 0;
|
||||
}
|
||||
n = tprecode8to16(p, z, q).ax;
|
||||
if (n == z - 1) return enametoolong();
|
||||
if (n == z - 1) {
|
||||
SYSDEBUG("path too long for windows: %s", path);
|
||||
return enametoolong();
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (p[i] == '/') {
|
||||
p[i] = '\\';
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -33,7 +34,10 @@ int __mkntpathat(int dirfd, const char *path, int flags,
|
|||
dirlen = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
if (!dirlen) return __winerr();
|
||||
if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) return enametoolong();
|
||||
if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) {
|
||||
SYSDEBUG("path too long: %.*hs\\%.*hs", dirlen, dir, filelen, file);
|
||||
return enametoolong();
|
||||
}
|
||||
dir[dirlen] = u'\\';
|
||||
memcpy(dir + dirlen + 1, file, (filelen + 1) * sizeof(char16_t));
|
||||
memcpy(file, dir, (dirlen + 1 + filelen + 1) * sizeof(char16_t));
|
||||
|
|
|
@ -34,7 +34,7 @@ extern __msabi typeof(VirtualProtect) *const __imp_VirtualProtect;
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see mmap()
|
||||
*/
|
||||
privileged int mprotect(void *addr, uint64_t len, int prot) {
|
||||
noasan noubsan privileged int mprotect(void *addr, uint64_t len, int prot) {
|
||||
bool cf;
|
||||
int64_t rc;
|
||||
uint32_t oldprot;
|
||||
|
|
|
@ -95,7 +95,7 @@ textwindows int ntspawn(
|
|||
} else {
|
||||
__winerr();
|
||||
}
|
||||
SYSDEBUG("CreateProcess(`%S`, `%S`) -> %d", prog16, block->cmdline, rc);
|
||||
SYSDEBUG("CreateProcess(`%hs`, `%hs`) -> %d", prog16, block->cmdline, rc);
|
||||
}
|
||||
} else {
|
||||
__winerr();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
@ -59,9 +60,11 @@ int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
|
|||
}
|
||||
}
|
||||
if (d != -1) {
|
||||
SYSDEBUG("sys_openat(0x%x, %s, %d, %d) -> %d", dirfd, file, flags, mode, d);
|
||||
SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %d", (long)dirfd, file, flags,
|
||||
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, d);
|
||||
} else {
|
||||
SYSDEBUG("sys_openat(0x%x, %s, %d, %d) -> %m", dirfd, file, flags, mode);
|
||||
SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %s", (long)dirfd, file, flags,
|
||||
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, strerror(errno));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
|
|
@ -153,8 +153,17 @@ ssize_t readansi(int fd, char *p, size_t n) {
|
|||
}
|
||||
break;
|
||||
case kEsc:
|
||||
if (0x20 <= c && c <= 0x2f) {
|
||||
t = kNf;
|
||||
if (0x20 <= c && c <= 0x2f) { /* Nf */
|
||||
/*
|
||||
* Almost no one uses ANSI Nf sequences
|
||||
* They overlaps with alt+graphic keystrokes
|
||||
* We care more about being able to type alt-/
|
||||
*/
|
||||
if (c == ' ' || c == '#') {
|
||||
t = kNf;
|
||||
} else {
|
||||
t = kDone;
|
||||
}
|
||||
} else if (0x30 <= c && c <= 0x3f) { /* Fp */
|
||||
t = kDone;
|
||||
} else if (0x20 <= c && c <= 0x5F) { /* Fe */
|
||||
|
@ -173,8 +182,6 @@ ssize_t readansi(int fd, char *p, size_t n) {
|
|||
case '_': /* DCS (Application Program Command) */
|
||||
t = kStr;
|
||||
break;
|
||||
case '\\':
|
||||
goto Whoopsie;
|
||||
default:
|
||||
t = kDone;
|
||||
break;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
|
@ -37,7 +38,9 @@
|
|||
|
||||
static textwindows ssize_t sys_readlinkat_nt_error(void) {
|
||||
uint32_t e;
|
||||
switch ((e = GetLastError())) {
|
||||
e = GetLastError();
|
||||
SYSDEBUG("sys_readlinkat_nt() error %d", e);
|
||||
switch (e) {
|
||||
case kNtErrorNotAReparsePoint:
|
||||
return einval();
|
||||
default:
|
||||
|
@ -56,7 +59,10 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
uint32_t e, i, j, n, mem;
|
||||
char16_t path16[PATH_MAX], *p;
|
||||
struct NtReparseDataBuffer *rdb;
|
||||
if (!buf) return efault();
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) {
|
||||
SYSDEBUG("sys_readlinkat_nt() failed b/c __mkntpathat() failed");
|
||||
return -1;
|
||||
}
|
||||
if (weaken(malloc)) {
|
||||
mem = 16384;
|
||||
rdb = weaken(malloc)(mem);
|
||||
|
@ -66,9 +72,9 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
rdb = (struct NtReparseDataBuffer *)buf;
|
||||
freeme = 0;
|
||||
} else {
|
||||
SYSDEBUG("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked");
|
||||
return enomem();
|
||||
}
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((h = CreateFile(path16, 0, 0, 0, kNtOpenExisting,
|
||||
kNtFileFlagOpenReparsePoint | kNtFileFlagBackupSemantics,
|
||||
0)) != -1) {
|
||||
|
@ -107,16 +113,20 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
|
|||
if (freeme || (intptr_t)(buf + j) <= (intptr_t)(p + i)) {
|
||||
rc = j;
|
||||
} else {
|
||||
SYSDEBUG("sys_readlinkat_nt() too many astral codepoints");
|
||||
rc = enametoolong();
|
||||
}
|
||||
} else {
|
||||
SYSDEBUG("sys_readlinkat_nt() should have kNtIoReparseTagSymlink");
|
||||
rc = einval();
|
||||
}
|
||||
} else {
|
||||
SYSDEBUG("DeviceIoControl(kNtFsctlGetReparsePoint) failed");
|
||||
rc = sys_readlinkat_nt_error();
|
||||
}
|
||||
CloseHandle(h);
|
||||
} else {
|
||||
SYSDEBUG("CreateFile(kNtFileFlagOpenReparsePoint) failed");
|
||||
rc = sys_readlinkat_nt_error();
|
||||
}
|
||||
if (freeme && weaken(free)) {
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -46,14 +49,19 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
||||
ssize_t bytes;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid(buf, bufsiz)) return efault();
|
||||
if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): code me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_readlinkat(dirfd, path, buf, bufsiz);
|
||||
if ((IsAsan() && !__asan_is_valid(buf, bufsiz)) || (bufsiz && !buf)) {
|
||||
bytes = efault();
|
||||
} else if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) {
|
||||
SYSDEBUG("TOOD: zipos support for readlinkat");
|
||||
bytes = enosys(); /* TODO(jart): code me */
|
||||
} else if (!IsWindows()) {
|
||||
bytes = sys_readlinkat(dirfd, path, buf, bufsiz);
|
||||
} else {
|
||||
return sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||
}
|
||||
SYSDEBUG("readlinkat(%d, %s, 0x%p, 0x%x) -> %d %s", (long)dirfd, path, buf,
|
||||
bufsiz, bytes, bytes != -1 ? "" : strerror(errno));
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
@ -160,6 +161,7 @@ restart:
|
|||
if (!check_dir) goto skip_readlink;
|
||||
}
|
||||
k = readlink(output, stack, p);
|
||||
if (k<0) SYSDEBUG("realpath readlink failed %d", (long)errno);
|
||||
if (k==p) goto toolong;
|
||||
if (!k) {
|
||||
errno = ENOENT;
|
||||
|
|
106
libc/calls/sigaltstack.c
Normal file
106
libc/calls/sigaltstack.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/metasigaltstack.h"
|
||||
#include "libc/calls/struct/sigaltstack.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static noasan void sigaltstack2bsd(struct sigaltstack_bsd *bsd,
|
||||
const struct sigaltstack *linux) {
|
||||
void *sp;
|
||||
int flags;
|
||||
size_t size;
|
||||
sp = linux->ss_sp;
|
||||
flags = linux->ss_flags;
|
||||
size = linux->ss_size;
|
||||
bsd->ss_sp = sp;
|
||||
bsd->ss_flags = flags;
|
||||
bsd->ss_size = size;
|
||||
}
|
||||
|
||||
static noasan void sigaltstack2linux(struct sigaltstack *linux,
|
||||
const struct sigaltstack_bsd *bsd) {
|
||||
void *sp;
|
||||
int flags;
|
||||
size_t size;
|
||||
sp = bsd->ss_sp;
|
||||
flags = bsd->ss_flags;
|
||||
size = bsd->ss_size;
|
||||
linux->ss_sp = sp;
|
||||
linux->ss_flags = flags;
|
||||
linux->ss_size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets and/or gets alternate signal stack, e.g.
|
||||
*
|
||||
* struct sigaction sa;
|
||||
* struct sigaltstack ss;
|
||||
* ss.ss_flags = 0;
|
||||
* ss.ss_size = SIGSTKSZ;
|
||||
* ss.ss_sp = malloc(ss.ss_size);
|
||||
* sa.sa_flags = SA_ONSTACK;
|
||||
* sa.sa_handler = OnStackOverflow;
|
||||
* __cxa_atexit(free, ss[0].ss_sp, 0);
|
||||
* sigemptyset(&sa.ss_mask);
|
||||
* sigaltstack(&ss, 0);
|
||||
* sigaction(SIGSEGV, &sa, 0);
|
||||
*
|
||||
* @param neu if non-null will install new signal alt stack
|
||||
* @param old if non-null will receive current signal alt stack
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
noasan int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
|
||||
int rc;
|
||||
void *a, *b;
|
||||
struct sigaltstack_bsd bsd;
|
||||
if (IsAsan() && ((old && __asan_check(old, sizeof(*old)).kind) ||
|
||||
(neu && (__asan_check(neu, sizeof(*neu)).kind ||
|
||||
__asan_check(neu->ss_sp, neu->ss_size).kind)))) {
|
||||
return efault();
|
||||
}
|
||||
if (IsLinux()) {
|
||||
a = neu;
|
||||
b = old;
|
||||
} else if (IsBsd()) {
|
||||
if (neu) {
|
||||
sigaltstack2bsd(&bsd, neu);
|
||||
a = &bsd;
|
||||
} else {
|
||||
a = 0;
|
||||
}
|
||||
if (old) {
|
||||
b = &bsd;
|
||||
} else {
|
||||
b = 0;
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
if ((rc = sys_sigaltstack(a, b)) != -1) {
|
||||
if (old) {
|
||||
sigaltstack2linux(old, &bsd);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -18,10 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/metasigaltstack.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/intrin/repstosb.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
||||
/**
|
||||
* @fileoverview XNU kernel callback normalization.
|
||||
|
@ -45,12 +48,6 @@ struct __darwin_siginfo {
|
|||
uint64_t __pad[7];
|
||||
};
|
||||
|
||||
struct __darwin_sigaltstack {
|
||||
void *ss_sp;
|
||||
uint64_t ss_size;
|
||||
int32_t ss_flags;
|
||||
};
|
||||
|
||||
struct __darwin_mmst_reg {
|
||||
char __mmst_reg[10];
|
||||
char __mmst_rsrv[6];
|
||||
|
@ -368,7 +365,7 @@ struct __darwin_mcontext64 {
|
|||
struct __darwin_ucontext {
|
||||
int32_t uc_onstack;
|
||||
uint32_t uc_sigmask;
|
||||
struct __darwin_sigaltstack uc_stack;
|
||||
struct sigaltstack_bsd uc_stack;
|
||||
struct __darwin_ucontext *uc_link;
|
||||
uint64_t uc_mcsize;
|
||||
struct __darwin_mcontext64 *uc_mcontext;
|
||||
|
@ -387,7 +384,7 @@ noasan static void linuxexceptionstate2xnu(
|
|||
}
|
||||
|
||||
noasan static void xnuthreadstate2linux(
|
||||
ucontext_t *uc, mcontext_t *mc, struct __darwin_x86_thread_state64 *xnuss) {
|
||||
mcontext_t *mc, struct __darwin_x86_thread_state64 *xnuss) {
|
||||
mc->rdi = xnuss->__rdi;
|
||||
mc->rsi = xnuss->__rsi;
|
||||
mc->rbp = xnuss->__rbp;
|
||||
|
@ -401,7 +398,6 @@ noasan static void xnuthreadstate2linux(
|
|||
mc->gs = xnuss->__gs;
|
||||
mc->fs = xnuss->__fs;
|
||||
mc->eflags = xnuss->__rflags;
|
||||
uc->uc_flags = xnuss->__rflags;
|
||||
mc->r8 = xnuss->__r8;
|
||||
mc->r9 = xnuss->__r9;
|
||||
mc->r10 = xnuss->__r10;
|
||||
|
@ -427,7 +423,6 @@ noasan static void linuxthreadstate2xnu(
|
|||
xnuss->__gs = mc->gs;
|
||||
xnuss->__fs = mc->fs;
|
||||
xnuss->__rflags = mc->eflags;
|
||||
xnuss->__rflags = uc->uc_flags;
|
||||
xnuss->__r8 = mc->r8;
|
||||
xnuss->__r9 = mc->r9;
|
||||
xnuss->__r10 = mc->r10;
|
||||
|
@ -484,6 +479,7 @@ noasan void __sigenter_xnu(void *fn, int infostyle, int sig,
|
|||
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;
|
||||
|
@ -498,8 +494,7 @@ noasan void __sigenter_xnu(void *fn, int infostyle, int sig,
|
|||
if (xnuctx->uc_mcsize >=
|
||||
(sizeof(struct __darwin_x86_exception_state64) +
|
||||
sizeof(struct __darwin_x86_thread_state64))) {
|
||||
xnuthreadstate2linux(&g.uc, &g.uc.uc_mcontext,
|
||||
&xnuctx->uc_mcontext->__ss);
|
||||
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);
|
||||
|
|
15
libc/calls/struct/metasigaltstack.h
Normal file
15
libc/calls/struct/metasigaltstack.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_METASIGALTSTACK_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_METASIGALTSTACK_H_
|
||||
#include "libc/calls/struct/sigaltstack.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sigaltstack_bsd {
|
||||
void *ss_sp;
|
||||
uint64_t ss_size;
|
||||
int32_t ss_flags;
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_METASIGALTSTACK_H_ */
|
|
@ -14,7 +14,60 @@ struct sigaction { /* cosmo abi */
|
|||
void (*sa_restorer)(void);
|
||||
struct sigset sa_mask;
|
||||
int64_t __pad;
|
||||
} forcealign(8);
|
||||
};
|
||||
|
||||
sighandler_t signal(int, sighandler_t);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void _init_onntconsoleevent(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
#ifndef __SIGACTION_YOINK
|
||||
#define __SIGACTION_YOINK(SIG) \
|
||||
do { \
|
||||
if (SupportsWindows()) { \
|
||||
if (__builtin_constant_p(SIG)) { \
|
||||
switch (SIG) { \
|
||||
case SIGINT: \
|
||||
case SIGQUIT: \
|
||||
case SIGHUP: \
|
||||
case SIGTERM: \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
break; \
|
||||
case SIGTRAP: \
|
||||
case SIGILL: \
|
||||
case SIGSEGV: \
|
||||
case SIGABRT: \
|
||||
case SIGFPE: \
|
||||
YOINK(_init_wincrash); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
YOINK(_init_wincrash); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define sigaction(SIG, ACT, OLD) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
sigaction(SIG, (ACT), OLD); \
|
||||
})
|
||||
|
||||
#define signal(SIG, HAND) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
signal(SIG, HAND); \
|
||||
})
|
||||
|
||||
#endif /* GNU && !ANSI */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_H_ */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGALTSTACK_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGALTSTACK_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sigaltstack {
|
||||
void *ss_sp;
|
||||
|
@ -10,5 +11,8 @@ struct sigaltstack {
|
|||
|
||||
typedef struct sigaltstack stack_t;
|
||||
|
||||
int sigaltstack(const struct sigaltstack *, struct sigaltstack *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGALTSTACK_H_ */
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/mem/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
|
@ -29,6 +31,9 @@ int unsetenv(const char *s) {
|
|||
for (j = 0;; ++j) {
|
||||
if (!s[j]) {
|
||||
if (p[i][j] == '=') {
|
||||
if (weaken(__freeenv)) {
|
||||
weaken(__freeenv)(p[i]);
|
||||
}
|
||||
k = i + 1;
|
||||
do {
|
||||
p[k - 1] = p[k];
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -29,8 +31,13 @@
|
|||
* @note this is a code-size saving device
|
||||
*/
|
||||
privileged noasan int64_t __winerr(void) {
|
||||
errno_t e;
|
||||
if (IsWindows()) {
|
||||
errno = GetLastError();
|
||||
e = GetLastError();
|
||||
if (weaken(__dos2errno)) {
|
||||
e = weaken(__dos2errno)(e);
|
||||
}
|
||||
errno = e;
|
||||
return -1;
|
||||
} else {
|
||||
return enosys();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue