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

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -30,10 +31,14 @@
* @see fchdir()
*/
int chdir(const char *path) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
return sys_chdir(path);
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_chdir(path);
} else {
return sys_chdir_nt(path);
rc = sys_chdir_nt(path);
}
STRACE("chdir(%#s) → %d% m", path, rc);
return rc;
}

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
@ -61,6 +61,6 @@ int close(int fd) {
}
}
__releasefd(fd);
SYSDEBUG("close(%d) -> %d", fd, rc);
STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc;
}

View file

@ -19,7 +19,7 @@
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.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/log/libfatal.internal.h"
@ -159,6 +159,6 @@ noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
errno = f;
}
}
SYSDEBUG("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
return res;
}

View 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/intrin/kprintf.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[32];
if (IsShadowFrame(x)) {
ksnprintf(buf, sizeof(buf), " /*shadow:%.12p*/", UNSHADOW(ADDR(x)));
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

@ -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/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
static noasan char DescribeMapType(int flags) {
switch (flags & MAP_TYPE) {
case MAP_FILE:
return 'f';
case MAP_PRIVATE:
return 'p';
case MAP_SHARED:
return 's';
default:
return '?';
}
}
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' : '-';
p[3] = DescribeMapType(flags);
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';
p[6] = (flags & MAP_FIXED) ? 'F' : '-';
p[7] = 0;
return p;
}

View file

@ -0,0 +1,65 @@
/*-*- 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;
}

101
libc/calls/directmap-nt.c Normal file
View file

@ -0,0 +1,101 @@
/*-*- 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/strace.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);
STRACE(
"CreateFileMappingNuma(-1, kNtPageExecuteReadwrite, %'zu/%'zu) -> %p",
upsize, size, dm.maphandle);
if (dm.maphandle) {
dm.addr =
MapViewOfFileExNuma(dm.maphandle, kNtFileMapWrite | kNtFileMapExecute,
0, 0, upsize, addr, kNtNumaNoPreferredNode);
STRACE("MapViewOfFileExNuma(WX, %p) → addr:%p", 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);
STRACE("CreateFileMappingNuma(fhand:%ld, prot:%s, size:%'zu) → %p", 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);
STRACE("MapViewOfFileExNuma(prot:%s, off:%'ld, size:%'zu, addr:%p) → %p",
(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;
}

53
libc/calls/directmap.c Normal file
View file

@ -0,0 +1,53 @@
/*-*- 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/strace.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 d;
if (!IsWindows() && !IsMetal()) {
d.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
d.maphandle = kNtInvalidHandleValue;
} else if (IsMetal()) {
d = sys_mmap_metal(addr, size, prot, flags, fd, off);
} else {
d = sys_mmap_nt(addr, size, prot, flags,
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, off);
}
STRACE("sys_mmap(%.12p%s, %'zu, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size,
DescribeMapping(prot, flags, mode), fd, off, d.addr, d.maphandle);
return d;
}

View file

@ -18,7 +18,7 @@
*/
#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"
/**
@ -36,6 +36,6 @@ int dup(int fd) {
} else {
fd2 = sys_dup_nt(fd, -1, 0);
}
SYSDEBUG("dup(%d) -> %d", fd, fd2);
STRACE("%s(%d) → %d% m", "dup", fd, fd2);
return fd2;
}

View file

@ -18,7 +18,7 @@
*/
#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"
/**
@ -32,11 +32,14 @@
* @vforksafe
*/
int dup2(int oldfd, int newfd) {
SYSDEBUG("dup2(%d, %d)", oldfd, newfd);
if (oldfd == newfd) return newfd;
if (!IsWindows()) {
return sys_dup3(oldfd, newfd, 0);
int rc;
if (oldfd == newfd) {
rc = newfd;
} else if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, 0);
} else {
return sys_dup_nt(oldfd, newfd, 0);
rc = sys_dup_nt(oldfd, newfd, 0);
}
STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc);
return rc;
}

View file

@ -18,7 +18,7 @@
*/
#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/sysv/errfuns.h"
@ -36,10 +36,12 @@
* @see dup(), dup2()
*/
int dup3(int oldfd, int newfd, int flags) {
SYSDEBUG("dup3(%d, %d, %d)", oldfd, newfd, flags);
int rc;
if (!IsWindows()) {
return sys_dup3(oldfd, newfd, flags);
rc = sys_dup3(oldfd, newfd, flags);
} else {
return sys_dup_nt(oldfd, newfd, flags);
rc = sys_dup_nt(oldfd, newfd, flags);
}
STRACE("dup3(%d, %d, %d) → %d% m", oldfd, newfd, flags, rc);
return rc;
}

View file

@ -18,7 +18,7 @@
*/
#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/intrin/kprintf.h"
@ -39,35 +39,41 @@
* @asyncsignalsafe
* @vforksafe
*/
int execve(const char *program, char *const argv[], char *const envp[]) {
int execve(const char *prog, char *const argv[], char *const envp[]) {
int rc;
size_t i;
if (!program || !argv || !envp) return efault();
if (IsAsan() &&
(!__asan_is_valid(program, 1) || !__asan_is_valid_strlist(argv) ||
!__asan_is_valid_strlist(envp))) {
return efault();
}
if (DEBUGSYS) {
kprintf("SYS: execve(%s, {", program);
for (i = 0; argv[i]; ++i) {
if (i) kprintf(", ");
kprintf("%s", argv[i]);
}
kprintf("}, {");
for (i = 0; envp[i]; ++i) {
if (i) kprintf(", ");
kprintf("%s", envp[i]);
}
kprintf("})\n");
}
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
if (!IsWindows()) {
return sys_execve(program, argv, envp);
if (!prog || !argv || !envp ||
(IsAsan() &&
(!__asan_is_valid(prog, 1) || !__asan_is_valid_strlist(argv) ||
!__asan_is_valid_strlist(envp)))) {
rc = efault();
} else {
return sys_execve_nt(program, argv, envp);
#ifdef SYSDEBUG
if (__strace > 0) {
kprintf(STRACE_PROLOGUE "execve(%#s, {", prog);
for (i = 0; argv[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", argv[i]);
}
kprintf("}, {");
for (i = 0; envp[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", envp[i]);
}
kprintf("})%n");
}
#endif
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
if (!IsWindows()) {
rc = sys_execve(prog, argv, envp);
} else {
rc = sys_execve_nt(prog, argv, envp);
}
}
STRACE("execve(%#s) failed %d% m", prog, rc);
return rc;
}

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -42,14 +42,13 @@
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
rc = -1; /* TODO(jart): implement me */
if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
STRACE("zipos fchmodat not supported yet");
} else if (!IsWindows()) {
rc = sys_fchmodat(dirfd, path, mode, flags);
} else {
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
}
SYSDEBUG("fchmodat(%d, %s, %o, %d) -> %d %s", (long)dirfd, path, mode, flags,
rc != -1 ? "" : strerror(errno));
STRACE("fchmodat(%d, %#s, %#o, %d) → %d% m", dirfd, path, mode, flags, rc);
return rc;
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -39,9 +40,15 @@
*/
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
int flags) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
STRACE("zipos fchownat not supported yet");
} else {
rc = sys_fchownat(dirfd, path, uid, gid, flags);
}
return sys_fchownat(dirfd, path, uid, gid, flags);
STRACE("fchownat(%d, %#s, %d, %d, %#b) → %d% m", dirfd, path, uid, gid, flags,
rc);
return rc;
}

View file

@ -28,6 +28,12 @@
*
* CHECK_NE(-1, fcntl(fd, F_SETFD, FD_CLOEXEC));
*
* This function lets you duplicate file descriptors without running
* into an edge case where they take over stdio handles:
*
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3);
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3);
*
* This function implements POSIX Advisory Locks, e.g.
*
* CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
@ -28,9 +29,12 @@
* @asyncsignalsafe
*/
int fdatasync(int fd) {
int rc;
if (!IsWindows()) {
return sys_fdatasync(fd);
rc = sys_fdatasync(fd);
} else {
return sys_fdatasync_nt(fd);
rc = sys_fdatasync_nt(fd);
}
STRACE("%s(%d) → %d% m", "fdatasync", fd, rc);
return rc;
}

View file

@ -69,8 +69,7 @@ bool fileexists(const char *path) {
} else {
res = false;
}
SYSDEBUG("fileexists(%s) -> %s %s", path, res ? "true" : "false",
res ? "" : strerror(errno));
STRACE("fileexists(%#s) → %hhhd% m", path, res);
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
@ -30,9 +31,12 @@
* @return 0 on success, or -1 w/ errno
*/
int flock(int fd, int op) {
int rc;
if (!IsWindows()) {
return sys_flock(fd, op);
rc = sys_flock(fd, op);
} else {
return sys_flock_nt(fd, op);
rc = sys_flock_nt(fd, op);
}
STRACE("flock(%d, %d) → %d% m", fd, op, rc);
return rc;
}

View file

@ -18,8 +18,8 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/bsr.h"
@ -64,7 +64,7 @@ static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3;
}
} else {
SYSDEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
STRACE("%s failed %m", "GetSizeOfReparsePoint");
}
return z;
}
@ -122,7 +122,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
st->st_blocks = ROUNDUP(actualsize, PAGESIZE) / 512;
}
} else {
SYSDEBUG("GetFileInformationByHandle failed %d", GetLastError());
STRACE("%s failed %m", "GetFileInformationByHandle");
}
break;
default:
@ -130,7 +130,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
}
return 0;
} else {
SYSDEBUG("GetFileType failed %d", GetLastError());
STRACE("%s failed %m", "GetFileType");
return __winerr();
}
}

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -42,7 +41,6 @@ int32_t sys_fstat(int32_t fd, struct stat *st) {
__stat2cosmo(st, &ms);
return 0;
} else {
SYSDEBUG("sys_fstat(%d) failed w/ %m", fd);
return -1;
}
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -29,15 +30,19 @@
* @asyncsignalsafe
*/
int fstat(int fd, struct stat *st) {
int rc;
if (__isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)(
rc = weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
} else if (!IsWindows() && !IsMetal()) {
return sys_fstat(fd, st);
rc = sys_fstat(fd, st);
} else if (IsMetal()) {
return sys_fstat_metal(fd, st);
rc = sys_fstat_metal(fd, st);
} else if (!__isfdkind(fd, kFdFile)) {
rc = ebadf();
} else {
if (!__isfdkind(fd, kFdFile)) return ebadf();
return sys_fstat_nt(g_fds.p[fd].handle, st);
rc = sys_fstat_nt(g_fds.p[fd].handle, st);
}
STRACE("fstat(%d, [%s]) → %d% m", fd, __strace_stat(rc, st), rc);
return rc;
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -38,15 +39,28 @@
* @return 0 on success, or -1 w/ errno
* @see S_ISDIR(st.st_mode), S_ISREG()
* @asyncsignalsafe
* @vforksafe
*/
int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
/* execve() depends on this */
int rc;
struct ZiposUri zipname;
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
return weaken(__zipos_stat)(&zipname, st);
if (__isfdkind(dirfd, kFdZip)) {
STRACE("zipos dirfd not supported yet");
rc = einval();
} else if (weaken(__zipos_stat) &&
weaken(__zipos_parseuri)(path, &zipname) != -1) {
if (!__vforked) {
rc = weaken(__zipos_stat)(&zipname, st);
} else {
rc = enotsup();
}
} else if (!IsWindows()) {
return sys_fstatat(dirfd, path, st, flags);
rc = sys_fstatat(dirfd, path, st, flags);
} else {
return sys_fstatat_nt(dirfd, path, st, flags);
rc = sys_fstatat_nt(dirfd, path, st, flags);
}
STRACE("fstatat(%d, %#s, [%s], %#b) → %d% m", dirfd, path,
__strace_stat(rc, st), flags, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
@ -28,9 +29,12 @@
* @asyncsignalsafe
*/
int fsync(int fd) {
int rc;
if (!IsWindows()) {
return sys_fsync(fd);
rc = sys_fsync(fd);
} else {
return sys_fdatasync_nt(fd);
rc = sys_fdatasync_nt(fd);
}
STRACE("%s(%d) → %d% m", "fsync", fd, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
@ -32,11 +33,15 @@
* @asyncsignalsafe
*/
int ftruncate(int fd, int64_t length) {
if (fd < 0) return einval();
if (!IsWindows()) {
return sys_ftruncate(fd, length, length);
int rc;
if (fd < 0) {
rc = einval();
} else if (!IsWindows()) {
rc = sys_ftruncate(fd, length, length);
} else {
if (fd >= g_fds.n) return ebadf();
return sys_ftruncate_nt(g_fds.p[fd].handle, length);
if (fd >= g_fds.n) rc = ebadf();
rc = sys_ftruncate_nt(g_fds.p[fd].handle, length);
}
STRACE("ftruncate(%d, %'ld) → %d% m", fd, length, rc);
return rc;
}

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.internal.h"
.init.start 302,_init_g_fds
.init.start 305,_init_g_fds
push %rdi
push %rsi
call InitializeFileDescriptors
pop %rsi
pop %rdi
.init.end 302,_init_g_fds
.init.end 305,_init_g_fds

View file

@ -16,11 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#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/log/backtrace.internal.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
@ -43,19 +45,20 @@ char *getcwd(char *buf, size_t size) {
if (buf) {
p = buf;
if (!size) {
SYSDEBUG("getcwd(%p, %x) EINVAL", buf, size);
einval();
STRACE("getcwd(%p, %'zu) %m", buf, size);
return 0;
}
} else if (weaken(malloc)) {
assert(!__vforked);
if (!size) size = PATH_MAX + 1;
if (!(p = weaken(malloc)(size))) {
SYSDEBUG("getcwd(%p, %x) ENOMEM", buf, size);
STRACE("getcwd(%p, %'zu) %m", buf, size);
return 0;
}
} else {
SYSDEBUG("getcwd() EINVAL needs buf≠0 or STATIC_YOINK(\"malloc\")");
einval();
STRACE("getcwd() needs buf≠0 or STATIC_YOINK(\"malloc\")");
return 0;
}
*p = '\0';
@ -85,6 +88,6 @@ char *getcwd(char *buf, size_t size) {
}
}
}
SYSDEBUG("getcwd(%p, %x) -> %s", buf, size, r);
STRACE("getcwd(%p, %'zu) → %#s", buf, size, r);
return r;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -29,13 +30,22 @@
* @return 0 on success or -1 w/ errno
*/
int getitimer(int which, struct itimerval *curvalue) {
int rc;
if (IsAsan() && !__asan_is_valid(curvalue, sizeof(*curvalue))) {
return efault();
}
if (!IsWindows()) {
return sys_getitimer(which, curvalue);
rc = efault();
} else if (!IsWindows()) {
rc = sys_getitimer(which, curvalue);
} else if (!curvalue) {
rc = efault();
} else {
if (!curvalue) return efault();
return sys_setitimer_nt(which, 0, curvalue);
rc = sys_setitimer_nt(which, 0, curvalue);
}
if (curvalue) {
STRACE("getitimer(%d, [{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m", which,
curvalue->it_interval.tv_sec, curvalue->it_interval.tv_usec,
curvalue->it_value.tv_sec, curvalue->it_value.tv_usec, rc);
} else {
STRACE("getitimer(%d, 0) → %d% m", which, rc);
}
return rc;
}

View file

@ -18,15 +18,19 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Returns process group id.
*/
int getpgid(int pid) {
int rc;
if (!IsWindows()) {
return sys_getpgid(pid);
rc = sys_getpgid(pid);
} else {
return getpid();
rc = getpid();
}
STRACE("%s(%d) → %d% m", "getpgid", pid, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -31,7 +32,16 @@
* @see libc/sysv/consts.sh
*/
int getrlimit(int resource, struct rlimit *rlim) {
if (resource == 127) return einval();
if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
return sys_getrlimit(resource, rlim);
int rc;
char buf[64];
if (resource == 127) {
rc = einval();
} else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) {
rc = efault();
} else {
rc = sys_getrlimit(resource, rlim);
}
STRACE("getrlimit(%s, [%s]) → %d% m", __strace_rlimit_name(resource),
__strace_rlimit(buf, sizeof(buf), rc, rlim), rc);
return rc;
}

View file

@ -18,10 +18,14 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Creates session and sets the process group id.
*/
uint32_t getsid(int pid) {
return sys_getsid(pid);
int rc;
rc = sys_getsid(pid);
STRACE("%s(%d) → %d% m", "getsid", pid, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
@ -51,11 +52,14 @@ static textwindows dontinline uint32_t GetUserNameHash(void) {
* @vforksafe
*/
uint32_t getuid(void) {
int rc;
if (!IsWindows()) {
return sys_getuid();
rc = sys_getuid();
} else {
return GetUserNameHash();
rc = GetUserNameHash();
}
STRACE("%s() → %d% m", "getuid", rc);
return rc;
}
/**
@ -68,9 +72,12 @@ uint32_t getuid(void) {
* @vforksafe
*/
uint32_t getgid(void) {
int rc;
if (!IsWindows()) {
return sys_getgid();
rc = sys_getgid();
} else {
return GetUserNameHash();
rc = GetUserNameHash();
}
STRACE("%s() → %d% m", "getgid", rc);
return rc;
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.internal.h"
#include "libc/calls/ttydefaults.h"
@ -65,23 +66,27 @@ static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
* @see ioctl(fd, TIOCGETA, tio) dispatches here
*/
int ioctl_tcgets(int fd, ...) {
int rc;
va_list va;
struct termios *tio;
va_start(va, fd);
tio = va_arg(va, struct termios *);
va_end(va);
if (fd >= 0) {
if (!tio) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
if (!tio) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = enotty();
} else if (IsMetal()) {
return ioctl_tcgets_metal(fd, tio);
rc = ioctl_tcgets_metal(fd, tio);
} else if (!IsWindows()) {
return ioctl_tcgets_sysv(fd, tio);
rc = ioctl_tcgets_sysv(fd, tio);
} else {
return ioctl_tcgets_nt(fd, tio);
rc = ioctl_tcgets_nt(fd, tio);
}
} else {
return einval();
rc = einval();
}
STRACE("ioctl_tcgets(%d, %p) → %d% m", fd, tio, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.internal.h"
#include "libc/dce.h"
@ -86,5 +87,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
if (rc != -1) {
__nomultics = !(tio->c_oflag & OPOST);
}
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
return rc;
}

View file

@ -19,9 +19,9 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -68,8 +68,7 @@ bool isdirectory(const char *path) {
} else {
res = isdirectory_nt(path);
}
SYSDEBUG("isdirectory(%s) -> %s %s", path, res ? "true" : "false",
res ? "" : strerror(errno));
STRACE("isdirectory(%#s) → %hhhd% m", path, res);
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/s.h"
/**
@ -25,9 +26,11 @@
*
* @see access(exe, X_OK) which is more accurate on NT
* @asyncsignalsafe
* @vforksafe
*/
bool isexecutable(const char *path) {
/* execve() depends on this */
struct stat st;
if (stat(path, &st)) return 0;
return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
if (fstatat(AT_FDCWD, path, &st, 0)) return 0;
return !!(st.st_mode & 0111);
}

View file

@ -40,7 +40,7 @@
* @see isdirectory(), ischardev(), issymlink()
*/
bool isregularfile(const char *path) {
int rc, e;
int e;
union metastat st;
struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -36,18 +37,20 @@
*/
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
int flags) {
int rc;
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
return efault();
}
if (weaken(__zipos_notat) &&
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) {
return sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
rc = efault();
} else if (weaken(__zipos_notat) &&
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
STRACE("zipos fchownat not supported yet");
} else if (!IsWindows()) {
rc = sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
} else {
return sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath);
}
STRACE("linkat(%d, %#s, %d, %#s, %#b) → %d% m", olddirfd, oldpath, newdirfd,
newpath, flags, rc);
return rc;
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/log/backtrace.internal.h"
#include "libc/zipos/zipos.internal.h"
@ -33,14 +34,17 @@
* @asyncsignalsafe
*/
int64_t lseek(int fd, int64_t offset, unsigned whence) {
int64_t rc;
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_lseek)(
rc = weaken(__zipos_lseek)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, offset, whence);
} else if (!IsWindows() && !IsOpenbsd() && !IsNetbsd()) {
return sys_lseek(fd, offset, whence, 0);
rc = sys_lseek(fd, offset, whence, 0);
} else if (IsOpenbsd() || IsNetbsd()) {
return sys_lseek(fd, offset, offset, whence);
rc = sys_lseek(fd, offset, offset, whence);
} else {
return sys_lseek_nt(fd, offset, whence);
rc = sys_lseek_nt(fd, offset, whence);
}
STRACE("lseek(%d, %'ld, %d) → %'ld% m", fd, offset, whence, rc);
return rc;
}

View file

@ -50,8 +50,7 @@ forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) {
textwindows int sys_madvise_nt(void *addr, size_t length, int advice) {
uint32_t rangecount;
struct NtMemoryRangeEntry ranges[1];
if ((advice & (int)MADV_WILLNEED) == (int)MADV_WILLNEED ||
(advice & (int)MADV_SEQUENTIAL) == (int)MADV_SEQUENTIAL) {
if (advice == MADV_WILLNEED || advice == MADV_SEQUENTIAL) {
typeof(PrefetchVirtualMemory) *fn = GetPrefetchVirtualMemory();
if (fn) {
ranges[0].VirtualAddress = addr;
@ -65,7 +64,7 @@ textwindows int sys_madvise_nt(void *addr, size_t length, int advice) {
} else {
return enosys();
}
} else if ((advice & (int)MADV_FREE) == (int)MADV_FREE) {
} else if (advice == MADV_FREE) {
typeof(OfferVirtualMemory) *fn = GetOfferVirtualMemory();
if (fn) {
if (fn(addr, length, kNtVmOfferPriorityNormal)) {

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -31,10 +32,18 @@
* @see fadvise()
*/
int madvise(void *addr, size_t length, int advice) {
if (IsAsan() && !__asan_is_valid(addr, length)) return efault();
if (!IsWindows()) {
return sys_madvise(addr, length, advice);
int rc;
if (advice != 127 /* see consts.sh */) {
if (IsAsan() && !__asan_is_valid(addr, length)) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_madvise(addr, length, advice);
} else {
rc = sys_madvise_nt(addr, length, advice);
}
} else {
return sys_madvise_nt(addr, length, advice);
rc = einval();
}
STRACE("madvise(%p, %'zu, %d) → %d% m", addr, length, advice, rc);
return rc;
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h"
@ -38,13 +39,16 @@
* @see makedirs()
*/
int mkdirat(int dirfd, const char *path, unsigned mode) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) {
return sys_mkdirat(dirfd, path, mode);
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
rc = efault();
} else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
STRACE("zipos mkdirat not supported yet");
} else if (!IsWindows()) {
rc = sys_mkdirat(dirfd, path, mode);
} else {
return sys_mkdirat_nt(dirfd, path, mode);
rc = sys_mkdirat_nt(dirfd, path, mode);
}
STRACE("mkdirat(%d, %#s, %#o) → %d% m", dirfd, path, mode, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/s.h"
@ -38,14 +39,17 @@
* @asyncsignalsafe
*/
int mknod(const char *path, uint32_t mode, uint64_t dev) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (mode & S_IFREG) return creat(path, mode & ~S_IFREG);
if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR);
if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO);
if (!IsWindows()) {
/* TODO(jart): Whys there code out there w/ S_xxx passed via dev? */
return sys_mknod(path, mode, dev);
rc = sys_mknod(path, mode, dev);
} else {
return enosys();
rc = enosys();
}
STRACE("mknod(%#s, %#o, %#lx) → %d% m", path, mode, dev, rc);
return rc;
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
@ -76,8 +76,8 @@ textwindows int __mkntpath2(const char *path,
* 4. Reserve 10 for CreateNamedPipe "\\.\pipe\" prefix requirement
* 5. Reserve 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
*/
char *q;
char16_t *p;
const char *q;
size_t i, n, m, z;
if (!path) return efault();
path = FixNtMagicPath(path, flags);
@ -96,7 +96,7 @@ textwindows int __mkntpath2(const char *path,
}
n = tprecode8to16(p, z, q).ax;
if (n == z - 1) {
SYSDEBUG("path too long for windows: %s", path);
STRACE("path too long for windows: %#s", path);
return enametoolong();
}
for (i = 0; i < n; ++i) {

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
@ -35,7 +35,7 @@ int __mkntpathat(int dirfd, const char *path, int flags,
kNtFileNameNormalized | kNtVolumeNameDos);
if (!dirlen) return __winerr();
if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) {
SYSDEBUG("path too long: %.*hs\\%.*hs", dirlen, dir, filelen, file);
STRACE("path too long: %#.*hs\\%#.*hs", dirlen, dir, filelen, file);
return enametoolong();
}
dir[dirlen] = u'\\';

160
libc/calls/mman.greg.c Normal file
View file

@ -0,0 +1,160 @@
/*-*- 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

@ -0,0 +1,65 @@
/*-*- 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/calls/strace.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/mremap.h"
#include "libc/sysv/errfuns.h"
/**
* Relocates memory.
*
* This function lets you move to to different addresses witohut copying
* it. This system call is currently supported on Linux and NetBSD. Your
* C library runtime won't have any awareness of this memory, so certain
* features like ASAN memory safety and kprintf() won't work as well.
*/
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", "r9", "r11", "memory", "cc");
if (cf) errno = rax, rax = -1;
} else {
rax = einval();
}
} else {
rax = enosys();
}
STRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p% m", p, n, m, f, q, rax);
return (void *)rax;
}

33
libc/calls/munmap-metal.c Normal file
View file

@ -0,0 +1,33 @@
/*-*- 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;
}

34
libc/calls/munmap-sysv.c Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.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);
}
STRACE("sys_munmap(%p%s, %'zu) → %d", p, DescribeFrame((intptr_t)p >> 16), n,
rc);
return rc;
}

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityimpersonationlevel.h"
@ -87,24 +87,24 @@ TryAgain:
if (result || flags == F_OK) {
rc = 0;
} else {
SYSDEBUG("ntaccesscheck finale failed %d %d", result, flags);
STRACE("ntaccesscheck finale failed %d %d", result, flags);
rc = eacces();
}
} else {
rc = __winerr();
SYSDEBUG("AccessCheck failed: %m");
STRACE("%s failed: %m", "AccessCheck");
}
} else {
rc = __winerr();
SYSDEBUG("DuplicateToken failed: %m");
STRACE("%s failed: %m", "DuplicateToken");
}
} else {
rc = __winerr();
SYSDEBUG("OpenProcessToken failed: %m");
STRACE("%s failed: %m", "OpenProcessToken");
}
} else {
e = GetLastError();
SYSDEBUG("GetFileSecurity failed: %d %d", e, secsize);
STRACE("GetFileSecurity failed: %d %u", e, secsize);
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
s = freeme;

View file

@ -19,7 +19,7 @@
#include "libc/bits/pushpop.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/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
@ -95,7 +95,7 @@ textwindows int ntspawn(
} else {
__winerr();
}
SYSDEBUG("CreateProcess(`%hs`, `%hs`) -> %d", prog16, block->cmdline, rc);
STRACE("CreateProcess(%#hs, %#hs) → %d% m", prog16, block->cmdline, rc);
}
} else {
__winerr();

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/log.h"
@ -73,8 +73,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
} else {
rc = efault();
}
SYSDEBUG("openat(%d, %s, %d, %d) -> %d %s", (long)dirfd, file, flags,
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, (long)rc,
rc == -1 ? strerror(errno) : "");
STRACE("openat(%d, %#s, %#x, %#o) → %d% m", dirfd, file, flags,
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/errno.h"
#include "libc/sysv/consts/sig.h"
@ -36,6 +37,7 @@ int pause(void) {
int rc, olderr;
sigset_t oldmask;
olderr = errno;
STRACE("pause()");
if ((rc = sys_pause()) == -1 && errno == ENOSYS) {
errno = olderr;
if (sigprocmask(SIG_BLOCK, NULL, &oldmask) == -1) return -1;

View file

@ -20,7 +20,7 @@
#include "libc/bits/bits.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/log/libfatal.internal.h"
@ -125,7 +125,7 @@ textstartup void program_executable_name_init(int argc, char **argv,
GetProgramExecutableName(executable, argv[0], auxv);
errno = e;
__stpcpy(program_executable_name, executable);
SYSDEBUG("program_executable_name → %#s", program_executable_name);
STRACE("program_executable_name → %#s", program_executable_name);
}
const void *const program_executable_name_init_ctor[] initarray = {

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/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nt/createfile.h"
@ -39,7 +39,7 @@
static textwindows ssize_t sys_readlinkat_nt_error(void) {
uint32_t e;
e = GetLastError();
SYSDEBUG("sys_readlinkat_nt() error %d", e);
STRACE("sys_readlinkat_nt() error %d", e);
switch (e) {
case kNtErrorNotAReparsePoint:
return einval();
@ -56,11 +56,11 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
uint64_t w;
wint_t x, y;
void *freeme;
uint32_t e, i, j, n, mem;
uint32_t i, j, n, mem;
char16_t path16[PATH_MAX], *p;
struct NtReparseDataBuffer *rdb;
if (__mkntpathat(dirfd, path, 0, path16) == -1) {
SYSDEBUG("sys_readlinkat_nt() failed b/c __mkntpathat() failed");
STRACE("sys_readlinkat_nt() failed b/c __mkntpathat() failed");
return -1;
}
if (weaken(malloc)) {
@ -72,7 +72,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
rdb = (struct NtReparseDataBuffer *)buf;
freeme = 0;
} else {
SYSDEBUG("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked");
STRACE("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked");
return enomem();
}
if ((h = CreateFile(path16, 0, 0, 0, kNtOpenExisting,
@ -113,20 +113,20 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
if (freeme || (intptr_t)(buf + j) <= (intptr_t)(p + i)) {
rc = j;
} else {
SYSDEBUG("sys_readlinkat_nt() too many astral codepoints");
STRACE("sys_readlinkat_nt() too many astral codepoints");
rc = enametoolong();
}
} else {
SYSDEBUG("sys_readlinkat_nt() should have kNtIoReparseTagSymlink");
STRACE("sys_readlinkat_nt() should have kNtIoReparseTagSymlink");
rc = einval();
}
} else {
SYSDEBUG("DeviceIoControl(kNtFsctlGetReparsePoint) failed");
STRACE("%s failed %m", "DeviceIoControl(kNtFsctlGetReparsePoint)");
rc = sys_readlinkat_nt_error();
}
CloseHandle(h);
} else {
SYSDEBUG("CreateFile(kNtFileFlagOpenReparsePoint) failed");
STRACE("%s failed %m", "CreateFile(kNtFileFlagOpenReparsePoint)");
rc = sys_readlinkat_nt_error();
}
if (freeme && weaken(free)) {

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
@ -50,18 +50,17 @@
*/
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
ssize_t bytes;
struct ZiposUri zipname;
if ((IsAsan() && !__asan_is_valid(buf, bufsiz)) || (bufsiz && !buf)) {
bytes = efault();
} else if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) {
SYSDEBUG("TOOD: zipos support for readlinkat");
bytes = enosys(); /* TODO(jart): code me */
} else if (weaken(__zipos_notat) &&
(bytes = __zipos_notat(dirfd, path)) == -1) {
STRACE("TOOD: zipos support for readlinkat");
} else if (!IsWindows()) {
bytes = sys_readlinkat(dirfd, path, buf, bufsiz);
} else {
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
}
SYSDEBUG("readlinkat(%d, %s, 0x%p, 0x%x) -> %d %s", (long)dirfd, path, buf,
bufsiz, bytes, bytes != -1 ? "" : strerror(errno));
STRACE("readlinkat(%d, %#s, [%#.*s]) → %d% m", dirfd, path, MAX(0, bytes),
buf, bytes);
return bytes;
}

View file

@ -22,7 +22,7 @@
void __releasefd(int fd) {
int x;
if (!__vforked && 0 <= fd && fd < g_fds.n) {
g_fds.p[fd].kind = kFdEmpty;
bzero(g_fds.p + fd, sizeof(*g_fds.p));
do {
x = g_fds.f;
if (fd >= x) break;

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h"
@ -36,18 +37,20 @@
*/
int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
int rc;
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
return efault();
}
if (weaken(__zipos_notat) &&
(weaken(__zipos_notat)(olddirfd, oldpath) == -1 ||
weaken(__zipos_notat)(newdirfd, newpath) == -1)) {
return -1; /* TODO(jart): implement me */
}
if (!IsWindows()) {
return sys_renameat(olddirfd, oldpath, newdirfd, newpath);
rc = efault();
} else if (weaken(__zipos_notat) &&
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
STRACE("zipos renameat not supported yet");
} else if (!IsWindows()) {
rc = sys_renameat(olddirfd, oldpath, newdirfd, newpath);
} else {
return sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath);
}
STRACE("renameat(%d, %#s, %d, %#s) → %d% m", olddirfd, oldpath, newdirfd,
newpath, rc);
return rc;
}

View file

@ -16,14 +16,15 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Asks kernel to deschedule thread momentarily.
*/
int sched_yield(void) {
/* TODO(jart): Add get_sched_yield() so we can STRACE() */
if (!IsWindows()) {
return sys_sched_yield();
} else {

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -32,7 +33,16 @@
* @vforksafe
*/
int setrlimit(int resource, const struct rlimit *rlim) {
if (resource == 127) return einval();
if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault();
return sys_setrlimit(resource, rlim);
int rc;
char buf[64];
if (resource == 127) {
rc = einval();
} else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) {
rc = efault();
} else {
rc = sys_setrlimit(resource, rlim);
}
STRACE("setrlimit(%s, %s) → %d% m", __strace_rlimit_name(resource),
__strace_rlimit(buf, sizeof(buf), 0, rlim), rc);
return rc;
}

View file

@ -21,6 +21,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigaction-freebsd.internal.h"
#include "libc/calls/struct/sigaction-linux.internal.h"
#include "libc/calls/struct/sigaction-netbsd.h"
@ -129,19 +130,8 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
}
}
/**
* Installs handler for kernel interrupt, e.g.:
*
* void GotCtrlC(int sig, siginfo_t *si, ucontext_t *ctx);
* struct sigaction sa = {.sa_sigaction = GotCtrlC,
* .sa_flags = SA_RESETHAND|SA_RESTART|SA_SIGINFO};
* CHECK_NE(-1, sigaction(SIGINT, &sa, NULL));
*
* @see xsigaction() for a much better api
* @asyncsignalsafe
* @vforksafe
*/
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
static int __sigaction(int sig, const struct sigaction *act,
struct sigaction *oldact) {
_Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
@ -233,3 +223,25 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
}
return rc;
}
/**
* Installs handler for kernel interrupt, e.g.:
*
* void GotCtrlC(int sig, siginfo_t *si, ucontext_t *ctx);
* struct sigaction sa = {.sa_sigaction = GotCtrlC,
* .sa_flags = SA_RESETHAND|SA_RESTART|SA_SIGINFO};
* CHECK_NE(-1, sigaction(SIGINT, &sa, NULL));
*
* @see xsigaction() for a much better api
* @asyncsignalsafe
* @vforksafe
*/
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
int rc;
char buf[2][128];
rc = __sigaction(sig, act, oldact);
STRACE("sigaction(%s, %s, [%s]) → %d% m", strsignal(sig),
__strace_sigaction(buf[0], sizeof(buf[0]), 0, act),
__strace_sigaction(buf[1], sizeof(buf[1]), rc, oldact), rc);
return rc;
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metasigaltstack.h"
#include "libc/calls/struct/sigaltstack.h"
#include "libc/dce.h"
@ -70,37 +71,41 @@ static noasan void sigaltstack2linux(struct sigaltstack *linux,
*/
noasan int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
int rc;
void *a, *b;
void *b;
const void *a;
struct sigaltstack_bsd bsd;
if (IsAsan() && ((old && __asan_check(old, sizeof(*old)).kind) ||
(neu && (__asan_check(neu, sizeof(*neu)).kind ||
__asan_check(neu->ss_sp, neu->ss_size).kind)))) {
return efault();
}
if (IsLinux()) {
a = neu;
b = old;
} else if (IsBsd()) {
if (neu) {
sigaltstack2bsd(&bsd, neu);
a = &bsd;
rc = efault();
} else if (IsLinux() || IsBsd()) {
if (IsLinux()) {
a = neu;
b = old;
} else {
a = 0;
if (neu) {
sigaltstack2bsd(&bsd, neu);
a = &bsd;
} else {
a = 0;
}
if (old) {
b = &bsd;
} else {
b = 0;
}
}
if (old) {
b = &bsd;
if ((rc = sys_sigaltstack(a, b)) != -1) {
if (IsBsd() && old) {
sigaltstack2linux(old, &bsd);
}
rc = 0;
} else {
b = 0;
rc = -1;
}
} else {
return enosys();
}
if ((rc = sys_sigaltstack(a, b)) != -1) {
if (IsBsd() && old) {
sigaltstack2linux(old, &bsd);
}
return 0;
} else {
return -1;
rc = enosys();
}
STRACE("sigaltstack() → %d% m", rc);
return rc;
}

View file

@ -18,12 +18,23 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
static const char *DescribeHow(char buf[12], int how) {
if (how == SIG_BLOCK) return "SIG_BLOCK";
if (how == SIG_UNBLOCK) return "SIG_UNBLOCK";
if (how == SIG_SETMASK) return "SIG_SETMASK";
FormatInt32(buf, how);
return buf;
}
/**
* Changes program signal blocking state, e.g.:
*
@ -40,25 +51,50 @@
* @vforksafe
*/
int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) {
int32_t x;
if (IsAsan() &&
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
(opt_out_oldset &&
!__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset))))) {
return efault();
}
if (!IsWindows() && !IsOpenbsd()) {
return sys_sigprocmask(how, opt_set, opt_out_oldset, 8);
} else if (IsOpenbsd()) {
if (!opt_set) how = 1;
if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set);
if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) {
if (opt_out_oldset) memcpy(opt_out_oldset, &x, sizeof(x));
return 0;
int x, rc;
char howbuf[12];
char buf[2][41];
sigset_t old, *oldp;
if (!(IsAsan() &&
((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) ||
(opt_out_oldset &&
!__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset)))))) {
if (!IsWindows() && !IsOpenbsd()) {
if (opt_out_oldset) {
bzero(&old, sizeof(old));
oldp = &old;
} else {
oldp = 0;
}
if (sys_sigprocmask(how, opt_set, oldp, 8) != -1) {
if (opt_out_oldset) {
memcpy(opt_out_oldset, &old, sizeof(old));
}
rc = 0;
} else {
rc = -1;
}
} else if (IsOpenbsd()) {
if (!opt_set) how = 1;
if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set);
if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) {
if (opt_out_oldset) {
bzero(opt_out_oldset, sizeof(*opt_out_oldset));
memcpy(opt_out_oldset, &x, sizeof(x));
}
rc = 0;
} else {
rc = -1;
}
} else {
return -1;
if (opt_out_oldset) bzero(opt_out_oldset, sizeof(*opt_out_oldset));
rc = 0; /* TODO(jart): Implement me! */
}
} else {
return 0; /* TODO(jart): Implement me! */
rc = efault();
}
STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how),
__strace_sigset(buf[0], sizeof(buf[0]), 0, opt_set),
__strace_sigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
@ -31,12 +32,18 @@
* @asyncsignalsafe
*/
int sigsuspend(const sigset_t *ignore) {
unsigned x;
if (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore))) return efault();
if (!IsWindows()) {
int rc;
char buf[41];
if (!ignore || (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore)))) {
rc = efault();
} else if (!IsWindows()) {
STRACE("sigsuspend(%s)", __strace_sigset(buf, sizeof(buf), 0, ignore));
if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore);
return sys_sigsuspend(ignore, 8);
} else {
return enosys(); /* TODO(jart): Implement me! */
rc = enosys(); /* TODO(jart): Implement me! */
}
STRACE("sigsuspend(%s) → %d% m", __strace_sigset(buf, sizeof(buf), 0, ignore),
rc);
return rc;
}

View file

@ -18,8 +18,8 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/errno.h"
#include "libc/nt/struct/consolescreenbufferinfoex.h"
#include "libc/str/str.h"
@ -38,8 +38,8 @@ textwindows bool _check_sigwinch(struct Fd *fd) {
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
__ws = ws;
if (old.ws_col | old.ws_row) {
SYSDEBUG("SIGWINCH %hhu×%hhu → %hhu×%hhu", old.ws_col, old.ws_row,
ws.ws_col, ws.ws_row);
STRACE("SIGWINCH %hhu×%hhu → %hhu×%hhu", old.ws_col, old.ws_row,
ws.ws_col, ws.ws_row);
if (__sighandrvas[SIGWINCH] >= kSigactionMinRva) {
bzero(&si, sizeof(si));
((sigaction_f)(_base + __sighandrvas[SIGWINCH]))(SIGWINCH, &si, 0);

View file

@ -0,0 +1,34 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_
#include "libc/calls/struct/rlimit.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#ifdef SYSDEBUG
#define STRACE(FMT, ...) \
do { \
if (__strace > 0) { \
__stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \
} \
} while (0)
#else
#define STRACE(FMT, ...) (void)0
#endif
extern int __strace;
void __stracef(const char *, ...);
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 *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ */

View file

@ -0,0 +1,40 @@
/*-*- 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 == RLIMIT_AS) return "RLIMIT_AS";
if (resource == RLIMIT_CPU) return "RLIMIT_CPU";
if (resource == RLIMIT_FSIZE) return "RLIMIT_FSIZE";
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, "{%'lu, %'lu}", rlim->rlim_cur, rlim->rlim_max);
return buf;
}

View file

@ -0,0 +1,31 @@
/*-*- 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"
privileged const char *__strace_sigaction(char *buf, size_t bufsize, int rc,
const struct sigaction *sa) {
char maskbuf[41];
if (rc == -1) return "n/a";
if (!sa) return "NULL";
ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}",
sa->sa_handler, sa->sa_flags,
__strace_sigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask));
return buf;
}

View file

@ -0,0 +1,28 @@
/*-*- 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"
privileged const char *__strace_sigset(char buf[41], size_t bufsize, int rc,
const sigset_t *ss) {
if (rc == -1) return "n/a";
if (!ss) return "NULL";
ksnprintf(buf, bufsize, "{%#lx, %#lx}", ss->__bits[0], ss->__bits[1]);
return buf;
}

View file

@ -0,0 +1,29 @@
/*-*- 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"
privileged const char *__strace_stat(int rc, const struct stat *st) {
static char buf[256];
if (rc == -1) return "n/a";
if (!st) return "NULL";
ksnprintf(buf, sizeof(buf), "{.st_size=%'ld, .st_mode=%#o, .st_ino=%'lu}",
st->st_size, st->st_mode, st->st_ino);
return buf;
}

View file

@ -1,15 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#include "libc/log/libfatal.internal.h"
#ifndef DEBUGSYS
#define DEBUGSYS 0
#endif
#if DEBUGSYS
#define SYSDEBUG(FMT, ...) kprintf("SYS: " FMT "\n", ##__VA_ARGS__)
#else
#define SYSDEBUG(FMT, ...) (void)0
#endif
#endif /* COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ */

View file

@ -19,8 +19,8 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
@ -71,12 +71,12 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
i = WaitForMultipleObjects(count, handles, false, -1);
}
if (i == kNtWaitFailed) {
SYSDEBUG("WaitForMultipleObjects failed %d", GetLastError());
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
return __winerr();
}
assert(__isfdkind(pids[i], kFdProcess));
if (!GetExitCodeProcess(handles[i], &dwExitCode)) {
SYSDEBUG("GetExitCodeProcess failed %d", GetLastError());
STRACE("%s failed %u", "GetExitCodeProcess", GetLastError());
return __winerr();
}
if (dwExitCode == kNtStillActive) continue;
@ -92,7 +92,7 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
opt_out_rusage->ru_stime =
WindowsDurationToTimeVal(ReadFileTime(kernelfiletime));
} else {
SYSDEBUG("GetProcessTimes failed %d", GetLastError());
STRACE("%s failed %u", "GetProcessTimes", GetLastError());
}
}
CloseHandle(g_fds.p[pids[i]].handle);

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/wait4.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
@ -38,21 +38,20 @@
*/
int wait4(int pid, int *opt_out_wstatus, int options,
struct rusage *opt_out_rusage) {
int rc, ws;
int rc, ws = 0;
if (IsAsan() &&
((opt_out_wstatus &&
!__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) ||
(opt_out_rusage &&
!__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))))) {
return efault();
}
ws = 0;
if (!IsWindows()) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_wait4(pid, &ws, options, opt_out_rusage);
} else {
rc = sys_wait4_nt(pid, &ws, options, opt_out_rusage);
}
SYSDEBUG("waitpid(%d, [0x%x], %d) -> [%d]", pid, ws, options, rc);
if (opt_out_wstatus) *opt_out_wstatus = ws;
if (rc != -1 && opt_out_wstatus) *opt_out_wstatus = ws;
STRACE("wait4(%d, [%#x], %d, %p) → %d% m", pid, ws, options, opt_out_rusage,
rc);
return rc;
}

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/nt/enum/exceptionhandleractions.h"
@ -31,7 +31,7 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
ucontext_t ctx;
struct siginfo si;
} g;
SYSDEBUG("__wincrash");
STRACE("__wincrash");
switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint:
sig = SIGTRAP;