mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Make improvements
- Get threads working on NetBSD - Get threads working on OpenBSD - Fix Emacs config for Emacs v28 - Improve --strace logging of sigset_t - Improve --strace logging of struct stat - Improve memory safety of DescribeThing functions - Refactor auto stack allocation into LIBC_RUNTIME - Introduce shell.com example which works on Windows - Refactor __strace_thing into DescribeThing functions - Document the CHECK macros and improve them in NDEBUG mode - Rewrite MAP_STACK so it uses FreeBSD behavior across platforms - Deprecate and discourage the use of MAP_GROWSDOWN (it's weird)
This commit is contained in:
parent
dd9ab01d25
commit
e7611a8476
101 changed files with 967 additions and 464 deletions
88
examples/check.c
Normal file
88
examples/check.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/log/check.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Check Macros
|
||||
*
|
||||
* The simplest assertion is:
|
||||
*
|
||||
* assert(123 == x);
|
||||
*
|
||||
* This has some downsides:
|
||||
*
|
||||
* 1. It's nice to know what `x` is when it crashes
|
||||
* 2. It's sometimes nice to have the check always take effect.
|
||||
* 3. It's problematic that assert() can't do __builtin_assume()
|
||||
*
|
||||
* Cosmopolitan provides alternative macros like:
|
||||
*
|
||||
* - `CHECK(EXPR, ...)`
|
||||
* - `CHECK_EQ(WANT, GOT, ...)`
|
||||
* - `CHECK_NE(WANT, GOT, ...)`
|
||||
* - `CHECK_GT(WANT, GOT, ...)`
|
||||
* - `CHECK_LT(WANT, GOT, ...)`
|
||||
* - `CHECK_NOTNULL(EXPR, ...)`
|
||||
*
|
||||
* The CHECK macros always happen. They always kill the process when
|
||||
* they fail. Printf formatting information may be provided as extra
|
||||
* arguments. On the other hand, there exists:
|
||||
*
|
||||
* - `DCHECK(EXPR, ...)`
|
||||
* - `DCHECK_EQ(WANT, GOT, ...)`
|
||||
* - `DCHECK_NE(WANT, GOT, ...)`
|
||||
* - `DCHECK_GT(WANT, GOT, ...)`
|
||||
* - `DCHECK_LT(WANT, GOT, ...)`
|
||||
* - `DCHECK_NOTNULL(EXPR, ...)`
|
||||
*
|
||||
* The DCHECK macros always happen when NDEBUG isn't defined. When
|
||||
* NDEBUG is defined, they still happen, but in a special way that
|
||||
* causes the compiler to recognize their failure as undefined behavior.
|
||||
* What this means is that, if the provided expressions are pure without
|
||||
* side-effects, then the code compiles down to nothing and the compiler
|
||||
* may be able to use the knowledge of something being the case in order
|
||||
* to optimize other code adjacent to your DCHECK.
|
||||
*
|
||||
* In the default build modes, this prints lots of information:
|
||||
*
|
||||
* error:examples/check.c:23:check.com: check failed on nightmare pid 15412
|
||||
* CHECK_EQ(123, some_source_code);
|
||||
* → 0x7b (123)
|
||||
* == 0x64 (some_source_code)
|
||||
* extra info: hello
|
||||
* EUNKNOWN/0/No error information
|
||||
* ./o//examples/check.com
|
||||
* 0x0000000000407404: __die at libc/log/die.c:42
|
||||
* 0x0000000000407340: __check_fail at libc/log/checkfail.c:73
|
||||
* 0x00000000004071d0: main at examples/check.c:23
|
||||
* 0x000000000040256e: cosmo at libc/runtime/cosmo.S:69
|
||||
* 0x000000000040217d: _start at libc/crt/crt.S:85
|
||||
*
|
||||
* In NDEBUG mode (e.g. MODE=rel, MODE=tiny, etc.) this prints a much
|
||||
* simpler message that, most importantly, doesn't include any source
|
||||
* code, although it still includes the file name for reference.
|
||||
*
|
||||
* error:examples/check.c:14: check failed: 123 == 100: extra info: hello
|
||||
*
|
||||
* That way your release binaries won't leak CI. You may optionally link
|
||||
* the following functions to further expand the information shown by
|
||||
* the NDEBUG check failure:
|
||||
*
|
||||
* STATIC_YOINK("__die");
|
||||
* STATIC_YOINK("strerror");
|
||||
*
|
||||
* Please note that backtraces aren't ever available in MODE=tiny.
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int some_source_code = 100;
|
||||
CHECK_EQ(123, some_source_code, "extra info: %s", "hello");
|
||||
return 0;
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
* o//examples/crashreport.com
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
noubsan int main(int argc, char *argv[]) {
|
||||
volatile int64_t x;
|
||||
ShowCrashReports();
|
||||
return 1 / (x = 0);
|
||||
|
|
14
examples/exit.c
Normal file
14
examples/exit.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/fmt/conv.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return atoi(argc > 1 ? argv[1] : "0");
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -37,12 +38,12 @@ static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
|
|||
lim.rlim_cur = MIN(soft, lim.rlim_max);
|
||||
if (!setrlimit(resource, &lim)) {
|
||||
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
||||
__strace_rlimit_name(resource), lim.rlim_cur, lim.rlim_max);
|
||||
DescribeRlimitName(resource), lim.rlim_cur, lim.rlim_max);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
|
||||
__strace_rlimit_name(resource), soft, hard);
|
||||
DescribeRlimitName(resource), soft, hard);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -63,9 +64,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
for (i = 0; i < RLIM_NLIMITS; ++i) {
|
||||
rc = getrlimit(i, &rlim);
|
||||
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n",
|
||||
__strace_rlimit_name(i), rlim.rlim_cur, rlim.rlim_max, rc,
|
||||
!rc ? "" : strerror(errno));
|
||||
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n", DescribeRlimitName(i),
|
||||
rlim.rlim_cur, rlim.rlim_max, rc, !rc ? "" : strerror(errno));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
172
examples/shell.c
Normal file
172
examples/shell.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/linenoise/linenoise.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Shell that works on Windows.
|
||||
*
|
||||
* This doesn't have script language features like UNBOURNE.COM but it
|
||||
* works on Windows and, unlike CMD.EXE, actually has CTRL-P and CTRL-R
|
||||
* which alone make it so much better.
|
||||
*
|
||||
* One day we'll have UNBOURNE.COM working on Windows but the code isn't
|
||||
* very maintainable sadly.
|
||||
*/
|
||||
|
||||
static void AddUniqueCompletion(linenoiseCompletions *c, char *s) {
|
||||
size_t i;
|
||||
if (!s) return;
|
||||
for (i = 0; i < c->len; ++i) {
|
||||
if (!strcmp(s, c->cvec[i])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
c->cvec = realloc(c->cvec, ++c->len * sizeof(*c->cvec));
|
||||
c->cvec[c->len - 1] = s;
|
||||
}
|
||||
|
||||
static void CompleteFilename(const char *p, const char *q, const char *b,
|
||||
linenoiseCompletions *c) {
|
||||
DIR *d;
|
||||
char *buf;
|
||||
const char *g;
|
||||
struct dirent *e;
|
||||
if ((buf = malloc(512))) {
|
||||
if ((g = memrchr(p, '/', q - p))) {
|
||||
*(char *)mempcpy(buf, p, MIN(g - p, 511)) = 0;
|
||||
p = ++g;
|
||||
} else {
|
||||
strcpy(buf, ".");
|
||||
}
|
||||
if ((d = opendir(buf))) {
|
||||
while ((e = readdir(d))) {
|
||||
if (!strcmp(e->d_name, ".")) continue;
|
||||
if (!strcmp(e->d_name, "..")) continue;
|
||||
if (!strncmp(e->d_name, p, q - p)) {
|
||||
snprintf(buf, 512, "%.*s%s%s", p - b, b, e->d_name,
|
||||
e->d_type == DT_DIR ? "/" : "");
|
||||
AddUniqueCompletion(c, strdup(buf));
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void ShellCompletion(const char *p, linenoiseCompletions *c) {
|
||||
bool slashed;
|
||||
const char *q, *b;
|
||||
for (slashed = false, b = p, q = (p += strlen(p)); p > b; --p) {
|
||||
if (p[-1] == '/' && p[-1] == '\\') slashed = true;
|
||||
if (!isalnum(p[-1]) &&
|
||||
(p[-1] != '.' && p[-1] != '_' && p[-1] != '-' && p[-1] != '+' &&
|
||||
p[-1] != '[' && p[-1] != '/' && p[-1] != '\\')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CompleteFilename(p, q, b, c);
|
||||
}
|
||||
|
||||
static char *ShellHint(const char *p, const char **ansi1, const char **ansi2) {
|
||||
char *h = 0;
|
||||
linenoiseCompletions c = {0};
|
||||
ShellCompletion(p, &c);
|
||||
if (c.len == 1) {
|
||||
h = strdup(c.cvec[0] + strlen(p));
|
||||
}
|
||||
linenoiseFreeCompletions(&c);
|
||||
return h;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int n, ws, pid;
|
||||
char *prog, path[PATH_MAX];
|
||||
sigset_t chldmask, savemask;
|
||||
struct sigaction ignore, saveint, savequit;
|
||||
char *p, *line, **args, *arg, *start, *state, prompt[64];
|
||||
linenoiseSetFreeHintsCallback(free);
|
||||
linenoiseSetHintsCallback(ShellHint);
|
||||
linenoiseSetCompletionCallback(ShellCompletion);
|
||||
stpcpy(prompt, "$ ");
|
||||
while ((line = linenoiseWithHistory(prompt, "cmd"))) {
|
||||
n = 0;
|
||||
start = line;
|
||||
args = xcalloc(1, sizeof(*args));
|
||||
while ((arg = strtok_r(start, " \t\r\n", &state))) {
|
||||
args = xrealloc(args, (++n + 1) * sizeof(*args));
|
||||
args[n - 1] = arg;
|
||||
args[n - 0] = 0;
|
||||
start = 0;
|
||||
}
|
||||
if (n > 0) {
|
||||
if ((prog = commandv(args[0], path, sizeof(path)))) {
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
|
||||
if (!fork()) {
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
execv(prog, args);
|
||||
_Exit(127);
|
||||
}
|
||||
|
||||
wait(&ws);
|
||||
p = prompt;
|
||||
if (WIFEXITED(ws)) {
|
||||
if (WEXITSTATUS(ws)) {
|
||||
if (!__nocolor) p = stpcpy(p, "\e[1;31m");
|
||||
p = stpcpy(p, "rc=");
|
||||
p = FormatInt32(p, WEXITSTATUS(ws));
|
||||
if (!__nocolor) p = stpcpy(p, "\e[0m");
|
||||
*p++ = ' ';
|
||||
}
|
||||
} else {
|
||||
if (!__nocolor) p = stpcpy(p, "\e[1;31m");
|
||||
p = stpcpy(p, "rc=");
|
||||
p = stpcpy(p, strsignal(WTERMSIG(ws)));
|
||||
if (!__nocolor) p = stpcpy(p, "\e[0m");
|
||||
*p++ = ' ';
|
||||
}
|
||||
p = stpcpy(p, "$ ");
|
||||
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s: command not found\n", argv[0], args[0]);
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
free(args);
|
||||
}
|
||||
}
|
|
@ -68,6 +68,10 @@ $(LIBC_CALLS_A).pkg: \
|
|||
o/$(MODE)/libc/calls/vdsofunc.greg.o \
|
||||
o/$(MODE)/libc/calls/directmap.o \
|
||||
o/$(MODE)/libc/calls/directmap-nt.o \
|
||||
o/$(MODE)/libc/calls/mapstack.greg.o \
|
||||
o/$(MODE)/libc/calls/getcwd.greg.o \
|
||||
o/$(MODE)/libc/calls/getcwd-xnu.greg.o \
|
||||
o/$(MODE)/libc/calls/getprogramexecutablename.greg.o \
|
||||
o/$(MODE)/libc/calls/raise.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
-ffreestanding \
|
||||
|
@ -116,7 +120,6 @@ o/$(MODE)/libc/calls/renameat-nt.o \
|
|||
o/$(MODE)/libc/calls/execve-sysv.o \
|
||||
o/$(MODE)/libc/calls/symlinkat-nt.o \
|
||||
o/$(MODE)/libc/calls/readlinkat-nt.o \
|
||||
o/$(MODE)/libc/calls/describeopenflags.greg.o \
|
||||
o/$(MODE)/libc/calls/mkntenvblock.o: \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -70,7 +71,7 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
|
|||
}
|
||||
if (!__time_critical) {
|
||||
STRACE("clock_gettime(%d, [%s]) → %d% m", clockid,
|
||||
__strace_timespec(buf, sizeof(buf), rc, ts), rc);
|
||||
DescribeTimespec(buf, sizeof(buf), rc, ts), rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,16 +16,23 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
privileged const char *__strace_sigaction(char *buf, size_t bufsize, int rc,
|
||||
const struct sigaction *sa) {
|
||||
char maskbuf[41];
|
||||
const char *DescribeSigaction(char *buf, size_t bufsize, int rc,
|
||||
const struct sigaction *sa) {
|
||||
char maskbuf[64];
|
||||
if (rc == -1) return "n/a";
|
||||
if (!sa) return "NULL";
|
||||
ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
|
||||
sa->sa_handler, sa->sa_flags,
|
||||
__strace_sigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
|
||||
if ((!IsAsan() && kisdangerous(sa)) ||
|
||||
(IsAsan() && !__asan_is_valid(sa, sizeof(*sa)))) {
|
||||
ksnprintf(buf, sizeof(buf), "%p", sa);
|
||||
} else {
|
||||
ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
|
||||
sa->sa_handler, sa->sa_flags,
|
||||
DescribeSigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
|
||||
}
|
||||
return buf;
|
||||
}
|
|
@ -16,14 +16,49 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/bits/popcnt.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *DescribeSigset(char *buf, size_t bufsize, int rc,
|
||||
const sigset_t *ss) {
|
||||
bool gotsome;
|
||||
int i, n, sig;
|
||||
sigset_t sigset;
|
||||
|
||||
privileged const char *__strace_stat(int rc, const struct stat *st) {
|
||||
static char buf[256];
|
||||
if (rc == -1) return "n/a";
|
||||
if (!st) return "NULL";
|
||||
ksnprintf(buf, sizeof(buf), "{.st_size=%'ld, .st_mode=%#o, .st_ino=%'lu}",
|
||||
st->st_size, st->st_mode, st->st_ino);
|
||||
if (!ss) return "NULL";
|
||||
if ((!IsAsan() && kisdangerous(ss)) ||
|
||||
(IsAsan() && !__asan_is_valid(ss, sizeof(*ss)))) {
|
||||
ksnprintf(buf, sizeof(buf), "%p", ss);
|
||||
return buf;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
n = bufsize;
|
||||
sigset = *ss;
|
||||
gotsome = false;
|
||||
if (popcnt(sigset.__bits[0]) + popcnt(sigset.__bits[1]) > 64) {
|
||||
i += ksnprintf(buf + i, n - i, "~");
|
||||
sigset.__bits[0] = ~sigset.__bits[0];
|
||||
sigset.__bits[1] = ~sigset.__bits[1];
|
||||
}
|
||||
i += ksnprintf(buf + i, n - i, "{");
|
||||
for (sig = 1; sig < 128; ++sig) {
|
||||
if (sigismember(&sigset, sig)) {
|
||||
if (gotsome) {
|
||||
sig += ksnprintf(buf + sig, n - sig, ", ");
|
||||
} else {
|
||||
gotsome = true;
|
||||
}
|
||||
sig += ksnprintf(buf + sig, n - sig, "%s", strsignal(sig));
|
||||
}
|
||||
}
|
||||
i += ksnprintf(buf + i, n - i, "}");
|
||||
|
||||
return buf;
|
||||
}
|
|
@ -48,7 +48,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
handle = kNtInvalidHandleValue;
|
||||
}
|
||||
|
||||
if (flags & MAP_PRIVATE) {
|
||||
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||
sec = 0; // MAP_PRIVATE isn't inherited across fork()
|
||||
} else {
|
||||
sec = &kNtIsInheritable; // MAP_SHARED gives us zero-copy fork()
|
||||
|
@ -60,14 +60,13 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
// note that open-nt.c always requests an kNtGenericExecute accessmask
|
||||
iscow = false;
|
||||
if (handle != -1) {
|
||||
if (flags & MAP_PRIVATE) {
|
||||
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||
// 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 {
|
||||
assert(flags & MAP_SHARED);
|
||||
if ((g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY) {
|
||||
fl = (struct ProtectNt){kNtPageExecuteRead,
|
||||
kNtFileMapRead | kNtFileMapExecute};
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -50,7 +51,7 @@ int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
|||
} else {
|
||||
rc = sys_faccessat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
STRACE("faccessat(%s, %#s, %#o, %#x) → %d% m", __strace_dirfd(buf, dirfd),
|
||||
STRACE("faccessat(%s, %#s, %#o, %#x) → %d% m", DescribeDirfd(buf, dirfd),
|
||||
path, mode, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -51,7 +52,7 @@ int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
|||
} else {
|
||||
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
STRACE("fchmodat(%s, %#s, %#o, %d) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
STRACE("fchmodat(%s, %#s, %#o, %d) → %d% m", DescribeDirfd(buf, dirfd), path,
|
||||
mode, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -49,7 +50,7 @@ int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
|||
} else {
|
||||
rc = sys_fchownat(dirfd, path, uid, gid, flags);
|
||||
}
|
||||
STRACE("fchownat(%s, %#s, %d, %d, %#b) → %d% m", __strace_dirfd(sb, dirfd),
|
||||
STRACE("fchownat(%s, %#s, %d, %d, %#b) → %d% m", DescribeDirfd(sb, dirfd),
|
||||
path, uid, gid, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -45,6 +46,6 @@ int fstat(int fd, struct stat *st) {
|
|||
} else {
|
||||
rc = sys_fstat_nt(__getfdhandleactual(fd), st);
|
||||
}
|
||||
STRACE("fstat(%d, [%s]) → %d% m", fd, __strace_stat(rc, st), rc);
|
||||
STRACE("fstat(%d, [%s]) → %d% m", fd, DescribeStat(rc, st), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -70,7 +71,7 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
|||
} else {
|
||||
rc = sys_fstatat_nt(dirfd, path, st, flags);
|
||||
}
|
||||
STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
__strace_stat(rc, st), __strace_fstatat_flags(flags), rc);
|
||||
STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", DescribeDirfd(buf, dirfd), path,
|
||||
DescribeStat(rc, st), __strace_fstatat_flags(flags), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -48,7 +49,7 @@ int getrlimit(int resource, struct rlimit *rlim) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("getrlimit(%s, [%s]) → %d% m", __strace_rlimit_name(resource),
|
||||
__strace_rlimit(buf, sizeof(buf), rc, rlim), rc);
|
||||
STRACE("getrlimit(%s, [%s]) → %d% m", DescribeRlimitName(resource),
|
||||
DescribeRlimit(buf, sizeof(buf), rc, rlim), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -52,7 +53,7 @@ int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
|||
rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||
}
|
||||
STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m",
|
||||
__strace_dirfd(buf[0], olddirfd), oldpath,
|
||||
__strace_dirfd(buf[1], newdirfd), newpath, flags, rc);
|
||||
DescribeDirfd(buf[0], olddirfd), oldpath,
|
||||
DescribeDirfd(buf[1], newdirfd), newpath, flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -50,7 +51,7 @@ int mkdirat(int dirfd, const char *path, unsigned mode) {
|
|||
} else {
|
||||
rc = sys_mkdirat_nt(dirfd, path, mode);
|
||||
}
|
||||
STRACE("mkdirat(%s, %#s, %#o) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
mode, rc);
|
||||
STRACE("mkdirat(%s, %#s, %#o) → %d% m", DescribeDirfd(buf, dirfd), path, mode,
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -45,8 +46,8 @@ noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
|
|||
}
|
||||
if (!__time_critical) {
|
||||
STRACE("nanosleep(%s, [%s]) → %d% m",
|
||||
__strace_timespec(buf[0], sizeof(buf[0]), rc, req),
|
||||
__strace_timespec(buf[1], sizeof(buf[1]), rc, rem), rc);
|
||||
DescribeTimespec(buf[0], sizeof(buf[0]), rc, req),
|
||||
DescribeTimespec(buf[1], sizeof(buf[1]), rc, rem), rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
@ -75,7 +76,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
} else {
|
||||
rc = efault();
|
||||
}
|
||||
STRACE("openat(%s, %#s, %s, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
|
||||
STRACE("openat(%s, %#s, %s, %#o) → %d% m", DescribeDirfd(buf, dirfd), file,
|
||||
DescribeOpenFlags(flags), (flags & (O_CREAT | O_TMPFILE)) ? mode : 0,
|
||||
rc);
|
||||
return rc;
|
||||
|
|
|
@ -84,20 +84,22 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
|||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("poll(%p, %'lu, %'d) → %d% lm", fds, nfds, timeout_ms, rc);
|
||||
kprintf(STRACE_PROLOGUE "poll(");
|
||||
if ((!IsAsan() && kisdangerous(fds)) ||
|
||||
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
|
||||
kprintf("%p", fds);
|
||||
} else {
|
||||
char flagbuf[2][64];
|
||||
kprintf(STRACE_PROLOGUE "poll({");
|
||||
kprintf("[{");
|
||||
for (i = 0; i < MIN(5, nfds); ++i) {
|
||||
kprintf(
|
||||
"%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
|
||||
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
|
||||
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
||||
}
|
||||
kprintf("%s}, %'zu, %'d) → %d% lm\n", i == 5 ? "..." : "", nfds,
|
||||
timeout_ms, rc);
|
||||
kprintf("%s}]", i == 5 ? "..." : "");
|
||||
}
|
||||
kprintf(", %'zu, %'d) → %d% lm\n", nfds, timeout_ms, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
|
@ -113,13 +114,9 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
|||
rc = Preadv(fd, iov, iovlen, off);
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("preadv(%d, %p, %d, %'ld) → %'zd% m", fd, iov, iovlen, off, rc);
|
||||
} else {
|
||||
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
|
@ -118,13 +119,9 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
|||
rc = Pwritev(fd, iov, iovlen, off);
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("pwritev(%d, %p, %d, %'ld) → %'zd% m", fd, iov, iovlen, off, rc);
|
||||
} else {
|
||||
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -53,7 +54,7 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
|||
} else {
|
||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||
}
|
||||
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", __strace_dirfd(sb, dirfd),
|
||||
path, MAX(0, bytes), buf, bytes);
|
||||
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(sb, dirfd), path,
|
||||
MAX(0, bytes), buf, bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -71,7 +72,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
|||
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
} else {
|
||||
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d) → %'ld% m\n", iovlen, rc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -57,7 +58,7 @@ int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
|||
} else {
|
||||
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||
}
|
||||
STRACE("renameat(%s, %#s, %s, %#s) → %d% m", __strace_dirfd(buf[0], olddirfd),
|
||||
oldpath, __strace_dirfd(buf[1], newdirfd), newpath, rc);
|
||||
STRACE("renameat(%s, %#s, %s, %#s) → %d% m", DescribeDirfd(buf[0], olddirfd),
|
||||
oldpath, DescribeDirfd(buf[1], newdirfd), newpath, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -82,7 +83,7 @@ int setrlimit(int resource, const struct rlimit *rlim) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("setrlimit(%s, %s) → %d% m", __strace_rlimit_name(resource),
|
||||
__strace_rlimit(buf, sizeof(buf), 0, rlim), rc);
|
||||
STRACE("setrlimit(%s, %s) → %d% m", DescribeRlimitName(resource),
|
||||
DescribeRlimit(buf, sizeof(buf), 0, rlim), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
|
@ -449,7 +450,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
|||
rc = __sigaction(sig, act, oldact);
|
||||
}
|
||||
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
|
||||
__strace_sigaction(buf[0], sizeof(buf[0]), 0, act),
|
||||
__strace_sigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
|
||||
DescribeSigaction(buf[0], sizeof(buf[0]), 0, act),
|
||||
DescribeSigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -78,7 +79,7 @@ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
|
|||
*opt_out_oldset = old;
|
||||
}
|
||||
STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how),
|
||||
__strace_sigset(buf[0], sizeof(buf[0]), 0, opt_set),
|
||||
__strace_sigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
|
||||
DescribeSigset(buf[0], sizeof(buf[0]), 0, opt_set),
|
||||
DescribeSigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
|
@ -47,7 +48,7 @@ int sigsuspend(const sigset_t *ignore) {
|
|||
char buf[41];
|
||||
long ms, totoms;
|
||||
sigset_t save, mask, *arg;
|
||||
STRACE("sigsuspend(%s) → ...", __strace_sigset(buf, sizeof(buf), 0, ignore));
|
||||
STRACE("sigsuspend(%s) → ...", DescribeSigset(buf, sizeof(buf), 0, ignore));
|
||||
if (IsAsan() && ignore && !__asan_is_valid(ignore, sizeof(*ignore))) {
|
||||
rc = efault();
|
||||
} else if (IsXnu() || IsOpenbsd()) {
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _KERNTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
||||
|
||||
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
|
||||
|
||||
|
@ -53,14 +53,6 @@ COSMOPOLITAN_C_START_
|
|||
extern int __strace;
|
||||
|
||||
void __stracef(const char *, ...);
|
||||
void __strace_iov(const struct iovec *, int, ssize_t);
|
||||
const char *__strace_stat(int, const struct stat *);
|
||||
const char *__strace_sigaction(char *, size_t, int, const struct sigaction *);
|
||||
const char *__strace_sigset(char[41], size_t, int, const sigset_t *);
|
||||
const char *__strace_rlimit_name(int);
|
||||
const char *__strace_rlimit(char[41], size_t, int, const struct rlimit *);
|
||||
const char *__strace_timespec(char[45], size_t, int, const struct timespec *);
|
||||
const char *__strace_dirfd(char[12], int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -1,58 +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 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/strace.internal.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
|
||||
const char *__strace_rlimit_name(int resource) {
|
||||
static char buf[12];
|
||||
if (resource != 127) {
|
||||
if (resource == RLIMIT_AS) return "RLIMIT_AS";
|
||||
if (resource == RLIMIT_CPU) return "RLIMIT_CPU";
|
||||
if (resource == RLIMIT_FSIZE) return "RLIMIT_FSIZE";
|
||||
if (resource == RLIMIT_NPROC) return "RLIMIT_NPROC";
|
||||
if (resource == RLIMIT_NOFILE) return "RLIMIT_NOFILE";
|
||||
if (resource == RLIMIT_RSS) return "RLIMIT_RSS";
|
||||
if (resource == RLIMIT_DATA) return "RLIMIT_DATA";
|
||||
if (resource == RLIMIT_CORE) return "RLIMIT_CORE";
|
||||
if (resource == RLIMIT_STACK) return "RLIMIT_STACK";
|
||||
if (resource == RLIMIT_SIGPENDING) return "RLIMIT_SIGPENDING";
|
||||
if (resource == RLIMIT_MEMLOCK) return "RLIMIT_MEMLOCK";
|
||||
if (resource == RLIMIT_LOCKS) return "RLIMIT_LOCKS";
|
||||
if (resource == RLIMIT_MSGQUEUE) return "RLIMIT_MSGQUEUE";
|
||||
if (resource == RLIMIT_NICE) return "RLIMIT_NICE";
|
||||
if (resource == RLIMIT_RTPRIO) return "RLIMIT_RTPRIO";
|
||||
if (resource == RLIMIT_RTTIME) return "RLIMIT_RTTIME";
|
||||
if (resource == RLIMIT_SWAP) return "RLIMIT_SWAP";
|
||||
if (resource == RLIMIT_SBSIZE) return "RLIMIT_SBSIZE";
|
||||
if (resource == RLIMIT_NPTS) return "RLIMIT_NPTS";
|
||||
}
|
||||
FormatInt32(buf, resource);
|
||||
return buf;
|
||||
}
|
||||
|
||||
privileged const char *__strace_rlimit(char buf[64], size_t bufsize, int rc,
|
||||
const struct rlimit *rlim) {
|
||||
if (rc == -1) return "n/a";
|
||||
if (!rlim) return "NULL";
|
||||
ksnprintf(buf, bufsize, "{%'ld, %'ld}", rlim->rlim_cur, rlim->rlim_max);
|
||||
return buf;
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -50,6 +51,6 @@ int symlinkat(const char *target, int newdirfd, const char *linkpath) {
|
|||
rc = sys_symlinkat_nt(target, newdirfd, linkpath);
|
||||
}
|
||||
STRACE("symlinkat(%#s, %s, %#s) → %d% m", target,
|
||||
__strace_dirfd(buf, newdirfd), linkpath);
|
||||
DescribeDirfd(buf, newdirfd), linkpath);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -49,7 +50,7 @@ int unlinkat(int dirfd, const char *path, int flags) {
|
|||
} else {
|
||||
rc = sys_unlinkat_nt(dirfd, path, flags);
|
||||
}
|
||||
STRACE("unlinkat(%s, %#s, %#b) → %d% m", __strace_dirfd(buf, dirfd), path,
|
||||
STRACE("unlinkat(%s, %#s, %#b) → %d% m", DescribeDirfd(buf, dirfd), path,
|
||||
flags, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -49,10 +50,10 @@ int utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
|||
}
|
||||
if (ts) {
|
||||
STRACE("utimensat(%s, %#s, {{%,ld, %,ld}, {%,ld, %,ld}}, %#b) → %d% m",
|
||||
__strace_dirfd(buf, dirfd), path, ts[0].tv_sec, ts[0].tv_nsec,
|
||||
DescribeDirfd(buf, dirfd), path, ts[0].tv_sec, ts[0].tv_nsec,
|
||||
ts[1].tv_sec, ts[1].tv_nsec, flags, rc);
|
||||
} else {
|
||||
STRACE("utimensat(%s, %#s, 0, %#b) → %d% m", __strace_dirfd(buf, dirfd),
|
||||
STRACE("utimensat(%s, %#s, 0, %#b) → %d% m", DescribeDirfd(buf, dirfd),
|
||||
path, flags, rc);
|
||||
}
|
||||
return rc;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -74,13 +75,9 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
} else {
|
||||
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||
}
|
||||
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1282,7 +1282,10 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
|||
int prot, flag;
|
||||
struct DirectMap sm;
|
||||
struct MemoryIntervals *m;
|
||||
assert(!OverlapsShadowSpace((void *)p, n));
|
||||
if (OverlapsShadowSpace((void *)p, n)) {
|
||||
kprintf("error: %p size %'zu overlaps shadow space\n", p, n);
|
||||
_Exit(1);
|
||||
}
|
||||
m = weaken(_mmi);
|
||||
a = (0x7fff8000 + (p >> 3)) >> 16;
|
||||
b = (0x7fff8000 + (p >> 3) + (n >> 3) + 0xffff) >> 16;
|
||||
|
|
|
@ -46,6 +46,7 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
|
|||
} else {
|
||||
rc = 24;
|
||||
}
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
__restorewintty();
|
||||
_Exit(rc);
|
||||
}
|
|
@ -16,11 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
privileged const char *__strace_dirfd(char buf[12], int dirfd) {
|
||||
const char *DescribeDirfd(char buf[hasatleast 12], int dirfd) {
|
||||
if (dirfd == AT_FDCWD) return "AT_FDCWD";
|
||||
FormatInt32(buf, dirfd);
|
||||
return buf;
|
|
@ -1,5 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -15,8 +21,15 @@ const char *DescribeFlags(char *, size_t, struct DescribeFlags *, size_t,
|
|||
const char *DescribeMapFlags(int);
|
||||
const char *DescribeProtFlags(int);
|
||||
const char *DescribeRemapFlags(int);
|
||||
const char *DescribeRlimitName(int);
|
||||
const char *DescribeSeccompOperationFlags(int);
|
||||
const char *DescribePollFlags(char *, size_t, int);
|
||||
const char *DescribeStat(int, const struct stat *);
|
||||
const char *DescribeDirfd(char[hasatleast 12], int);
|
||||
const char *DescribeSigaction(char *, size_t, int, const struct sigaction *);
|
||||
const char *DescribeSigset(char *, size_t, int, const sigset_t *);
|
||||
const char *DescribeRlimit(char *, size_t, int, const struct rlimit *);
|
||||
const char *DescribeTimespec(char *, size_t, int, const struct timespec *);
|
||||
|
||||
const char *DescribeNtPageFlags(uint32_t);
|
||||
const char *DescribeNtStartFlags(uint32_t);
|
||||
|
@ -35,6 +48,8 @@ const char *DescribeNtConsoleModeOutputFlags(uint32_t);
|
|||
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
|
||||
|
||||
void DescribeIov(const struct iovec *, int, ssize_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_ */
|
||||
|
|
|
@ -16,12 +16,19 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
void __strace_iov(const struct iovec *iov, int iovlen, ssize_t rem) {
|
||||
void DescribeIov(const struct iovec *iov, int iovlen, ssize_t rem) {
|
||||
int i;
|
||||
if ((!IsAsan() && kisdangerous(iov)) ||
|
||||
(IsAsan() && !__asan_is_valid(iov, iovlen * sizeof(struct iovec)))) {
|
||||
kprintf("%p", iov);
|
||||
return;
|
||||
}
|
||||
kprintf("{");
|
||||
for (i = 0; rem && i < MIN(5, iovlen); ++i) {
|
||||
kprintf(
|
|
@ -25,6 +25,7 @@
|
|||
const char *DescribeMapFlags(int x) {
|
||||
_Alignas(char) static char mapflags[256];
|
||||
const struct DescribeFlags kMapFlags[] = {
|
||||
{MAP_STACK, "STACK"}, // order matters
|
||||
{MAP_ANONYMOUS, "ANONYMOUS"}, //
|
||||
{MAP_PRIVATE, "PRIVATE"}, //
|
||||
{MAP_SHARED, "SHARED"}, //
|
||||
|
@ -37,7 +38,6 @@ const char *DescribeMapFlags(int x) {
|
|||
{MAP_NORESERVE, "NORESERVE"}, //
|
||||
{MAP_NONBLOCK, "NONBLOCK"}, //
|
||||
{MAP_POPULATE, "POPULATE"}, //
|
||||
{MAP_STACK, "STACK"}, // order matters
|
||||
};
|
||||
return DescribeFlags(mapflags, sizeof(mapflags), kMapFlags,
|
||||
ARRAYLEN(kMapFlags), "MAP_", x);
|
||||
|
|
|
@ -28,6 +28,8 @@ static noasan char DescribeMapType(int flags) {
|
|||
return 'p';
|
||||
case MAP_SHARED:
|
||||
return 's';
|
||||
case MAP_STACK:
|
||||
return 'S';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
|
@ -46,7 +48,7 @@ noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
|
|||
DescribeProt(prot, p);
|
||||
p[3] = DescribeMapType(flags);
|
||||
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
|
||||
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';
|
||||
p[5] = (flags & MAP_GROWSDOWN) ? 'G' : '-';
|
||||
p[6] = (flags & MAP_FIXED) ? 'F' : '-';
|
||||
p[7] = 0;
|
||||
return p;
|
|
@ -17,12 +17,19 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
privileged const char *__strace_sigset(char buf[41], size_t bufsize, int rc,
|
||||
const sigset_t *ss) {
|
||||
const char *DescribeRlimit(char *buf, size_t bufsize, int rc,
|
||||
const struct rlimit *rlim) {
|
||||
if (rc == -1) return "n/a";
|
||||
if (!ss) return "NULL";
|
||||
ksnprintf(buf, bufsize, "{%#lx, %#lx}", ss->__bits[0], ss->__bits[1]);
|
||||
if (!rlim) return "NULL";
|
||||
if ((!IsAsan() && kisdangerous(rlim)) ||
|
||||
(IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||
ksnprintf(buf, sizeof(buf), "%p", rlim);
|
||||
} else {
|
||||
ksnprintf(buf, bufsize, "{%'ld, %'ld}", rlim->rlim_cur, rlim->rlim_max);
|
||||
}
|
||||
return buf;
|
||||
}
|
47
libc/intrin/describerlimit_name.greg.c
Normal file
47
libc/intrin/describerlimit_name.greg.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- 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/strace.internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
|
||||
const char *DescribeRlimitName(int resource) {
|
||||
static char buf[12];
|
||||
if (resource == 127) return "n/a";
|
||||
if (resource == RLIMIT_AS) return "RLIMIT_AS";
|
||||
if (resource == RLIMIT_CPU) return "RLIMIT_CPU";
|
||||
if (resource == RLIMIT_FSIZE) return "RLIMIT_FSIZE";
|
||||
if (resource == RLIMIT_NPROC) return "RLIMIT_NPROC";
|
||||
if (resource == RLIMIT_NOFILE) return "RLIMIT_NOFILE";
|
||||
if (resource == RLIMIT_RSS) return "RLIMIT_RSS";
|
||||
if (resource == RLIMIT_DATA) return "RLIMIT_DATA";
|
||||
if (resource == RLIMIT_CORE) return "RLIMIT_CORE";
|
||||
if (resource == RLIMIT_STACK) return "RLIMIT_STACK";
|
||||
if (resource == RLIMIT_SIGPENDING) return "RLIMIT_SIGPENDING";
|
||||
if (resource == RLIMIT_MEMLOCK) return "RLIMIT_MEMLOCK";
|
||||
if (resource == RLIMIT_LOCKS) return "RLIMIT_LOCKS";
|
||||
if (resource == RLIMIT_MSGQUEUE) return "RLIMIT_MSGQUEUE";
|
||||
if (resource == RLIMIT_NICE) return "RLIMIT_NICE";
|
||||
if (resource == RLIMIT_RTPRIO) return "RLIMIT_RTPRIO";
|
||||
if (resource == RLIMIT_RTTIME) return "RLIMIT_RTTIME";
|
||||
if (resource == RLIMIT_SWAP) return "RLIMIT_SWAP";
|
||||
if (resource == RLIMIT_SBSIZE) return "RLIMIT_SBSIZE";
|
||||
if (resource == RLIMIT_NPTS) return "RLIMIT_NPTS";
|
||||
FormatInt32(buf, resource);
|
||||
return buf;
|
||||
}
|
85
libc/intrin/describestat.greg.c
Normal file
85
libc/intrin/describestat.greg.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*-*- 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/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
const char *DescribeStat(int rc, const struct stat *st) {
|
||||
_Alignas(char) static char buf[300];
|
||||
int i, n;
|
||||
|
||||
if (rc == -1) return "n/a";
|
||||
if (!st) return "NULL";
|
||||
if ((!IsAsan() && kisdangerous(st)) ||
|
||||
(IsAsan() && !__asan_is_valid(st, sizeof(*st)))) {
|
||||
ksnprintf(buf, sizeof(buf), "%p", st);
|
||||
return buf;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
n = sizeof(buf);
|
||||
|
||||
i += ksnprintf(buf + i, n - i, "{.st_%s=%'ld", "size", st->st_size);
|
||||
|
||||
if (st->st_blocks) {
|
||||
i +=
|
||||
ksnprintf(buf + i, n - i, ", .st_blocks=%'lu/512", st->st_blocks * 512);
|
||||
}
|
||||
|
||||
if (st->st_mode) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%#o", "mode", st->st_mode);
|
||||
}
|
||||
|
||||
if (st->st_nlink != 1) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "nlink", st->st_nlink);
|
||||
}
|
||||
|
||||
if (st->st_uid) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "uid", st->st_uid);
|
||||
}
|
||||
|
||||
if (st->st_gid) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "gid", st->st_gid);
|
||||
}
|
||||
|
||||
if (st->st_ino) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "ino", st->st_ino);
|
||||
}
|
||||
|
||||
if (st->st_gen) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "gen", st->st_gen);
|
||||
}
|
||||
|
||||
if (st->st_flags) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%lx", "flags", st->st_flags);
|
||||
}
|
||||
|
||||
if (st->st_rdev) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "rdev", st->st_rdev);
|
||||
}
|
||||
|
||||
if (st->st_blksize != PAGESIZE) {
|
||||
i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "blksize", st->st_blksize);
|
||||
}
|
||||
|
||||
buf[i++] = '}';
|
||||
|
||||
return buf;
|
||||
}
|
|
@ -16,14 +16,20 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
|
||||
privileged const char *__strace_timespec(char buf[45], size_t bufsize, int rc,
|
||||
const struct timespec *ts) {
|
||||
const char *DescribeTimespec(char *buf, size_t bufsize, int rc,
|
||||
const struct timespec *ts) {
|
||||
if (rc == -1) return "n/a";
|
||||
if (!ts) return "NULL";
|
||||
ksnprintf(buf, bufsize, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
|
||||
if ((!IsAsan() && kisdangerous(ts)) ||
|
||||
(IsAsan() && !__asan_is_valid(ts, sizeof(*ts)))) {
|
||||
ksnprintf(buf, bufsize, "%p", ts);
|
||||
} else {
|
||||
ksnprintf(buf, bufsize, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
|
||||
}
|
||||
return buf;
|
||||
}
|
|
@ -68,17 +68,22 @@ o/$(MODE)/libc/intrin/tls.greg.o \
|
|||
o/$(MODE)/libc/intrin/exit.greg.o \
|
||||
o/$(MODE)/libc/intrin/exit1.greg.o \
|
||||
o/$(MODE)/libc/intrin/gettid.greg.o \
|
||||
o/$(MODE)/libc/intrin/getenv.greg.o \
|
||||
o/$(MODE)/libc/intrin/createfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/assertfail.greg.o \
|
||||
o/$(MODE)/libc/intrin/reopenfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/deletefile.greg.o \
|
||||
o/$(MODE)/libc/intrin/createpipe.greg.o \
|
||||
o/$(MODE)/libc/intrin/closehandle.greg.o \
|
||||
o/$(MODE)/libc/intrin/describeiov.greg.o \
|
||||
o/$(MODE)/libc/intrin/openprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/createthread.greg.o \
|
||||
o/$(MODE)/libc/intrin/describestat.greg.o \
|
||||
o/$(MODE)/libc/intrin/findnextfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/createprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/findfirstfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/describeflags.greg.o \
|
||||
o/$(MODE)/libc/intrin/describerlimit.greg.o \
|
||||
o/$(MODE)/libc/intrin/removedirectory.greg.o \
|
||||
o/$(MODE)/libc/intrin/createnamedpipe.greg.o \
|
||||
o/$(MODE)/libc/intrin/unmapviewoffile.greg.o \
|
||||
|
@ -88,6 +93,7 @@ o/$(MODE)/libc/intrin/createdirectory.greg.o \
|
|||
o/$(MODE)/libc/intrin/flushfilebuffers.greg.o \
|
||||
o/$(MODE)/libc/intrin/terminateprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/describemapflags.greg.o \
|
||||
o/$(MODE)/libc/intrin/describetimespec.greg.o \
|
||||
o/$(MODE)/libc/intrin/getfileattributes.greg.o \
|
||||
o/$(MODE)/libc/intrin/getexitcodeprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/waitforsingleobject.greg.o \
|
||||
|
@ -104,6 +110,10 @@ o/$(MODE)/libc/intrin/ntconsolemode.o: \
|
|||
-ffreestanding \
|
||||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/intrin/describeopenflags.greg.o: \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
o/$(MODE)/libc/intrin/asan.o \
|
||||
o/$(MODE)/libc/intrin/ubsan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
|
|
|
@ -520,10 +520,13 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
type = 0;
|
||||
goto FormatString;
|
||||
} else {
|
||||
if (p + 4 <= e) {
|
||||
if (p + 7 <= e) {
|
||||
*p++ = ' ';
|
||||
*p++ = 'e';
|
||||
*p++ = 'r';
|
||||
*p++ = 'r';
|
||||
*p++ = 'n';
|
||||
*p++ = 'o';
|
||||
*p++ = '=';
|
||||
}
|
||||
type = 0;
|
||||
|
@ -568,7 +571,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
if (!__replstderr || __nocolor) {
|
||||
break;
|
||||
} else {
|
||||
s = "\r\033[K";
|
||||
s = "\r\e[K";
|
||||
goto FormatString;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,19 +24,20 @@ COSMOPOLITAN_C_START_
|
|||
#define DCHECK_NOTNULL(X, ...) \
|
||||
__DCHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
|
||||
|
||||
#define CHECK_ALIGNED(BYTES, VAR) \
|
||||
do { \
|
||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||
__check_fail_aligned(BYTES, (uintptr_t)VAR); \
|
||||
unreachable; \
|
||||
} \
|
||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||
#define CHECK_ALIGNED(BYTES, VAR, ...) \
|
||||
do { \
|
||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||
__check_fail_aligned(BYTES, (uintptr_t)VAR, __FILE__, __LINE__, \
|
||||
"" __VA_ARGS__); \
|
||||
unreachable; \
|
||||
} \
|
||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||
} while (0)
|
||||
|
||||
#define DCHECK_ALIGNED(BYTES, VAR) \
|
||||
#define DCHECK_ALIGNED(BYTES, VAR, ...) \
|
||||
do { \
|
||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR); \
|
||||
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR, "" __VA_ARGS__); \
|
||||
unreachable; \
|
||||
} \
|
||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||
|
@ -51,7 +52,8 @@ COSMOPOLITAN_C_START_
|
|||
__check_fail(#SUFFIX, #OP, (uint64_t)Want, (WANTSTR), (uint64_t)Got, \
|
||||
(GOTSTR), __FILE__, __LINE__, __VA_ARGS__); \
|
||||
} else { \
|
||||
__check_fail_##SUFFIX((uint64_t)Want, (uint64_t)Got); \
|
||||
__check_fail_##SUFFIX((uint64_t)Want, (uint64_t)Got, __FILE__, \
|
||||
__LINE__, 0, __VA_ARGS__); \
|
||||
} \
|
||||
unreachable; \
|
||||
} \
|
||||
|
@ -72,22 +74,30 @@ COSMOPOLITAN_C_START_
|
|||
#endif /* NDEBUG */
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define __DCHK_ALIGNED(BYTES, VAR)
|
||||
#define __DCHK_ALIGNED(BYTES, VAR, ...)
|
||||
#else
|
||||
#define __DCHK_ALIGNED(BYTES, VAR) __check_fail_aligned(BYTES, VAR)
|
||||
#define __DCHK_ALIGNED(BYTES, VAR, ...) \
|
||||
__check_fail_aligned(BYTES, VAR, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
void __check_fail(const char *, const char *, uint64_t, const char *, uint64_t,
|
||||
const char *, const char *, int, const char *,
|
||||
...) relegated wontreturn;
|
||||
|
||||
void __check_fail_eq(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_ne(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_le(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_lt(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_ge(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_gt(uint64_t, uint64_t) relegated wontreturn;
|
||||
void __check_fail_aligned(unsigned, uint64_t) relegated wontreturn;
|
||||
void __check_fail_eq(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_ne(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_le(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_lt(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_ge(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_gt(uint64_t, uint64_t, const char *, int, const char *,
|
||||
const char *, ...) relegated wontreturn;
|
||||
void __check_fail_aligned(unsigned, uint64_t, const char *, int, const char *,
|
||||
...) relegated wontreturn;
|
||||
|
||||
#ifdef __VSCODE_INTELLISENSE__
|
||||
#undef __CHK
|
||||
|
|
|
@ -18,14 +18,16 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void __check_fail_aligned(unsigned bytes, uint64_t ptr) {
|
||||
void __check_fail_aligned(unsigned bytes, uint64_t ptr, const char *file,
|
||||
int line, const char *fmt, ...) {
|
||||
fflush(stderr);
|
||||
if (!IsTiny()) memsummary(fileno(stderr));
|
||||
(dprintf)(fileno(stderr), "%s%d%s%#p\n", "error: pointer not ", bytes,
|
||||
"-byte aligned: ", ptr);
|
||||
kprintf("%s:%d: error: pointer not %d-byte aligned: %p\n", file, line, bytes,
|
||||
ptr);
|
||||
__die();
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Handles failure of CHECK_xx() macros in -DNDEBUG mode.
|
||||
|
@ -33,12 +33,22 @@
|
|||
*
|
||||
* @see libc/log/thunks/__check_fail_ndebug.S
|
||||
*/
|
||||
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
||||
const char *opchar) {
|
||||
relegated wontreturn void __check_fail_ndebug(uint64_t want, uint64_t got,
|
||||
const char *file, int line,
|
||||
const char *opchar,
|
||||
const char *fmt, ...) {
|
||||
va_list va;
|
||||
__restore_tty();
|
||||
(fprintf)(stderr, "\n%serror: %s: check failed: 0x%x %s 0x%x (%s)\n",
|
||||
!__nocolor ? "\e[J" : "", program_invocation_name, want, opchar,
|
||||
got, strerror(errno));
|
||||
kprintf("%rerror:%s:%d: check failed: %'ld %s %'ld% m", file, line, want,
|
||||
opchar, got);
|
||||
if (*fmt) {
|
||||
kprintf(": ");
|
||||
va_start(va, fmt);
|
||||
kvprintf(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
kprintf("\n");
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
__restorewintty();
|
||||
_Exit(68);
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
|||
uname(&names);
|
||||
p = buf;
|
||||
errno = err;
|
||||
kprintf("\n%serror%s: Uncaught %G (%s) on %s pid %d\n"
|
||||
kprintf("\n%serror%s: Uncaught %G (%s) on %s pid %d tid %d\n"
|
||||
" %s\n"
|
||||
" %m\n"
|
||||
" %s %s %s %s\n",
|
||||
|
@ -210,8 +210,8 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
|||
ctx->uc_mcontext.rsp <= GetStaticStackAddr(0) + PAGESIZE))
|
||||
? "Stack Overflow"
|
||||
: GetSiCodeName(sig, si->si_code),
|
||||
host, getpid(), program_invocation_name, names.sysname, names.version,
|
||||
names.nodename, names.release);
|
||||
host, getpid(), gettid(), program_invocation_name, names.sysname,
|
||||
names.version, names.nodename, names.release);
|
||||
if (ctx) {
|
||||
kprintf("\n");
|
||||
ShowFunctionCalls(ctx);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigaltstack.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -33,6 +35,10 @@ STATIC_YOINK("__get_symbol_by_addr"); /* for asan memory origin */
|
|||
|
||||
extern const unsigned char __oncrash_thunks[8][11];
|
||||
|
||||
static void FreeSigaltstack(void *p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs crash signal handlers.
|
||||
*
|
||||
|
@ -67,7 +73,7 @@ void ShowCrashReports(void) {
|
|||
ss.ss_flags = 0;
|
||||
ss.ss_size = SIGSTKSZ;
|
||||
ss.ss_sp = malloc(SIGSTKSZ);
|
||||
__cxa_atexit(free, ss.ss_sp, 0);
|
||||
__cxa_atexit(FreeSigaltstack, ss.ss_sp, 0);
|
||||
sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
|
||||
sigfillset(&sa.sa_mask);
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
||||
__check_fail_eq:
|
||||
loadstr "==",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_eq,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz "=="
|
||||
.previous
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_GE() in NDEBUG mode.
|
||||
__check_fail_ge:
|
||||
loadstr ">=",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_ge,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz ">="
|
||||
.previous
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_GT() in NDEBUG mode.
|
||||
__check_fail_gt:
|
||||
loadstr ">",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_gt,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz ">"
|
||||
.previous
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_LE() in NDEBUG mode.
|
||||
__check_fail_le:
|
||||
loadstr "<=",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_le,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz "<="
|
||||
.previous
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_LT() in NDEBUG mode.
|
||||
__check_fail_lt:
|
||||
loadstr "<",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_lt,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz "<"
|
||||
.previous
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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/macros.internal.h"
|
||||
|
||||
__check_fail_ndebug:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call ___check_fail_ndebug
|
||||
pop %rbp
|
||||
jmp __die # fewer elements in backtrace
|
||||
.endfn __check_fail_ndebug,globl
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
// Code-size saving thunk for CHECK_NE() in NDEBUG mode.
|
||||
__check_fail_ne:
|
||||
loadstr "!=",dx
|
||||
lea .Lop(%rip),%r8
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_ne,globl
|
||||
|
||||
.rodata.str1.1
|
||||
.Lop: .asciz "!="
|
||||
.previous
|
||||
|
|
|
@ -38,7 +38,6 @@ __nt2sysv:
|
|||
push %rdi
|
||||
push %rsi
|
||||
pushf
|
||||
ezlea _base,bx
|
||||
lea -0x80(%rbp),%rdi
|
||||
call _savexmm
|
||||
mov %rcx,%rdi
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/notice.inc"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/dce.h"
|
||||
.text.startup
|
||||
|
||||
|
@ -76,6 +76,44 @@ cosmo: push %rbp
|
|||
ret
|
||||
.endfn cosmo,weak
|
||||
|
||||
#if !IsTiny()
|
||||
.init.start 304,_init_stack
|
||||
testb IsWindows()
|
||||
jnz 9f
|
||||
push %rdi
|
||||
push %rsi
|
||||
// allocate stack
|
||||
movabs $ape_stack_vaddr,%rdi
|
||||
mov $ape_stack_memsz,%esi
|
||||
mov $ape_stack_prot,%edx
|
||||
mov $MAP_STACK,%ecx
|
||||
or MAP_ANONYMOUS,%ecx
|
||||
or $-1,%r8
|
||||
xor %r9d,%r9d
|
||||
push %rsi
|
||||
call mmap
|
||||
pop %r8
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
cmp $-1,%rax
|
||||
je 9f
|
||||
// switch stacks
|
||||
leave
|
||||
pop %rcx
|
||||
lea (%rax,%r8),%rsp
|
||||
sub $ape_stack_align,%rsp # openbsd:stackbound
|
||||
mov %rbp,(%rsp)
|
||||
push %rcx
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
9: nop
|
||||
.init.end 304,_init_stack
|
||||
.weak ape_stack_prot
|
||||
.weak ape_stack_vaddr
|
||||
.weak ape_stack_memsz
|
||||
.weak ape_stack_align
|
||||
#endif
|
||||
|
||||
#ifdef __PG__
|
||||
.init.start 306,_init_ftrace
|
||||
push %rdi
|
||||
|
|
|
@ -122,6 +122,15 @@ static textwindows void ViewOrDie(int64_t h, uint32_t access, size_t pos,
|
|||
}
|
||||
}
|
||||
|
||||
static textwindows int OnForkCrash(struct NtExceptionPointers *ep) {
|
||||
kprintf("error: fork() child crashed!%n"
|
||||
"\tExceptionCode = %#x%n"
|
||||
"\tRip = %x%n",
|
||||
ep->ExceptionRecord->ExceptionCode,
|
||||
ep->ContextRecord ? ep->ContextRecord->Rip : -1);
|
||||
ExitProcess(73);
|
||||
}
|
||||
|
||||
textwindows void WinMainForked(void) {
|
||||
bool ok;
|
||||
jmp_buf jb;
|
||||
|
@ -129,9 +138,9 @@ textwindows void WinMainForked(void) {
|
|||
char *addr, *shad;
|
||||
struct DirectMap dm;
|
||||
uint64_t size, upsize;
|
||||
int64_t savetsc, savebir;
|
||||
struct MemoryInterval *maps;
|
||||
char16_t fvar[21 + 1 + 21 + 1];
|
||||
int64_t oncrash, savetsc, savebir;
|
||||
uint32_t i, varlen, oldprot, savepid;
|
||||
long mapcount, mapcapacity, specialz;
|
||||
extern uint64_t ts asm("kStartTsc");
|
||||
|
@ -142,6 +151,9 @@ textwindows void WinMainForked(void) {
|
|||
if (!varlen || varlen >= ARRAYLEN(fvar)) return;
|
||||
NTTRACE("WinMainForked()");
|
||||
SetEnvironmentVariable(u"_FORK", NULL);
|
||||
#ifdef SYSDEBUG
|
||||
oncrash = AddVectoredExceptionHandler(1, NT2SYSV(OnForkCrash));
|
||||
#endif
|
||||
ParseInt(fvar, &reader);
|
||||
|
||||
// read the cpu state from the parent process & plus
|
||||
|
@ -167,7 +179,7 @@ textwindows void WinMainForked(void) {
|
|||
for (i = 0; i < mapcount; ++i) {
|
||||
addr = (char *)((uint64_t)maps[i].x << 16);
|
||||
size = maps[i].size;
|
||||
if (maps[i].flags & MAP_PRIVATE) {
|
||||
if ((maps[i].flags & MAP_TYPE) != MAP_SHARED) {
|
||||
upsize = ROUNDUP(size, FRAMESIZE);
|
||||
// we don't need to close the map handle because sys_mmap_nt
|
||||
// doesn't mark it inheritable across fork() for MAP_PRIVATE
|
||||
|
@ -226,6 +238,9 @@ textwindows void WinMainForked(void) {
|
|||
}
|
||||
|
||||
// restore the crash reporting stuff
|
||||
#ifdef SYSDEBUG
|
||||
RemoveVectoredExceptionHandler(oncrash);
|
||||
#endif
|
||||
if (weaken(__wincrash_nt)) {
|
||||
if (!IsTiny()) {
|
||||
RemoveVectoredExceptionHandler(__wincrashearly);
|
||||
|
@ -292,7 +307,7 @@ textwindows int sys_fork_nt(void) {
|
|||
(_mmi.i * sizeof(_mmi.p[0])) >> 3);
|
||||
}
|
||||
for (i = 0; i < _mmi.i && ok; ++i) {
|
||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||
if ((_mmi.p[i].flags & MAP_TYPE) != MAP_SHARED) {
|
||||
ok = WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
|
||||
_mmi.p[i].size);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,12 @@
|
|||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define MAP_ANONYMOUS_linux 0x00000020
|
||||
#define MAP_ANONYMOUS_openbsd 0x00001000
|
||||
#define MAP_GROWSDOWN_linux 0x00000100
|
||||
#define MAP_STACK_freebsd 0x00000400
|
||||
#define MAP_STACK_openbsd 0x00004000
|
||||
|
||||
#define IP(X) (intptr_t)(X)
|
||||
#define VIP(X) (void *)IP(X)
|
||||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||
|
@ -122,20 +128,9 @@ noasan static size_t GetMemtrackSize(struct MemoryIntervals *mm) {
|
|||
return n;
|
||||
}
|
||||
|
||||
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n) {
|
||||
struct DirectMap dm;
|
||||
dm = sys_mmap(addr, size, prot, f, fd, off);
|
||||
if (UNLIKELY(dm.addr == MAP_FAILED)) {
|
||||
if (IsWindows() && (flags & MAP_FIXED)) {
|
||||
OnUnrecoverableMmapError(
|
||||
"can't recover from MAP_FIXED errors on Windows");
|
||||
}
|
||||
return MAP_FAILED;
|
||||
}
|
||||
if (UNLIKELY(dm.addr != addr)) {
|
||||
OnUnrecoverableMmapError("KERNEL DIDN'T RESPECT MAP_FIXED");
|
||||
}
|
||||
static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n,
|
||||
struct DirectMap dm) {
|
||||
if (!IsWindows() && (flags & MAP_FIXED)) {
|
||||
if (UntrackMemoryIntervals(addr, size)) {
|
||||
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
||||
|
@ -154,6 +149,23 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
|||
return addr;
|
||||
}
|
||||
|
||||
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n) {
|
||||
struct DirectMap dm;
|
||||
dm = sys_mmap(addr, size, prot, f, fd, off);
|
||||
if (UNLIKELY(dm.addr == MAP_FAILED)) {
|
||||
if (IsWindows() && (flags & MAP_FIXED)) {
|
||||
OnUnrecoverableMmapError(
|
||||
"can't recover from MAP_FIXED errors on Windows");
|
||||
}
|
||||
return MAP_FAILED;
|
||||
}
|
||||
if (UNLIKELY(dm.addr != addr)) {
|
||||
OnUnrecoverableMmapError("KERNEL DIDN'T RESPECT MAP_FIXED");
|
||||
}
|
||||
return FinishMemory(addr, size, prot, flags, fd, off, f, x, n, dm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps memory from system, one frame at a time.
|
||||
*
|
||||
|
@ -175,8 +187,8 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
|
|||
sz = size - m;
|
||||
dm = sys_mmap(addr + m, sz, prot, f, fd, oi);
|
||||
if (dm.addr == MAP_FAILED) return MAP_FAILED;
|
||||
iscow = (flags & MAP_PRIVATE) && fd != -1;
|
||||
readonlyfile = (flags & MAP_SHARED) && fd != -1 &&
|
||||
iscow = (flags & MAP_TYPE) != MAP_SHARED && fd != -1;
|
||||
readonlyfile = (flags & MAP_TYPE) == MAP_SHARED && fd != -1 &&
|
||||
(g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY;
|
||||
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
|
||||
flags, readonlyfile, iscow, oi, sz) == -1) {
|
||||
|
@ -208,6 +220,7 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
}
|
||||
#endif
|
||||
char *p = addr;
|
||||
bool needguard;
|
||||
struct DirectMap dm;
|
||||
size_t virtualused, virtualneed;
|
||||
int a, b, i, f, m, n, x;
|
||||
|
@ -311,19 +324,68 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(enomem());
|
||||
}
|
||||
|
||||
needguard = false;
|
||||
p = (char *)ADDR(x);
|
||||
if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */
|
||||
dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off);
|
||||
if (dm.addr == MAP_FAILED) {
|
||||
return MAP_FAILED;
|
||||
if ((f & MAP_TYPE) == MAP_STACK) {
|
||||
if (~f & MAP_ANONYMOUS) {
|
||||
STRACE("MAP_STACK must be anonymous");
|
||||
return VIP(einval());
|
||||
}
|
||||
f &= ~MAP_TYPE;
|
||||
f |= MAP_PRIVATE;
|
||||
if (IsOpenbsd()) { // openbsd:dubstack
|
||||
// on openbsd this is less about scalability of threads, and more
|
||||
// about defining the legal intervals for the RSP register. sadly
|
||||
// openbsd doesn't let us create a new fixed stack mapping. but..
|
||||
// openbsd does allow us to overwrite existing fixed mappings, to
|
||||
// authorize its usage as a stack.
|
||||
if (sys_mmap(p, size, prot, f, fd, off).addr == MAP_FAILED) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
f |= MAP_STACK_openbsd;
|
||||
} else if (IsLinux()) {
|
||||
// by default MAP_GROWSDOWN will auto-allocate 10mb of pages. it's
|
||||
// supposed to stop growing if an adjacent allocation exists, to
|
||||
// prevent your stacks from overlapping on each other. we're not
|
||||
// able to easily assume a mapping beneath this one exists. even
|
||||
// if we could, the linux kernel requires for muh security reasons
|
||||
// that stacks be at least 1mb away from each other, so it's not
|
||||
// possible to avoid this call if our goal is to have 60kb stacks
|
||||
// with 4kb guards like a sane multithreaded production system.
|
||||
// however this 1mb behavior oddly enough is smart enough to not
|
||||
// apply if the mapping is a manually-created guard page.
|
||||
if ((dm = sys_mmap(p + size - PAGESIZE, PAGESIZE, prot,
|
||||
f | MAP_GROWSDOWN_linux, fd, off))
|
||||
.addr == MAP_FAILED) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
sys_mmap(p, PAGESIZE, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1, 0);
|
||||
dm.addr = p;
|
||||
return FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm);
|
||||
} else {
|
||||
if (IsFreebsd()) {
|
||||
f |= MAP_STACK_freebsd;
|
||||
}
|
||||
needguard = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsWindows()) {
|
||||
return MapMemory(p, size, prot, flags, fd, off, f, x, n);
|
||||
p = MapMemory(p, size, prot, flags, fd, off, f, x, n);
|
||||
} else {
|
||||
return MapMemories(p, size, prot, flags, fd, off, f, x, n);
|
||||
p = MapMemories(p, size, prot, flags, fd, off, f, x, n);
|
||||
}
|
||||
|
||||
if (p != MAP_FAILED) {
|
||||
if (needguard) {
|
||||
if (IsWindows()) _spunlock(&_mmi.lock);
|
||||
mprotect(p, PAGESIZE, PROT_NONE);
|
||||
if (IsWindows()) _spinlock(&_mmi.lock);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
|
|
@ -87,7 +87,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
|
|||
kprintf(".control=%#.*hhs, ", msg->msg_controllen, msg->msg_control);
|
||||
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
|
||||
kprintf(".iov=", fd);
|
||||
__strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
|
||||
DescribeIov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("}], %#x) → %'ld% m\n", flags, rc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -45,6 +46,7 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
|
|||
int64_t rc;
|
||||
char addr2[128];
|
||||
struct msghdr msg2;
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_msghdr(msg)) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
|
@ -77,22 +79,26 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
|
|||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (!msg || (rc == -1 && errno == EFAULT)) {
|
||||
DATATRACE("sendmsg(%d, %p, %#x) → %'ld% m", fd, msg, flags, rc);
|
||||
kprintf(STRACE_PROLOGUE "sendmsg(");
|
||||
if ((!IsAsan() && kisdangerous(msg)) ||
|
||||
(IsAsan() && !__asan_is_valid(msg, sizeof(*msg)))) {
|
||||
kprintf("%p", msg);
|
||||
} else {
|
||||
kprintf(STRACE_PROLOGUE "sendmsg(%d, {");
|
||||
if (msg->msg_namelen)
|
||||
kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name);
|
||||
kprintf("{");
|
||||
kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name);
|
||||
if (msg->msg_controllen)
|
||||
kprintf(".control=%#.*hhs, ", msg->msg_controllen, msg->msg_control);
|
||||
kprintf(", .control=%#.*hhs, ", msg->msg_controllen, msg->msg_control);
|
||||
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
|
||||
kprintf(".iov=", fd);
|
||||
__strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("}, %#x) → %'ld% m\n", flags, rc);
|
||||
kprintf(", .iov=", fd);
|
||||
DescribeIov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("}");
|
||||
}
|
||||
kprintf(", %#x) → %'ld% m\n", flags, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -221,20 +221,20 @@ syscon compat O_LARGEFILE 0 0 0 0 0 0 #
|
|||
syscon compat MAP_FILE 0 0 0 0 0 0 # consensus
|
||||
syscon mmap MAP_SHARED 1 1 1 1 1 1 # forced consensus & faked nt
|
||||
syscon mmap MAP_PRIVATE 2 2 2 2 2 2 # forced consensus & faked nt
|
||||
syscon mmap MAP_STACK 6 6 6 6 6 6 # our definition
|
||||
syscon mmap MAP_TYPE 15 15 15 15 15 15 # mask for type of mapping
|
||||
syscon mmap MAP_FIXED 0x0000010 0x0000010 0x0000010 0x0000010 0x0000010 0x0000010 # unix consensus; openbsd appears to forbid; faked nt
|
||||
syscon mmap MAP_FIXED_NOREPLACE 0x8000000 0x8000000 0x8000000 0x8000000 0x8000000 0x8000000 # handled and defined by cosmo runtime; 0x100000 on linux 4.7+
|
||||
syscon mmap MAP_ANONYMOUS 0x20 0x1000 0x0001000 0x1000 0x1000 0x20 # bsd consensus; faked nt
|
||||
syscon mmap MAP_GROWSDOWN 0x0100 0 0x0000400 0x4000 0x4000 0x100000 # mandatory for OpenBSD stacks; MAP_STACK on Free/OpenBSD; MEM_TOP_DOWN on NT
|
||||
syscon mmap MAP_CONCEAL 0 0 0x0020000 0x8000 0x8000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
|
||||
syscon mmap MAP_NORESERVE 0x4000 0x40 0 0 64 0 # Linux calls it "reserve"; NT calls it "commit"? which is default?
|
||||
syscon mmap MAP_HUGETLB 0x040000 0 0 0 0 0x80000000 # kNtSecLargePages
|
||||
syscon mmap MAP_FIXED 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 # unix consensus; openbsd appears to forbid; faked nt
|
||||
syscon mmap MAP_FIXED_NOREPLACE 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 # handled and defined by cosmo runtime; 0x100000 on linux 4.7+
|
||||
syscon mmap MAP_ANONYMOUS 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt
|
||||
syscon mmap MAP_GROWSDOWN 0x00000100 0 0 0 0 0 # use MAP_STACK; abstracted by MAP_STACK; may be passed to __sys_mmap() for low-level Linux fiddling
|
||||
syscon mmap MAP_CONCEAL 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
|
||||
syscon mmap MAP_LOCKED 0x00002000 0 0 0 0 0
|
||||
syscon mmap MAP_NORESERVE 0x00004000 0x00000040 0 0 0x00000040 0 # Linux calls it "reserve"; NT calls it "commit"? which is default?
|
||||
syscon mmap MAP_POPULATE 0x00008000 0 0 0 0 0 # can avoid madvise(MADV_WILLNEED) on private file mapping
|
||||
syscon mmap MAP_NONBLOCK 0x00010000 0 0 0 0 0
|
||||
syscon mmap MAP_HUGETLB 0x00040000 0 0 0 0 0x80000000 # kNtSecLargePages
|
||||
syscon mmap MAP_HUGE_MASK 63 0 0 0 0 0
|
||||
syscon mmap MAP_HUGE_SHIFT 26 0 0 0 0 0
|
||||
syscon mmap MAP_LOCKED 0x2000 0 0 0 0 0
|
||||
syscon mmap MAP_NONBLOCK 0x10000 0 0 0 0 0
|
||||
syscon mmap MAP_POPULATE 0x8000 0 0 0 0 0 # can avoid madvise(MADV_WILLNEED) on private file mapping
|
||||
syscon mmap MAP_STACK 0x0100 0 0x0000400 0x4000 0x2000 0x100000 # use MAP_GROWSDOWN
|
||||
syscon compat MAP_NOCORE 0 0 0x0020000 0x8000 0x8000 0 # use MAP_CONCEAL
|
||||
syscon compat MAP_ANON 0x20 0x1000 0x0001000 0x1000 0x1000 0x20 # bsd consensus; faked nt
|
||||
syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 0 # ignored
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_ANONYMOUS,0x20,0x1000,0x0001000,0x1000,0x1000,0x20
|
||||
.syscon mmap,MAP_ANONYMOUS,0x00000020,0x00001000,0x00001000,0x00001000,0x00001000,0x00000020
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_CONCEAL,0,0,0x0020000,0x8000,0x8000,0
|
||||
.syscon mmap,MAP_CONCEAL,0,0,0x00020000,0x00008000,0x00008000,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_FIXED,0x0000010,0x0000010,0x0000010,0x0000010,0x0000010,0x0000010
|
||||
.syscon mmap,MAP_FIXED,0x00000010,0x00000010,0x00000010,0x00000010,0x00000010,0x00000010
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_FIXED_NOREPLACE,0x8000000,0x8000000,0x8000000,0x8000000,0x8000000,0x8000000
|
||||
.syscon mmap,MAP_FIXED_NOREPLACE,0x08000000,0x08000000,0x08000000,0x08000000,0x08000000,0x08000000
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_GROWSDOWN,0x0100,0,0x0000400,0x4000,0x4000,0x100000
|
||||
.syscon mmap,MAP_GROWSDOWN,0x00000100,0,0,0,0,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_HUGETLB,0x040000,0,0,0,0,0x80000000
|
||||
.syscon mmap,MAP_HUGETLB,0x00040000,0,0,0,0,0x80000000
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_LOCKED,0x2000,0,0,0,0,0
|
||||
.syscon mmap,MAP_LOCKED,0x00002000,0,0,0,0,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_NONBLOCK,0x10000,0,0,0,0,0
|
||||
.syscon mmap,MAP_NONBLOCK,0x00010000,0,0,0,0,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_NORESERVE,0x4000,0x40,0,0,64,0
|
||||
.syscon mmap,MAP_NORESERVE,0x00004000,0x00000040,0,0,0x00000040,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_POPULATE,0x8000,0,0,0,0,0
|
||||
.syscon mmap,MAP_POPULATE,0x00008000,0,0,0,0,0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_STACK,0x0100,0,0x0000400,0x4000,0x2000,0x100000
|
||||
.syscon mmap,MAP_STACK,6,6,6,6,6,6
|
||||
|
|
|
@ -7,6 +7,7 @@ COSMOPOLITAN_C_START_
|
|||
extern const long MAP_32BIT;
|
||||
extern const long MAP_ANON;
|
||||
extern const long MAP_ANONYMOUS;
|
||||
extern const long MAP_CONCEAL;
|
||||
extern const long MAP_DENYWRITE;
|
||||
extern const long MAP_EXECUTABLE;
|
||||
extern const long MAP_FILE;
|
||||
|
@ -21,7 +22,6 @@ extern const long MAP_NORESERVE;
|
|||
extern const long MAP_POPULATE;
|
||||
extern const long MAP_PRIVATE;
|
||||
extern const long MAP_SHARED;
|
||||
extern const long MAP_CONCEAL;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
@ -29,6 +29,7 @@ COSMOPOLITAN_C_END_
|
|||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_STACK 6
|
||||
#define MAP_TYPE 15
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_FIXED_NOREPLACE 0x8000000
|
||||
|
@ -36,6 +37,7 @@ COSMOPOLITAN_C_END_
|
|||
#define MAP_32BIT SYMBOLIC(MAP_32BIT)
|
||||
#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS)
|
||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||
#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE)
|
||||
#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE)
|
||||
#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN)
|
||||
|
@ -46,10 +48,8 @@ COSMOPOLITAN_C_END_
|
|||
#define MAP_NONBLOCK SYMBOLIC(MAP_NONBLOCK)
|
||||
#define MAP_NORESERVE SYMBOLIC(MAP_NORESERVE)
|
||||
#define MAP_POPULATE SYMBOLIC(MAP_POPULATE)
|
||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_NOCORE MAP_CONCEAL
|
||||
#define MAP_STACK MAP_GROWSDOWN
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_MAP_H_ */
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/macros.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/* ▄▄▄
|
||||
▄▄▄ ▀▓▓▒▄
|
||||
|
@ -355,107 +353,6 @@ _init_systemfive_pid:
|
|||
.endfn _init_systemfive_pid
|
||||
#endif
|
||||
#if SupportsSystemv() && !defined(TINY)
|
||||
|
||||
// Create a stack with deterministic readable addresses.
|
||||
// If ape_execve() already created us a stack that meets
|
||||
// the requirements of STATIC_STACK_SIZE() then we skip.
|
||||
_init_systemfive_stack:
|
||||
#if SupportsWindows() || SupportsMetal() || SupportsOpenbsd()
|
||||
testb $WINDOWS|METAL,__hostos(%rip)
|
||||
jnz _init_systemfive_done
|
||||
#endif
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov __NR_mmap,%eax
|
||||
movabs $ape_stack_vaddr,%rdi
|
||||
mov $ape_stack_memsz,%esi
|
||||
mov $ape_stack_prot,%edx
|
||||
mov $MAP_PRIVATE|MAP_FIXED,%r10d
|
||||
or MAP_ANONYMOUS,%r10d
|
||||
or $-1,%r8d
|
||||
xor %r9d,%r9d
|
||||
push %rdi # vaddr of stack
|
||||
push %rsi # size of stack
|
||||
push %r9 # openbsd:pad
|
||||
push %r9 # openbsd:align
|
||||
#if SupportsOpenbsd()
|
||||
testb IsOpenbsd()
|
||||
jz 0f
|
||||
syscall # openbsd:dubstack
|
||||
jc 1f
|
||||
mov __NR_mmap,%eax
|
||||
#endif
|
||||
0: or MAP_GROWSDOWN,%r10d # openbsd:mapstack
|
||||
clc
|
||||
syscall
|
||||
pop %r9
|
||||
pop %r9
|
||||
pop %r9 # size of stack
|
||||
pop %r11 # vaddr of stack
|
||||
jnc 2f
|
||||
1: mov %eax,%edi
|
||||
mov __NR_exit_group,%eax
|
||||
syscall
|
||||
2: test %rax,%rax
|
||||
js 1b
|
||||
|
||||
// prevent operating system from auto-mapping stack
|
||||
// we guarantee stack overflows are always detected
|
||||
// so long as you never use -DSTACK_FRAME_UNLIMITED
|
||||
// TODO: Why does this fail sometimes with FreeBSD?
|
||||
testb IsFreebsd()
|
||||
jnz 9f
|
||||
push %rax
|
||||
push %rdx
|
||||
push %r11
|
||||
mov __NR_mprotect,%eax
|
||||
mov $PAGESIZE,%esi
|
||||
xor %edx,%edx # PROT_NONE
|
||||
syscall
|
||||
pop %r11
|
||||
pop %rdx
|
||||
pop %rax
|
||||
9:
|
||||
|
||||
// update the memory intervals
|
||||
// m.i 0 4
|
||||
// m.n 8 4
|
||||
// m.p 16 8
|
||||
// m.p[0].x 24 4
|
||||
// m.p[0].y 28 4
|
||||
// m.p[0].h 32 8
|
||||
// m.p[0].prot 40 4
|
||||
// m.p[0].flags 44 4
|
||||
// m.p[0].offset 48 8
|
||||
// m.p[0].size 56 8
|
||||
.weak _mmi
|
||||
ezlea _mmi,cx
|
||||
test %rcx,%rcx
|
||||
jz 3f
|
||||
push %r9 # save the stack size
|
||||
lea -1(%r11,%r9),%r9 # need incl. interval
|
||||
shr $16,%r11 # for the stack range
|
||||
shr $16,%r9
|
||||
movb $1,(%rcx) # _mmi.i
|
||||
mov %r11d,24(%rcx) # _mmi.s[0].x
|
||||
mov %r9d,28(%rcx) # _mmi.s[0].y
|
||||
orq $-1,32(%rcx) # _mmi.s[0].h
|
||||
mov %edx,40(%rcx) # _mmi.s[0].prot
|
||||
mov %r10d,44(%rcx) # _mmi.s[0].flags
|
||||
pop %r9 # restore stack size
|
||||
mov %r9,56(%rcx) # _mmi.s[0].size
|
||||
3: pop %rsi
|
||||
pop %rdi
|
||||
leave
|
||||
// switch stacks
|
||||
pop %rcx
|
||||
lea (%rax,%r9),%rsp
|
||||
sub $ape_stack_align,%rsp # openbsd:stackbound
|
||||
mov %rbp,(%rsp)
|
||||
push %rcx
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
// 𝑠𝑙𝑖𝑑𝑒
|
||||
_init_systemfive_syscall:
|
||||
mov __NR_msyscall,%eax # syscall origin protect
|
||||
cmp $0xfff,%ax # openbsd is pretty cool
|
||||
|
@ -556,8 +453,3 @@ syscon_windows:/*
|
|||
.asciz " %'u magnums loaded on %s\n"
|
||||
.previous
|
||||
#endif /* DEBUGSYS */
|
||||
|
||||
.weak ape_stack_prot
|
||||
.weak ape_stack_vaddr
|
||||
.weak ape_stack_memsz
|
||||
.weak ape_stack_align
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
STATIC_YOINK("gettid"); // for kprintf()
|
||||
|
||||
#define __NR_thr_new 455
|
||||
#define __NR_sys___tfork 8
|
||||
#define __NR___tfork 8
|
||||
#define __NR_clone_linux 56
|
||||
#define __NR__lwp_create 309
|
||||
#define __NR_getcontext_netbsd 307
|
||||
|
@ -67,6 +67,7 @@ static struct Cloner {
|
|||
} __cloner;
|
||||
|
||||
static textwindows uint32_t WinThreadMain(void *notused) {
|
||||
intptr_t rdi, rdx;
|
||||
int (*func)(void *);
|
||||
void *arg, *stack;
|
||||
struct WinThread *wt;
|
||||
|
@ -82,16 +83,18 @@ static textwindows uint32_t WinThreadMain(void *notused) {
|
|||
wt->pid = tid;
|
||||
TlsSetValue(__winthread, wt);
|
||||
if (flags & CLONE_CHILD_SETTID) *ctid = tid;
|
||||
asm volatile("mov\t%%rbp,%%rbx\n\t"
|
||||
asm volatile("push\t%%rbp\n\t"
|
||||
"mov\t%%rsp,%%r15\n\t"
|
||||
"xor\t%%ebp,%%ebp\n\t"
|
||||
"xchg\t%%rax,%%rsp\n\t"
|
||||
"call\t*%2\n\t"
|
||||
"mov\t%%rbx,%%rbp\n\t"
|
||||
"mov\t%%r15,%%rsp"
|
||||
: "=a"(exitcode)
|
||||
: "0"(stack), "d"(func), "D"(arg)
|
||||
: "rbx", "r15", "memory");
|
||||
"mov\t%%r15,%%rsp\n\t"
|
||||
"pop\t%%rbp"
|
||||
: "=a"(exitcode), "=D"(rdi), "=d"(rdx)
|
||||
: "0"(stack), "1"(arg), "2"(func)
|
||||
: "rbx", "rcx", "rsi", "r8", "r9", "r10", "r11", "r15",
|
||||
"memory");
|
||||
if (flags & CLONE_CHILD_CLEARTID) *ctid = 0;
|
||||
__releasefd(tid);
|
||||
free(wt);
|
||||
|
@ -113,8 +116,7 @@ static textwindows int CloneWindows(int (*func)(void *), void *stk,
|
|||
__cloner.ctid = ctid;
|
||||
__cloner.flags = flags;
|
||||
__cloner.stack = (char *)stk + stksz;
|
||||
if (!(hand = CreateThread(&kNtIsInheritable, 0, NT2SYSV(WinThreadMain), 0, 0,
|
||||
&wintid))) {
|
||||
if (!(hand = CreateThread(0, 0, NT2SYSV(WinThreadMain), 0, 0, &wintid))) {
|
||||
_spunlock(&__cloner.lock);
|
||||
return -1;
|
||||
}
|
||||
|
@ -132,6 +134,7 @@ static dontinline wontreturn void BsdThreadMain(void *unused) {
|
|||
void *arg;
|
||||
int (*func)(void *);
|
||||
int tid, flags, exitcode, *ctid;
|
||||
asm("xor\t%ebp,%ebp");
|
||||
tid = __cloner.tid;
|
||||
arg = __cloner.arg;
|
||||
func = __cloner.func;
|
||||
|
@ -193,26 +196,24 @@ static privileged noasan int CloneOpenbsd(int (*func)(void *), char *stk,
|
|||
asm volatile("" ::: "memory");
|
||||
params.tf_tid = (int *)&__cloner.tid;
|
||||
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
||||
params.tf_stack = stk + stksz;
|
||||
// we need openbsd:stackbound because openbsd kernel enforces rsp must
|
||||
// be on interval [stack, stack+size) thus the top address is an error
|
||||
// furthermore this needs to be allocated using MAP_STACK OR GROWSDOWN
|
||||
params.tf_stack = (void *)((intptr_t)((char *)stk + stksz - 1) & -16);
|
||||
asm volatile(CFLAG_ASM("syscall")
|
||||
: CFLAG_CONSTRAINT(failed), "=a"(ax)
|
||||
: "1"(__NR_sys___tfork), "D"(¶ms), "S"(sizeof(params))
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
if (!failed) {
|
||||
if (!ax) {
|
||||
// this is the child thread
|
||||
// we probably can't access local variables anymore
|
||||
asm volatile("" ::: "memory");
|
||||
BsdThreadMain(0);
|
||||
unreachable;
|
||||
} else {
|
||||
if (flags & CLONE_PARENT_SETTID) *ptid = ax;
|
||||
return ax;
|
||||
}
|
||||
} else {
|
||||
: "1"(__NR___tfork), "D"(¶ms), "S"(sizeof(params))
|
||||
: "r11", "memory", "cc");
|
||||
if (failed) {
|
||||
errno = ax;
|
||||
return -1;
|
||||
}
|
||||
if (ax) {
|
||||
if (flags & CLONE_PARENT_SETTID) *ptid = ax;
|
||||
return ax;
|
||||
}
|
||||
BsdThreadMain(0);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
static privileged noasan int CloneNetbsd(int (*func)(void *), void *stk,
|
||||
|
@ -231,8 +232,8 @@ static privileged noasan int CloneNetbsd(int (*func)(void *), void *stk,
|
|||
errno = ax;
|
||||
return -1;
|
||||
}
|
||||
stack = (void *)(((long)((char *)stk + stksz) & -16) - 8 * 3);
|
||||
*(long *)stack = (long)_Exit1;
|
||||
stack = (intptr_t *)((intptr_t)((char *)stk + stksz) & -16);
|
||||
*--stack = (intptr_t)_Exit1;
|
||||
ctx.uc_link = 0;
|
||||
ctx.uc_mcontext.rip = (intptr_t)func;
|
||||
ctx.uc_mcontext.rdi = (intptr_t)arg;
|
||||
|
@ -265,14 +266,15 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
size_t tlssz, int *ctid) {
|
||||
int ax;
|
||||
bool failed;
|
||||
intptr_t *stack;
|
||||
register int *r8 asm("r8") = tls;
|
||||
register int (*r9)(void *) asm("r9") = func;
|
||||
register int *r10 asm("r10") = ctid;
|
||||
stk = (void *)(((long)((char *)stk + stksz) & -16) - 8);
|
||||
*(long *)stk = (long)arg;
|
||||
stack = (intptr_t *)((long)((char *)stk + stksz) & -16);
|
||||
*--stack = (long)arg; // push 1
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_clone_linux), "D"(flags), "S"(stk), "d"(ptid),
|
||||
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "d"(ptid),
|
||||
"r"(r10), "r"(r8), "r"(r9)
|
||||
: "rcx", "r11", "memory");
|
||||
if (ax > -4096u) {
|
||||
|
@ -281,8 +283,8 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
}
|
||||
if (ax) return ax;
|
||||
asm volatile("xor\t%%ebp,%%ebp\n\t"
|
||||
"pop\t%%rdi\n\t"
|
||||
"call\t%0\n\t"
|
||||
"pop\t%%rdi\n\t" // pop 1
|
||||
"call\t*%0\n\t"
|
||||
"xchg\t%%eax,%%edi\n\t"
|
||||
"jmp\t_Exit1"
|
||||
: /* no outputs */
|
||||
|
@ -302,6 +304,8 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
|||
* @param func is your callback function
|
||||
* @param stk points to the bottom of a caller allocated stack, which
|
||||
* must be null when fork() and vfork() equivalent flags are used
|
||||
* and furthermore this must be mmap()'d using MAP_STACK in order
|
||||
* to work on OpenBSD
|
||||
* @param stksz is the size of that stack in bytes which must be zero
|
||||
* if the fork() or vfork() equivalent flags are used it's highly
|
||||
* recommended that this value be GetStackSize(), or else kprintf
|
||||
|
@ -350,7 +354,8 @@ privileged int clone(int (*func)(void *), void *stk, size_t stksz, int flags,
|
|||
}
|
||||
|
||||
// polyfill fork() and vfork() use case on platforms w/o clone
|
||||
else if (flags == (CLONE_VFORK | CLONE_VM | SIGCHLD)) {
|
||||
else if ((SupportsWindows() || SupportsBsd()) &&
|
||||
flags == (CLONE_VFORK | CLONE_VM | SIGCHLD)) {
|
||||
if (IsTiny()) {
|
||||
rc = einval();
|
||||
} else if (!arg && !stksz) {
|
||||
|
@ -358,7 +363,7 @@ privileged int clone(int (*func)(void *), void *stk, size_t stksz, int flags,
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
} else if (flags == SIGCHLD) {
|
||||
} else if ((SupportsWindows() || SupportsBsd()) && flags == SIGCHLD) {
|
||||
if (IsTiny()) {
|
||||
rc = eopnotsupp();
|
||||
} else if (!arg && !stksz) {
|
||||
|
|
|
@ -46,6 +46,7 @@ $(LIBC_THREAD_A).pkg: \
|
|||
$(LIBC_THREAD_A_OBJS) \
|
||||
$(foreach x,$(LIBC_THREAD_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
# no red zone because asm("call")
|
||||
o/$(MODE)/libc/thread/clone.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-mno-red-zone
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "libc/runtime/stack.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -71,13 +73,10 @@ TEST(rand64, testLcg_doesntProduceIdenticalValues) {
|
|||
}
|
||||
|
||||
TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
||||
char *stack;
|
||||
sigset_t ss, oldss;
|
||||
void *stacks[THREADS];
|
||||
int i, j, rc, ws, tid[THREADS];
|
||||
if (IsXnu()) return;
|
||||
if (IsNetbsd()) return; // still flaky :'(
|
||||
if (IsOpenbsd()) return; // still flaky :'(
|
||||
if (IsTiny() && IsWindows()) return; // todo(jart): wut
|
||||
struct sigaction oldsa;
|
||||
struct sigaction sa = {.sa_handler = OnChld, .sa_flags = SA_RESTART};
|
||||
EXPECT_NE(-1, sigaction(SIGCHLD, &sa, &oldsa));
|
||||
|
@ -90,8 +89,9 @@ TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
|||
}
|
||||
ready = false;
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
stack = gc(malloc(GetStackSize()));
|
||||
tid[i] = clone(Thrasher, stack, GetStackSize(),
|
||||
stacks[i] = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||
tid[i] = clone(Thrasher, stacks[i], FRAMESIZE,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
||||
(void *)(intptr_t)i, 0, 0, 0, 0);
|
||||
ASSERT_NE(-1, tid[i]);
|
||||
|
@ -109,4 +109,7 @@ TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
|||
EXPECT_NE(A[i], A[j], "i=%d j=%d", i, j);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < THREADS; ++i) {
|
||||
EXPECT_SYS(0, 0, munmap(stacks[i], FRAMESIZE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,9 +99,8 @@ TEST(mmap, testMapFixed_destroysEverythingInItsPath) {
|
|||
TEST(mmap, customStackMemory_isAuthorized) {
|
||||
char *stack;
|
||||
uintptr_t w, r;
|
||||
ASSERT_NE(MAP_FAILED,
|
||||
(stack = mmap(NULL, STACKSIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN, -1, 0)));
|
||||
ASSERT_NE(MAP_FAILED, (stack = mmap(NULL, STACKSIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_STACK, -1, 0)));
|
||||
asm("mov\t%%rsp,%0\n\t"
|
||||
"mov\t%2,%%rsp\n\t"
|
||||
"push\t%3\n\t"
|
||||
|
@ -110,6 +109,7 @@ TEST(mmap, customStackMemory_isAuthorized) {
|
|||
: "=&r"(w), "=&r"(r)
|
||||
: "rm"(stack + STACKSIZE - 8), "i"(123));
|
||||
ASSERT_EQ(123, r);
|
||||
EXPECT_SYS(0, 0, munmap(stack, STACKSIZE));
|
||||
}
|
||||
|
||||
TEST(mmap, fileOffset) {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
int x, thechilde;
|
||||
|
@ -41,17 +43,18 @@ int thread(void *arg) {
|
|||
|
||||
TEST(clone, test) {
|
||||
if (IsXnu()) return;
|
||||
if (IsOpenbsd()) return; // still flaky :'(
|
||||
int me, tid;
|
||||
char *stack;
|
||||
me = gettid();
|
||||
_spinlock(&lock);
|
||||
stack = _gc(valloc(STACKSIZE));
|
||||
ASSERT_NE(-1, (tid = clone(thread, stack, STACKSIZE,
|
||||
stack = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||
ASSERT_NE(-1, (tid = clone(thread, stack, FRAMESIZE,
|
||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
||||
(void *)23, 0, 0, 0, 0)));
|
||||
_spinlock(&lock);
|
||||
ASSERT_EQ(42, x);
|
||||
ASSERT_NE(me, tid);
|
||||
ASSERT_EQ(tid, thechilde);
|
||||
EXPECT_SYS(0, 0, munmap(stack, FRAMESIZE));
|
||||
}
|
||||
|
|
3
third_party/linenoise/linenoise.c
vendored
3
third_party/linenoise/linenoise.c
vendored
|
@ -140,7 +140,6 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -2498,7 +2497,7 @@ char *linenoiseWithHistory(const char *prompt, const char *prog) {
|
|||
fflush(stdout);
|
||||
if ((path = linenoiseGetHistoryPath(prog))) {
|
||||
if (linenoiseHistoryLoad(path) == -1) {
|
||||
kprintf("%r%s: failed to load history: %m%n", path);
|
||||
fprintf(stderr, "%s: failed to load history: %m\n", path);
|
||||
free(path);
|
||||
path = 0;
|
||||
}
|
||||
|
|
2
third_party/make/job.c
vendored
2
third_party/make/job.c
vendored
|
@ -1485,7 +1485,7 @@ load_too_high (void)
|
|||
}
|
||||
}
|
||||
|
||||
/* If we got here, something went wrong. Give up on this method. */
|
||||
/* If we 𝑔𝑜𝑡 𝑒𝑟𝑒, something went wrong. Give up on this method. */
|
||||
if (r < 0)
|
||||
DB (DB_JOBS, ("Failed to read " LOADAVG ": %s\n", strerror (errno)));
|
||||
|
||||
|
|
|
@ -353,10 +353,7 @@
|
|||
(add-hook 'asm-mode-hook 'cosmo-asm-supplemental-hook)
|
||||
(setq asm-font-lock-keywords cosmo-asm-font-lock-keywords))
|
||||
|
||||
;; Make -*-unix-assembly-*- mode line work correctly.
|
||||
;; TODO(jart): Would be nice to use GitHub's name instead of changing asm-mode.
|
||||
(defun unix-assembly-mode ()
|
||||
(interactive)
|
||||
(asm-mode))
|
||||
;; Make -*-unix-assembly-*- mode line work correctly like GitHub.
|
||||
(define-derived-mode unix-assembly-mode asm-mode "UNIX Assembly")
|
||||
|
||||
(provide 'cosmo-asm-mode)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue