mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +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
|
* o//examples/crashreport.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
noubsan int main(int argc, char *argv[]) {
|
||||||
volatile int64_t x;
|
volatile int64_t x;
|
||||||
ShowCrashReports();
|
ShowCrashReports();
|
||||||
return 1 / (x = 0);
|
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/strace.internal.h"
|
||||||
#include "libc/calls/struct/rlimit.h"
|
#include "libc/calls/struct/rlimit.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/log/color.internal.h"
|
#include "libc/log/color.internal.h"
|
||||||
#include "libc/macros.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);
|
lim.rlim_cur = MIN(soft, lim.rlim_max);
|
||||||
if (!setrlimit(resource, &lim)) {
|
if (!setrlimit(resource, &lim)) {
|
||||||
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
|
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
|
||||||
__strace_rlimit_name(resource), soft, hard);
|
DescribeRlimitName(resource), soft, hard);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,9 +64,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
for (i = 0; i < RLIM_NLIMITS; ++i) {
|
for (i = 0; i < RLIM_NLIMITS; ++i) {
|
||||||
rc = getrlimit(i, &rlim);
|
rc = getrlimit(i, &rlim);
|
||||||
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n",
|
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n", DescribeRlimitName(i),
|
||||||
__strace_rlimit_name(i), rlim.rlim_cur, rlim.rlim_max, rc,
|
rlim.rlim_cur, rlim.rlim_max, rc, !rc ? "" : strerror(errno));
|
||||||
!rc ? "" : strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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/vdsofunc.greg.o \
|
||||||
o/$(MODE)/libc/calls/directmap.o \
|
o/$(MODE)/libc/calls/directmap.o \
|
||||||
o/$(MODE)/libc/calls/directmap-nt.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: \
|
o/$(MODE)/libc/calls/raise.o: \
|
||||||
OVERRIDE_COPTS += \
|
OVERRIDE_COPTS += \
|
||||||
-ffreestanding \
|
-ffreestanding \
|
||||||
|
@ -116,7 +120,6 @@ o/$(MODE)/libc/calls/renameat-nt.o \
|
||||||
o/$(MODE)/libc/calls/execve-sysv.o \
|
o/$(MODE)/libc/calls/execve-sysv.o \
|
||||||
o/$(MODE)/libc/calls/symlinkat-nt.o \
|
o/$(MODE)/libc/calls/symlinkat-nt.o \
|
||||||
o/$(MODE)/libc/calls/readlinkat-nt.o \
|
o/$(MODE)/libc/calls/readlinkat-nt.o \
|
||||||
o/$(MODE)/libc/calls/describeopenflags.greg.o \
|
|
||||||
o/$(MODE)/libc/calls/mkntenvblock.o: \
|
o/$(MODE)/libc/calls/mkntenvblock.o: \
|
||||||
OVERRIDE_CPPFLAGS += \
|
OVERRIDE_CPPFLAGS += \
|
||||||
-DSTACK_FRAME_UNLIMITED
|
-DSTACK_FRAME_UNLIMITED
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/nt/synchronization.h"
|
#include "libc/nt/synchronization.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
|
||||||
}
|
}
|
||||||
if (!__time_critical) {
|
if (!__time_critical) {
|
||||||
STRACE("clock_gettime(%d, [%s]) → %d% m", clockid,
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,23 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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/intrin/kprintf.h"
|
||||||
|
|
||||||
privileged const char *__strace_sigaction(char *buf, size_t bufsize, int rc,
|
const char *DescribeSigaction(char *buf, size_t bufsize, int rc,
|
||||||
const struct sigaction *sa) {
|
const struct sigaction *sa) {
|
||||||
char maskbuf[41];
|
char maskbuf[64];
|
||||||
if (rc == -1) return "n/a";
|
if (rc == -1) return "n/a";
|
||||||
if (!sa) return "NULL";
|
if (!sa) return "NULL";
|
||||||
|
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}",
|
ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
|
||||||
sa->sa_handler, sa->sa_flags,
|
sa->sa_handler, sa->sa_flags,
|
||||||
__strace_sigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
|
DescribeSigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
|
@ -16,14 +16,49 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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/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 (rc == -1) return "n/a";
|
||||||
if (!st) return "NULL";
|
if (!ss) return "NULL";
|
||||||
ksnprintf(buf, sizeof(buf), "{.st_size=%'ld, .st_mode=%#o, .st_ino=%'lu}",
|
if ((!IsAsan() && kisdangerous(ss)) ||
|
||||||
st->st_size, st->st_mode, st->st_ino);
|
(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;
|
return buf;
|
||||||
}
|
}
|
|
@ -48,7 +48,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
||||||
handle = kNtInvalidHandleValue;
|
handle = kNtInvalidHandleValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & MAP_PRIVATE) {
|
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||||
sec = 0; // MAP_PRIVATE isn't inherited across fork()
|
sec = 0; // MAP_PRIVATE isn't inherited across fork()
|
||||||
} else {
|
} else {
|
||||||
sec = &kNtIsInheritable; // MAP_SHARED gives us zero-copy fork()
|
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
|
// note that open-nt.c always requests an kNtGenericExecute accessmask
|
||||||
iscow = false;
|
iscow = false;
|
||||||
if (handle != -1) {
|
if (handle != -1) {
|
||||||
if (flags & MAP_PRIVATE) {
|
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||||
// windows has cow pages but they can't propagate across fork()
|
// windows has cow pages but they can't propagate across fork()
|
||||||
// that means we only get copy-on-write for the root process :(
|
// that means we only get copy-on-write for the root process :(
|
||||||
fl = (struct ProtectNt){kNtPageExecuteWritecopy,
|
fl = (struct ProtectNt){kNtPageExecuteWritecopy,
|
||||||
kNtFileMapCopy | kNtFileMapExecute};
|
kNtFileMapCopy | kNtFileMapExecute};
|
||||||
iscow = true;
|
iscow = true;
|
||||||
} else {
|
} else {
|
||||||
assert(flags & MAP_SHARED);
|
|
||||||
if ((g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY) {
|
if ((g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY) {
|
||||||
fl = (struct ProtectNt){kNtPageExecuteRead,
|
fl = (struct ProtectNt){kNtPageExecuteRead,
|
||||||
kNtFileMapRead | kNtFileMapExecute};
|
kNtFileMapRead | kNtFileMapExecute};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
@ -50,7 +51,7 @@ int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_faccessat_nt(dirfd, path, mode, flags);
|
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);
|
path, mode, flags, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
|
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);
|
mode, flags, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.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 {
|
} else {
|
||||||
rc = sys_fchownat(dirfd, path, uid, gid, flags);
|
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);
|
path, uid, gid, flags, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
|
@ -45,6 +46,6 @@ int fstat(int fd, struct stat *st) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_fstat_nt(__getfdhandleactual(fd), st);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -70,7 +71,7 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_fstatat_nt(dirfd, path, st, flags);
|
rc = sys_fstatat_nt(dirfd, path, st, flags);
|
||||||
}
|
}
|
||||||
STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", __strace_dirfd(buf, dirfd), path,
|
STRACE("fstatat(%s, %#s, [%s], %s) → %d% m", DescribeDirfd(buf, dirfd), path,
|
||||||
__strace_stat(rc, st), __strace_fstatat_flags(flags), rc);
|
DescribeStat(rc, st), __strace_fstatat_flags(flags), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ int getrlimit(int resource, struct rlimit *rlim) {
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
}
|
}
|
||||||
STRACE("getrlimit(%s, [%s]) → %d% m", __strace_rlimit_name(resource),
|
STRACE("getrlimit(%s, [%s]) → %d% m", DescribeRlimitName(resource),
|
||||||
__strace_rlimit(buf, sizeof(buf), rc, rlim), rc);
|
DescribeRlimit(buf, sizeof(buf), rc, rlim), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.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);
|
rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||||
}
|
}
|
||||||
STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m",
|
STRACE("linkat(%s, %#s, %s, %#s, %#b) → %d% m",
|
||||||
__strace_dirfd(buf[0], olddirfd), oldpath,
|
DescribeDirfd(buf[0], olddirfd), oldpath,
|
||||||
__strace_dirfd(buf[1], newdirfd), newpath, flags, rc);
|
DescribeDirfd(buf[1], newdirfd), newpath, flags, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
@ -50,7 +51,7 @@ int mkdirat(int dirfd, const char *path, unsigned mode) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_mkdirat_nt(dirfd, path, mode);
|
rc = sys_mkdirat_nt(dirfd, path, mode);
|
||||||
}
|
}
|
||||||
STRACE("mkdirat(%s, %#s, %#o) → %d% m", __strace_dirfd(buf, dirfd), path,
|
STRACE("mkdirat(%s, %#s, %#o) → %d% m", DescribeDirfd(buf, dirfd), path, mode,
|
||||||
mode, rc);
|
rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,8 +46,8 @@ noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||||
}
|
}
|
||||||
if (!__time_critical) {
|
if (!__time_critical) {
|
||||||
STRACE("nanosleep(%s, [%s]) → %d% m",
|
STRACE("nanosleep(%s, [%s]) → %d% m",
|
||||||
__strace_timespec(buf[0], sizeof(buf[0]), rc, req),
|
DescribeTimespec(buf[0], sizeof(buf[0]), rc, req),
|
||||||
__strace_timespec(buf[1], sizeof(buf[1]), rc, rem), rc);
|
DescribeTimespec(buf[1], sizeof(buf[1]), rc, rem), rc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/magnumstrs.internal.h"
|
#include "libc/fmt/magnumstrs.internal.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
|
@ -75,7 +76,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
||||||
} else {
|
} else {
|
||||||
rc = efault();
|
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,
|
DescribeOpenFlags(flags), (flags & (O_CREAT | O_TMPFILE)) ? mode : 0,
|
||||||
rc);
|
rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -84,20 +84,22 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _POLLTRACE
|
#if defined(SYSDEBUG) && _POLLTRACE
|
||||||
if (__strace > 0) {
|
if (__strace > 0) {
|
||||||
if (rc == -1 && errno == EFAULT) {
|
kprintf(STRACE_PROLOGUE "poll(");
|
||||||
STRACE("poll(%p, %'lu, %'d) → %d% lm", fds, nfds, timeout_ms, rc);
|
if ((!IsAsan() && kisdangerous(fds)) ||
|
||||||
|
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
|
||||||
|
kprintf("%p", fds);
|
||||||
} else {
|
} else {
|
||||||
char flagbuf[2][64];
|
char flagbuf[2][64];
|
||||||
kprintf(STRACE_PROLOGUE "poll({");
|
kprintf("[{");
|
||||||
for (i = 0; i < MIN(5, nfds); ++i) {
|
for (i = 0; i < MIN(5, nfds); ++i) {
|
||||||
kprintf(
|
kprintf(
|
||||||
"%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
|
"%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
|
||||||
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
|
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
|
||||||
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
||||||
}
|
}
|
||||||
kprintf("%s}, %'zu, %'d) → %d% lm\n", i == 5 ? "..." : "", nfds,
|
kprintf("%s}]", i == 5 ? "..." : "");
|
||||||
timeout_ms, rc);
|
|
||||||
}
|
}
|
||||||
|
kprintf(", %'zu, %'d) → %d% lm\n", nfds, timeout_ms, rc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/sysv/consts/iov.h"
|
#include "libc/sysv/consts/iov.h"
|
||||||
|
@ -113,14 +114,10 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||||
rc = Preadv(fd, iov, iovlen, off);
|
rc = Preadv(fd, iov, iovlen, off);
|
||||||
#if defined(SYSDEBUG) && _DATATRACE
|
#if defined(SYSDEBUG) && _DATATRACE
|
||||||
if (__strace > 0) {
|
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);
|
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/sysv/consts/iov.h"
|
#include "libc/sysv/consts/iov.h"
|
||||||
|
@ -118,14 +119,10 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
||||||
rc = Pwritev(fd, iov, iovlen, off);
|
rc = Pwritev(fd, iov, iovlen, off);
|
||||||
#if defined(SYSDEBUG) && _DATATRACE
|
#if defined(SYSDEBUG) && _DATATRACE
|
||||||
if (__strace > 0) {
|
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);
|
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.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 {
|
} else {
|
||||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||||
}
|
}
|
||||||
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", __strace_dirfd(sb, dirfd),
|
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(sb, dirfd), path,
|
||||||
path, MAX(0, bytes), buf, bytes);
|
MAX(0, bytes), buf, bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.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);
|
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
|
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);
|
kprintf("], %d) → %'ld% m\n", iovlen, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
@ -57,7 +58,7 @@ int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
||||||
} else {
|
} else {
|
||||||
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
|
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
|
||||||
}
|
}
|
||||||
STRACE("renameat(%s, %#s, %s, %#s) → %d% m", __strace_dirfd(buf[0], olddirfd),
|
STRACE("renameat(%s, %#s, %s, %#s) → %d% m", DescribeDirfd(buf[0], olddirfd),
|
||||||
oldpath, __strace_dirfd(buf[1], newdirfd), newpath, rc);
|
oldpath, DescribeDirfd(buf[1], newdirfd), newpath, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ int setrlimit(int resource, const struct rlimit *rlim) {
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
}
|
}
|
||||||
STRACE("setrlimit(%s, %s) → %d% m", __strace_rlimit_name(resource),
|
STRACE("setrlimit(%s, %s) → %d% m", DescribeRlimitName(resource),
|
||||||
__strace_rlimit(buf, sizeof(buf), 0, rlim), rc);
|
DescribeRlimit(buf, sizeof(buf), 0, rlim), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "libc/calls/ucontext.h"
|
#include "libc/calls/ucontext.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/backtrace.internal.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);
|
rc = __sigaction(sig, act, oldact);
|
||||||
}
|
}
|
||||||
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
|
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
|
||||||
__strace_sigaction(buf[0], sizeof(buf[0]), 0, act),
|
DescribeSigaction(buf[0], sizeof(buf[0]), 0, act),
|
||||||
__strace_sigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
|
DescribeSigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/str/str.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;
|
*opt_out_oldset = old;
|
||||||
}
|
}
|
||||||
STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how),
|
STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how),
|
||||||
__strace_sigset(buf[0], sizeof(buf[0]), 0, opt_set),
|
DescribeSigset(buf[0], sizeof(buf[0]), 0, opt_set),
|
||||||
__strace_sigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
|
DescribeSigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "libc/calls/struct/sigset.h"
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/log/backtrace.internal.h"
|
#include "libc/log/backtrace.internal.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
#include "libc/nt/synchronization.h"
|
#include "libc/nt/synchronization.h"
|
||||||
|
@ -47,7 +48,7 @@ int sigsuspend(const sigset_t *ignore) {
|
||||||
char buf[41];
|
char buf[41];
|
||||||
long ms, totoms;
|
long ms, totoms;
|
||||||
sigset_t save, mask, *arg;
|
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))) {
|
if (IsAsan() && ignore && !__asan_is_valid(ignore, sizeof(*ignore))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
} else if (IsXnu() || IsOpenbsd()) {
|
} else if (IsXnu() || IsOpenbsd()) {
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
|
|
||||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
#define _KERNTRACE 1 /* not configurable w/ flag yet */
|
||||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
#define _POLLTRACE 1 /* not configurable w/ flag yet */
|
||||||
#define _DATATRACE 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 "
|
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
|
||||||
|
|
||||||
|
@ -53,14 +53,6 @@ COSMOPOLITAN_C_START_
|
||||||
extern int __strace;
|
extern int __strace;
|
||||||
|
|
||||||
void __stracef(const char *, ...);
|
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_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#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/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.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);
|
rc = sys_symlinkat_nt(target, newdirfd, linkpath);
|
||||||
}
|
}
|
||||||
STRACE("symlinkat(%#s, %s, %#s) → %d% m", target,
|
STRACE("symlinkat(%#s, %s, %#s) → %d% m", target,
|
||||||
__strace_dirfd(buf, newdirfd), linkpath);
|
DescribeDirfd(buf, newdirfd), linkpath);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
@ -49,7 +50,7 @@ int unlinkat(int dirfd, const char *path, int flags) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_unlinkat_nt(dirfd, path, flags);
|
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);
|
flags, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.internal.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) {
|
if (ts) {
|
||||||
STRACE("utimensat(%s, %#s, {{%,ld, %,ld}, {%,ld, %,ld}}, %#b) → %d% m",
|
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);
|
ts[1].tv_sec, ts[1].tv_nsec, flags, rc);
|
||||||
} else {
|
} 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);
|
path, flags, rc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
@ -74,14 +75,10 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _DATATRACE
|
#if defined(SYSDEBUG) && _DATATRACE
|
||||||
if (__strace > 0) {
|
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);
|
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -1282,7 +1282,10 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
||||||
int prot, flag;
|
int prot, flag;
|
||||||
struct DirectMap sm;
|
struct DirectMap sm;
|
||||||
struct MemoryIntervals *m;
|
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);
|
m = weaken(_mmi);
|
||||||
a = (0x7fff8000 + (p >> 3)) >> 16;
|
a = (0x7fff8000 + (p >> 3)) >> 16;
|
||||||
b = (0x7fff8000 + (p >> 3) + (n >> 3) + 0xffff) >> 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 {
|
} else {
|
||||||
rc = 24;
|
rc = 24;
|
||||||
}
|
}
|
||||||
|
if (weaken(__die)) weaken(__die)();
|
||||||
__restorewintty();
|
__restorewintty();
|
||||||
_Exit(rc);
|
_Exit(rc);
|
||||||
}
|
}
|
|
@ -16,11 +16,11 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/strace.internal.h"
|
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/sysv/consts/at.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";
|
if (dirfd == AT_FDCWD) return "AT_FDCWD";
|
||||||
FormatInt32(buf, dirfd);
|
FormatInt32(buf, dirfd);
|
||||||
return buf;
|
return buf;
|
|
@ -1,5 +1,11 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
|
#ifndef COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_
|
||||||
#define 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"
|
#include "libc/nt/struct/securityattributes.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
@ -15,8 +21,15 @@ const char *DescribeFlags(char *, size_t, struct DescribeFlags *, size_t,
|
||||||
const char *DescribeMapFlags(int);
|
const char *DescribeMapFlags(int);
|
||||||
const char *DescribeProtFlags(int);
|
const char *DescribeProtFlags(int);
|
||||||
const char *DescribeRemapFlags(int);
|
const char *DescribeRemapFlags(int);
|
||||||
|
const char *DescribeRlimitName(int);
|
||||||
const char *DescribeSeccompOperationFlags(int);
|
const char *DescribeSeccompOperationFlags(int);
|
||||||
const char *DescribePollFlags(char *, size_t, 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 *DescribeNtPageFlags(uint32_t);
|
||||||
const char *DescribeNtStartFlags(uint32_t);
|
const char *DescribeNtStartFlags(uint32_t);
|
||||||
|
@ -35,6 +48,8 @@ const char *DescribeNtConsoleModeOutputFlags(uint32_t);
|
||||||
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
||||||
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
|
const char *DescribeNtSecurityAttributes(struct NtSecurityAttributes *);
|
||||||
|
|
||||||
|
void DescribeIov(const struct iovec *, int, ssize_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_ */
|
#endif /* COSMOPOLITAN_LIBC_INTRIN_DESCRIBEFLAGS_INTERNAL_H_ */
|
||||||
|
|
|
@ -16,12 +16,19 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.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;
|
int i;
|
||||||
|
if ((!IsAsan() && kisdangerous(iov)) ||
|
||||||
|
(IsAsan() && !__asan_is_valid(iov, iovlen * sizeof(struct iovec)))) {
|
||||||
|
kprintf("%p", iov);
|
||||||
|
return;
|
||||||
|
}
|
||||||
kprintf("{");
|
kprintf("{");
|
||||||
for (i = 0; rem && i < MIN(5, iovlen); ++i) {
|
for (i = 0; rem && i < MIN(5, iovlen); ++i) {
|
||||||
kprintf(
|
kprintf(
|
|
@ -25,6 +25,7 @@
|
||||||
const char *DescribeMapFlags(int x) {
|
const char *DescribeMapFlags(int x) {
|
||||||
_Alignas(char) static char mapflags[256];
|
_Alignas(char) static char mapflags[256];
|
||||||
const struct DescribeFlags kMapFlags[] = {
|
const struct DescribeFlags kMapFlags[] = {
|
||||||
|
{MAP_STACK, "STACK"}, // order matters
|
||||||
{MAP_ANONYMOUS, "ANONYMOUS"}, //
|
{MAP_ANONYMOUS, "ANONYMOUS"}, //
|
||||||
{MAP_PRIVATE, "PRIVATE"}, //
|
{MAP_PRIVATE, "PRIVATE"}, //
|
||||||
{MAP_SHARED, "SHARED"}, //
|
{MAP_SHARED, "SHARED"}, //
|
||||||
|
@ -37,7 +38,6 @@ const char *DescribeMapFlags(int x) {
|
||||||
{MAP_NORESERVE, "NORESERVE"}, //
|
{MAP_NORESERVE, "NORESERVE"}, //
|
||||||
{MAP_NONBLOCK, "NONBLOCK"}, //
|
{MAP_NONBLOCK, "NONBLOCK"}, //
|
||||||
{MAP_POPULATE, "POPULATE"}, //
|
{MAP_POPULATE, "POPULATE"}, //
|
||||||
{MAP_STACK, "STACK"}, // order matters
|
|
||||||
};
|
};
|
||||||
return DescribeFlags(mapflags, sizeof(mapflags), kMapFlags,
|
return DescribeFlags(mapflags, sizeof(mapflags), kMapFlags,
|
||||||
ARRAYLEN(kMapFlags), "MAP_", x);
|
ARRAYLEN(kMapFlags), "MAP_", x);
|
||||||
|
|
|
@ -28,6 +28,8 @@ static noasan char DescribeMapType(int flags) {
|
||||||
return 'p';
|
return 'p';
|
||||||
case MAP_SHARED:
|
case MAP_SHARED:
|
||||||
return 's';
|
return 's';
|
||||||
|
case MAP_STACK:
|
||||||
|
return 'S';
|
||||||
default:
|
default:
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
@ -46,7 +48,7 @@ noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
|
||||||
DescribeProt(prot, p);
|
DescribeProt(prot, p);
|
||||||
p[3] = DescribeMapType(flags);
|
p[3] = DescribeMapType(flags);
|
||||||
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
|
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[6] = (flags & MAP_FIXED) ? 'F' : '-';
|
||||||
p[7] = 0;
|
p[7] = 0;
|
||||||
return p;
|
return p;
|
|
@ -17,12 +17,19 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
|
||||||
privileged const char *__strace_sigset(char buf[41], size_t bufsize, int rc,
|
const char *DescribeRlimit(char *buf, size_t bufsize, int rc,
|
||||||
const sigset_t *ss) {
|
const struct rlimit *rlim) {
|
||||||
if (rc == -1) return "n/a";
|
if (rc == -1) return "n/a";
|
||||||
if (!ss) return "NULL";
|
if (!rlim) return "NULL";
|
||||||
ksnprintf(buf, bufsize, "{%#lx, %#lx}", ss->__bits[0], ss->__bits[1]);
|
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;
|
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 │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
|
||||||
privileged const char *__strace_timespec(char buf[45], size_t bufsize, int rc,
|
const char *DescribeTimespec(char *buf, size_t bufsize, int rc,
|
||||||
const struct timespec *ts) {
|
const struct timespec *ts) {
|
||||||
if (rc == -1) return "n/a";
|
if (rc == -1) return "n/a";
|
||||||
if (!ts) return "NULL";
|
if (!ts) return "NULL";
|
||||||
|
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);
|
ksnprintf(buf, bufsize, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
|
@ -68,17 +68,22 @@ o/$(MODE)/libc/intrin/tls.greg.o \
|
||||||
o/$(MODE)/libc/intrin/exit.greg.o \
|
o/$(MODE)/libc/intrin/exit.greg.o \
|
||||||
o/$(MODE)/libc/intrin/exit1.greg.o \
|
o/$(MODE)/libc/intrin/exit1.greg.o \
|
||||||
o/$(MODE)/libc/intrin/gettid.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/createfile.greg.o \
|
||||||
|
o/$(MODE)/libc/intrin/assertfail.greg.o \
|
||||||
o/$(MODE)/libc/intrin/reopenfile.greg.o \
|
o/$(MODE)/libc/intrin/reopenfile.greg.o \
|
||||||
o/$(MODE)/libc/intrin/deletefile.greg.o \
|
o/$(MODE)/libc/intrin/deletefile.greg.o \
|
||||||
o/$(MODE)/libc/intrin/createpipe.greg.o \
|
o/$(MODE)/libc/intrin/createpipe.greg.o \
|
||||||
o/$(MODE)/libc/intrin/closehandle.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/openprocess.greg.o \
|
||||||
o/$(MODE)/libc/intrin/createthread.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/findnextfile.greg.o \
|
||||||
o/$(MODE)/libc/intrin/createprocess.greg.o \
|
o/$(MODE)/libc/intrin/createprocess.greg.o \
|
||||||
o/$(MODE)/libc/intrin/findfirstfile.greg.o \
|
o/$(MODE)/libc/intrin/findfirstfile.greg.o \
|
||||||
o/$(MODE)/libc/intrin/describeflags.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/removedirectory.greg.o \
|
||||||
o/$(MODE)/libc/intrin/createnamedpipe.greg.o \
|
o/$(MODE)/libc/intrin/createnamedpipe.greg.o \
|
||||||
o/$(MODE)/libc/intrin/unmapviewoffile.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/flushfilebuffers.greg.o \
|
||||||
o/$(MODE)/libc/intrin/terminateprocess.greg.o \
|
o/$(MODE)/libc/intrin/terminateprocess.greg.o \
|
||||||
o/$(MODE)/libc/intrin/describemapflags.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/getfileattributes.greg.o \
|
||||||
o/$(MODE)/libc/intrin/getexitcodeprocess.greg.o \
|
o/$(MODE)/libc/intrin/getexitcodeprocess.greg.o \
|
||||||
o/$(MODE)/libc/intrin/waitforsingleobject.greg.o \
|
o/$(MODE)/libc/intrin/waitforsingleobject.greg.o \
|
||||||
|
@ -104,6 +110,10 @@ o/$(MODE)/libc/intrin/ntconsolemode.o: \
|
||||||
-ffreestanding \
|
-ffreestanding \
|
||||||
$(NO_MAGIC)
|
$(NO_MAGIC)
|
||||||
|
|
||||||
|
o/$(MODE)/libc/intrin/describeopenflags.greg.o: \
|
||||||
|
OVERRIDE_CPPFLAGS += \
|
||||||
|
-DSTACK_FRAME_UNLIMITED
|
||||||
|
|
||||||
o/$(MODE)/libc/intrin/asan.o \
|
o/$(MODE)/libc/intrin/asan.o \
|
||||||
o/$(MODE)/libc/intrin/ubsan.o: \
|
o/$(MODE)/libc/intrin/ubsan.o: \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
|
|
|
@ -520,10 +520,13 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
||||||
type = 0;
|
type = 0;
|
||||||
goto FormatString;
|
goto FormatString;
|
||||||
} else {
|
} else {
|
||||||
if (p + 4 <= e) {
|
if (p + 7 <= e) {
|
||||||
|
*p++ = ' ';
|
||||||
*p++ = 'e';
|
*p++ = 'e';
|
||||||
*p++ = 'r';
|
*p++ = 'r';
|
||||||
*p++ = 'r';
|
*p++ = 'r';
|
||||||
|
*p++ = 'n';
|
||||||
|
*p++ = 'o';
|
||||||
*p++ = '=';
|
*p++ = '=';
|
||||||
}
|
}
|
||||||
type = 0;
|
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) {
|
if (!__replstderr || __nocolor) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
s = "\r\033[K";
|
s = "\r\e[K";
|
||||||
goto FormatString;
|
goto FormatString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,20 @@ COSMOPOLITAN_C_START_
|
||||||
#define DCHECK_NOTNULL(X, ...) \
|
#define DCHECK_NOTNULL(X, ...) \
|
||||||
__DCHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
|
__DCHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
|
||||||
|
|
||||||
#define CHECK_ALIGNED(BYTES, VAR) \
|
#define CHECK_ALIGNED(BYTES, VAR, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||||
__check_fail_aligned(BYTES, (uintptr_t)VAR); \
|
__check_fail_aligned(BYTES, (uintptr_t)VAR, __FILE__, __LINE__, \
|
||||||
|
"" __VA_ARGS__); \
|
||||||
unreachable; \
|
unreachable; \
|
||||||
} \
|
} \
|
||||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DCHECK_ALIGNED(BYTES, VAR) \
|
#define DCHECK_ALIGNED(BYTES, VAR, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||||
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR); \
|
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR, "" __VA_ARGS__); \
|
||||||
unreachable; \
|
unreachable; \
|
||||||
} \
|
} \
|
||||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
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, \
|
__check_fail(#SUFFIX, #OP, (uint64_t)Want, (WANTSTR), (uint64_t)Got, \
|
||||||
(GOTSTR), __FILE__, __LINE__, __VA_ARGS__); \
|
(GOTSTR), __FILE__, __LINE__, __VA_ARGS__); \
|
||||||
} else { \
|
} 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; \
|
unreachable; \
|
||||||
} \
|
} \
|
||||||
|
@ -72,22 +74,30 @@ COSMOPOLITAN_C_START_
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define __DCHK_ALIGNED(BYTES, VAR)
|
#define __DCHK_ALIGNED(BYTES, VAR, ...)
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
void __check_fail(const char *, const char *, uint64_t, const char *, uint64_t,
|
void __check_fail(const char *, const char *, uint64_t, const char *, uint64_t,
|
||||||
const char *, const char *, int, const char *,
|
const char *, const char *, int, const char *,
|
||||||
...) relegated wontreturn;
|
...) relegated wontreturn;
|
||||||
|
|
||||||
void __check_fail_eq(uint64_t, uint64_t) relegated wontreturn;
|
void __check_fail_eq(uint64_t, uint64_t, const char *, int, const char *,
|
||||||
void __check_fail_ne(uint64_t, uint64_t) relegated wontreturn;
|
const char *, ...) relegated wontreturn;
|
||||||
void __check_fail_le(uint64_t, uint64_t) relegated wontreturn;
|
void __check_fail_ne(uint64_t, uint64_t, const char *, int, const char *,
|
||||||
void __check_fail_lt(uint64_t, uint64_t) relegated wontreturn;
|
const char *, ...) relegated wontreturn;
|
||||||
void __check_fail_ge(uint64_t, uint64_t) relegated wontreturn;
|
void __check_fail_le(uint64_t, uint64_t, const char *, int, const char *,
|
||||||
void __check_fail_gt(uint64_t, uint64_t) relegated wontreturn;
|
const char *, ...) relegated wontreturn;
|
||||||
void __check_fail_aligned(unsigned, uint64_t) 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__
|
#ifdef __VSCODE_INTELLISENSE__
|
||||||
#undef __CHK
|
#undef __CHK
|
||||||
|
|
|
@ -18,14 +18,16 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/stdio/stdio.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);
|
fflush(stderr);
|
||||||
if (!IsTiny()) memsummary(fileno(stderr));
|
if (!IsTiny()) memsummary(fileno(stderr));
|
||||||
(dprintf)(fileno(stderr), "%s%d%s%#p\n", "error: pointer not ", bytes,
|
kprintf("%s:%d: error: pointer not %d-byte aligned: %p\n", file, line, bytes,
|
||||||
"-byte aligned: ", ptr);
|
ptr);
|
||||||
__die();
|
__die();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ 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/internal.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.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.
|
* Handles failure of CHECK_xx() macros in -DNDEBUG mode.
|
||||||
|
@ -33,12 +33,22 @@
|
||||||
*
|
*
|
||||||
* @see libc/log/thunks/__check_fail_ndebug.S
|
* @see libc/log/thunks/__check_fail_ndebug.S
|
||||||
*/
|
*/
|
||||||
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
relegated wontreturn void __check_fail_ndebug(uint64_t want, uint64_t got,
|
||||||
const char *opchar) {
|
const char *file, int line,
|
||||||
|
const char *opchar,
|
||||||
|
const char *fmt, ...) {
|
||||||
|
va_list va;
|
||||||
__restore_tty();
|
__restore_tty();
|
||||||
(fprintf)(stderr, "\n%serror: %s: check failed: 0x%x %s 0x%x (%s)\n",
|
kprintf("%rerror:%s:%d: check failed: %'ld %s %'ld% m", file, line, want,
|
||||||
!__nocolor ? "\e[J" : "", program_invocation_name, want, opchar,
|
opchar, got);
|
||||||
got, strerror(errno));
|
if (*fmt) {
|
||||||
|
kprintf(": ");
|
||||||
|
va_start(va, fmt);
|
||||||
|
kvprintf(fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
kprintf("\n");
|
||||||
|
if (weaken(__die)) weaken(__die)();
|
||||||
__restorewintty();
|
__restorewintty();
|
||||||
_Exit(68);
|
_Exit(68);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
||||||
uname(&names);
|
uname(&names);
|
||||||
p = buf;
|
p = buf;
|
||||||
errno = err;
|
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"
|
" %s\n"
|
||||||
" %m\n"
|
" %m\n"
|
||||||
" %s %s %s %s\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))
|
ctx->uc_mcontext.rsp <= GetStaticStackAddr(0) + PAGESIZE))
|
||||||
? "Stack Overflow"
|
? "Stack Overflow"
|
||||||
: GetSiCodeName(sig, si->si_code),
|
: GetSiCodeName(sig, si->si_code),
|
||||||
host, getpid(), program_invocation_name, names.sysname, names.version,
|
host, getpid(), gettid(), program_invocation_name, names.sysname,
|
||||||
names.nodename, names.release);
|
names.version, names.nodename, names.release);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
ShowFunctionCalls(ctx);
|
ShowFunctionCalls(ctx);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "libc/calls/sigbits.h"
|
#include "libc/calls/sigbits.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/sigaltstack.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/internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.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];
|
extern const unsigned char __oncrash_thunks[8][11];
|
||||||
|
|
||||||
|
static void FreeSigaltstack(void *p) {
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs crash signal handlers.
|
* Installs crash signal handlers.
|
||||||
*
|
*
|
||||||
|
@ -67,7 +73,7 @@ void ShowCrashReports(void) {
|
||||||
ss.ss_flags = 0;
|
ss.ss_flags = 0;
|
||||||
ss.ss_size = SIGSTKSZ;
|
ss.ss_size = SIGSTKSZ;
|
||||||
ss.ss_sp = malloc(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;
|
sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
|
||||||
sigfillset(&sa.sa_mask);
|
sigfillset(&sa.sa_mask);
|
||||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
|
|
||||||
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
||||||
__check_fail_eq:
|
__check_fail_eq:
|
||||||
loadstr "==",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_eq,globl
|
.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.
|
// Code-size saving thunk for CHECK_GE() in NDEBUG mode.
|
||||||
__check_fail_ge:
|
__check_fail_ge:
|
||||||
loadstr ">=",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_ge,globl
|
.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.
|
// Code-size saving thunk for CHECK_GT() in NDEBUG mode.
|
||||||
__check_fail_gt:
|
__check_fail_gt:
|
||||||
loadstr ">",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_gt,globl
|
.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.
|
// Code-size saving thunk for CHECK_LE() in NDEBUG mode.
|
||||||
__check_fail_le:
|
__check_fail_le:
|
||||||
loadstr "<=",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_le,globl
|
.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.
|
// Code-size saving thunk for CHECK_LT() in NDEBUG mode.
|
||||||
__check_fail_lt:
|
__check_fail_lt:
|
||||||
loadstr "<",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_lt,globl
|
.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.
|
// Code-size saving thunk for CHECK_NE() in NDEBUG mode.
|
||||||
__check_fail_ne:
|
__check_fail_ne:
|
||||||
loadstr "!=",dx
|
lea .Lop(%rip),%r8
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
.endfn __check_fail_ne,globl
|
.endfn __check_fail_ne,globl
|
||||||
|
|
||||||
|
.rodata.str1.1
|
||||||
|
.Lop: .asciz "!="
|
||||||
|
.previous
|
||||||
|
|
|
@ -38,7 +38,6 @@ __nt2sysv:
|
||||||
push %rdi
|
push %rdi
|
||||||
push %rsi
|
push %rsi
|
||||||
pushf
|
pushf
|
||||||
ezlea _base,bx
|
|
||||||
lea -0x80(%rbp),%rdi
|
lea -0x80(%rbp),%rdi
|
||||||
call _savexmm
|
call _savexmm
|
||||||
mov %rcx,%rdi
|
mov %rcx,%rdi
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/notice.inc"
|
#include "libc/notice.inc"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
.text.startup
|
.text.startup
|
||||||
|
|
||||||
|
@ -76,6 +76,44 @@ cosmo: push %rbp
|
||||||
ret
|
ret
|
||||||
.endfn cosmo,weak
|
.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__
|
#ifdef __PG__
|
||||||
.init.start 306,_init_ftrace
|
.init.start 306,_init_ftrace
|
||||||
push %rdi
|
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) {
|
textwindows void WinMainForked(void) {
|
||||||
bool ok;
|
bool ok;
|
||||||
jmp_buf jb;
|
jmp_buf jb;
|
||||||
|
@ -129,9 +138,9 @@ textwindows void WinMainForked(void) {
|
||||||
char *addr, *shad;
|
char *addr, *shad;
|
||||||
struct DirectMap dm;
|
struct DirectMap dm;
|
||||||
uint64_t size, upsize;
|
uint64_t size, upsize;
|
||||||
int64_t savetsc, savebir;
|
|
||||||
struct MemoryInterval *maps;
|
struct MemoryInterval *maps;
|
||||||
char16_t fvar[21 + 1 + 21 + 1];
|
char16_t fvar[21 + 1 + 21 + 1];
|
||||||
|
int64_t oncrash, savetsc, savebir;
|
||||||
uint32_t i, varlen, oldprot, savepid;
|
uint32_t i, varlen, oldprot, savepid;
|
||||||
long mapcount, mapcapacity, specialz;
|
long mapcount, mapcapacity, specialz;
|
||||||
extern uint64_t ts asm("kStartTsc");
|
extern uint64_t ts asm("kStartTsc");
|
||||||
|
@ -142,6 +151,9 @@ textwindows void WinMainForked(void) {
|
||||||
if (!varlen || varlen >= ARRAYLEN(fvar)) return;
|
if (!varlen || varlen >= ARRAYLEN(fvar)) return;
|
||||||
NTTRACE("WinMainForked()");
|
NTTRACE("WinMainForked()");
|
||||||
SetEnvironmentVariable(u"_FORK", NULL);
|
SetEnvironmentVariable(u"_FORK", NULL);
|
||||||
|
#ifdef SYSDEBUG
|
||||||
|
oncrash = AddVectoredExceptionHandler(1, NT2SYSV(OnForkCrash));
|
||||||
|
#endif
|
||||||
ParseInt(fvar, &reader);
|
ParseInt(fvar, &reader);
|
||||||
|
|
||||||
// read the cpu state from the parent process & plus
|
// read the cpu state from the parent process & plus
|
||||||
|
@ -167,7 +179,7 @@ textwindows void WinMainForked(void) {
|
||||||
for (i = 0; i < mapcount; ++i) {
|
for (i = 0; i < mapcount; ++i) {
|
||||||
addr = (char *)((uint64_t)maps[i].x << 16);
|
addr = (char *)((uint64_t)maps[i].x << 16);
|
||||||
size = maps[i].size;
|
size = maps[i].size;
|
||||||
if (maps[i].flags & MAP_PRIVATE) {
|
if ((maps[i].flags & MAP_TYPE) != MAP_SHARED) {
|
||||||
upsize = ROUNDUP(size, FRAMESIZE);
|
upsize = ROUNDUP(size, FRAMESIZE);
|
||||||
// we don't need to close the map handle because sys_mmap_nt
|
// we don't need to close the map handle because sys_mmap_nt
|
||||||
// doesn't mark it inheritable across fork() for MAP_PRIVATE
|
// doesn't mark it inheritable across fork() for MAP_PRIVATE
|
||||||
|
@ -226,6 +238,9 @@ textwindows void WinMainForked(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore the crash reporting stuff
|
// restore the crash reporting stuff
|
||||||
|
#ifdef SYSDEBUG
|
||||||
|
RemoveVectoredExceptionHandler(oncrash);
|
||||||
|
#endif
|
||||||
if (weaken(__wincrash_nt)) {
|
if (weaken(__wincrash_nt)) {
|
||||||
if (!IsTiny()) {
|
if (!IsTiny()) {
|
||||||
RemoveVectoredExceptionHandler(__wincrashearly);
|
RemoveVectoredExceptionHandler(__wincrashearly);
|
||||||
|
@ -292,7 +307,7 @@ textwindows int sys_fork_nt(void) {
|
||||||
(_mmi.i * sizeof(_mmi.p[0])) >> 3);
|
(_mmi.i * sizeof(_mmi.p[0])) >> 3);
|
||||||
}
|
}
|
||||||
for (i = 0; i < _mmi.i && ok; ++i) {
|
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),
|
ok = WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
|
||||||
_mmi.p[i].size);
|
_mmi.p[i].size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,12 @@
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/errfuns.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 IP(X) (intptr_t)(X)
|
||||||
#define VIP(X) (void *)IP(X)
|
#define VIP(X) (void *)IP(X)
|
||||||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||||
|
@ -122,20 +128,9 @@ noasan static size_t GetMemtrackSize(struct MemoryIntervals *mm) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
|
||||||
int fd, int64_t off, int f, int x, int n) {
|
int fd, int64_t off, int f, int x, int n,
|
||||||
struct DirectMap dm;
|
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");
|
|
||||||
}
|
|
||||||
if (!IsWindows() && (flags & MAP_FIXED)) {
|
if (!IsWindows() && (flags & MAP_FIXED)) {
|
||||||
if (UntrackMemoryIntervals(addr, size)) {
|
if (UntrackMemoryIntervals(addr, size)) {
|
||||||
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
||||||
|
@ -154,6 +149,23 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
||||||
return addr;
|
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.
|
* 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;
|
sz = size - m;
|
||||||
dm = sys_mmap(addr + m, sz, prot, f, fd, oi);
|
dm = sys_mmap(addr + m, sz, prot, f, fd, oi);
|
||||||
if (dm.addr == MAP_FAILED) return MAP_FAILED;
|
if (dm.addr == MAP_FAILED) return MAP_FAILED;
|
||||||
iscow = (flags & MAP_PRIVATE) && fd != -1;
|
iscow = (flags & MAP_TYPE) != MAP_SHARED && fd != -1;
|
||||||
readonlyfile = (flags & MAP_SHARED) && fd != -1 &&
|
readonlyfile = (flags & MAP_TYPE) == MAP_SHARED && fd != -1 &&
|
||||||
(g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY;
|
(g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY;
|
||||||
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
|
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
|
||||||
flags, readonlyfile, iscow, oi, sz) == -1) {
|
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
|
#endif
|
||||||
char *p = addr;
|
char *p = addr;
|
||||||
|
bool needguard;
|
||||||
struct DirectMap dm;
|
struct DirectMap dm;
|
||||||
size_t virtualused, virtualneed;
|
size_t virtualused, virtualneed;
|
||||||
int a, b, i, f, m, n, x;
|
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());
|
return VIP(enomem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
needguard = false;
|
||||||
p = (char *)ADDR(x);
|
p = (char *)ADDR(x);
|
||||||
if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */
|
if ((f & MAP_TYPE) == MAP_STACK) {
|
||||||
dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off);
|
if (~f & MAP_ANONYMOUS) {
|
||||||
if (dm.addr == MAP_FAILED) {
|
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;
|
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()) {
|
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 {
|
} 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/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sysv/consts/prot.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);
|
kprintf(".control=%#.*hhs, ", msg->msg_controllen, msg->msg_control);
|
||||||
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
|
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
|
||||||
kprintf(".iov=", fd);
|
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);
|
kprintf("}], %#x) → %'ld% m\n", flags, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
|
@ -45,6 +46,7 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
|
||||||
int64_t rc;
|
int64_t rc;
|
||||||
char addr2[128];
|
char addr2[128];
|
||||||
struct msghdr msg2;
|
struct msghdr msg2;
|
||||||
|
|
||||||
if (IsAsan() && !__asan_is_valid_msghdr(msg)) {
|
if (IsAsan() && !__asan_is_valid_msghdr(msg)) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
|
@ -77,22 +79,26 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
|
||||||
} else {
|
} else {
|
||||||
rc = ebadf();
|
rc = ebadf();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _DATATRACE
|
#if defined(SYSDEBUG) && _DATATRACE
|
||||||
if (__strace > 0) {
|
if (__strace > 0) {
|
||||||
if (!msg || (rc == -1 && errno == EFAULT)) {
|
kprintf(STRACE_PROLOGUE "sendmsg(");
|
||||||
DATATRACE("sendmsg(%d, %p, %#x) → %'ld% m", fd, msg, flags, rc);
|
if ((!IsAsan() && kisdangerous(msg)) ||
|
||||||
|
(IsAsan() && !__asan_is_valid(msg, sizeof(*msg)))) {
|
||||||
|
kprintf("%p", msg);
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "sendmsg(%d, {");
|
kprintf("{");
|
||||||
if (msg->msg_namelen)
|
|
||||||
kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name);
|
kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name);
|
||||||
if (msg->msg_controllen)
|
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);
|
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
|
||||||
kprintf(".iov=", fd);
|
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);
|
kprintf("}");
|
||||||
}
|
}
|
||||||
|
kprintf(", %#x) → %'ld% m\n", flags, rc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
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 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_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_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_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 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 # 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_FIXED_NOREPLACE 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 # 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_ANONYMOUS 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # 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_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 0x0020000 0x8000 0x8000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
|
syscon mmap MAP_CONCEAL 0 0 0x00020000 0x00008000 0x00008000 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_LOCKED 0x00002000 0 0 0 0 0
|
||||||
syscon mmap MAP_HUGETLB 0x040000 0 0 0 0 0x80000000 # kNtSecLargePages
|
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_MASK 63 0 0 0 0 0
|
||||||
syscon mmap MAP_HUGE_SHIFT 26 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_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_ANON 0x20 0x1000 0x0001000 0x1000 0x1000 0x20 # bsd consensus; faked nt
|
||||||
syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 0 # ignored
|
syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 0 # ignored
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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"
|
#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_32BIT;
|
||||||
extern const long MAP_ANON;
|
extern const long MAP_ANON;
|
||||||
extern const long MAP_ANONYMOUS;
|
extern const long MAP_ANONYMOUS;
|
||||||
|
extern const long MAP_CONCEAL;
|
||||||
extern const long MAP_DENYWRITE;
|
extern const long MAP_DENYWRITE;
|
||||||
extern const long MAP_EXECUTABLE;
|
extern const long MAP_EXECUTABLE;
|
||||||
extern const long MAP_FILE;
|
extern const long MAP_FILE;
|
||||||
|
@ -21,7 +22,6 @@ extern const long MAP_NORESERVE;
|
||||||
extern const long MAP_POPULATE;
|
extern const long MAP_POPULATE;
|
||||||
extern const long MAP_PRIVATE;
|
extern const long MAP_PRIVATE;
|
||||||
extern const long MAP_SHARED;
|
extern const long MAP_SHARED;
|
||||||
extern const long MAP_CONCEAL;
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
@ -29,6 +29,7 @@ COSMOPOLITAN_C_END_
|
||||||
#define MAP_FILE 0
|
#define MAP_FILE 0
|
||||||
#define MAP_SHARED 1
|
#define MAP_SHARED 1
|
||||||
#define MAP_PRIVATE 2
|
#define MAP_PRIVATE 2
|
||||||
|
#define MAP_STACK 6
|
||||||
#define MAP_TYPE 15
|
#define MAP_TYPE 15
|
||||||
#define MAP_FIXED 16
|
#define MAP_FIXED 16
|
||||||
#define MAP_FIXED_NOREPLACE 0x8000000
|
#define MAP_FIXED_NOREPLACE 0x8000000
|
||||||
|
@ -36,6 +37,7 @@ COSMOPOLITAN_C_END_
|
||||||
#define MAP_32BIT SYMBOLIC(MAP_32BIT)
|
#define MAP_32BIT SYMBOLIC(MAP_32BIT)
|
||||||
#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS)
|
#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS)
|
||||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||||
|
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||||
#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE)
|
#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE)
|
||||||
#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE)
|
#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE)
|
||||||
#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN)
|
#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN)
|
||||||
|
@ -46,10 +48,8 @@ COSMOPOLITAN_C_END_
|
||||||
#define MAP_NONBLOCK SYMBOLIC(MAP_NONBLOCK)
|
#define MAP_NONBLOCK SYMBOLIC(MAP_NONBLOCK)
|
||||||
#define MAP_NORESERVE SYMBOLIC(MAP_NORESERVE)
|
#define MAP_NORESERVE SYMBOLIC(MAP_NORESERVE)
|
||||||
#define MAP_POPULATE SYMBOLIC(MAP_POPULATE)
|
#define MAP_POPULATE SYMBOLIC(MAP_POPULATE)
|
||||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
|
||||||
|
|
||||||
#define MAP_ANON MAP_ANONYMOUS
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
#define MAP_NOCORE MAP_CONCEAL
|
#define MAP_NOCORE MAP_CONCEAL
|
||||||
#define MAP_STACK MAP_GROWSDOWN
|
|
||||||
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_MAP_H_ */
|
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_MAP_H_ */
|
||||||
|
|
|
@ -20,9 +20,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nexgen32e/macros.h"
|
#include "libc/nexgen32e/macros.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
|
||||||
#include "libc/sysv/consts/nr.h"
|
#include "libc/sysv/consts/nr.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
|
||||||
|
|
||||||
/* ▄▄▄
|
/* ▄▄▄
|
||||||
▄▄▄ ▀▓▓▒▄
|
▄▄▄ ▀▓▓▒▄
|
||||||
|
@ -355,107 +353,6 @@ _init_systemfive_pid:
|
||||||
.endfn _init_systemfive_pid
|
.endfn _init_systemfive_pid
|
||||||
#endif
|
#endif
|
||||||
#if SupportsSystemv() && !defined(TINY)
|
#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:
|
_init_systemfive_syscall:
|
||||||
mov __NR_msyscall,%eax # syscall origin protect
|
mov __NR_msyscall,%eax # syscall origin protect
|
||||||
cmp $0xfff,%ax # openbsd is pretty cool
|
cmp $0xfff,%ax # openbsd is pretty cool
|
||||||
|
@ -556,8 +453,3 @@ syscon_windows:/*
|
||||||
.asciz " %'u magnums loaded on %s\n"
|
.asciz " %'u magnums loaded on %s\n"
|
||||||
.previous
|
.previous
|
||||||
#endif /* DEBUGSYS */
|
#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()
|
STATIC_YOINK("gettid"); // for kprintf()
|
||||||
|
|
||||||
#define __NR_thr_new 455
|
#define __NR_thr_new 455
|
||||||
#define __NR_sys___tfork 8
|
#define __NR___tfork 8
|
||||||
#define __NR_clone_linux 56
|
#define __NR_clone_linux 56
|
||||||
#define __NR__lwp_create 309
|
#define __NR__lwp_create 309
|
||||||
#define __NR_getcontext_netbsd 307
|
#define __NR_getcontext_netbsd 307
|
||||||
|
@ -67,6 +67,7 @@ static struct Cloner {
|
||||||
} __cloner;
|
} __cloner;
|
||||||
|
|
||||||
static textwindows uint32_t WinThreadMain(void *notused) {
|
static textwindows uint32_t WinThreadMain(void *notused) {
|
||||||
|
intptr_t rdi, rdx;
|
||||||
int (*func)(void *);
|
int (*func)(void *);
|
||||||
void *arg, *stack;
|
void *arg, *stack;
|
||||||
struct WinThread *wt;
|
struct WinThread *wt;
|
||||||
|
@ -82,16 +83,18 @@ static textwindows uint32_t WinThreadMain(void *notused) {
|
||||||
wt->pid = tid;
|
wt->pid = tid;
|
||||||
TlsSetValue(__winthread, wt);
|
TlsSetValue(__winthread, wt);
|
||||||
if (flags & CLONE_CHILD_SETTID) *ctid = tid;
|
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"
|
"mov\t%%rsp,%%r15\n\t"
|
||||||
"xor\t%%ebp,%%ebp\n\t"
|
"xor\t%%ebp,%%ebp\n\t"
|
||||||
"xchg\t%%rax,%%rsp\n\t"
|
"xchg\t%%rax,%%rsp\n\t"
|
||||||
"call\t*%2\n\t"
|
"call\t*%2\n\t"
|
||||||
"mov\t%%rbx,%%rbp\n\t"
|
"mov\t%%rbx,%%rbp\n\t"
|
||||||
"mov\t%%r15,%%rsp"
|
"mov\t%%r15,%%rsp\n\t"
|
||||||
: "=a"(exitcode)
|
"pop\t%%rbp"
|
||||||
: "0"(stack), "d"(func), "D"(arg)
|
: "=a"(exitcode), "=D"(rdi), "=d"(rdx)
|
||||||
: "rbx", "r15", "memory");
|
: "0"(stack), "1"(arg), "2"(func)
|
||||||
|
: "rbx", "rcx", "rsi", "r8", "r9", "r10", "r11", "r15",
|
||||||
|
"memory");
|
||||||
if (flags & CLONE_CHILD_CLEARTID) *ctid = 0;
|
if (flags & CLONE_CHILD_CLEARTID) *ctid = 0;
|
||||||
__releasefd(tid);
|
__releasefd(tid);
|
||||||
free(wt);
|
free(wt);
|
||||||
|
@ -113,8 +116,7 @@ static textwindows int CloneWindows(int (*func)(void *), void *stk,
|
||||||
__cloner.ctid = ctid;
|
__cloner.ctid = ctid;
|
||||||
__cloner.flags = flags;
|
__cloner.flags = flags;
|
||||||
__cloner.stack = (char *)stk + stksz;
|
__cloner.stack = (char *)stk + stksz;
|
||||||
if (!(hand = CreateThread(&kNtIsInheritable, 0, NT2SYSV(WinThreadMain), 0, 0,
|
if (!(hand = CreateThread(0, 0, NT2SYSV(WinThreadMain), 0, 0, &wintid))) {
|
||||||
&wintid))) {
|
|
||||||
_spunlock(&__cloner.lock);
|
_spunlock(&__cloner.lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +134,7 @@ static dontinline wontreturn void BsdThreadMain(void *unused) {
|
||||||
void *arg;
|
void *arg;
|
||||||
int (*func)(void *);
|
int (*func)(void *);
|
||||||
int tid, flags, exitcode, *ctid;
|
int tid, flags, exitcode, *ctid;
|
||||||
|
asm("xor\t%ebp,%ebp");
|
||||||
tid = __cloner.tid;
|
tid = __cloner.tid;
|
||||||
arg = __cloner.arg;
|
arg = __cloner.arg;
|
||||||
func = __cloner.func;
|
func = __cloner.func;
|
||||||
|
@ -193,26 +196,24 @@ static privileged noasan int CloneOpenbsd(int (*func)(void *), char *stk,
|
||||||
asm volatile("" ::: "memory");
|
asm volatile("" ::: "memory");
|
||||||
params.tf_tid = (int *)&__cloner.tid;
|
params.tf_tid = (int *)&__cloner.tid;
|
||||||
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
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")
|
asm volatile(CFLAG_ASM("syscall")
|
||||||
: CFLAG_CONSTRAINT(failed), "=a"(ax)
|
: CFLAG_CONSTRAINT(failed), "=a"(ax)
|
||||||
: "1"(__NR_sys___tfork), "D"(¶ms), "S"(sizeof(params))
|
: "1"(__NR___tfork), "D"(¶ms), "S"(sizeof(params))
|
||||||
: "rcx", "r11", "memory", "cc");
|
: "r11", "memory", "cc");
|
||||||
if (!failed) {
|
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 {
|
|
||||||
errno = ax;
|
errno = ax;
|
||||||
return -1;
|
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,
|
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;
|
errno = ax;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
stack = (void *)(((long)((char *)stk + stksz) & -16) - 8 * 3);
|
stack = (intptr_t *)((intptr_t)((char *)stk + stksz) & -16);
|
||||||
*(long *)stack = (long)_Exit1;
|
*--stack = (intptr_t)_Exit1;
|
||||||
ctx.uc_link = 0;
|
ctx.uc_link = 0;
|
||||||
ctx.uc_mcontext.rip = (intptr_t)func;
|
ctx.uc_mcontext.rip = (intptr_t)func;
|
||||||
ctx.uc_mcontext.rdi = (intptr_t)arg;
|
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) {
|
size_t tlssz, int *ctid) {
|
||||||
int ax;
|
int ax;
|
||||||
bool failed;
|
bool failed;
|
||||||
|
intptr_t *stack;
|
||||||
register int *r8 asm("r8") = tls;
|
register int *r8 asm("r8") = tls;
|
||||||
register int (*r9)(void *) asm("r9") = func;
|
register int (*r9)(void *) asm("r9") = func;
|
||||||
register int *r10 asm("r10") = ctid;
|
register int *r10 asm("r10") = ctid;
|
||||||
stk = (void *)(((long)((char *)stk + stksz) & -16) - 8);
|
stack = (intptr_t *)((long)((char *)stk + stksz) & -16);
|
||||||
*(long *)stk = (long)arg;
|
*--stack = (long)arg; // push 1
|
||||||
asm volatile("syscall"
|
asm volatile("syscall"
|
||||||
: "=a"(ax)
|
: "=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)
|
"r"(r10), "r"(r8), "r"(r9)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
if (ax > -4096u) {
|
if (ax > -4096u) {
|
||||||
|
@ -281,8 +283,8 @@ static privileged int CloneLinux(int (*func)(void *), void *stk, size_t stksz,
|
||||||
}
|
}
|
||||||
if (ax) return ax;
|
if (ax) return ax;
|
||||||
asm volatile("xor\t%%ebp,%%ebp\n\t"
|
asm volatile("xor\t%%ebp,%%ebp\n\t"
|
||||||
"pop\t%%rdi\n\t"
|
"pop\t%%rdi\n\t" // pop 1
|
||||||
"call\t%0\n\t"
|
"call\t*%0\n\t"
|
||||||
"xchg\t%%eax,%%edi\n\t"
|
"xchg\t%%eax,%%edi\n\t"
|
||||||
"jmp\t_Exit1"
|
"jmp\t_Exit1"
|
||||||
: /* no outputs */
|
: /* 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 func is your callback function
|
||||||
* @param stk points to the bottom of a caller allocated stack, which
|
* @param stk points to the bottom of a caller allocated stack, which
|
||||||
* must be null when fork() and vfork() equivalent flags are used
|
* 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
|
* @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
|
* if the fork() or vfork() equivalent flags are used it's highly
|
||||||
* recommended that this value be GetStackSize(), or else kprintf
|
* 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
|
// 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()) {
|
if (IsTiny()) {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
} else if (!arg && !stksz) {
|
} else if (!arg && !stksz) {
|
||||||
|
@ -358,7 +363,7 @@ privileged int clone(int (*func)(void *), void *stk, size_t stksz, int flags,
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
}
|
}
|
||||||
} else if (flags == SIGCHLD) {
|
} else if ((SupportsWindows() || SupportsBsd()) && flags == SIGCHLD) {
|
||||||
if (IsTiny()) {
|
if (IsTiny()) {
|
||||||
rc = eopnotsupp();
|
rc = eopnotsupp();
|
||||||
} else if (!arg && !stksz) {
|
} else if (!arg && !stksz) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ $(LIBC_THREAD_A).pkg: \
|
||||||
$(LIBC_THREAD_A_OBJS) \
|
$(LIBC_THREAD_A_OBJS) \
|
||||||
$(foreach x,$(LIBC_THREAD_A_DIRECTDEPS),$($(x)_A).pkg)
|
$(foreach x,$(LIBC_THREAD_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
# no red zone because asm("call")
|
||||||
o/$(MODE)/libc/thread/clone.o: \
|
o/$(MODE)/libc/thread/clone.o: \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
-mno-red-zone
|
-mno-red-zone
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/clone.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/sa.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
@ -71,13 +73,10 @@ TEST(rand64, testLcg_doesntProduceIdenticalValues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
||||||
char *stack;
|
|
||||||
sigset_t ss, oldss;
|
sigset_t ss, oldss;
|
||||||
|
void *stacks[THREADS];
|
||||||
int i, j, rc, ws, tid[THREADS];
|
int i, j, rc, ws, tid[THREADS];
|
||||||
if (IsXnu()) return;
|
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 oldsa;
|
||||||
struct sigaction sa = {.sa_handler = OnChld, .sa_flags = SA_RESTART};
|
struct sigaction sa = {.sa_handler = OnChld, .sa_flags = SA_RESTART};
|
||||||
EXPECT_NE(-1, sigaction(SIGCHLD, &sa, &oldsa));
|
EXPECT_NE(-1, sigaction(SIGCHLD, &sa, &oldsa));
|
||||||
|
@ -90,8 +89,9 @@ TEST(rand64, testThreadSafety_doesntProduceIdenticalValues) {
|
||||||
}
|
}
|
||||||
ready = false;
|
ready = false;
|
||||||
for (i = 0; i < THREADS; ++i) {
|
for (i = 0; i < THREADS; ++i) {
|
||||||
stack = gc(malloc(GetStackSize()));
|
stacks[i] = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||||
tid[i] = clone(Thrasher, stack, GetStackSize(),
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||||
|
tid[i] = clone(Thrasher, stacks[i], FRAMESIZE,
|
||||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
||||||
(void *)(intptr_t)i, 0, 0, 0, 0);
|
(void *)(intptr_t)i, 0, 0, 0, 0);
|
||||||
ASSERT_NE(-1, tid[i]);
|
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);
|
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) {
|
TEST(mmap, customStackMemory_isAuthorized) {
|
||||||
char *stack;
|
char *stack;
|
||||||
uintptr_t w, r;
|
uintptr_t w, r;
|
||||||
ASSERT_NE(MAP_FAILED,
|
ASSERT_NE(MAP_FAILED, (stack = mmap(NULL, STACKSIZE, PROT_READ | PROT_WRITE,
|
||||||
(stack = mmap(NULL, STACKSIZE, PROT_READ | PROT_WRITE,
|
MAP_ANONYMOUS | MAP_STACK, -1, 0)));
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN, -1, 0)));
|
|
||||||
asm("mov\t%%rsp,%0\n\t"
|
asm("mov\t%%rsp,%0\n\t"
|
||||||
"mov\t%2,%%rsp\n\t"
|
"mov\t%2,%%rsp\n\t"
|
||||||
"push\t%3\n\t"
|
"push\t%3\n\t"
|
||||||
|
@ -110,6 +109,7 @@ TEST(mmap, customStackMemory_isAuthorized) {
|
||||||
: "=&r"(w), "=&r"(r)
|
: "=&r"(w), "=&r"(r)
|
||||||
: "rm"(stack + STACKSIZE - 8), "i"(123));
|
: "rm"(stack + STACKSIZE - 8), "i"(123));
|
||||||
ASSERT_EQ(123, r);
|
ASSERT_EQ(123, r);
|
||||||
|
EXPECT_SYS(0, 0, munmap(stack, STACKSIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mmap, fileOffset) {
|
TEST(mmap, fileOffset) {
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/sysv/consts/clone.h"
|
#include "libc/sysv/consts/clone.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
int x, thechilde;
|
int x, thechilde;
|
||||||
|
@ -41,17 +43,18 @@ int thread(void *arg) {
|
||||||
|
|
||||||
TEST(clone, test) {
|
TEST(clone, test) {
|
||||||
if (IsXnu()) return;
|
if (IsXnu()) return;
|
||||||
if (IsOpenbsd()) return; // still flaky :'(
|
|
||||||
int me, tid;
|
int me, tid;
|
||||||
char *stack;
|
char *stack;
|
||||||
me = gettid();
|
me = gettid();
|
||||||
_spinlock(&lock);
|
_spinlock(&lock);
|
||||||
stack = _gc(valloc(STACKSIZE));
|
stack = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||||
ASSERT_NE(-1, (tid = clone(thread, stack, STACKSIZE,
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||||
|
ASSERT_NE(-1, (tid = clone(thread, stack, FRAMESIZE,
|
||||||
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
|
||||||
(void *)23, 0, 0, 0, 0)));
|
(void *)23, 0, 0, 0, 0)));
|
||||||
_spinlock(&lock);
|
_spinlock(&lock);
|
||||||
ASSERT_EQ(42, x);
|
ASSERT_EQ(42, x);
|
||||||
ASSERT_NE(me, tid);
|
ASSERT_NE(me, tid);
|
||||||
ASSERT_EQ(tid, thechilde);
|
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/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
|
||||||
#include "libc/intrin/nomultics.internal.h"
|
#include "libc/intrin/nomultics.internal.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
|
@ -2498,7 +2497,7 @@ char *linenoiseWithHistory(const char *prompt, const char *prog) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if ((path = linenoiseGetHistoryPath(prog))) {
|
if ((path = linenoiseGetHistoryPath(prog))) {
|
||||||
if (linenoiseHistoryLoad(path) == -1) {
|
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);
|
free(path);
|
||||||
path = 0;
|
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)
|
if (r < 0)
|
||||||
DB (DB_JOBS, ("Failed to read " LOADAVG ": %s\n", strerror (errno)));
|
DB (DB_JOBS, ("Failed to read " LOADAVG ": %s\n", strerror (errno)));
|
||||||
|
|
||||||
|
|
|
@ -353,10 +353,7 @@
|
||||||
(add-hook 'asm-mode-hook 'cosmo-asm-supplemental-hook)
|
(add-hook 'asm-mode-hook 'cosmo-asm-supplemental-hook)
|
||||||
(setq asm-font-lock-keywords cosmo-asm-font-lock-keywords))
|
(setq asm-font-lock-keywords cosmo-asm-font-lock-keywords))
|
||||||
|
|
||||||
;; Make -*-unix-assembly-*- mode line work correctly.
|
;; Make -*-unix-assembly-*- mode line work correctly like GitHub.
|
||||||
;; TODO(jart): Would be nice to use GitHub's name instead of changing asm-mode.
|
(define-derived-mode unix-assembly-mode asm-mode "UNIX Assembly")
|
||||||
(defun unix-assembly-mode ()
|
|
||||||
(interactive)
|
|
||||||
(asm-mode))
|
|
||||||
|
|
||||||
(provide 'cosmo-asm-mode)
|
(provide 'cosmo-asm-mode)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue