cosmopolitan/test/libc/calls/diagnose_syscall_test.c
Justine Tunney c776a32f75
Replace COSMO define with _COSMO_SOURCE
This change might cause ABI breakages for /opt/cosmos. It's needed to
help us better conform to header declaration practices.
2023-08-13 20:55:04 -07:00

143 lines
5.4 KiB
C

/*-*- 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 2022 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/ucontext.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/mem/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/nr.h"
#include "libc/testlib/testlib.h"
#ifdef __x86_64__
#define Z 0x5555555555555555
#define FLAGS_cf 0
#define FLAGS_pf 2
#define FLAGS_sf 7
#define FLAGS_of 11
intptr_t diagnose_syscall(intptr_t nr, //
intptr_t arg1, //
intptr_t arg2, //
intptr_t arg3, //
intptr_t arg4, //
intptr_t arg5, //
intptr_t arg6, //
intptr_t arg7, //
ucontext_t *before, //
ucontext_t *after); //
#define GREG(FIELD) \
do { \
uint64_t f1 = x->uc_mcontext.FIELD; \
uint64_t f2 = y->uc_mcontext.FIELD; \
if (f1 != f2) { \
if (b) appendw(&b, ' '); \
appends(&b, #FIELD); \
kprintf("%3s %016lx → %016lx\n", #FIELD, f1, f2); \
} \
} while (0)
#define FLAG(FLAG) \
if ((x->uc_mcontext.eflags & (1ul << FLAGS_##FLAG)) ^ \
(y->uc_mcontext.eflags & (1ul << FLAGS_##FLAG))) { \
if (b) appendw(&b, ' '); \
appends(&b, #FLAG); \
}
char *DiffContexts(ucontext_t *x, ucontext_t *y) {
char *b = 0;
GREG(rax);
GREG(rdx);
GREG(rdi);
GREG(rsi);
GREG(rcx);
GREG(r8);
GREG(r9);
GREG(r10);
GREG(r11);
GREG(r12);
GREG(r13);
GREG(r14);
GREG(r15);
GREG(rbx);
GREG(rbp);
FLAG(cf);
FLAG(sf);
FLAG(of);
FLAG(pf);
return b;
}
void SetUp(void) {
if (IsWindows()) {
exit(0);
}
}
TEST(diagnose_syscall, getpid) {
ucontext_t x, y;
diagnose_syscall(__NR_getpid, Z, Z, Z, Z, Z, Z, Z, &x, &y);
if (IsFreebsd()) {
ASSERT_STREQ("rax rcx r8 r9 r10 r11", _gc(DiffContexts(&x, &y)));
} else if (IsNetbsd() || IsXnu()) {
// netbsd puts parent pid in edx
// xnu seems to just clobber it!
ASSERT_STREQ("rax rdx rcx r11", _gc(DiffContexts(&x, &y)));
} else if (__iswsl1()) {
// XXX: WSL1 must be emulating SYSCALL instructions.
ASSERT_STREQ("rax rcx", _gc(DiffContexts(&x, &y)));
} else {
ASSERT_STREQ("rax rcx r11", _gc(DiffContexts(&x, &y)));
}
}
TEST(diagnose_syscall, testWriteSuccess) {
ucontext_t x, y;
diagnose_syscall(__NR_write, 2, Z, 0, Z, Z, Z, Z, &x, &y);
if (IsFreebsd()) {
ASSERT_STREQ("rax rcx r8 r9 r10 r11", _gc(DiffContexts(&x, &y)));
} else if (__iswsl1()) {
// XXX: WSL1 must be emulating SYSCALL instructions.
ASSERT_STREQ("rax rcx", _gc(DiffContexts(&x, &y)));
} else {
ASSERT_STREQ("rax rcx r11", _gc(DiffContexts(&x, &y)));
}
}
TEST(diagnose_syscall, testWriteFailed) {
ucontext_t x, y;
diagnose_syscall(__NR_write, -1, Z, Z, Z, Z, Z, Z, &x, &y);
if (IsFreebsd()) {
ASSERT_STREQ("rax rcx r8 r9 r10 r11 cf", _gc(DiffContexts(&x, &y)));
} else if (IsBsd()) {
ASSERT_STREQ("rax rcx r11 cf", _gc(DiffContexts(&x, &y)));
} else if (__iswsl1()) {
// XXX: WSL1 must be emulating SYSCALL instructions.
ASSERT_STREQ("rax rcx", _gc(DiffContexts(&x, &y)));
} else {
ASSERT_STREQ("rax rcx r11", _gc(DiffContexts(&x, &y)));
}
}
#endif /* __x86_64__ */