Introduce --strace flag for system call tracing

This is similar to the --ftrace (c function call trace) flag, except
it's less noisy since it only logs system calls to stderr. Having this
flag is valuable because (1) system call tracing tells us a lot about
the behavior of complex programs and (2) it's usually very hard to get
system call tracing on various operating systems, e.g. strace, ktrace,
dtruss, truss, nttrace, etc. Especially on Apple platforms where even
with the special boot trick, debuggers still aren't guaranteed to work.

    make -j8 o//examples
    o//examples/hello.com --strace

This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg
extra information will be printed.

    make -j8 MODE=dbg o/dbg/examples
    o/dbg/examples/hello.com --strace |& less

This change also changes:

- Rename IsText() → _istext()
- Rename IsUtf8() → _isutf8()
- Fix madvise() on Windows NT
- Fix empty string case of inet_ntop()
- vfork() wrapper now saves and restores errno
- Update xsigaction() to yoink syscall support
This commit is contained in:
Justine Tunney 2022-03-18 18:07:28 -07:00
parent c541225af0
commit 14e192e5ba
138 changed files with 1519 additions and 631 deletions

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/runtime/memtrack.internal.h"
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
@ -24,7 +24,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
int i;
for (i = 0; i < mm->i; ++i) {
if (mm->p[i].y < mm->p[i].x) {
SYSDEBUG("AreMemoryIntervalsOk() y should be >= x!");
STRACE("AreMemoryIntervalsOk() y should be >= x!");
return false;
}
if (i) {
@ -34,7 +34,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
}
} else {
if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) {
SYSDEBUG("AreMemoryIntervalsOk() out of order or overlap!");
STRACE("AreMemoryIntervalsOk() out of order or overlap!");
return false;
}
}

View file

@ -16,12 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/strace.internal.h"
#include "libc/runtime/runtime.h"
/**
* Removes all environment variables.
*/
int clearenv(void) {
STRACE("clearenv() → 0");
environ = NULL;
return 0;
}

View file

@ -21,6 +21,7 @@
#include "libc/notice.inc"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/map.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
.text.startup
@ -37,6 +38,10 @@ cosmo: push %rbp
mov %rsi,%r13
mov %rdx,%r14
mov %rcx,%r15
#ifdef SYSDEBUG
call __strace_init
mov %eax,%r12d
#endif /* SYSDEBUG */
#ifdef __FAST_MATH__
push %rax
stmxcsr (%rsp)
@ -72,7 +77,7 @@ cosmo: push %rbp
.endfn cosmo,weak
#ifdef __PG__
.init.start 800,_init_ftrace
.init.start 306,_init_ftrace
push %rdi
push %rsi
mov %r12d,%edi
@ -86,5 +91,21 @@ cosmo: push %rbp
mov %eax,%r12d
pop %rsi
pop %rdi
.init.end 800,_init_ftrace
.init.end 306,_init_ftrace
#endif
#if IsModeDbg()
#ifdef SYSDEBUG
.init.start 307,_init_printargs
push %rdi
push %rsi
mov %r12d,%edi
mov %r13,%rsi
mov %r14,%rdx
mov %r15,%rcx
call __printargs
pop %rsi
pop %rdi
.init.end 307,_init_printargs
#endif
#endif

View file

@ -1,49 +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/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define UNSHADOW(x) ((int64_t)(MAX(0, (x)-0x7fff8000)) << 3)
#define FRAME(x) ((int)((x) >> 16))
noasan const char *DescribeFrame(int x) {
/* asan runtime depends on this function */
char *p;
static char buf[128];
if (IsShadowFrame(x)) {
p = buf;
p = __stpcpy(p, " shadow of ");
p = __fixcpy(p, UNSHADOW(ADDR(x)), 48);
return buf;
return " shadow ";
} else if (IsAutoFrame(x)) {
return " automap";
} else if (IsFixedFrame(x)) {
return " fixed ";
} else if (IsArenaFrame(x)) {
return " arena ";
} else if (IsStaticStackFrame(x)) {
return " stack ";
} else {
return "";
}
}

View file

@ -1,39 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
char *describeos(char *buf, size_t size) {
const char *s;
if (IsLinux()) {
s = "gnu/systemd";
} else if (IsXnu()) {
s = "xnu's not unix";
} else if (IsFreebsd()) {
s = "freebesiyatadishmaya";
} else if (IsOpenbsd()) {
s = "openbsd";
} else if (IsWindows()) {
s = "the new technology";
} else {
s = "wut";
}
return memccpy(buf, s, '\0', size);
}

View file

@ -1,65 +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/calls.h"
#include "libc/macros.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/pc.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
static uint64_t sys_mmap_metal_break;
noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot,
int flags, int fd, int64_t off) {
/* asan runtime depends on this function */
size_t i;
struct mman *mm;
struct DirectMap res;
uint64_t addr, page, *pte, *pml4t;
mm = (struct mman *)(BANE + 0x0500);
pml4t = __get_pml4t();
size = ROUNDUP(size, 4096);
addr = (uint64_t)paddr;
if (!(flags & MAP_FIXED)) {
for (i = 0; i < size; i += 4096) {
pte = __get_virtual(mm, pml4t, addr, false);
if (pte && (*pte & PAGE_V)) {
addr = MAX(addr, sys_mmap_metal_break) + i + 4096;
i = 0;
}
}
sys_mmap_metal_break = MAX(addr + size, sys_mmap_metal_break);
}
for (i = 0; i < size; i += 4096) {
page = __new_page(mm);
pte = __get_virtual(mm, pml4t, addr + i, true);
if (pte && page) {
__clear_page(BANE + page);
*pte = page | ((prot & PROT_WRITE) ? PAGE_RW : 0) | PAGE_U | PAGE_V;
} else {
addr = -1;
break;
}
}
res.addr = (void *)addr;
res.maphandle = -1;
return res;
}

View file

@ -1,105 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
int prot, int flags,
int64_t handle, int64_t off) {
/* asan runtime depends on this function */
uint32_t got;
size_t i, upsize;
struct DirectMap dm;
struct NtOverlapped op;
if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE) && handle != -1) {
/*
* WIN32 claims it can do COW mappings but we still haven't found a
* combination of flags, that'll cause Windows to actually do this!
*/
upsize = ROUNDUP(size, FRAMESIZE);
dm.maphandle = CreateFileMappingNuma(-1, &kNtIsInheritable,
kNtPageExecuteReadwrite, upsize >> 32,
upsize, NULL, kNtNumaNoPreferredNode);
SYSDEBUG("CreateFileMappingNuma(-1, kNtPageExecuteReadwrite, 0x%x/0x%x) -> "
"0x%x",
upsize, size, dm.maphandle);
if (dm.maphandle) {
dm.addr =
MapViewOfFileExNuma(dm.maphandle, kNtFileMapWrite | kNtFileMapExecute,
0, 0, upsize, addr, kNtNumaNoPreferredNode);
SYSDEBUG("MapViewOfFileExNuma(WX, 0x%x) -> addr:0x%x", addr, dm.addr);
if (dm.addr) {
for (i = 0; i < size; i += got) {
got = 0;
op.Internal = 0;
op.InternalHigh = 0;
op.Pointer = (void *)(uintptr_t)i;
op.hEvent = 0;
if (!ReadFile(handle, (char *)dm.addr + i, size - i, &got, &op)) {
break;
}
}
if (i == size) {
return dm;
}
UnmapViewOfFile(dm.addr);
}
CloseHandle(dm.maphandle);
}
} else {
dm.maphandle = CreateFileMappingNuma(
handle, &kNtIsInheritable,
(prot & PROT_WRITE) ? kNtPageExecuteReadwrite : kNtPageExecuteRead,
handle != -1 ? 0 : size >> 32, handle != -1 ? 0 : size, NULL,
kNtNumaNoPreferredNode);
SYSDEBUG("CreateFileMappingNuma(fhand:%d, prot:%s, size:0x%x) -> "
"handle:0x%x",
handle, (prot & PROT_WRITE) ? "XRW" : "XR",
handle != -1 ? 0 : size);
if (dm.maphandle) {
dm.addr = MapViewOfFileExNuma(
dm.maphandle,
(prot & PROT_WRITE) ? kNtFileMapWrite | kNtFileMapExecute
: kNtFileMapRead | kNtFileMapExecute,
off >> 32, off, size, addr, kNtNumaNoPreferredNode);
SYSDEBUG(
"MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> "
"addr:0x%x",
(prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr);
if (dm.addr) {
return dm;
} else {
CloseHandle(dm.maphandle);
}
}
}
dm.maphandle = kNtInvalidHandleValue;
dm.addr = (void *)(intptr_t)__winerr();
return dm;
}

View file

@ -1,55 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/errno.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/str/str.h"
/**
* Obtains memory mapping directly from system.
*
* The mmap() function needs to track memory mappings in order to
* support Windows NT and Address Sanitizer. That memory tracking can be
* bypassed by calling this function. However the caller is responsible
* for passing the magic memory handle on Windows NT to CloseHandle().
*/
noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags,
int fd, int64_t off) {
/* asan runtime depends on this function */
char mode[8];
struct DirectMap dm;
if (!IsWindows() && !IsMetal()) {
dm.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
SYSDEBUG("sys_mmap(0x%p%s, 0x%x, %s, %d, %d) -> 0x%p %s", addr,
DescribeFrame((intptr_t)addr >> 16), size,
DescribeMapping(prot, flags, mode), (long)fd, off, dm.addr,
dm.addr != MAP_FAILED ? "" : strerror(errno));
dm.maphandle = kNtInvalidHandleValue;
return dm;
} else if (IsMetal()) {
return sys_mmap_metal(addr, size, prot, flags, fd, off);
} else {
return sys_mmap_nt(addr, size, prot, flags,
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
off);
}
}

View file

@ -19,7 +19,9 @@
#include "libc/macros.internal.h"
#include "libc/notice.inc"
.underrun
// Uniquely identifies each artifact linked in an address space.
__dso_handle:
.quad __dso_handle
.endobj __dso_handle,globl,hidden
.overrun

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/strace.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
@ -32,6 +33,7 @@
* @noreturn
*/
wontreturn void exit(int exitcode) {
STRACE("exit(%d)", exitcode);
if (weaken(__cxa_finalize)) {
weaken(__cxa_finalize)(NULL);
}

View file

@ -22,46 +22,37 @@
#include "libc/runtime/symbols.internal.h"
#include "libc/str/str.h"
static char *g_comdbg;
static char g_comdbg_buf[PATH_MAX + 1];
static optimizesize textstartup void g_comdbg_init() {
char *p;
size_t n;
static bool once;
if (!once) {
if (!(g_comdbg = getenv("COMDBG"))) {
p = program_executable_name;
n = strlen(p);
if (n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) {
g_comdbg = p;
} else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") &&
n + 4 <= PATH_MAX) {
mempcpy(mempcpy(g_comdbg_buf, p, n), ".dbg", 5);
if (fileexists(g_comdbg_buf)) {
g_comdbg = g_comdbg_buf;
}
} else if (n + 8 <= PATH_MAX) {
mempcpy(mempcpy(g_comdbg_buf, p, n), ".com.dbg", 9);
if (fileexists(g_comdbg_buf)) {
g_comdbg = g_comdbg_buf;
}
}
}
once = true;
}
}
/**
* Returns path of binary with the debug information, or null.
*
* @return path to debug binary, or NULL
*/
const char *FindDebugBinary(void) {
g_comdbg_init();
return g_comdbg;
static bool once;
static char *res;
static char buf[PATH_MAX + 1];
char *p;
size_t n;
if (!once) {
if (!(res = getenv("COMDBG"))) {
p = program_executable_name;
n = strlen(p);
if (n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) {
res = p;
} else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") &&
n + 4 <= PATH_MAX) {
mempcpy(mempcpy(buf, p, n), ".dbg", 5);
if (fileexists(buf)) {
res = buf;
}
} else if (n + 8 <= PATH_MAX) {
mempcpy(mempcpy(buf, p, n), ".com.dbg", 9);
if (fileexists(buf)) {
res = buf;
}
}
}
once = true;
}
return res;
}
const void *const g_comdbg_ctor[] initarray = {
g_comdbg_init,
};

View file

@ -21,7 +21,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/fmt/itoa.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/nt2sysv.h"
@ -60,7 +60,7 @@ static textwindows noasan char16_t *ParseInt(char16_t *p, int64_t *x) {
}
static dontinline textwindows noasan bool ForkIo(int64_t h, void *buf, size_t n,
bool32 (*f)()) {
bool32 (*f)()) {
char *p;
size_t i;
uint32_t x;
@ -73,17 +73,15 @@ static dontinline textwindows noasan bool ForkIo(int64_t h, void *buf, size_t n,
}
static dontinline textwindows noasan void WriteAll(int64_t h, void *buf,
size_t n) {
if (!ForkIo(h, buf, n, WriteFile)) {
SYSDEBUG("fork() WriteFile(%zu) failed %d\n", n, GetLastError());
}
size_t n) {
bool rc = ForkIo(h, buf, n, WriteFile);
STRACE("%s(%ld, %'zu) %d% m", "WriteFile", h, n);
}
static textwindows dontinline noasan void ReadAll(int64_t h, void *buf,
size_t n) {
if (!ForkIo(h, buf, n, ReadFile)) {
SYSDEBUG("fork() ReadFile(%zu) failed %d\n", n, GetLastError());
}
size_t n) {
bool rc = ForkIo(h, buf, n, ReadFile);
STRACE("%s(%ld, %'zu) %d% m", "ReadFile", h, n);
}
textwindows noasan noinstrument void WinMainForked(void) {
@ -99,6 +97,7 @@ textwindows noasan noinstrument void WinMainForked(void) {
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
if (!varlen) return;
if (varlen >= ARRAYLEN(var)) ExitProcess(123);
STRACE("WinMainForked()");
SetEnvironmentVariable(u"_FORK", NULL);
ParseInt(ParseInt(var, &reader), &writer);
ReadAll(reader, jb, sizeof(jb));

View file

@ -20,7 +20,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/nt/process.h"
@ -55,12 +55,12 @@ int fork(void) {
}
parent = __pid;
__pid = dx;
SYSDEBUG("fork() → 0 (child of %d)", parent);
STRACE("fork() → 0 (child of %d)", parent);
if (weaken(__onfork)) {
weaken(__onfork)();
}
} else {
SYSDEBUG("fork() → %d% m", ax);
STRACE("fork() → %d% m", ax);
}
return ax;
}

View file

@ -21,7 +21,7 @@
ftrace_hook:
cmp $0,g_ftrace(%rip)
je 1f
jg 1f
ret
1: push %rbp
mov %rsp,%rbp

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
@ -31,26 +32,10 @@
*
* @see libc/runtime/_init.S for documentation
*/
textstartup int ftrace_init(int argc, char *argv[]) {
int i;
bool foundflag;
foundflag = false;
for (i = 1; i <= argc; ++i) {
if (!foundflag) {
if (argv[i]) {
if (strcmp(argv[i], "--ftrace") == 0) {
foundflag = true;
} else if (strcmp(argv[i], "----ftrace") == 0) {
strcpy(argv[i], "--ftrace");
}
}
} else {
argv[i - 1] = argv[i];
}
}
if (foundflag) {
--argc;
textstartup int ftrace_init(void) {
if (__intercept_flag(&__argc, __argv, "--ftrace")) {
ftrace_install();
++g_ftrace;
}
return argc;
return __argc;
}

View file

@ -16,25 +16,31 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/internal.h"
#include "libc/str/str.h"
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
/* asan runtime depends on this function */
p[0] = (prot & PROT_READ) ? 'r' : '-';
p[1] = (prot & PROT_WRITE) ? 'w' : '-';
p[2] = (prot & PROT_EXEC) ? 'x' : '-';
if (flags & MAP_PRIVATE) {
p[3] = 'p';
} else if (flags & MAP_SHARED) {
p[3] = 's';
} else {
p[3] = '?';
textstartup bool __intercept_flag(int *argc, char *argv[], const char *flag) {
/* asan isn't initialized yet at runlevel 300 */
char *a;
int i, j;
bool found;
found = false;
for (j = i = 1; i <= *argc;) {
a = argv[j++];
if (a && !__strcmp(a, flag)) {
found = true;
--*argc;
} else {
/*
* e.g. turns ----strace --strace for execve.
* todo: update this to allow ------strace etc.
*/
if (a && a[0] == '-' && a[1] == '-' && !__strcmp(a + 2, flag)) {
a = flag;
}
argv[i++] = a;
}
}
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : 'f';
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';
p[6] = (flags & MAP_FIXED) ? 'F' : '-';
p[7] = 0;
return p;
return found;
}

View file

@ -27,6 +27,7 @@ long _setstack(void *, void *, ...) hidden;
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
Elf64_Ehdr *MapElfRead(const char *, struct MappedFile *) hidden;
int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t) hidden;
bool __intercept_flag(int *, char *[], const char *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -21,7 +21,7 @@
#include "libc/bits/likely.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -76,13 +76,13 @@ static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #1");
STRACE("ExtendMemoryIntervals() fail #1");
return false;
}
}
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #2");
STRACE("ExtendMemoryIntervals() fail #2");
return false;
}
MoveMemoryIntervals(dm.addr, mm->p, mm->i);
@ -95,13 +95,13 @@ static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #3");
STRACE("ExtendMemoryIntervals() fail #3");
return false;
}
}
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #4");
STRACE("ExtendMemoryIntervals() fail #4");
return false;
}
mm->n = (size + gran) / sizeof(*mm->p);

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/version.h"
@ -164,6 +165,7 @@ forceinline unsigned FindMemoryInterval(const struct MemoryIntervals *mm,
r = m;
}
}
assert(l == mm->i || x <= mm->p[l].y);
return l;
}
@ -171,7 +173,7 @@ forceinline bool IsMemtracked(int x, int y) {
unsigned i;
i = FindMemoryInterval(&_mmi, x);
if (i == _mmi.i) return false;
if (!(_mmi.p[i].x <= x && x <= _mmi.p[i].y)) return false;
if (x < _mmi.p[i].x) return false;
for (;;) {
if (y <= _mmi.p[i].y) return true;
if (++i == _mmi.i) return false;

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/memtrack.internal.h"
@ -37,8 +37,8 @@ noasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
for (i = l; i <= r; ++i) {
addr = GetFrameAddr(mm->p[i].x);
last = GetFrameAddr(mm->p[i].y);
SYSDEBUG("UnmapViewOfFile(addr:0x%x, size:0x%x, hand:0x%x)", addr,
last - addr + FRAMESIZE, mm->p[i].h);
STRACE("UnmapViewOfFile(%p, size:%'zu, hand:%ld)", addr,
last - addr + FRAMESIZE, mm->p[i].h);
ok = UnmapViewOfFile(addr);
assert(ok);
ok = CloseHandle(mm->p[i].h);

View file

@ -1,160 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management
*/
#include "ape/relocations.h"
#include "libc/elf/def.h"
#include "libc/elf/struct/phdr.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/runtime/e820.internal.h"
#include "libc/runtime/metalprintf.internal.h"
#include "libc/runtime/pc.internal.h"
#include "libc/runtime/runtime.h"
/**
* Allocates new page of physical memory.
*/
noasan texthead uint64_t __new_page(struct mman *mm) {
uint64_t p;
if (mm->pdpi == mm->e820n) {
/* TODO: reclaim free pages */
return 0;
}
while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) {
if (++mm->pdpi == mm->e820n) return 0;
mm->pdp = mm->e820[mm->pdpi].addr;
}
p = mm->pdp;
mm->pdp += 4096;
return p;
}
/**
* Returns pointer to page table entry for page at virtual address.
* Additional page tables are allocated if needed as a side-effect.
*/
noasan texthead uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
int64_t vaddr, bool maketables) {
uint64_t *e, p;
unsigned char h;
for (h = 39;; h -= 9) {
e = t + ((vaddr >> h) & 511);
if (h == 12) return e;
if (!(*e & PAGE_V)) {
if (!maketables) return NULL;
if (!(p = __new_page(mm))) return NULL;
*e = p | PAGE_V | PAGE_RW;
}
t = (uint64_t *)(BANE + (*e & PAGE_TA));
}
}
/**
* Sorts, rounds, and filters BIOS memory map.
*/
static noasan texthead void __normalize_e820(struct mman *mm) {
uint64_t a, b;
uint64_t x, y;
unsigned i, j, n;
for (n = i = 0; mm->e820[i].size; ++i) {
mm->e820[n] = mm->e820[i];
x = mm->e820[n].addr;
y = mm->e820[n].addr + mm->e820[n].size;
a = ROUNDUP(x, 4096);
b = ROUNDDOWN(y, 4096) - a;
if (b > 0 && mm->e820[i].type == kMemoryUsable) {
mm->e820[n].addr = a;
mm->e820[n].size = b;
++n;
}
}
for (i = 1; i < n; ++i) {
for (j = i; j > 0 && mm->e820[i].addr < mm->e820[j - 1].addr; --j) {
mm->e820[j] = mm->e820[j - 1];
}
mm->e820[j] = mm->e820[i];
}
mm->pdp = MAX(0x80000, mm->e820[0].addr);
mm->pdpi = 0;
mm->e820n = n;
}
/**
* Identity maps all usable physical memory to its negative address.
*/
static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size;
p + 0x200000 < pe; p += 4096) {
m = __get_virtual(mm, pml4t, BANE + p, true);
if (m && !(*m & PAGE_V)) {
*m = p | PAGE_V | PAGE_RW;
}
}
}
}
noasan texthead void __setup_mman(struct mman *mm, uint64_t *pml4t) {
__normalize_e820(mm);
__invert_memory(mm, pml4t);
}
/**
* Maps APE-defined ELF program headers into memory and clears BSS.
*/
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) {
struct Elf64_Phdr *p;
uint64_t i, f, v, m, *e;
extern char ape_phdrs[] __attribute__((__weak__));
extern char ape_phdrs_end[] __attribute__((__weak__));
__setup_mman(mm, pml4t);
for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0;
p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) {
if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) {
f = PAGE_V | PAGE_U;
if (p->p_flags & PF_W) f |= PAGE_RW;
for (i = 0; i < p->p_memsz; i += 4096) {
if (i < p->p_filesz) {
v = b + p->p_offset + i;
m = MAX(m, v);
} else {
v = __clear_page(__new_page(mm));
}
*__get_virtual(mm, pml4t, p->p_vaddr + i, true) = (v & PAGE_TA) | f;
}
}
}
mm->pdp = MAX(mm->pdp, m);
}

View file

@ -21,7 +21,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -40,7 +40,6 @@
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
@ -60,7 +59,7 @@ noasan static bool NeedAutomap(char *p, size_t n) {
IsMapped(p, n);
}
noasan static bool ChooseInterval(int x, int n, int *res) {
noasan static bool ChooseMemoryInterval(int x, int n, int *res) {
int i;
if (_mmi.i) {
i = FindMemoryInterval(&_mmi, x);
@ -89,18 +88,17 @@ noasan static bool ChooseInterval(int x, int n, int *res) {
noasan static bool Automap(int n, int *res) {
*res = -1;
if (ChooseInterval(FRAME(kAutomapStart), n, res)) {
if (ChooseMemoryInterval(FRAME(kAutomapStart), n, res)) {
assert(*res >= FRAME(kAutomapStart));
if (*res + n <= FRAME(kAutomapStart + (kAutomapStart - 1))) {
return true;
} else {
SYSDEBUG("mmap(0x%p, 0x%x) ENOMEM (automap interval exhausted)",
ADDR(*res), ADDR(n + 1));
STRACE("mmap(%.12p, %p) ENOMEM (automap interval exhausted)", ADDR(*res),
ADDR(n + 1));
return false;
}
} else {
SYSDEBUG("mmap(0x%p, 0x%x) ENOMEM (automap failed)", ADDR(*res),
ADDR(n + 1));
STRACE("mmap(%.12p, %p) ENOMEM (automap failed)", ADDR(*res), ADDR(n + 1));
return false;
}
}
@ -111,28 +109,28 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
dm = sys_mmap(addr, size, prot, f, fd, off);
if (UNLIKELY(dm.addr == MAP_FAILED)) {
if (IsWindows() && (flags & MAP_FIXED)) {
SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", addr, size, strerror(errno),
"can't recover from MAP_FIXED errors on Windows");
STRACE("mmap(%.12p, %'ld) → %s (%s)", addr, size, strerror(errno),
"can't recover from MAP_FIXED errors on Windows");
assert(!"MapMemory() failed");
Die();
}
return MAP_FAILED;
}
if (UNLIKELY(dm.addr != addr)) {
SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED");
STRACE("KERNEL DIDN'T RESPECT MAP_FIXED");
assert(!"MapMemory() failed");
Die();
}
if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(addr, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
STRACE("FIXED UNTRACK FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
}
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(addr, n) == -1) {
SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno));
STRACE("TRACK MUNMAP FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
@ -151,21 +149,21 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
* punch holes into existing mappings.
*/
static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
int prot, int flags,
int fd, int64_t off, int f,
int x, size_t n) {
int prot, int flags,
int fd, int64_t off,
int f, int x, size_t n) {
struct DirectMap dm;
size_t i, m = (n - 1) * FRAMESIZE;
assert(m < size && m + FRAMESIZE >= size);
dm = sys_mmap(addr + m, size - m, prot, f, fd, fd == -1 ? 0 : off + m);
if (dm.addr == MAP_FAILED) {
SYSDEBUG("MapMemories(%p+%x/%x) %s", addr, m, size, strerror(errno));
STRACE("MapMemories(%.12p+%lx/%lx) %m", addr, m, size);
return MAP_FAILED;
}
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #1 %s", addr, m, size,
strerror(errno));
STRACE("MapMemories(%.12p+%lx/%lx) unrecoverable failure #1 %m", addr, m,
size);
assert(!"MapMemories() failed");
Die();
}
@ -174,8 +172,8 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
if (dm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, x + i / FRAMESIZE, x + i / FRAMESIZE,
dm.maphandle, prot, flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #2 %s", addr, i,
size, strerror(errno));
STRACE("MapMemories(%p+%x/%x) unrecoverable failure #2 %m", addr, i,
size);
assert(!"MapMemories() failed");
Die();
}
@ -221,56 +219,56 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
int a, b, i, f, m, n, x;
char mode[8], *p = addr;
if (UNLIKELY(!size)) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size=0)", p, size);
STRACE("mmap(%.12p, %'zu) EINVAL (size=0)", p, size);
return VIP(einval());
}
if (UNLIKELY(!SMALL(size))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size);
if (UNLIKELY(!IsLegalSize(size))) {
STRACE("mmap(%.12p, %'zu) EINVAL (size isn't 48-bit)", p, size);
return VIP(einval());
}
if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size);
STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 48-bit)", p, size);
return VIP(einval());
}
if (UNLIKELY(!ALIGNED(p))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, size);
STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, size);
return VIP(einval());
}
if (UNLIKELY(fd < -1)) {
SYSDEBUG("mmap(0x%p, 0x%x, fd=%d) EBADF", p, size, (long)fd);
STRACE("mmap(%.12p, %'zu, fd=%d) EBADF", p, size, fd);
return VIP(ebadf());
}
if (UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
SYSDEBUG("mmap(0x%p, 0x%x, %s, %d, %d) EINVAL (fd anonymous mismatch)", p,
size, DescribeMapping(prot, flags, mode), (long)fd, off);
STRACE("mmap(%.12p, %'zu, %s, %d, %'ld) EINVAL (fd anonymous mismatch)", p,
size, DescribeMapping(prot, flags, mode), fd, off);
return VIP(einval());
}
if (UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (MAP_SHARED ^ MAP_PRIVATE)", p, size);
STRACE("mmap(%.12p, %'zu) EINVAL (MAP_SHARED ^ MAP_PRIVATE)", p, size);
return VIP(einval());
}
if (UNLIKELY(off < 0)) {
SYSDEBUG("mmap(0x%p, 0x%x, off=%d) EINVAL (neg off)", p, size, off);
STRACE("mmap(%.12p, %'zu, off=%'ld) EINVAL (neg off)", p, size, off);
return VIP(einval());
}
if (UNLIKELY(INT64_MAX - size < off)) {
SYSDEBUG("mmap(0x%p, 0x%x, off=%d) EINVAL (too large)", p, size, off);
STRACE("mmap(%.12p, %'zu, off=%'ld) EINVAL (too large)", p, size, off);
return VIP(einval());
}
if (UNLIKELY(!ALIGNED(off))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, size);
STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, size);
return VIP(einval());
}
if ((flags & MAP_FIXED_NOREPLACE) && IsMapped(p, size)) {
if (OverlapsImageSpace(p, size)) {
SYSDEBUG("mmap(0x%p, 0x%x) EFAULT (overlaps image)", p, size);
STRACE("mmap(%.12p, %'zu) EFAULT (overlaps image)", p, size);
} else {
SYSDEBUG("mmap(0x%p, 0x%x) EFAULT (overlaps existing)", p, size);
STRACE("mmap(%.12p, %'zu) EFAULT (overlaps existing)", p, size);
}
return VIP(efault());
}
SYSDEBUG("mmap(0x%p, 0x%x, %s, %d, %d)", p, size,
DescribeMapping(prot, flags, mode), (long)fd, off);
STRACE("mmap(%.12p, %'zu, %s, %d, %'ld)% m", p, size,
DescribeMapping(prot, flags, mode), fd, off);
if (fd == -1) {
size = ROUNDUP(size, FRAMESIZE);
if (IsWindows()) {
@ -283,7 +281,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
x = FRAME(p);
if (IsWindows()) {
if (UntrackMemoryIntervals(p, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
STRACE("FIXED UNTRACK FAILED %m");
assert(!"mmap() failed");
Die();
}

View file

@ -1,55 +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/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/mremap.h"
#include "libc/sysv/errfuns.h"
privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) {
bool cf;
uintptr_t rax, rdi, rsi, rdx;
register uintptr_t r8 asm("r8");
register uintptr_t r10 asm("r10");
if (IsLinux()) {
r10 = f;
r8 = (uintptr_t)q;
asm("syscall"
: "=a"(rax)
: "0"(0x019), "D"(p), "S"(n), "d"(m), "r"(r10), "r"(r8)
: "rcx", "r11", "memory", "cc");
if (rax > -4096ul) errno = -rax, rax = -1;
} else if (IsNetbsd()) {
if (f & MREMAP_MAYMOVE) {
rax = 0x19B;
r10 = m;
r8 = (f & MREMAP_FIXED) ? MAP_FIXED : 0;
asm(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(cf), "+a"(rax)
: "D"(p), "S"(n), "d"(q), "r"(r10), "r"(r8)
: "rcx", "r11", "memory", "cc");
if (cf) errno = rax, rax = -1;
} else {
rax = einval();
}
} else {
rax = enosys();
}
return (void *)rax;
}

View file

@ -21,10 +21,9 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
@ -36,7 +35,6 @@
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
@ -76,43 +74,44 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
size_t i, j, k;
struct DirectMap dm;
int a, b, prot, flags;
assert(!__vforked);
if (UNLIKELY(!m)) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (m=0)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (m=0)", p, n, m, f);
return VIP(einval());
}
if (UNLIKELY(!n)) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n=0)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n=0)", p, n, m, f);
return VIP(eopnotsupp());
}
if (UNLIKELY(!ALIGNED(n))) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n align)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n align)", p, n, m, f);
return VIP(eopnotsupp());
}
if (UNLIKELY(!ALIGNED(m))) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n align)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n align)", p, n, m, f);
return VIP(eopnotsupp());
}
if (UNLIKELY(!ALIGNED(p))) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (64kb align)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (64kb align)", p, n, m, f);
return VIP(einval());
}
if (UNLIKELY(!SMALL(n))) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (n too big)", p, n, m, f);
if (UNLIKELY(!IsLegalSize(n))) {
STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (n too big)", p, n, m, f);
return VIP(enomem());
}
if (UNLIKELY(!SMALL(m))) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (m too big)", p, n, m, f);
if (UNLIKELY(!IsLegalSize(m))) {
STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (m too big)", p, n, m, f);
return VIP(enomem());
}
if (f & ~(MREMAP_MAYMOVE | MREMAP_FIXED)) {
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (bad flag)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (bad flag)", p, n, m, f);
return VIP(einval());
}
if (!IsMemtracked(FRAME(p), FRAME((intptr_t)p + (n - 1)))) {
SYSDEBUG("munmap(0x%x, 0x%x) EFAULT (interval not tracked)", p, n);
STRACE("munmap(%p, %'zu) EFAULT (interval not tracked)", p, n);
return VIP(efault());
}
SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x)", p, n, m, f);
STRACE("mremap(%p, %'zu, %'zu, %#b)", p, n, m, f);
i = FindMemoryInterval(&_mmi, FRAME(p));
if (i >= _mmi.i) return VIP(efault());
flags = _mmi.p[i].flags;
@ -174,8 +173,8 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
}
q = sys_mremap((void *)p, n, m, MREMAP_MAYMOVE | MREMAP_FIXED,
(void *)ADDR(a));
SYSDEBUG("sys_mremap(0x%p, 0x%x, 0x%x, 0x%x, 0x%x) -> 0x%p", p, n, m,
MREMAP_MAYMOVE | MREMAP_FIXED, ADDR(a));
STRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p", p, n, m,
MREMAP_MAYMOVE | MREMAP_FIXED, ADDR(a), q);
if (q == MAP_FAILED) return 0;
if (ReleaseMemoryIntervals(&_mmi, (uintptr_t)p >> 16,
((uintptr_t)p + n - FRAMESIZE) >> 16, 0) != -1 &&

View file

@ -1,33 +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/runtime/directmap.internal.h"
#include "libc/runtime/pc.internal.h"
noasan int sys_munmap_metal(void *addr, size_t size) {
size_t i;
uint64_t *e;
struct mman *mm;
mm = (struct mman *)(BANE + 0x0500);
for (i = 0; i < size; i += 4096) {
e = __get_virtual(mm, __get_pml4t(), (uint64_t)addr + i, false);
if (e) *e = ~PAGE_V;
invlpg(e);
}
return 0;
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/bits/likely.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -31,10 +31,8 @@
#include "libc/sysv/errfuns.h"
#define IP(X) (intptr_t)(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
/**
@ -56,28 +54,29 @@ noasan int munmap(void *v, size_t n) {
int rc;
char poison, *p = v;
intptr_t a, b, x, y;
assert(!__vforked);
if (UNLIKELY(!n)) {
SYSDEBUG("munmap(0x%p, 0x%x) %s (n=0)", p, n);
STRACE("munmap(%.12p, %'zu) %s (n=0)", p, n);
return einval();
}
if (UNLIKELY(!SMALL(n))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n);
if (UNLIKELY(!IsLegalSize(n))) {
STRACE("munmap(%.12p, %'zu) EINVAL (n isn't 48-bit)", p, n);
return einval();
}
if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n);
STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 48-bit)", p, n);
return einval();
}
if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n);
STRACE("munmap(%.12p, %'zu) EINVAL (p+(n-1) isn't 48-bit)", p, n);
return einval();
}
if (UNLIKELY(!ALIGNED(p))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, n);
STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, n);
return einval();
}
if (!IsMemtracked(FRAME(p), FRAME(p + (n - 1)))) {
SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n);
STRACE("munmap(%.12p, %'zu) EFAULT (interval not tracked)", p, n);
return efault();
}
if (UntrackMemoryIntervals(p, n) != -1) {
@ -85,7 +84,7 @@ noasan int munmap(void *v, size_t n) {
rc = sys_munmap(p, n);
if (rc != -1) {
if (IsAsan() && !OverlapsShadowSpace(p, n)) {
a = SHADE(p);
a = ((intptr_t)p >> 3) + 0x7fff8000;
b = a + (n >> 3);
if (IsMemtracked(FRAME(a), FRAME(b - 1))) {
x = ROUNDUP(a, FRAMESIZE);
@ -100,7 +99,7 @@ noasan int munmap(void *v, size_t n) {
__repstosb((void *)a, kAsanUnmapped, b - a);
}
} else {
SYSDEBUG("unshadow(0x%x, 0x%x) EFAULT", a, b - a);
STRACE("unshadow(%.12p, %p) EFAULT", a, b - a);
}
}
}
@ -110,7 +109,7 @@ noasan int munmap(void *v, size_t n) {
} else {
rc = -1;
}
SYSDEBUG("munmap(0x%p, 0x%x) -> %d %s", p, n, (long)rc,
rc == -1 ? strerror(errno) : "");
STRACE("munmap(%.12p, %'zu) → %d %s", p, n, rc,
rc == -1 ? strerror(errno) : "");
return rc;
}

View file

@ -20,7 +20,7 @@
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/elf/scalar.h"
@ -187,7 +187,7 @@ RaiseEnobufs:
RaiseEnoexec:
errno = ENOEXEC;
SystemError:
SYSDEBUG("OpenSymbolTable() %s", strerror(errno));
STRACE("OpenSymbolTable() %m");
if (map != MAP_FAILED) {
munmap(map, st.st_size);
}

116
libc/runtime/printargs.c Normal file
View file

@ -0,0 +1,116 @@
/*-*- 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/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/auxv.h"
static const struct AuxiliaryValue {
const char *fmt;
long *id;
const char *name;
} kAuxiliaryValues[] = {
{"%-14p", &AT_EXECFD, "AT_EXECFD"},
{"%-14p", &AT_PHDR, "AT_PHDR"},
{"%-14p", &AT_PHENT, "AT_PHENT"},
{"%-14p", &AT_PHNUM, "AT_PHNUM"},
{"%-14p", &AT_PAGESZ, "AT_PAGESZ"},
{"%-14p", &AT_BASE, "AT_BASE"},
{"%-14p", &AT_ENTRY, "AT_ENTRY"},
{"%-14p", &AT_NOTELF, "AT_NOTELF"},
{"%-14d", &AT_UID, "AT_UID"},
{"%-14d", &AT_EUID, "AT_EUID"},
{"%-14d", &AT_GID, "AT_GID"},
{"%-14d", &AT_EGID, "AT_EGID"},
{"%-14d", &AT_CLKTCK, "AT_CLKTCK"},
{"%-14d", &AT_OSRELDATE, "AT_OSRELDATE"},
{"%-14p", &AT_PLATFORM, "AT_PLATFORM"},
{"%-14p", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE"},
{"%-14p", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE"},
{"%-14p", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE"},
{"%-14p", &AT_SECURE, "AT_SECURE"},
{"%-14s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM"},
{"%-14p", &AT_RANDOM, "AT_RANDOM"},
{"%-14s", &AT_EXECFN, "AT_EXECFN"},
{"%-14p", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR"},
{"%-14p", &AT_FLAGS, "AT_FLAGS"},
{"%-14p", &AT_HWCAP, "AT_HWCAP"},
{"%-14p", &AT_HWCAP2, "AT_HWCAP2"},
{"%-14p", &AT_STACKBASE, "AT_STACKBASE"},
{"%-14p", &AT_CANARY, "AT_CANARY"},
{"%-14p", &AT_CANARYLEN, "AT_CANARYLEN"},
{"%-14ld", &AT_NCPUS, "AT_NCPUS"},
{"%-14p", &AT_PAGESIZES, "AT_PAGESIZES"},
{"%-14d", &AT_PAGESIZESLEN, "AT_PAGESIZESLEN"},
{"%-14p", &AT_TIMEKEEP, "AT_TIMEKEEP"},
{"%-14p", &AT_STACKPROT, "AT_STACKPROT"},
{"%-14p", &AT_EHDRFLAGS, "AT_EHDRFLAGS"},
};
static const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
int i;
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
if (*kAuxiliaryValues[i].id && x == *kAuxiliaryValues[i].id) {
return kAuxiliaryValues + i;
}
}
return NULL;
}
textstartup void __printargs(int argc, char **argv, char **envp,
intptr_t *auxv) {
#ifdef SYSDEBUG
long key;
char **env;
unsigned i;
intptr_t *auxp;
char path[PATH_MAX];
struct AuxiliaryValue *auxinfo;
STRACE("ARGUMENTS (%p)", argv);
for (i = 0; i < argc; ++i) {
STRACE(" ☼ %s", argv[i]);
}
STRACE("ENVIRONMENT (%p)", envp);
for (env = envp; *env; ++env) {
STRACE(" ☼ %s", *env);
}
STRACE("AUXILIARY (%p)", auxv);
for (auxp = auxv; *auxp; auxp += 2) {
if ((auxinfo = DescribeAuxv(auxp[0]))) {
ksnprintf(path, sizeof(path), auxinfo->fmt, auxp[1]);
STRACE(" ☼ %16s[%4ld] = %s", auxinfo->name, auxp[0], path);
} else {
STRACE(" ☼ %16s[%4ld] = %014p", "unknown", auxp[0], auxp[1]);
}
}
STRACE("SPECIALS");
STRACE(" ☼ %21s = %#s", "kTmpPath", kTmpPath);
STRACE(" ☼ %21s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
STRACE(" ☼ %21s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
STRACE(" ☼ %21s = %#s", "program_executable_name", program_executable_name);
STRACE(" ☼ %21s = %#s", "GetInterpreterExecutableName()",
GetInterpreterExecutableName(path, sizeof(path)));
STRACE(" ☼ %21s = %p", "RSP", __builtin_frame_address(0));
STRACE(" ☼ %21s = %p", "GetStackAddr()", GetStackAddr(0));
STRACE(" ☼ %21s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
STRACE(" ☼ %21s = %p", "GetStackSize()", GetStackSize());
#endif
}

View file

@ -16,19 +16,22 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/internal.h"
#include "libc/str/str.h"
int sys_munmap(void *p, size_t n) {
int rc;
if (!IsMetal()) {
rc = __sys_munmap(p, n);
} else {
rc = sys_munmap_metal(p, n);
/**
* Enables plaintext system call logging if `--strace` flag is passed.
*/
textstartup int __strace_init(int argc, char **argv, char **envp, long *auxv) {
/* asan isn't initialized yet at runlevel 300 */
if (__intercept_flag(&argc, argv, "--strace") ||
__atoul(nulltoempty(__getenv(envp, "STRACE")))) {
++__strace;
}
SYSDEBUG("sys_munmap(0x%p%s, 0x%x) -> %d", p,
DescribeFrame((intptr_t)p >> 16), n, (long)rc);
return rc;
return argc;
}

View file

@ -17,14 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
.privileged
#ifdef __FSANITIZE_ADDRESS__
vfork: jmp fork # TODO: asan and vfork don't mix?
.endfn vfork,globl
#else
// Forks process without copying page tables.
//
// This is the same as fork() except it's optimized for the case
@ -40,11 +36,24 @@ vfork: jmp fork # TODO: asan and vfork don't mix?
// @returnstwice
// @vforksafe
vfork:
#ifdef __FSANITIZE_ADDRESS__
jmp fork # TODO: asan and vfork don't mix?
.endfn vfork,globl
#else
#if SupportsWindows()
testb IsWindows()
jnz sys_fork_nt
jnz sys_fork_nt # and we're lucky to have that
#endif
#if SupportsOpenbsd()
testb IsOpenbsd()
jnz fork # fake vfork plus msyscall issues
#endif
#ifdef SYSDEBUG
ezlea .Llog,di
call __stracef
#endif /* SYSDEBUG */
mov __NR_vfork(%rip),%eax
mov errno(%rip),%r8d # avoid question of @vforksafe errno
pop %rsi # saves return address in a register
#if SupportsBsd()
testb IsBsd()
@ -56,7 +65,8 @@ vfork:
cmp $-4095,%eax
jae systemfive_error
#endif
0: ezlea __vforked,di
0: mov %r8d,errno(%rip)
ezlea __vforked,di
test %eax,%eax
jz 1f
decl (%rdi)
@ -81,4 +91,11 @@ vfork.bsd:
.endfn vfork.bsd
#endif /* BSD */
#ifdef SYSDEBUG
.rodata.str1.1
.Llog: .ascii STRACE_PROLOGUE
.asciz "vfork()%n"
.previous
#endif /* DEBUGSYS */
#endif /* __FSANITIZE_ADDRESS__ */

View file

@ -20,6 +20,7 @@
#include "libc/bits/pushpop.h"
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/kprintf.h"
@ -127,6 +128,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
stacksize = GetStackSize();
allocsize = argsize + stacksize;
allocaddr = stackaddr - argsize;
STRACE("WinMainNew() mapping arg block / stack");
MapViewOfFileExNuma(
(_mmi.p[0].h = CreateFileMappingNuma(
-1, &kNtIsInheritable, kNtPageExecuteReadwrite, allocsize >> 32,
@ -139,6 +141,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
_mmi.p[0].flags = MAP_PRIVATE | MAP_ANONYMOUS;
_mmi.i = 1;
wa = (struct WinArgs *)allocaddr;
STRACE("WinMainNew() loading arg block");
count = GetDosArgv(GetCommandLine(), wa->argblock, ARRAYLEN(wa->argblock),
wa->argv, ARRAYLEN(wa->argv));
for (i = 0; wa->argv[0][i]; ++i) {
@ -147,11 +150,13 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
}
}
env16 = GetEnvironmentStrings();
STRACE("WinMainNew() loading environment");
GetDosEnviron(env16, wa->envblock, ARRAYLEN(wa->envblock) - 8, wa->envp,
ARRAYLEN(wa->envp) - 1);
FreeEnvironmentStrings(env16);
wa->auxv[0][0] = pushpop(AT_EXECFN);
wa->auxv[0][1] = (intptr_t)wa->argv[0];
STRACE("WinMainNew() switching stacks");
_jmpstack((char *)stackaddr + stacksize, cosmo, count, wa->argv, wa->envp,
wa->auxv);
}
@ -198,6 +203,7 @@ noasan textwindows noinstrument int64_t WinMain(int64_t hInstance,
ts = rdtsc();
__nomultics = true;
__pid = GetCurrentProcessId();
STRACE("WinMain()");
MakeLongDoubleLongAgain();
if (weaken(WinSockInit)) weaken(WinSockInit)();
if (weaken(WinMainForked)) weaken(WinMainForked)();