mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-30 01:02:29 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
52
libc/runtime/_exit.S
Normal file
52
libc/runtime/_exit.S
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/macros.h"
|
||||
.privileged
|
||||
.yoink __FILE__
|
||||
|
||||
/ Terminates process, ignoring destructors and atexit() handlers.
|
||||
/
|
||||
/ Normally exit() or quick_exit() is better. This won't even flush
|
||||
/ stdio streams. Sometimes that makes sense, like after fork().
|
||||
/
|
||||
/ @param edi is exit code ∈ [0,256)
|
||||
/ @note _exit() is same thing
|
||||
/ @asyncsignalsafe
|
||||
_Exit: orl $RUNSTATE_TERMINATE,g_runstate(%rip)
|
||||
#if SupportsWindows()
|
||||
testb IsWindows()
|
||||
jz 1f
|
||||
movzbl %dil,%ecx # %ERRORLEVEL% is limitless
|
||||
4: call *__imp_ExitProcess(%rip)
|
||||
jmp 4b
|
||||
0: int3 # @see setjmp() in WinMain()
|
||||
#endif
|
||||
1: mov __NR_exit(%rip),%eax
|
||||
syscall
|
||||
cli
|
||||
lidt 3f
|
||||
2: hlt
|
||||
jmp 2b
|
||||
3: .quad 0
|
||||
.endfn _Exit,globl,protected
|
||||
.hidden __NR_exit
|
||||
.hidden g_runstate
|
64
libc/runtime/abort.S
Normal file
64
libc/runtime/abort.S
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/macros.h"
|
||||
.real
|
||||
.yoink __FILE__
|
||||
|
||||
/ Terminates program abnormally.
|
||||
/
|
||||
/ This function first tries to trigger your SIGABRT handler. If
|
||||
/ there isn't one or execution resumes, then abort() terminates
|
||||
/ the program using an escalating variety methods of increasing
|
||||
/ brutality.
|
||||
/
|
||||
/ @forcealignargpointer
|
||||
/ @asyncsignalsafe
|
||||
/ @noreturn
|
||||
abort: push %rbp
|
||||
mov %rsp,%rbp
|
||||
and $-16,%rsp
|
||||
sub $16,%rsp
|
||||
orl $RUNSTATE_BROKEN,g_runstate(%rip)
|
||||
testb IsWindows()
|
||||
jnz 2f
|
||||
mov SIG_SETMASK,%edi
|
||||
mov %rsp,%rsi
|
||||
push $0xffffffffffffffdf # all bits blocked but SIGABRT
|
||||
push $0xffffffffffffffff # assumes von neum. arithmetic
|
||||
pop 8(%rsi)
|
||||
pop (%rsi)
|
||||
xor %edx,%edx # don't care about old sigmask
|
||||
pushpop 4*4,%r10 # sizeof(sigset_t) for systemd
|
||||
mov __NR_sigprocmask,%eax # sigprocmask$sysv is hookable
|
||||
syscall
|
||||
mov __NR_getpid,%eax
|
||||
syscall
|
||||
mov %eax,%edi
|
||||
mov SIGABRT,%esi
|
||||
mov __NR_kill,%eax
|
||||
syscall # avoid hook and less bt noise
|
||||
2: mov $134,%edi # exit(128+SIGABRT) [bash-ism]
|
||||
call _Exit
|
||||
.endfn abort,globl,protected
|
||||
.hidden g_runstate
|
184
libc/runtime/arch_prctl.c
Normal file
184
libc/runtime/arch_prctl.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/msr.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/interruptiblecall.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Memory segmentation system calls.
|
||||
*
|
||||
* This whole file basically does:
|
||||
*
|
||||
* mov foo,%fs
|
||||
* mov foo,%gs
|
||||
* mov %fs,foo
|
||||
* mov %gs,foo
|
||||
*
|
||||
* Which is nontrivial due to the limitless authoritarianism of
|
||||
* operating systems.
|
||||
*/
|
||||
|
||||
int arch_prctl$sysv(int, int64_t) hidden;
|
||||
|
||||
static inline int arch_prctl$fsgsbase(int code, int64_t addr) {
|
||||
switch (code) {
|
||||
case ARCH_SET_GS:
|
||||
asm volatile("wrgsbase\t%0" : /* no outputs */ : "r"(addr));
|
||||
return 0;
|
||||
case ARCH_SET_FS:
|
||||
asm volatile("wrfsbase\t%0" : /* no outputs */ : "r"(addr));
|
||||
return 0;
|
||||
case ARCH_GET_GS:
|
||||
asm volatile("rdgsbase\t%0" : "=r"(*(int64_t *)addr));
|
||||
return 0;
|
||||
case ARCH_GET_FS:
|
||||
asm volatile("rdfsbase\t%0" : "=r"(*(int64_t *)addr));
|
||||
return 0;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$msr(int code, int64_t addr) {
|
||||
switch (code) {
|
||||
case ARCH_SET_GS:
|
||||
wrmsr(MSR_IA32_GS_BASE, addr);
|
||||
return 0;
|
||||
case ARCH_SET_FS:
|
||||
wrmsr(MSR_IA32_FS_BASE, addr);
|
||||
return 0;
|
||||
case ARCH_GET_GS:
|
||||
*(int64_t *)addr = rdmsr(MSR_IA32_GS_BASE);
|
||||
return 0;
|
||||
case ARCH_GET_FS:
|
||||
*(int64_t *)addr = rdmsr(MSR_IA32_FS_BASE);
|
||||
return 0;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$freebsd(int code, int64_t addr) {
|
||||
switch (code) {
|
||||
case ARCH_GET_FS:
|
||||
return arch_prctl$sysv(128, addr);
|
||||
case ARCH_SET_FS:
|
||||
return arch_prctl$sysv(129, addr);
|
||||
case ARCH_GET_GS:
|
||||
return arch_prctl$sysv(130, addr);
|
||||
case ARCH_SET_GS:
|
||||
return arch_prctl$sysv(131, addr);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$xnu(int code, int64_t addr) {
|
||||
int ax;
|
||||
switch (code) {
|
||||
case ARCH_SET_GS:
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(0x3000003), "D"(addr - 0x8a0 /* wat */)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
return ax;
|
||||
case ARCH_GET_FS:
|
||||
case ARCH_SET_FS:
|
||||
case ARCH_GET_GS:
|
||||
return enosys();
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$openbsd(int code, int64_t addr) {
|
||||
int64_t rax;
|
||||
switch (code) {
|
||||
case ARCH_GET_FS:
|
||||
asm volatile("syscall"
|
||||
: "=a"(rax)
|
||||
: "0"(0x014a /* __get_tcb */)
|
||||
: "rcx", "r11", "cc", "memory");
|
||||
*(int64_t *)addr = rax;
|
||||
return 0;
|
||||
case ARCH_SET_FS:
|
||||
asm volatile("syscall"
|
||||
: "=a"(rax)
|
||||
: "0"(0x0149 /* __set_tcb */), "D"(addr)
|
||||
: "rcx", "r11", "cc", "memory");
|
||||
return 0;
|
||||
case ARCH_GET_GS:
|
||||
case ARCH_SET_GS:
|
||||
return enosys();
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static char g_fsgs_once;
|
||||
static struct InterruptibleCall g_fsgs_icall;
|
||||
|
||||
/**
|
||||
* Don't bother.
|
||||
*/
|
||||
int arch_prctl(int code, int64_t addr) {
|
||||
void *fn = arch_prctl$fsgsbase;
|
||||
if (!g_fsgs_once) {
|
||||
g_fsgs_once = true;
|
||||
if (X86_HAVE(FSGSBASE)) {
|
||||
g_fsgs_icall.sig = SIGILL;
|
||||
if (interruptiblecall(&g_fsgs_icall, fn, code, addr, 0, 0) != -1 &&
|
||||
g_fsgs_icall.returnval != -1) {
|
||||
/* ivybridge+ (2012) lets us change segment registers without
|
||||
needing a 700ns system call. cpuid and /proc/cpuinfo will both
|
||||
report it's available; unfortunately, operating systems have an
|
||||
added ability to restrict this feature in %cr4, which we're not
|
||||
even allowed to read lool */
|
||||
g_fsgs_once = 2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_fsgs_once == 2) {
|
||||
return arch_prctl$fsgsbase(code, addr);
|
||||
}
|
||||
switch (hostos) {
|
||||
case METAL:
|
||||
return arch_prctl$msr(code, addr);
|
||||
case FREEBSD:
|
||||
/* claims support but it appears not */
|
||||
return arch_prctl$freebsd(code, addr);
|
||||
case OPENBSD:
|
||||
return arch_prctl$openbsd(code, addr);
|
||||
case LINUX:
|
||||
return arch_prctl$sysv(code, addr);
|
||||
case XNU:
|
||||
/* probably won't work */
|
||||
return arch_prctl$xnu(code, addr);
|
||||
default:
|
||||
return enosys();
|
||||
}
|
||||
}
|
75
libc/runtime/asan.greg.c
Normal file
75
libc/runtime/asan.greg.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
privileged void __asan_init(void) {
|
||||
}
|
||||
|
||||
privileged void __asan_register_globals(uintptr_t a, uintptr_t b) {
|
||||
}
|
||||
|
||||
privileged void __asan_unregister_globals(uintptr_t a, uintptr_t b) {
|
||||
}
|
||||
|
||||
privileged void __asan_loadN(uintptr_t ptr, size_t size) {
|
||||
dprintf(STDERR_FILENO, "load %p %zu");
|
||||
}
|
||||
|
||||
privileged void __asan_storeN(uintptr_t ptr, size_t size) {
|
||||
dprintf(STDERR_FILENO, "store %p %zu");
|
||||
}
|
||||
|
||||
privileged void __asan_report_load_n(uintptr_t ptr, size_t size) {
|
||||
dprintf(STDERR_FILENO, "%s%zu%s%#p", "asan: load ", size, " bytes at ", ptr);
|
||||
}
|
||||
|
||||
privileged void __asan_report_store_n(uintptr_t ptr, size_t size) {
|
||||
dprintf(STDERR_FILENO, "%s%zu%s%#p", "asan: store ", size, " bytes at ", ptr);
|
||||
}
|
||||
|
||||
privileged uintptr_t __asan_stack_malloc(size_t size, int classid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
privileged void __asan_stack_free(uintptr_t ptr, size_t size, int classid) {
|
||||
}
|
||||
|
||||
privileged void __asan_handle_no_return(void) {
|
||||
}
|
||||
|
||||
privileged void __asan_version_mismatch_check_v8(void) {
|
||||
}
|
||||
|
||||
privileged void __asan_alloca_poison(uintptr_t addr, uintptr_t size) {
|
||||
}
|
||||
|
||||
privileged void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
|
||||
}
|
||||
|
||||
privileged void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr,
|
||||
void **beg, void **end) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
privileged void *__asan_get_current_fake_stack(void) {
|
||||
return NULL;
|
||||
}
|
55
libc/runtime/assertfail.c
Normal file
55
libc/runtime/assertfail.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
/**
|
||||
* Handles failure of assert() macro.
|
||||
*/
|
||||
relegated void __assert_fail(const char *expr, const char *file, int line) {
|
||||
static bool once;
|
||||
char *msg, *p, linebuf[16];
|
||||
unsigned i, exprlen, filelen;
|
||||
if (!once) {
|
||||
once = true;
|
||||
exprlen = expr ? strlen(expr) : 0;
|
||||
filelen = file ? strlen(file) : 0;
|
||||
p = msg = alloca(MIN(512, exprlen + filelen + 64));
|
||||
p = mempcpy(p, file, filelen);
|
||||
p = stpcpy(p, ":");
|
||||
if (line < 1) line = 1;
|
||||
for (i = 0; line; line /= 10) linebuf[i++] = '0' + line % 10;
|
||||
while (i) *p++ = linebuf[--i];
|
||||
p = stpcpy(p, ":");
|
||||
p = mempcpy(p, expr, exprlen);
|
||||
p = stpcpy(p, "\r\n");
|
||||
write(STDERR_FILENO, msg, p - msg);
|
||||
if (weaken(die)) weaken(die)();
|
||||
}
|
||||
abort();
|
||||
unreachable;
|
||||
}
|
90
libc/runtime/balloc.c
Normal file
90
libc/runtime/balloc.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/buffer.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define kGuard PAGESIZE
|
||||
#define kGrain FRAMESIZE
|
||||
|
||||
/**
|
||||
* Allocates page-guarded buffer.
|
||||
*
|
||||
* ┌─────────────────────────────────────┬s─i─g─s─e─g─v┐
|
||||
* │ 𝑣₀..𝑣ₙ₋₁ │𝑣ₙ..𝑣ₙ₊₄₀₉₆₋₁│
|
||||
* └─────────────────────────────────────┴s─i─g─s─e─g─v┘
|
||||
*
|
||||
* @param b is metadata object owned by caller, initialized to zero for
|
||||
* first call; subsequent calls will resize
|
||||
* @param a is alignment requirement in bytes, e.g. 1,2,4,8,16,...
|
||||
* @param n is buffer size in bytes
|
||||
* @return b->p
|
||||
* @see ralloc()
|
||||
*/
|
||||
void *balloc(struct GuardedBuffer *b, unsigned a, size_t n) {
|
||||
int rc;
|
||||
char *p;
|
||||
size_t mi, need;
|
||||
struct AddrSize az;
|
||||
struct MemoryCoord mc;
|
||||
|
||||
assert(a >= 1);
|
||||
assert(a <= kGuard);
|
||||
assert(kGuard < kGrain);
|
||||
assert(popcount(a) == 1);
|
||||
assert(popcount(kGuard) == 1);
|
||||
assert(popcount(kGrain) == 1);
|
||||
assert(n < 0x800000000000ul - kGrain - kGuard);
|
||||
|
||||
if (n) {
|
||||
az.addr = 0;
|
||||
az.size = 0;
|
||||
n = roundup(n, a);
|
||||
need = roundup(n + kGuard, kGrain);
|
||||
if (b->p) {
|
||||
mc = ADDRSIZE_TO_COORD(b->p, 1);
|
||||
mi = findmapping(mc.y);
|
||||
if (mi && ISOVERLAPPING(mc, _mm.p[mi - 1])) {
|
||||
az = COORD_TO_ADDRSIZE(_mm.p[mi - 1]);
|
||||
if (az.size < need) {
|
||||
rc = munmap(az.addr, az.size);
|
||||
assert(rc != -1);
|
||||
az.addr = NULL;
|
||||
az.size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!az.size) {
|
||||
if ((p = mapanon(need)) == MAP_FAILED) abort();
|
||||
if (mprotect(p + need - kGuard, kGuard, PROT_NONE) == -1) abort();
|
||||
} else {
|
||||
p = az.addr;
|
||||
}
|
||||
b->p = p + need - kGuard - n;
|
||||
}
|
||||
|
||||
return b->p;
|
||||
}
|
40
libc/runtime/bfree.c
Normal file
40
libc/runtime/bfree.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/buffer.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
|
||||
void bfree(struct GuardedBuffer *b) {
|
||||
int mr;
|
||||
size_t mi;
|
||||
struct AddrSize az;
|
||||
struct MemoryCoord mc;
|
||||
if (b->p) {
|
||||
mc = ADDRSIZE_TO_COORD(b->p, 1);
|
||||
mi = findmapping(mc.y);
|
||||
assert(mi > 0);
|
||||
assert(ISOVERLAPPING(mc, _mm.p[mi - 1]));
|
||||
az = COORD_TO_ADDRSIZE(_mm.p[mi - 1]);
|
||||
mr = munmap(az.addr, az.size);
|
||||
assert(mr != -1);
|
||||
b->p = NULL;
|
||||
}
|
||||
}
|
15
libc/runtime/buffer.h
Normal file
15
libc/runtime/buffer.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_BUFFER_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_BUFFER_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct GuardedBuffer {
|
||||
void *p;
|
||||
};
|
||||
|
||||
void *balloc(struct GuardedBuffer *, unsigned, size_t);
|
||||
void bfree(struct GuardedBuffer *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_BUFFER_H_ */
|
28
libc/runtime/clearenv.c
Normal file
28
libc/runtime/clearenv.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Removes all environment variables.
|
||||
*/
|
||||
int clearenv(void) {
|
||||
environ = NULL;
|
||||
return 0;
|
||||
}
|
36
libc/runtime/close_s.c
Normal file
36
libc/runtime/close_s.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Closes file descriptor.
|
||||
*
|
||||
* The caller's variable is made -1. Note that close(-1) is a no-op.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int close_s(int *fdp) {
|
||||
int fd = -1;
|
||||
return close(lockxchg(fdp, &fd));
|
||||
}
|
37
libc/runtime/closesymboltable.c
Normal file
37
libc/runtime/closesymboltable.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/ezmap.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Frees symbol table.
|
||||
* @return 0 on success or -1 on system error
|
||||
*/
|
||||
int closesymboltable(struct SymbolTable **table) {
|
||||
int rc = 0;
|
||||
if (*table && (intptr_t)*table != (intptr_t)-1) {
|
||||
struct SymbolTable *t = *table;
|
||||
*table = NULL;
|
||||
if (unmapfile(&t->mf) == -1) rc = -1;
|
||||
if (munmap(t, t->scratch) == -1) rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
181
libc/runtime/cxaatexit.S
Normal file
181
libc/runtime/cxaatexit.S
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/macros.h"
|
||||
.section .text.exit,"ax",@progbits
|
||||
.yoink __FILE__
|
||||
|
||||
/ Delegates to __cxa_atexit().
|
||||
/
|
||||
/ @param rdi callback typed void(*)(void) (nullable)
|
||||
/ @return 0 on success or nonzero if out of space
|
||||
atexit: xor %esi,%esi
|
||||
xor %edx,%edx
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
|
||||
/ Registers destructor to be called upon exit().
|
||||
/
|
||||
/ Destructors are called in reverse order. They won't be called
|
||||
/ if the program aborts or _exit() is called. Invocations of this
|
||||
/ function are usually generated by the C++ compiler.
|
||||
/
|
||||
/ @param rdi callback typed void(*)(T) (nullable)
|
||||
/ @param rsi callback arg typed T (nullable)
|
||||
/ @param rdx dso handle (nullable)
|
||||
/ @return 0 on success or nonzero if out of space
|
||||
/ @note folks have forked libc in past just to unbloat atexit()
|
||||
/ @see news.ycombinator.com/item?id=20228082
|
||||
/ @preinitsafe
|
||||
__cxa_atexit:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
push %r15
|
||||
ezlea g_cxa,cx
|
||||
mov %rcx,%r15
|
||||
mov (%r15),%rax # get state->block
|
||||
mov 8(%r15),%rcx # get state->offset
|
||||
test %rcx,%rcx
|
||||
jz 2f
|
||||
0: sub $24,%rcx
|
||||
mov %rdx,(%rax,%rcx) # set cb->dso
|
||||
mov %rsi,8(%rax,%rcx) # set cb->arg
|
||||
mov %rdi,16(%rax,%rcx) # set cb->fn
|
||||
mov %rcx,8(%r15) # set state->offset
|
||||
xor %eax,%eax # success
|
||||
1: pop %r15
|
||||
pop %rbp
|
||||
ret
|
||||
2: .weak calloc
|
||||
ezlea calloc,cx
|
||||
test %rcx,%rcx
|
||||
jz 1b # fail (no malloc)
|
||||
push %rax
|
||||
push %rdi
|
||||
push %rsi
|
||||
pushpop ATEXIT_MAX+1,%rdi
|
||||
pushpop 16,%rsi
|
||||
call *%rcx
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %rcx # rax=new rcx=old
|
||||
test %rax,%rax
|
||||
jz 1b # fail (no memory)
|
||||
mov $ATEXIT_MAX*8*3,%r8
|
||||
mov %rax,(%r15) # set state->block
|
||||
mov %rcx,(%rax,%r8) # set block->next
|
||||
mov %r8,%rcx
|
||||
jmp 0b
|
||||
.endfn __cxa_atexit,globl
|
||||
.endfn atexit,globl
|
||||
|
||||
/ Triggers destructors.
|
||||
/
|
||||
/ This implementation supports DSO handles, but is optimized for
|
||||
/ cases when it's called only once by exit().
|
||||
/
|
||||
/ @param rdi is dso predicate or null to destroy all
|
||||
/ @see libc/exit.c
|
||||
__cxa_finalize:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
push %r14
|
||||
push %r13
|
||||
push %r12
|
||||
mov g_cxa(%rip),%rsi
|
||||
mov %rdi,%r14
|
||||
0: mov %rsi,%r12 # loop through blocks
|
||||
pushpop ATEXIT_MAX,%rcx
|
||||
1: lodsq #→ dso # loop through callbacks
|
||||
xchg %rax,%rdx
|
||||
lodsq #→ arg
|
||||
xchg %rax,%rdi
|
||||
lodsq #→ fn
|
||||
test %rax,%rax
|
||||
jz 2f # ignore empty slots
|
||||
test %r14,%r14
|
||||
jmp 5f # null predicate match all
|
||||
cmp %r14,%rdx
|
||||
jne 2f # predicate mismatch
|
||||
5: push %rsi
|
||||
push %rcx
|
||||
push %rcx
|
||||
call *%rax
|
||||
pop %rcx
|
||||
pop %rcx
|
||||
pop %rsi
|
||||
xor %eax,%eax # clear slot (never reused)
|
||||
mov %rax,-8(%rsi)
|
||||
2: loop 1b
|
||||
lodsq # get next block ptr
|
||||
test %rax,%rax # don't free static block no. 1
|
||||
jz 3f # which always has next == NULL
|
||||
test %r14,%r14
|
||||
jz 1f # don't free anything if just one dso
|
||||
push %rax
|
||||
mov %r12,%rdi
|
||||
.weak free
|
||||
call free # can't panic due to earlier test
|
||||
1: pop %rsi
|
||||
jmp 0b
|
||||
3: pop %r12 # align stack for next call
|
||||
test %r14,%r14 # no static dtor for dso exit
|
||||
jnz 9f
|
||||
ezlea __fini_array_end,ax # static dtors in reverse order
|
||||
.weak __fini_array_end # could be called multiple times
|
||||
ezlea __fini_array_start,cx # idempotency recommended
|
||||
.weak __fini_array_start # or consider atexit()
|
||||
8: sub $8,%rax # @see ape/ape.lds
|
||||
cmp %rcx,%rax
|
||||
jl 9f
|
||||
push %rax
|
||||
push %rcx
|
||||
call *(%rax)
|
||||
pop %rcx
|
||||
pop %rax
|
||||
jmp 8b
|
||||
9: pop %r13
|
||||
pop %r14
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __cxa_finalize,globl,hidden
|
||||
|
||||
.bss
|
||||
.align 16 # static/dynamic hybrid linked list
|
||||
g_cxa: .quad 0 # last block ptr: (long (*)[32][3])
|
||||
.quad 0 # block byte offset moves backwards
|
||||
.endobj g_cxa
|
||||
g_cxa_static:
|
||||
.rept ATEXIT_MAX
|
||||
.quad 0 # dso
|
||||
.quad 0 # arg
|
||||
.quad 0 # fn (or NULL for empty)
|
||||
.endr
|
||||
.quad 0 # next (always NULL in static block)
|
||||
.endobj g_cxa_static
|
||||
.previous
|
||||
|
||||
.init.start 300,_init_g_cxa
|
||||
ezlea g_cxa,cx
|
||||
lea g_cxa_static-g_cxa(%rcx),%rax
|
||||
mov %rax,(%rcx)
|
||||
movl $ATEXIT_MAX*8*3,8(%rcx)
|
||||
.init.end 300,_init_g_cxa
|
63
libc/runtime/defer.greg.c
Normal file
63
libc/runtime/defer.greg.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/gc.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
|
||||
struct StackFrame *parent,
|
||||
void *ptr) {
|
||||
return !(((intptr_t)ptr > (intptr_t)frame) &&
|
||||
((intptr_t)ptr < (intptr_t)parent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds destructor to garbage shadow stack.
|
||||
*
|
||||
* @param frame is passed automatically by wrapper macro
|
||||
* @param fn takes one argument
|
||||
* @param arg is passed to fn(arg)
|
||||
* @return arg
|
||||
*/
|
||||
void __defer(struct StackFrame *frame, void *fn, void *arg) {
|
||||
struct StackFrame *frame2;
|
||||
/*
|
||||
* To avoid an API requiring dlmalloc dependency, say:
|
||||
* defer(free_s, &ptr_not_owned_by_current_frame)
|
||||
* Rather than:
|
||||
* defer(weak(free), ptr)
|
||||
*/
|
||||
if (!arg) return;
|
||||
frame2 = __builtin_frame_address(0);
|
||||
assert(frame2->next == frame);
|
||||
assert(PointerNotOwnedByParentStackFrame(frame2, frame, arg));
|
||||
if (append(&__garbage,
|
||||
(&(const struct Garbage){frame->next, (intptr_t)fn, (intptr_t)arg,
|
||||
frame->addr})) != -1) {
|
||||
atomic_store(&frame->addr, (intptr_t)&__gc);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
39
libc/runtime/describeos.c
Normal file
39
libc/runtime/describeos.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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);
|
||||
}
|
27
libc/runtime/dsohandle.S
Normal file
27
libc/runtime/dsohandle.S
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Uniquely identifies each artifact linked in an address space.
|
||||
__dso_handle:
|
||||
.quad __dso_handle
|
||||
.endobj __dso_handle,globl,hidden
|
71
libc/runtime/enableavx.greg.c
Normal file
71
libc/runtime/enableavx.greg.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/lib/pc.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
#define kNtContextXstate 0x00100040
|
||||
#define kNtXstateAvx 2
|
||||
#define kNtXstateMaskAvx (1ull << kNtXstateAvx)
|
||||
|
||||
static void EnableAvx(void) {
|
||||
asm volatile("mov\t%%cr4,%%rax\n\t"
|
||||
"or\t%0,%%rax\n\t"
|
||||
"mov\t%%rax,%%cr4\n\t"
|
||||
"xor\t%%ecx,%%ecx\n\t"
|
||||
"xgetbv\n\t"
|
||||
"or\t%1,%%eax\n\t"
|
||||
"xsetbv"
|
||||
: /* no outputs */
|
||||
: "i"(CR4_OSXSAVE), "i"(XCR0_X87 | XCR0_SSE | XCR0_AVX)
|
||||
: "rax", "rcx", "rdx", "memory", "cc");
|
||||
}
|
||||
|
||||
static void EnableAvxOnWindows(void) {
|
||||
/* typedef uint64_t (*getenabledxstatefeatures_f)(void) __msabi; */
|
||||
/* typedef bool32 (*initializecontext_f)(void *buffer, uint32_t flags, */
|
||||
/* struct NtContext **out_context, */
|
||||
/* uint32_t *inout_buffersize) __msabi;
|
||||
*/
|
||||
/* typedef bool32 (*getxstatefeaturesmask_f)(struct NtContext * context, */
|
||||
/* uint64_t * out_featuremask)
|
||||
* __msabi; */
|
||||
/* typedef bool32 (*setxstatefeaturesmask_f)(struct NtContext * context, */
|
||||
/* uint64_t featuremask) __msabi; */
|
||||
/* getenabledxstatefeatures_f GetEnabledXStateFeatures; */
|
||||
/* initializecontext_f InitializeContext; */
|
||||
/* getxstatefeaturesmask_f GetXStateFeaturesMask; */
|
||||
/* setxstatefeaturesmask_f SetXStateFeaturesMask; */
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests authorization from operating system to do 256-bit math.
|
||||
* @assume avx cpuid check performed by caller
|
||||
*/
|
||||
int _init_enableavx(void) {
|
||||
if (IsMetal()) {
|
||||
EnableAvx();
|
||||
} else if (IsWindows()) {
|
||||
EnableAvxOnWindows();
|
||||
}
|
||||
return 0;
|
||||
}
|
30
libc/runtime/exit.c
Normal file
30
libc/runtime/exit.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Exits program with grace.
|
||||
*/
|
||||
noreturn textexit void exit(int rc) {
|
||||
__cxa_finalize(NULL);
|
||||
_exit(rc);
|
||||
unreachable;
|
||||
}
|
58
libc/runtime/ezmap.c
Normal file
58
libc/runtime/ezmap.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/ezmap.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* Memory-maps file for reading.
|
||||
* An internal veneer for a common mmap() use-case.
|
||||
*/
|
||||
int mapfileread(const char *filename, struct MappedFile *mf) {
|
||||
mf->addr = MAP_FAILED;
|
||||
if ((mf->fd = open(filename, O_RDONLY)) != -1 &&
|
||||
(mf->size = getfiledescriptorsize(mf->fd)) < INT_MAX &&
|
||||
(mf->addr = mf->size
|
||||
? mmap(NULL, mf->size, PROT_READ, MAP_SHARED, mf->fd, 0)
|
||||
: NULL) != MAP_FAILED) {
|
||||
return 0;
|
||||
} else {
|
||||
unmapfile(mf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases resource returned by mapfileread().
|
||||
*/
|
||||
int unmapfile(struct MappedFile *mf) {
|
||||
int rc = 0;
|
||||
rc |= munmap(mf->addr, mf->size);
|
||||
rc |= close(mf->fd);
|
||||
mf->fd = -1;
|
||||
mf->addr = MAP_FAILED;
|
||||
mf->size = 0;
|
||||
return rc;
|
||||
}
|
36
libc/runtime/ezmap.h
Normal file
36
libc/runtime/ezmap.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_EZMAP_H_
|
||||
#define COSMOPOLITAN_LIBC_EZMAP_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct MappedFile {
|
||||
int64_t fd;
|
||||
void *addr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
int mapfileread(const char *filename, struct MappedFile *mf) hidden;
|
||||
int unmapfile(struct MappedFile *mf) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_EZMAP_H_ */
|
46
libc/runtime/fastmath.S
Normal file
46
libc/runtime/fastmath.S
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
.text.startup
|
||||
.yoink __FILE__
|
||||
|
||||
/ Intel Manual V.1 §10.2.3 - MXCSR Control and Status Register
|
||||
#define MXCSR_DE (1 << 1) /* Denormal Flag */
|
||||
#define MXCSR_DAZ (1 << 6) /* Denormals Are Zeros */
|
||||
#define MXCSR_DM (1 << 8) /* Denormal Operation Mask */
|
||||
#define MXCSR_FTZ (1 << 15) /* Flush to Zero */
|
||||
|
||||
/ Initializes fast math.
|
||||
/
|
||||
/ “Seymour Cray didn't care that 81.0/3.0 did not give exactly
|
||||
/ 27.0 on the CDC 6000 class machines, and he was universally
|
||||
/ respected for making the fastest machines around.
|
||||
/ ──Linus Torvalds
|
||||
__fast_math:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
push %rax
|
||||
stmxcsr (%rsp)
|
||||
orl $MXCSR_FTZ+MXCSR_DAZ,(%rsp)
|
||||
ldmxcsr (%rsp)
|
||||
leave
|
||||
ret
|
||||
.endfn __fast_math,globl
|
52
libc/runtime/findcombinary.c
Normal file
52
libc/runtime/findcombinary.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
struct FindComBinary {
|
||||
bool once;
|
||||
const char *res;
|
||||
char buf[PATH_MAX];
|
||||
};
|
||||
|
||||
static struct FindComBinary findcombinary_;
|
||||
|
||||
/**
|
||||
* Returns path of binary without debug information, or null.
|
||||
*
|
||||
* @return path to non-debug binary, or -1 w/ errno
|
||||
*/
|
||||
const char *findcombinary(void) {
|
||||
size_t len;
|
||||
const char *p;
|
||||
if (!findcombinary_.once) {
|
||||
findcombinary_.once = true;
|
||||
if ((p = (const char *)getauxval(AT_EXECFN)) &&
|
||||
(len = strlen(p)) < ARRAYLEN(findcombinary_.buf)) {
|
||||
findcombinary_.res = memcpy(findcombinary_.buf, p, len + 1);
|
||||
if (len > 4 && memcmp(&findcombinary_.buf[len - 4], ".dbg", 4) == 0) {
|
||||
findcombinary_.buf[len - 4] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
return findcombinary_.res;
|
||||
}
|
52
libc/runtime/finddebugbinary.c
Normal file
52
libc/runtime/finddebugbinary.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
/**
|
||||
* Returns path of binary with the debug information, or null.
|
||||
*
|
||||
* @return path to debug binary, or -1 w/ errno
|
||||
*/
|
||||
const char *finddebugbinary(void) {
|
||||
static char buf[PATH_MAX];
|
||||
if (buf[0]) return &buf[0];
|
||||
const char *const trybins[] = {program_invocation_name,
|
||||
(const char *)getauxval(AT_EXECFN)};
|
||||
for (unsigned i = 0; i < ARRAYLEN(trybins); ++i) {
|
||||
const char *res = trybins[i];
|
||||
unsigned len = strlen(res);
|
||||
if (4 < len && len < sizeof(buf) - 5) {
|
||||
if (strcmp(res + len - 4, ".dbg") == 0) return res;
|
||||
/* try suffixing extension, e.g. .com → .com.dbg */
|
||||
memcpy(mempcpy(buf, res, len), ".dbg", 5);
|
||||
if (fileexists(buf)) return &buf[0];
|
||||
buf[0] = '\0';
|
||||
}
|
||||
}
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
49
libc/runtime/findmapping.c
Normal file
49
libc/runtime/findmapping.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/mappings.h"
|
||||
|
||||
size_t findmapping_(int32_t k, const struct MemoryCoord *coords, size_t count) {
|
||||
size_t l, r, m;
|
||||
l = 0;
|
||||
r = count;
|
||||
while (l < r) {
|
||||
m = (l + r) >> 1;
|
||||
if (coords[m].x > k) {
|
||||
r = m;
|
||||
} else {
|
||||
l = m + 1;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns appropriate rightmost index.
|
||||
*/
|
||||
size_t findmapping(int32_t k) {
|
||||
return findmapping_(k, _mm.p, _mm.i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns appropriate rightmost index.
|
||||
*/
|
||||
size_t pickmapping(int32_t k) {
|
||||
return findmapping_(k, _mm.p, _mm.i);
|
||||
}
|
31
libc/runtime/fpreset.S
Normal file
31
libc/runtime/fpreset.S
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Re-initializes FPU.
|
||||
fpreset:
|
||||
_fpreset:
|
||||
.leafprologue
|
||||
.profilable
|
||||
finit
|
||||
.leafepilogue
|
||||
.endfn _fpreset,globl
|
||||
.endfn fpreset,globl
|
36
libc/runtime/free_s.c
Normal file
36
libc/runtime/free_s.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Frees memory, the Cosmopolitan way.
|
||||
*
|
||||
* The caller's pointer is zeroed. Stack and static memory is ignored.
|
||||
* This doesn't require a dependency on malloc().
|
||||
*/
|
||||
void free_s(void *v) {
|
||||
void **pp = (void **)v;
|
||||
void *p = NULL;
|
||||
lockxchg(pp, &p);
|
||||
if (isheap(p)) weakfree(p);
|
||||
}
|
213
libc/runtime/ftrace.greg.c
Normal file
213
libc/runtime/ftrace.greg.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/bisectcarleft.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Plain-text function call logging.
|
||||
*
|
||||
* Able to log ~2 million function calls per second, which is mostly
|
||||
* bottlenecked by system call overhead. Log size is reasonable if piped
|
||||
* into gzip.
|
||||
*/
|
||||
|
||||
static char g_buf[512];
|
||||
static const char *g_lastsymbol;
|
||||
static struct SymbolTable *g_symbols;
|
||||
|
||||
forceinline int getnestinglevel(struct StackFrame *frame) {
|
||||
int nesting = -2;
|
||||
while (frame) {
|
||||
++nesting;
|
||||
frame = frame->next;
|
||||
}
|
||||
return max(0, nesting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints name of function being called.
|
||||
*
|
||||
* We insert CALL instructions that point to this function, in the
|
||||
* prologues of other functions. We assume those functions behave
|
||||
* according to the System Five NexGen32e ABI.
|
||||
*/
|
||||
privileged interruptfn void ftrace_hook(void) {
|
||||
size_t i, j, nesting;
|
||||
const char *symbol;
|
||||
struct StackFrame *frame;
|
||||
LOAD_DEFAULT_RBX();
|
||||
if (g_symbols && !(g_runstate & RUNSTATE_BROKEN)) {
|
||||
frame = __builtin_frame_address(0);
|
||||
symbol =
|
||||
&g_symbols->name_base[g_symbols
|
||||
->symbols[bisectcarleft(
|
||||
(const int32_t(*)[2])g_symbols->symbols,
|
||||
g_symbols->count,
|
||||
frame->addr - g_symbols->addr_base)]
|
||||
.name_rva];
|
||||
if (symbol != g_lastsymbol &&
|
||||
(nesting = getnestinglevel(frame)) * 2 < ARRAYLEN(g_buf) - 3) {
|
||||
i = 2;
|
||||
j = 0;
|
||||
while (nesting--) {
|
||||
g_buf[i++] = ' ';
|
||||
g_buf[i++] = ' ';
|
||||
}
|
||||
while (i < ARRAYLEN(g_buf) - 2 && symbol[j]) {
|
||||
g_buf[i++] = symbol[j++];
|
||||
}
|
||||
g_buf[i++] = '\n';
|
||||
__print(g_buf, i);
|
||||
}
|
||||
g_lastsymbol = symbol;
|
||||
}
|
||||
RESTORE_RBX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites code in memory to log function calls.
|
||||
*
|
||||
* We do this by searching each function for the nop instruction
|
||||
* inserted by GCC when we use the -pg -mnop-mcount flags. There's no
|
||||
* risk of corrupting data since the linker scripts won't mix code and
|
||||
* data.
|
||||
*
|
||||
* Modules built with -O3 and without the profiling flags might have
|
||||
* these same nop instructions, but that shouldn't be problematic since
|
||||
* they're only there for the puposes of aligning jumps, and therefore
|
||||
* aren't actually executed. However codebases that use huge function
|
||||
* alignments with wide-nop slides could pose minor issues. Further note
|
||||
* that Cosmopolitan sources are almost never intentionally written to
|
||||
* use code alignment, since we've only seen a few cases where it helps.
|
||||
*
|
||||
* @see ape/ape.lds
|
||||
*/
|
||||
privileged void ftrace_install(void) {
|
||||
/* TODO(jart): Is -fschedule-insns2 so aggro that we need XED here? */
|
||||
size_t i;
|
||||
intptr_t addr;
|
||||
sigset_t oldmask;
|
||||
uint64_t code, mcode;
|
||||
unsigned char *p, *pe;
|
||||
const intptr_t kMcount = (intptr_t)&mcount;
|
||||
const intptr_t kFtraceHook = (intptr_t)&ftrace_hook;
|
||||
const intptr_t kProgramCodeStart = (intptr_t)&_ereal;
|
||||
const intptr_t kPrivilegedStart = (intptr_t)&__privileged_start;
|
||||
const bool kIsBinaryAligned = !(kPrivilegedStart & (PAGESIZE - 1));
|
||||
g_buf[0] = '+';
|
||||
g_buf[1] = ' ';
|
||||
sigprocmask(SIG_BLOCK, &kSigsetFull, &oldmask);
|
||||
if (__mprotect((void *)g_symbols->addr_base,
|
||||
kPrivilegedStart - g_symbols->addr_base,
|
||||
kIsBinaryAligned ? PROT_READ | PROT_WRITE
|
||||
: PROT_READ | PROT_WRITE | PROT_EXEC) != -1) {
|
||||
for (i = 0; i < g_symbols->count - 1; ++i) {
|
||||
if (g_symbols->addr_base + g_symbols->symbols[i].addr_rva <
|
||||
kProgramCodeStart) {
|
||||
continue; /* skip over real mode symbols */
|
||||
}
|
||||
if (g_symbols->addr_base + g_symbols->symbols[i].addr_rva >=
|
||||
kPrivilegedStart) {
|
||||
break; /* stop before privileged symbols */
|
||||
}
|
||||
for (p = (unsigned char *)(g_symbols->addr_base +
|
||||
g_symbols->symbols[i].addr_rva),
|
||||
pe = (unsigned char *)(g_symbols->addr_base +
|
||||
g_symbols->symbols[i + 1].addr_rva);
|
||||
p < pe - 8; ++p) {
|
||||
code = read64le(p);
|
||||
|
||||
/*
|
||||
* Test for -mrecord-mcount (w/ -fpie or -fpic)
|
||||
*
|
||||
* nopw 0x00(%rax,%rax,1) ← morphed by package.com
|
||||
* call *mcount(%rip) ← linked w/o -static
|
||||
* addr32 call mcount ← relaxed w/ -static
|
||||
* addr32 call mcount ← relaxed w/ -static
|
||||
*
|
||||
* Note that gcc refuses to insert the six byte nop.
|
||||
*/
|
||||
if ((code & 0x0000FFFFFFFFFFFF) == 0x0000441F0F66 ||
|
||||
(code & 0x0000FFFFFFFFFFFF) ==
|
||||
((((kMcount - ((intptr_t)&p[2] + 4)) << 16) | 0xE867) &
|
||||
0x0000FFFFFFFFFFFF) ||
|
||||
(code & 0x0000FFFFFFFFFFFF) ==
|
||||
((((kMcount - ((intptr_t)&p[2] + 4)) << 16) | 0xFF15) &
|
||||
0x0000FFFFFFFFFFFF)) {
|
||||
p[0] = 0x67;
|
||||
p[1] = 0xE8;
|
||||
addr = kFtraceHook - ((intptr_t)&p[2] + 4);
|
||||
p[2] = addr >> 000;
|
||||
p[3] = addr >> 010;
|
||||
p[4] = addr >> 020;
|
||||
p[5] = addr >> 030;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for -mnop-mcount (w/ -fno-pie)
|
||||
*/
|
||||
mcode = code & 0x000000FFFFFFFFFF;
|
||||
if ((mcode == 0x00441F0F /* nopl 0x00(%eax,%eax,1) [canonical] */) ||
|
||||
(mcode == 0x00041F0F67 /* nopl (%eax,%eax,1) [older gcc] */)) {
|
||||
if (p[-1] != 0x66 /* nopw 0x0(%rax,%rax,1) [donotwant] */) {
|
||||
p[0] = 0xE8 /* call Jvds */;
|
||||
addr = kFtraceHook - ((intptr_t)&p[1] + 4);
|
||||
p[1] = addr >> 000;
|
||||
p[2] = addr >> 010;
|
||||
p[3] = addr >> 020;
|
||||
p[4] = addr >> 030;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
__mprotect((void *)g_symbols->addr_base,
|
||||
kPrivilegedStart - g_symbols->addr_base, PROT_READ | PROT_EXEC);
|
||||
}
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs plaintext function tracer. Do not call.
|
||||
* @see libc/runtime/_init.S for documentation
|
||||
*/
|
||||
textstartup void ftrace_init(void) {
|
||||
if ((g_symbols = opensymboltable(finddebugbinary()))) {
|
||||
ftrace_install();
|
||||
}
|
||||
}
|
31
libc/runtime/g_argc.S
Normal file
31
libc/runtime/g_argc.S
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.initbss 300,_init_g_argc
|
||||
g_argc: .quad 0
|
||||
.endobj g_argc,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 300,_init_g_argc
|
||||
mov %r12,%rax
|
||||
stosq
|
||||
.init.end 300,_init_g_argc
|
48
libc/runtime/gc.h
Normal file
48
libc/runtime/gc.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Return-Oriented Garbage Collector.
|
||||
*
|
||||
* This is the same thing as {@code std::unique_ptr<>} in C++ or the
|
||||
* {@code defer} keyword in Go. We harness the power of ROP for good
|
||||
* using very few lines of code.
|
||||
*/
|
||||
|
||||
struct StackFrame;
|
||||
|
||||
/**
|
||||
* Releases resource when function returns.
|
||||
*
|
||||
* @warning do not return a gc()'d pointer
|
||||
* @warning do not realloc() with gc()'d pointer
|
||||
*/
|
||||
#define gc(THING) defer(weakfree, (THING))
|
||||
|
||||
/**
|
||||
* Same as longjmp() but runs gc() / defer() destructors.
|
||||
*/
|
||||
void gclongjmp(jmp_buf, int) nothrow noreturn paramsnonnull();
|
||||
|
||||
/**
|
||||
* Calls FN(ARG) when function returns.
|
||||
*/
|
||||
#define defer(FN, ARG) \
|
||||
({ \
|
||||
autotype(ARG) Arg = (ARG); \
|
||||
/* prevent weird opts like tail call */ \
|
||||
asm volatile("" : "+g"(Arg) : : "memory"); \
|
||||
__defer(__builtin_frame_address(0), FN, Arg); \
|
||||
asm volatile("" : "+g"(Arg) : : "memory"); \
|
||||
Arg; \
|
||||
})
|
||||
|
||||
void __defer(struct StackFrame *, void *, void *) hidden paramsnonnull((1, 2));
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_GC_H_ */
|
115
libc/runtime/getdosargv.c
Normal file
115
libc/runtime/getdosargv.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/str/appendchar.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/* TODO(jart): Make early-stage data structures happen. */
|
||||
#undef isspace
|
||||
#undef iswspace
|
||||
#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
|
||||
#define iswspace(c) isspace(c)
|
||||
|
||||
struct DosArgv {
|
||||
const char16_t *s;
|
||||
char *p;
|
||||
char *pe;
|
||||
wint_t wc;
|
||||
};
|
||||
|
||||
static textwindows void decodedosargv(struct DosArgv *st) {
|
||||
st->s += getutf16(st->s, &st->wc);
|
||||
}
|
||||
|
||||
static textwindows void appenddosargv(struct DosArgv *st, wint_t wc) {
|
||||
if (st->p < st->pe) {
|
||||
st->p += tpencode(st->p, st->pe - st->p, wc, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes and transcodes Windows NT CLI args, thus avoiding
|
||||
* CommandLineToArgv() schlepping in forty megs of dependencies.
|
||||
*
|
||||
* @param s is the command line string provided by the executive
|
||||
* @param buf is where we'll store double-NUL-terminated decoded args
|
||||
* @param size is how many bytes are available in buf
|
||||
* @param argv is where we'll store the decoded arg pointer array, which
|
||||
* is guaranteed to be NULL-terminated if max>0
|
||||
* @param max specifies the item capacity of argv, or 0 to do scanning
|
||||
* @return number of args written, excluding the NULL-terminator; or,
|
||||
* if the output buffer wasn't passed, or was too short, then the
|
||||
* number of args that *would* have been written is returned; and
|
||||
* there are currently no failure conditions that would have this
|
||||
* return -1 since it doesn't do system calls
|
||||
* @see test/libc/dosarg_test.c
|
||||
* @see libc/runtime/ntspawn.c
|
||||
* @note kudos to Simon Tatham for figuring out quoting behavior
|
||||
*/
|
||||
textwindows int getdosargv(const char16_t *cmdline, char *buf, size_t size,
|
||||
char **argv, size_t max) {
|
||||
bool inquote;
|
||||
size_t i, argc, slashes, quotes;
|
||||
struct DosArgv st;
|
||||
st.s = cmdline;
|
||||
st.p = buf;
|
||||
st.pe = buf + size;
|
||||
argc = 0;
|
||||
decodedosargv(&st);
|
||||
while (st.wc) {
|
||||
while (st.wc && iswspace(st.wc)) decodedosargv(&st);
|
||||
if (!st.wc) break;
|
||||
if (++argc < max) {
|
||||
argv[argc - 1] = st.p < st.pe ? st.p : NULL;
|
||||
}
|
||||
inquote = false;
|
||||
while (st.wc) {
|
||||
if (!inquote && isspace(st.wc)) break;
|
||||
if (st.wc == '"' || st.wc == '\\') {
|
||||
slashes = 0;
|
||||
quotes = 0;
|
||||
while (st.wc == '\\') decodedosargv(&st), slashes++;
|
||||
while (st.wc == '"') decodedosargv(&st), quotes++;
|
||||
if (!quotes) {
|
||||
while (slashes--) appenddosargv(&st, '\\');
|
||||
} else {
|
||||
while (slashes >= 2) appenddosargv(&st, '\\'), slashes -= 2;
|
||||
if (slashes) appenddosargv(&st, '"'), quotes--;
|
||||
if (quotes > 0) {
|
||||
if (!inquote) quotes--;
|
||||
for (i = 3; i <= quotes + 1; i += 3) appenddosargv(&st, '"');
|
||||
inquote = (quotes % 3 == 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appenddosargv(&st, st.wc);
|
||||
decodedosargv(&st);
|
||||
}
|
||||
}
|
||||
appenddosargv(&st, '\0');
|
||||
}
|
||||
appenddosargv(&st, '\0');
|
||||
if (size) buf[min(st.p - buf, size - 1)] = '\0';
|
||||
if (max) argv[min(argc, max - 1)] = NULL;
|
||||
return argc;
|
||||
}
|
67
libc/runtime/getdosenviron.h
Normal file
67
libc/runtime/getdosenviron.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_DOSENVIRON_H_
|
||||
#define COSMOPOLITAN_LIBC_DOSENVIRON_H_
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/str/appendchar.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Transcodes NT environment variable block from UTF-16 to UTF-8.
|
||||
*
|
||||
* @param env is a double NUL-terminated block of key=values
|
||||
* @param buf is the new environment
|
||||
* @param size is the byte capacity of buf
|
||||
* @param envp stores NULL-terminated string pointer list
|
||||
* @param max is the pointer count capacity of envp
|
||||
* @return number of variables decoded, excluding NULL-terminator
|
||||
*/
|
||||
static inline int getdosenviron(const char16_t *env, char *buf, size_t size,
|
||||
char **envp, size_t max) {
|
||||
const char16_t *s = env;
|
||||
size_t envc = 0;
|
||||
if (size) {
|
||||
wint_t wc;
|
||||
char *p = buf;
|
||||
char *pe = buf + size - 1;
|
||||
if (p < pe) {
|
||||
s += getutf16(s, &wc);
|
||||
while (wc) {
|
||||
if (++envc < max) {
|
||||
envp[envc - 1] = p < pe ? p : NULL;
|
||||
}
|
||||
bool endstring;
|
||||
do {
|
||||
AppendChar(&p, pe, wc);
|
||||
endstring = !wc;
|
||||
s += getutf16(s, &wc);
|
||||
} while (!endstring);
|
||||
buf[min(p - buf, size - 2)] = u'\0';
|
||||
}
|
||||
}
|
||||
AppendChar(&p, pe, '\0');
|
||||
buf[min(p - buf, size - 1)] = u'\0';
|
||||
}
|
||||
if (max) envp[min(envc, max - 1)] = NULL;
|
||||
return envc;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_DOSENVIRON_H_ */
|
29
libc/runtime/getpagesize.S
Normal file
29
libc/runtime/getpagesize.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Returns granularity of memory manager.
|
||||
getpagesize:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov $FRAMESIZE,%eax
|
||||
.leafepilogue
|
||||
.endfn getpagesize,globl
|
54
libc/runtime/gothere.greg.c
Normal file
54
libc/runtime/gothere.greg.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
|
||||
/**
|
||||
* Debugs super low-level stuff, e.g.
|
||||
*
|
||||
* void GOT_HERE(int);
|
||||
* INITIALIZER(100, _init_got_here_100, GOT_HERE(100));
|
||||
* INITIALIZER(200, _init_got_here_200, GOT_HERE(200));
|
||||
* INITIALIZER(300, _init_got_here_300, GOT_HERE(300));
|
||||
* INITIALIZER(400, _init_got_here_400, GOT_HERE(400));
|
||||
* INITIALIZER(500, _init_got_here_500, GOT_HERE(500));
|
||||
* INITIALIZER(600, _init_got_here_600, GOT_HERE(600));
|
||||
* INITIALIZER(700, _init_got_here_700, GOT_HERE(700));
|
||||
* INITIALIZER(800, _init_got_here_800, GOT_HERE(800));
|
||||
*
|
||||
*/
|
||||
privileged interruptfn void GOT_HERE(long num) {
|
||||
size_t len;
|
||||
char msg[48];
|
||||
len = 0;
|
||||
msg[len++] = 'g';
|
||||
msg[len++] = 'o';
|
||||
msg[len++] = 't';
|
||||
msg[len++] = ' ';
|
||||
msg[len++] = 'h';
|
||||
msg[len++] = 'e';
|
||||
msg[len++] = 'r';
|
||||
msg[len++] = 'e';
|
||||
msg[len++] = ' ';
|
||||
len += int64toarray_radix10(num, &msg[len]);
|
||||
msg[len++] = '\n';
|
||||
msg[len] = '\0';
|
||||
__print(msg, len);
|
||||
}
|
88
libc/runtime/grow.c
Normal file
88
libc/runtime/grow.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/conv/sizemultiply.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define GUARANTEE_TERMINATOR 1
|
||||
#define INITIAL_CAPACITY (32 - GUARANTEE_TERMINATOR)
|
||||
|
||||
/**
|
||||
* Grows array, The Cosmopolitan Way.
|
||||
*
|
||||
* This function may be called once an array has run out of space. If p
|
||||
* is NULL, a new array is allocated; otherwise, the array's made 1.5x
|
||||
* bigger. It has been written that this amortizes list appends down to
|
||||
* constant-time. Extended memory is zeroed. Growth is monotonic.
|
||||
*
|
||||
* If p points to to static memory or something on the stack, it'll be
|
||||
* converted to dynamic memory automatically. This can make algorithms
|
||||
* faster when the average case is a small amount of data. It also means
|
||||
* functions using this (and free_s()) won't have a hard-requirement on
|
||||
* malloc().
|
||||
*
|
||||
* Consider trying the higher-level append() and concat() APIs (defined
|
||||
* in libc/alg/arraylist.h) as an alternative to directly using grow().
|
||||
*
|
||||
* @param pp points to pointer holding memory address
|
||||
* @param capacity tracks maximum items that can be stored in p
|
||||
* can only be 0 if p is NULL (see reallocarray() for non-monotonic)
|
||||
* @param itemsize is the sizeof each item
|
||||
* @return true on success, or false w/ errno and *p is NOT free()'d
|
||||
* @error ENOMEM if realloc() not linked or mmap() failed
|
||||
* @note tiny programs might need to explicitly YOINK(realloc)
|
||||
* @see test/libc/runtime/grow_test.c
|
||||
*/
|
||||
bool grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
|
||||
void **p, *p1, *p2;
|
||||
size_t n1, n2; /* item counts */
|
||||
size_t t1, t2; /* byte counts */
|
||||
extra += GUARANTEE_TERMINATOR; /* p ⊃ p[𝑖]==0 */
|
||||
p = (void **)pp;
|
||||
assert(itemsize);
|
||||
assert((*p && *capacity) || (!*p && !*capacity));
|
||||
assert(!isheap(*p) || ((intptr_t)*p & 15) == 0);
|
||||
p1 = isheap(*p) ? *p : NULL;
|
||||
p2 = NULL;
|
||||
n1 = *capacity;
|
||||
n2 = (*p ? n1 + (n1 >> 1) : max(4, INITIAL_CAPACITY / itemsize)) + extra;
|
||||
if (sizemultiply(&t1, n1, itemsize) && sizemultiply(&t2, n2, itemsize)) {
|
||||
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
|
||||
if (!p1 && *p) memcpy(p2, *p, t1);
|
||||
memset((char *)p2 + t1, 0, t2 - t1);
|
||||
*capacity = n2;
|
||||
*p = p2;
|
||||
return true;
|
||||
} else {
|
||||
enomem();
|
||||
}
|
||||
} else {
|
||||
eoverflow();
|
||||
}
|
||||
return false;
|
||||
}
|
66
libc/runtime/heapsortcar.c
Normal file
66
libc/runtime/heapsortcar.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static unsigned heapsortmax(int32_t (*A)[2], unsigned n, unsigned i, unsigned j,
|
||||
unsigned k) {
|
||||
unsigned m = i;
|
||||
if (j < n && A[j][0] > A[m][0]) m = j;
|
||||
if (k < n && A[k][0] > A[m][0]) m = k;
|
||||
return m;
|
||||
}
|
||||
|
||||
static void heapsortdown(int32_t (*A)[2], unsigned n, unsigned i) {
|
||||
unsigned j;
|
||||
int32_t t[2];
|
||||
for (;;) {
|
||||
unsigned j = heapsortmax(A, n, i, 2 * i + 1, 2 * i + 2);
|
||||
if (j == i) break;
|
||||
memcpy(t, A[i], sizeof(t));
|
||||
memcpy(A[i], A[j], sizeof(t));
|
||||
memcpy(A[j], t, sizeof(t));
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts key-values.
|
||||
*
|
||||
* heapsortcar is a linearithmic / constant-memory / non-stable sorting
|
||||
* function that's a tenth the size of the more generalized qsort() API.
|
||||
* It can only sort arrays of 64-bit values, and comparisons happen by
|
||||
* treating the lower 32-bits as a signed integer.
|
||||
*
|
||||
* @see test/libc/alg/heapsortcar_test.c
|
||||
*/
|
||||
void heapsortcar(int32_t (*A)[2], unsigned n) {
|
||||
unsigned i;
|
||||
int32_t t[2];
|
||||
for (i = ((n - 2) / 2) + 1; i > 0; i--) {
|
||||
heapsortdown(A, n, i - 1);
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
memcpy(t, A[n - i - 1], sizeof(t));
|
||||
memcpy(A[n - i - 1], A[0], sizeof(t));
|
||||
memcpy(A[0], t, sizeof(t));
|
||||
heapsortdown(A, n - i - 1, 0);
|
||||
}
|
||||
}
|
145
libc/runtime/init.S
Normal file
145
libc/runtime/init.S
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/dce.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Decentralized function for process initialization.
|
||||
/
|
||||
/ Modules may inject cheap data structure initialization code into
|
||||
/ this function using the .init.start and .init.end macros. That
|
||||
/ code can use the LODS and STOS instructions to initialize memory
|
||||
/ that's restricted to read-only after initialization by PIRO.
|
||||
/
|
||||
/ This is fast, since the linker is able to roll-up initialization
|
||||
/ for large codebases comprised of many modules, into a perfectly
|
||||
/ linear order. It also enables a common pattern we use, which we
|
||||
/ call “Referencing Is Initialization” (RII).
|
||||
/
|
||||
/ C/C++ code should favor using ordinary constructors, since under
|
||||
/ normal circumstances the compiler will clobber RDI and RSI which
|
||||
/ are granted special meanings within this function.
|
||||
/
|
||||
/ @param r12 is argc (still callee saved)
|
||||
/ @param r13 is argv (still callee saved)
|
||||
/ @param r14 is envp (still callee saved)
|
||||
/ @param r15 is envp (still callee saved)
|
||||
/ @note rdi is __init_bss_start (callee monotonic lockstep)
|
||||
/ @note rsi is __init_rodata_start (callee monotonic lockstep)
|
||||
/ @see .init.start & .init.end (libc/macros.inc)
|
||||
/ @see ape/ape.lds
|
||||
.section .initprologue,"ax",@progbits
|
||||
.type _init,@function
|
||||
.globl _init
|
||||
.comm g_runstate,4
|
||||
_init: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
ezlea __init_bss_start,di
|
||||
ezlea __init_rodata_start,si
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .initepilogue,"ax",@progbits
|
||||
#if IsModeDbg()
|
||||
_init_check_rdi_rsi:
|
||||
jmp 2f
|
||||
1: call abort
|
||||
2: ezlea __init_bss_end,ax
|
||||
cmp %rax,%rdi
|
||||
jne 1b
|
||||
ezlea __init_rodata_end,ax
|
||||
cmp %rax,%rsi
|
||||
jne 1b
|
||||
3: .endfn _init_check_rdi_rsi
|
||||
#endif
|
||||
_woot: leave
|
||||
ret
|
||||
.previous
|
||||
|
||||
/ Decentralized section for packed data structures & initializers.
|
||||
/
|
||||
/ @see .initro (libc/macros.inc)
|
||||
/ @see ape/ape.lds
|
||||
.section .initroprologue,"a",@progbits
|
||||
.type __init_rodata_start,@object
|
||||
.type __init_rodata_end,@object
|
||||
.globl __init_rodata_start,__init_rodata_end
|
||||
.hidden __init_rodata_start,__init_rodata_end
|
||||
.align __SIZEOF_POINTER__
|
||||
__init_rodata_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .initroepilogue,"a",@progbits
|
||||
__init_rodata_end:
|
||||
.byte 0x90
|
||||
.previous
|
||||
|
||||
/ Decentralized section for unpacked data structures.
|
||||
/
|
||||
/ Data in this section becomes read-only after initialization.
|
||||
/
|
||||
/ @see .piro.bss.init (libc/macros.inc)
|
||||
/ @see libc/runtime/piro.c
|
||||
/ @see ape/ape.lds
|
||||
.section .piro.bss.init.1,"aw",@nobits
|
||||
.type __init_bss_start,@object
|
||||
.type __init_bss_end,@object
|
||||
.globl __init_bss_start,__init_bss_end
|
||||
.hidden __init_bss_start,__init_bss_end
|
||||
.align __SIZEOF_POINTER__
|
||||
__init_bss_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.bss.init.3,"aw",@nobits
|
||||
__init_bss_end:
|
||||
.byte 0
|
||||
.previous
|
||||
|
||||
/ Special area for Windows NT support code.
|
||||
/
|
||||
/ Isolating this code adds value for Windows users by minimizing
|
||||
/ page faults through improved locality. On System Five the PIRO
|
||||
/ runtime can unmap these pages.
|
||||
/
|
||||
/ @see libc/runtime/piro.c
|
||||
/ @see ape/ape.lds
|
||||
.section .textwindowsprologue,"ax",@progbits
|
||||
.type __text_windows_start,@object
|
||||
.type __text_windows_end,@object
|
||||
.globl __text_windows_start,__text_windows_end
|
||||
.hidden __text_windows_start,__text_windows_end
|
||||
int3
|
||||
__text_windows_start:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .textwindowsepilogue,"ax",@progbits
|
||||
__text_windows_end:
|
||||
int3
|
||||
.previous
|
35
libc/runtime/internal.h
Normal file
35
libc/runtime/internal.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_INTERNAL_H_
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define RUNSTATE_INITIALIZED (1 << 0)
|
||||
#define RUNSTATE_BROKEN (1 << 1)
|
||||
#define RUNSTATE_TERMINATE (1 << 2)
|
||||
|
||||
#define STACK_CEIL 0x700000000000ul
|
||||
#define STACK_SIZE FRAMESIZE
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
hidden extern char **g_freebsdhint;
|
||||
hidden extern unsigned g_runstate;
|
||||
hidden extern void *g_stacktop;
|
||||
|
||||
void _init(void) hidden;
|
||||
void __piro(int) hidden;
|
||||
void *__cxa_finalize(void *) hidden;
|
||||
int getdosargv(const char16_t *, char *, size_t, char **, size_t) hidden;
|
||||
void __stack_chk_fail(void) noreturn relegated;
|
||||
void __stack_chk_fail_local(void) noreturn relegated hidden;
|
||||
|
||||
forceinline void AssertNeverCalledWhileTerminating(void) {
|
||||
if (!NoDebug() && (g_runstate & RUNSTATE_TERMINATE)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_INTERNAL_H_ */
|
75
libc/runtime/interruptiblecall.c
Normal file
75
libc/runtime/interruptiblecall.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/progn.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/interruptiblecall.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("_init_onntconsoleevent");
|
||||
|
||||
static struct InterruptibleCall *g_interruptiblecall;
|
||||
|
||||
noreturn static void interruptcall(int sig) {
|
||||
longjmp(g_interruptiblecall->jb, 1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls function that may be cancelled by a signal.
|
||||
*
|
||||
* @param state is allocated and zero'd by the caller; state→sig and
|
||||
* state→sa_new.sa_mask may be set; it may be re-used w/o
|
||||
* reinitializing; it may be static or heap memory; it may be stack
|
||||
* memory if re-entrant behavior isn't needed
|
||||
* @return the value returned by callback or -1 on interrupt; they may
|
||||
* be differentiated using the state→returnval filed, which is only
|
||||
* modified by this function when callbacks succeed
|
||||
*/
|
||||
intptr_t interruptiblecall(struct InterruptibleCall *icall,
|
||||
intptr_t callback(intptr_t p1, intptr_t p2,
|
||||
intptr_t p3, intptr_t p4),
|
||||
intptr_t p1, intptr_t p2, intptr_t p3, intptr_t p4) {
|
||||
intptr_t rc;
|
||||
if (!icall->sig) icall->sig = SIGINT;
|
||||
icall->sa_new.sa_handler = interruptcall;
|
||||
icall->sa_new.sa_flags |= SA_RESTART | SA_RESETHAND;
|
||||
if ((rc = (sigaction)(icall->sig, &icall->sa_new, &icall->sa_old)) != -1) {
|
||||
g_interruptiblecall = PROGN((icall->prev = g_interruptiblecall), icall);
|
||||
if (!setjmp(icall->jb)) {
|
||||
icall->returnval = rc = callback(p1, p2, p3, p4);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
asm volatile("" ::: "memory");
|
||||
struct InterruptibleCall *unwind;
|
||||
for (;;) {
|
||||
unwind = g_interruptiblecall;
|
||||
(sigaction)(unwind->sig, &unwind->sa_old, NULL);
|
||||
g_interruptiblecall = unwind->prev;
|
||||
if (unwind == icall) break;
|
||||
free_s(&unwind);
|
||||
}
|
||||
icall->prev = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
26
libc/runtime/interruptiblecall.h
Normal file
26
libc/runtime/interruptiblecall.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct InterruptibleCall {
|
||||
struct InterruptibleCall *prev;
|
||||
intptr_t returnval;
|
||||
int sig;
|
||||
int flags;
|
||||
jmp_buf jb;
|
||||
struct sigaction sa_new;
|
||||
struct sigaction sa_old;
|
||||
};
|
||||
|
||||
intptr_t interruptiblecall(struct InterruptibleCall *state,
|
||||
intptr_t callback(intptr_t p1, intptr_t p2,
|
||||
intptr_t p3, intptr_t p4),
|
||||
intptr_t p1, intptr_t p2, intptr_t p3, intptr_t p4);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_ */
|
38
libc/runtime/isheap.c
Normal file
38
libc/runtime/isheap.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/mappings.h"
|
||||
|
||||
/**
|
||||
* Returns false if address can't be heap memory.
|
||||
*/
|
||||
bool isheap(void *p) {
|
||||
size_t i;
|
||||
struct MemoryCoord c;
|
||||
if (!(kStackBottom <= (intptr_t)p && (intptr_t)p < kStackCeiling)) {
|
||||
c = ADDRSIZE_TO_COORD(p, FRAMESIZE);
|
||||
if ((i = findmapping(c.x))) {
|
||||
return ISOVERLAPPING(_mm.p[i - 1], c);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
23
libc/runtime/issetugid.c
Normal file
23
libc/runtime/issetugid.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
int issetugid(void) { return !!getauxval(AT_SECURE); }
|
38
libc/runtime/kntsystemdirectory.S
Normal file
38
libc/runtime/kntsystemdirectory.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
#define BYTES 64
|
||||
|
||||
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
|
||||
/
|
||||
/ @note guarantees trailing slash if non-empty
|
||||
.initbss 300,_init_kNtSystemDirectory
|
||||
kNtSystemDirectory:
|
||||
.zero BYTES
|
||||
.endobj kNtSystemDirectory,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init_kNtSystemDirectory
|
||||
pushpop BYTES,%rdx
|
||||
mov __imp_GetSystemDirectoryA(%rip),%rax
|
||||
call __getntsyspath
|
||||
.init.end 300,_init_kNtSystemDirectory
|
38
libc/runtime/kntwindowsdirectory.S
Normal file
38
libc/runtime/kntwindowsdirectory.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
#define BYTES 64
|
||||
|
||||
/ RII constant holding 'C:/WINDOWS' directory.
|
||||
/
|
||||
/ @note guarantees trailing slash if non-empty
|
||||
.initbss 300,_init_kNtWindowsDirectory
|
||||
kNtWindowsDirectory:
|
||||
.zero BYTES
|
||||
.endobj kNtWindowsDirectory,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init_kNtWindowsDirectory
|
||||
pushpop BYTES,%rdx
|
||||
mov __imp_GetWindowsDirectoryA(%rip),%rax
|
||||
call __getntsyspath
|
||||
.init.end 300,_init_kNtWindowsDirectory
|
33
libc/runtime/mapanon-thunk.S
Normal file
33
libc/runtime/mapanon-thunk.S
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
mapanon:push %rbp
|
||||
mov %rsp,%rbp
|
||||
push %rbx
|
||||
push %rbx
|
||||
ezlea _base,bx
|
||||
call __mapanon
|
||||
pop %rbx
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn mapanon,globl
|
28
libc/runtime/mapanon.c
Normal file
28
libc/runtime/mapanon.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
void *__mapanon(size_t mapsize) {
|
||||
return mmap(NULL, mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_NONBLOCK | MAP_ANONYMOUS, -1, 0);
|
||||
}
|
31
libc/runtime/mapelfread.c
Normal file
31
libc/runtime/mapelfread.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/runtime/ezmap.h"
|
||||
|
||||
Elf64_Ehdr *mapelfread(const char *filename, struct MappedFile *mf) {
|
||||
if (mapfileread(filename, mf) != -1 && iself64binary(mf->addr, mf->size)) {
|
||||
return mf->addr;
|
||||
} else {
|
||||
unmapfile(mf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
22
libc/runtime/mappings.c
Normal file
22
libc/runtime/mappings.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/mappings.h"
|
||||
|
||||
struct Mappings _mm;
|
78
libc/runtime/mappings.h
Normal file
78
libc/runtime/mappings.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MAPPINGS_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_MAPPINGS_H_
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define MMAP_MAX 300 /* TODO: crunch */
|
||||
|
||||
#define kStackCeiling 0x0000700000000000L
|
||||
#define kStackBottom 0x0000600000000000L
|
||||
|
||||
#define kFixedMappingsStart 0x0000100000000000L /* cosmo won't auto-assign */
|
||||
#define kFixedMappingsSize 0x0000100000000000L /* 16TB */
|
||||
|
||||
#define kMappingsStart 0x0000200000000000L /* cosmo auto-assigns here */
|
||||
#define kMappingsSize 0x0000100000000000L /* 16TB */
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define ISOVERLAPPING(C1, C2) \
|
||||
(((C1).x >= (C2).x && (C1).x <= (C2).y) || \
|
||||
((C1).y >= (C2).x && (C1).y <= (C2).y))
|
||||
|
||||
#define ADDR_TO_COORD(ADDR) \
|
||||
(int)(((intptr_t)(ADDR) & ~(FRAMESIZE - 1)) / FRAMESIZE)
|
||||
|
||||
#define COORD_TO_ADDR(COORD) (void *)((intptr_t)(COORD)*FRAMESIZE)
|
||||
#define COORD_TO_SIZE(COORD) (void *)((intptr_t)(COORD)*FRAMESIZE)
|
||||
|
||||
#define ADDRSIZE_TO_COORD(ADDR, SIZE) \
|
||||
((struct MemoryCoord){ \
|
||||
.x = ADDR_TO_COORD(ADDR), \
|
||||
.y = ADDR_TO_COORD(ADDR) + \
|
||||
((unsigned)(ROUNDUP((SIZE), FRAMESIZE) / FRAMESIZE) - 1)})
|
||||
|
||||
#define COORD_TO_ADDRSIZE(COORD) \
|
||||
((struct AddrSize){ \
|
||||
.addr = COORD_TO_ADDR((COORD).x), \
|
||||
.size = ((size_t)((COORD).y - (COORD).x + 1) * FRAMESIZE)})
|
||||
|
||||
#define GRANULATE_ADDRSIZE(ADDR, SIZE) \
|
||||
do { \
|
||||
struct AddrSize AdSiz; \
|
||||
struct MemoryCoord MemCo; \
|
||||
MemCo = ADDRSIZE_TO_COORD(*(ADDR), *(SIZE)); \
|
||||
AdSiz = COORD_TO_ADDRSIZE(MemCo); \
|
||||
*(ADDR) = AdSiz.addr; \
|
||||
*(SIZE) = AdSiz.size; \
|
||||
} while (0)
|
||||
|
||||
struct AddrSize {
|
||||
void *addr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ordered inclusive 64kb-granular ranges on NexGen32e w/o PML5.
|
||||
* c.𝑥 ≤ c.𝑦 so say c all.
|
||||
* cₙ.𝑥 ≤ cₙ₊₁.𝑥 so say c all.
|
||||
*/
|
||||
struct Mappings {
|
||||
size_t i;
|
||||
struct MemoryCoord {
|
||||
int32_t x, y;
|
||||
} p[MMAP_MAX];
|
||||
int64_t h[MMAP_MAX];
|
||||
};
|
||||
|
||||
extern struct Mappings _mm;
|
||||
|
||||
bool isheap(void *);
|
||||
size_t findmapping(int32_t);
|
||||
size_t findmapping_(int32_t, const struct MemoryCoord *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_MAPPINGS_H_ */
|
46
libc/runtime/mergepages.S
Normal file
46
libc/runtime/mergepages.S
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/macros.h"
|
||||
.text.startup
|
||||
.yoink __FILE__
|
||||
|
||||
/ Merges page table entries for pages with identical content.
|
||||
/
|
||||
/ This is a hint. It can help trim physical memory for things
|
||||
/ like extremely sparse data.
|
||||
/
|
||||
/ @param rdi is base address
|
||||
/ @param rsi is byte length
|
||||
mergepages:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov $-PAGESIZE,%rax
|
||||
and %rax,%rdi
|
||||
and %rax,%rsi
|
||||
mov __NR_madvise,%eax
|
||||
mov MADV_MERGEABLE,%edx
|
||||
test %edx,%edx
|
||||
jz 1f
|
||||
syscall
|
||||
1: .leafepilogue
|
||||
.endfn mergepages,globl
|
143
libc/runtime/missioncritical.h
Normal file
143
libc/runtime/missioncritical.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_
|
||||
#define COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* @fileoverview Mission critical system calls.
|
||||
*/
|
||||
|
||||
#define PRINT(STR) __print(STR, tinystrlen(STR))
|
||||
|
||||
#define NT_HAVE_IMPORT(SLOT) \
|
||||
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)
|
||||
|
||||
#define _EXIT(rc) \
|
||||
({ \
|
||||
int ExitAx; \
|
||||
asm volatile("syscall" \
|
||||
: "=a"(ExitAx) \
|
||||
: "0"(__NR_exit), "D"(rc) \
|
||||
: "rcx", "r11", "cc", "memory"); \
|
||||
ExitAx; \
|
||||
})
|
||||
|
||||
#define GETPID() \
|
||||
({ \
|
||||
int Res; \
|
||||
asm("syscall" : "=a"(Res) : "0"(__NR_getpid) : "rcx", "r11", "cc"); \
|
||||
Res; \
|
||||
})
|
||||
|
||||
#define KILL(pid, sig) \
|
||||
({ \
|
||||
int KillAx; \
|
||||
unsigned char Cf; \
|
||||
asm volatile(CFLAG("clc\n\t" \
|
||||
"syscall") \
|
||||
: CF(Cf), "=a"(KillAx) \
|
||||
: "1"(__NR_kill), "D"(pid), "S"(sig) \
|
||||
: "rcx", "r11", "cc", "memory"); \
|
||||
Cf ? -KillAx : KillAx; \
|
||||
})
|
||||
|
||||
#define RAISE(SIG) \
|
||||
({ \
|
||||
int RaiseAx = -1; \
|
||||
int Sig = (SIG); \
|
||||
if (Sig == SIGTRAP) { \
|
||||
DebugBreak(); \
|
||||
} else if (!IsWindows()) { \
|
||||
RaiseAx = KILL(GETPID(), Sig); \
|
||||
} else { \
|
||||
switch (Sig) { \
|
||||
case SIGINT: \
|
||||
GenerateConsoleCtrlEvent(kNtCtrlCEvent, 0); \
|
||||
break; \
|
||||
case SIGHUP: \
|
||||
GenerateConsoleCtrlEvent(kNtCtrlCloseEvent, 0); \
|
||||
break; \
|
||||
case SIGQUIT: \
|
||||
GenerateConsoleCtrlEvent(kNtCtrlBreakEvent, 0); \
|
||||
break; \
|
||||
default: \
|
||||
for (;;) TerminateProcess(GetCurrentProcess(), 128 + Sig); \
|
||||
} \
|
||||
} \
|
||||
RaiseAx; \
|
||||
})
|
||||
|
||||
#define SCHED_YIELD() \
|
||||
({ \
|
||||
int64_t SyAx; \
|
||||
if (!IsWindows()) { \
|
||||
asm volatile("syscall" \
|
||||
: "=a"(SyAx) \
|
||||
: "0"(__NR_sched_yield) \
|
||||
: "rcx", "r11", "cc", "memory"); \
|
||||
} else { \
|
||||
NtYieldExecution(); \
|
||||
} \
|
||||
0; \
|
||||
})
|
||||
|
||||
#define WAIT4(PID, OPT_OUT_WSTATUS, OPTIONS, OPT_OUT_RUSAGE) \
|
||||
({ \
|
||||
int64_t WaAx; \
|
||||
if (!IsWindows()) { \
|
||||
register void *Reg10 asm("r10") = (OPT_OUT_RUSAGE); \
|
||||
asm volatile("syscall" \
|
||||
: "=a"(WaAx) \
|
||||
: "0"(__NR_wait4), "D"(PID), "S"(OPT_OUT_WSTATUS), \
|
||||
"d"(OPTIONS), "r"(Reg10) \
|
||||
: "rcx", "r11", "cc", "memory"); \
|
||||
} else { \
|
||||
WaAx = wait4$nt(PID, OPT_OUT_WSTATUS, OPTIONS, OPT_OUT_RUSAGE); \
|
||||
} \
|
||||
WaAx; \
|
||||
})
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Exits on Windows the hard way.
|
||||
*/
|
||||
#endif
|
||||
#define NT_TERMINATE_PROCESS() \
|
||||
do \
|
||||
if (NtGetVersion() < kNtVersionFuture) { \
|
||||
int64_t ax, cx; \
|
||||
do \
|
||||
asm volatile( \
|
||||
"syscall" /* hook THIS system call */ \
|
||||
: "=a"(ax), "=c"(cx) \
|
||||
: "0"(NtGetVersion() < kNtVersionWindows8 \
|
||||
? 0x0029 \
|
||||
: NtGetVersion() < kNtVersionWindows81 \
|
||||
? 0x002a \
|
||||
: NtGetVersion() < kNtVersionWindows10 ? 0x002b \
|
||||
: 0x002c), \
|
||||
"1"(-1L /* GetCurrentProcess() */), "d"(42) \
|
||||
: "r11", "cc", "memory"); \
|
||||
while (!ax); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
interruptfn void __print(const void *, size_t);
|
||||
|
||||
#define LOAD_DEFAULT_RBX() /* disabled for now b/c clang */
|
||||
#define RESTORE_RBX() /* disabled for now b/c clang */
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_ */
|
155
libc/runtime/mmap.c
Normal file
155
libc/runtime/mmap.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define VIP(X) (void *)(intptr_t)(X)
|
||||
|
||||
struct DirectMap {
|
||||
void *addr;
|
||||
int64_t maphandle;
|
||||
};
|
||||
|
||||
static textwindows struct DirectMap directmap$nt(void *addr, size_t size,
|
||||
unsigned prot, unsigned flags,
|
||||
int fd, int64_t off) {
|
||||
struct DirectMap res;
|
||||
if ((res.maphandle = CreateFileMappingNuma(
|
||||
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
||||
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
|
||||
kNtNumaNoPreferredNode))) {
|
||||
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
|
||||
off >> 32, off, size, addr,
|
||||
kNtNumaNoPreferredNode))) {
|
||||
CloseHandle(res.maphandle);
|
||||
res.maphandle = kNtInvalidHandleValue;
|
||||
res.addr = VIP(winerr());
|
||||
}
|
||||
} else {
|
||||
res.maphandle = kNtInvalidHandleValue;
|
||||
res.addr = VIP(winerr());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct DirectMap directmap(void *addr, size_t size, unsigned prot,
|
||||
unsigned flags, int fd, int64_t off) {
|
||||
if (!IsWindows()) {
|
||||
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
|
||||
kNtInvalidHandleValue};
|
||||
} else {
|
||||
return directmap$nt(addr, size, prot, flags, fd, off);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Beseeches system for page-table entries.
|
||||
*
|
||||
* @param addr optionally requests a particular virtual base address,
|
||||
* which needs to be 64kb aligned if passed (for NT compatibility)
|
||||
* @param size should be >0 and multiple of PAGESIZE
|
||||
* @param prot can have PROT_READ, PROT_WRITE, PROT_EXEC, PROT_NONE, etc.
|
||||
* @param flags can have MAP_ANONYMOUS, MAP_SHARED, MAP_PRIVATE, etc.
|
||||
* @param fd is an open()'d file descriptor whose contents shall be
|
||||
* mapped, and is ignored if MAP_ANONYMOUS is specified
|
||||
* @param offset specifies absolute byte index of fd's file for mapping,
|
||||
* and should be zero if MAP_ANONYMOUS is specified
|
||||
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
|
||||
*/
|
||||
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||
size_t i;
|
||||
intptr_t p;
|
||||
struct DirectMap dm;
|
||||
struct MemoryCoord c;
|
||||
p = (intptr_t)addr;
|
||||
|
||||
assert(!(0 < p && p < 0x200000));
|
||||
assert(-0x800000000000L <= p && p <= 0x7fffffffffffL);
|
||||
assert((flags & MAP_PRIVATE) ^ (flags & MAP_SHARED));
|
||||
assert((flags & MAP_ANONYMOUS) ^ (fd != -1));
|
||||
assert(off % PAGESIZE == 0);
|
||||
assert(size > 0);
|
||||
|
||||
if (!(IsWindows() && fd != -1)) {
|
||||
size = ROUNDUP(size, FRAMESIZE);
|
||||
}
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
assert(addr != NULL);
|
||||
assert((intptr_t)addr % FRAMESIZE == 0);
|
||||
} else {
|
||||
if (!addr) {
|
||||
if (_mm.i) {
|
||||
addr = COORD_TO_ADDR(_mm.p[_mm.i - 1].y + 1);
|
||||
for (i = _mm.i; i; --i) {
|
||||
if (_mm.p[i - 1].y + 1 + size / FRAMESIZE <=
|
||||
ADDR_TO_COORD(kMappingsStart + kMappingsSize) &&
|
||||
_mm.p[i - 1].y + 1 >= ADDR_TO_COORD(kMappingsStart)) {
|
||||
addr = COORD_TO_ADDR(_mm.p[i - 1].y + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addr = VIP(kMappingsStart);
|
||||
}
|
||||
}
|
||||
addr = (void *)ROUNDDOWN((intptr_t)addr, FRAMESIZE);
|
||||
}
|
||||
|
||||
if (_mm.i == MMAP_MAX) {
|
||||
return VIP(enomem());
|
||||
}
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
munmap(addr, size);
|
||||
} else {
|
||||
c = ADDRSIZE_TO_COORD(addr, size);
|
||||
if ((i = findmapping(c.y)) && ISOVERLAPPING(c, _mm.p[i - 1])) {
|
||||
return VIP(einval());
|
||||
}
|
||||
}
|
||||
|
||||
dm = directmap(addr, size, prot, flags | MAP_FIXED, fd, off);
|
||||
if (dm.addr == MAP_FAILED) return MAP_FAILED;
|
||||
|
||||
i = findmapping(ADDR_TO_COORD(dm.addr));
|
||||
if (i < _mm.i) {
|
||||
memmove(&_mm.p[i + 1], &_mm.p[i],
|
||||
(intptr_t)&_mm.p[_mm.i] - (intptr_t)&_mm.p[i]);
|
||||
memmove(&_mm.h[i + 1], &_mm.h[i],
|
||||
(intptr_t)&_mm.h[_mm.i] - (intptr_t)&_mm.h[i]);
|
||||
}
|
||||
|
||||
_mm.p[i] = ADDRSIZE_TO_COORD(dm.addr, size);
|
||||
_mm.h[i] = dm.maphandle;
|
||||
_mm.i++;
|
||||
|
||||
assert((intptr_t)dm.addr % __BIGGEST_ALIGNMENT__ == 0);
|
||||
return dm.addr;
|
||||
}
|
26
libc/runtime/mremap.c
Normal file
26
libc/runtime/mremap.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
void *mremap(void *old_address, size_t old_size, size_t new_size, int flags,
|
||||
void *new_address) {
|
||||
return (void *)(intptr_t)enosys();
|
||||
}
|
36
libc/runtime/msync-nt.c
Normal file
36
libc/runtime/msync-nt.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
|
||||
textwindows int msync$nt(void *addr, size_t size, int flags) {
|
||||
size_t i, j;
|
||||
struct MemoryCoord c;
|
||||
if (!FlushViewOfFile(addr, size)) return winerr();
|
||||
j = findmapping(ADDR_TO_COORD(addr));
|
||||
c = ADDRSIZE_TO_COORD(addr, size);
|
||||
for (i = j; i; --i) {
|
||||
if (!ISOVERLAPPING(_mm.p[i - 1], c)) break;
|
||||
FlushFileBuffers(_mm.h[i - 1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
41
libc/runtime/msync.c
Normal file
41
libc/runtime/msync.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/sysv/consts/msync.h"
|
||||
|
||||
/**
|
||||
* Synchronize memory mapping changes to disk.
|
||||
*
|
||||
* @param flags needs MS_SYNC or MS_ASYNC and can have MS_INVALIDATE
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int msync(void *addr, size_t size, int flags) {
|
||||
assert(((flags & MS_SYNC) ^ (flags & MS_ASYNC)) || !(MS_SYNC && MS_ASYNC));
|
||||
if (!IsWindows()) {
|
||||
return msync$sysv(addr, size, flags);
|
||||
} else {
|
||||
return msync$nt(addr, size, flags);
|
||||
}
|
||||
}
|
33
libc/runtime/munmap-thunk.S
Normal file
33
libc/runtime/munmap-thunk.S
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
munmap: push %rbp
|
||||
mov %rsp,%rbp
|
||||
push %rbx
|
||||
push %rbx
|
||||
ezlea _base,bx
|
||||
call __munmap
|
||||
pop %rbx
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn munmap,globl
|
106
libc/runtime/munmap.c
Normal file
106
libc/runtime/munmap.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
/**
|
||||
* Releases memory pages.
|
||||
*
|
||||
* @param addr is a pointer within any memory mapped region the process
|
||||
* has permission to control, such as address ranges returned by
|
||||
* mmap(), the program image itself, etc.
|
||||
* @param size is the amount of memory to unmap, which should be a
|
||||
* multiple of PAGESIZE, and may be a subset of that which was
|
||||
* mapped previously
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int __munmap(void *addr, size_t size) {
|
||||
int rc;
|
||||
intptr_t p;
|
||||
size_t i, j;
|
||||
struct AddrSize a;
|
||||
struct MemoryCoord c, m;
|
||||
|
||||
p = (intptr_t)addr;
|
||||
assert(!(0 < p && p < 0x200000));
|
||||
assert(-0x800000000000L <= p && p <= 0x7fffffffffffL);
|
||||
|
||||
if (!size) return 0;
|
||||
if (!addr || addr == MAP_FAILED) return 0;
|
||||
if (addr == NULL && size <= 0x200000) return 0;
|
||||
|
||||
addr = (void *)ROUNDDOWN((intptr_t)addr, FRAMESIZE);
|
||||
size = ROUNDUP(size, FRAMESIZE);
|
||||
|
||||
rc = 0;
|
||||
c = ADDRSIZE_TO_COORD(addr, size);
|
||||
j = findmapping(c.y);
|
||||
for (i = j; i; --i) {
|
||||
m = _mm.p[i - 1];
|
||||
assert(m.x <= m.y);
|
||||
assert(c.y >= m.x);
|
||||
if (c.x > m.y) {
|
||||
break;
|
||||
} else if (c.x > m.x && c.y < m.y) {
|
||||
/* remove middle portion */
|
||||
assert(!"map hole punching not implemented");
|
||||
} else if (c.x > m.x && c.y >= m.y) {
|
||||
/* remove righthand portion */
|
||||
assert(!"map hole punching not implemented");
|
||||
/* _mm.p[i - 1].y = c.x - 1; */
|
||||
/* i++; */
|
||||
/* break; */
|
||||
} else if (c.x <= m.x && c.y < m.y) {
|
||||
/* remove lefthand portion */
|
||||
assert(!"map hole punching not implemented");
|
||||
/* _mm.p[i - 1].x = c.y + 1; */
|
||||
/* j--; */
|
||||
} else if ((m.x >= c.x && m.x <= c.y) && (m.y >= c.x && m.y <= c.y)) {
|
||||
a = COORD_TO_ADDRSIZE(m);
|
||||
if (!IsWindows()) {
|
||||
rc |= munmap$sysv(a.addr, a.size);
|
||||
} else {
|
||||
if (!UnmapViewOfFile(a.addr)) rc = -1;
|
||||
if (!CloseHandle(_mm.h[i - 1])) rc = -1;
|
||||
}
|
||||
} else {
|
||||
assert(!"wut");
|
||||
}
|
||||
}
|
||||
|
||||
if (i < j) {
|
||||
if (j < _mm.i) {
|
||||
memmove(&_mm.p[i], &_mm.p[j],
|
||||
(intptr_t)&_mm.p[_mm.i] - (intptr_t)&_mm.p[j]);
|
||||
memmove(&_mm.h[i], &_mm.h[j],
|
||||
(intptr_t)&_mm.h[_mm.i] - (intptr_t)&_mm.h[j]);
|
||||
}
|
||||
_mm.i -= j - i;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
38
libc/runtime/munmap_s.c
Normal file
38
libc/runtime/munmap_s.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Closes memory mapping, the Cosmopolitan way.
|
||||
*
|
||||
* The caller's address holder is set to MAP_FAILED (-1) which is a
|
||||
* no-op for subsequent invocations.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int munmap_s(void *addrp, uint64_t size) {
|
||||
void **addrpp = (void **)addrp;
|
||||
void *addr = (void *)pushpop(-1L);
|
||||
return munmap(lockxchg(addrpp, &addr), size);
|
||||
}
|
37
libc/runtime/ntgetmodule.c
Normal file
37
libc/runtime/ntgetmodule.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/nt/struct/ldr.h"
|
||||
#include "libc/nt/struct/ldrdatatableentry.h"
|
||||
#include "libc/nt/struct/linkedlist.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows const struct NtLdrDataTableEntry *NtGetModule(
|
||||
const char *basename) {
|
||||
struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
|
||||
struct NtLinkedList *ldr = head->Next;
|
||||
do {
|
||||
const struct NtLdrDataTableEntry *dll =
|
||||
(const struct NtLdrDataTableEntry *)ldr;
|
||||
if (strcasecmp8to16(basename, dll->BaseDllName.Data) == 0) return dll;
|
||||
} while ((ldr = ldr->Next) && ldr != head);
|
||||
return NULL;
|
||||
}
|
60
libc/runtime/opensymboltable.c
Normal file
60
libc/runtime/opensymboltable.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* Maps debuggable binary into memory and indexes symbol addresses.
|
||||
*
|
||||
* @return object freeable with closesymboltable(), or NULL w/ errno
|
||||
*/
|
||||
struct SymbolTable *opensymboltable(const char *filename) {
|
||||
struct SymbolTable *t = MAP_FAILED;
|
||||
const Elf64_Sym *symtab;
|
||||
if (filename && (t = mapanon(BIGPAGESIZE)) != MAP_FAILED &&
|
||||
mapelfread(filename, &t->mf) &&
|
||||
(t->name_base = getelfstringtable(t->elf, t->elfsize)) != NULL &&
|
||||
(symtab = getelfsymboltable(t->elf, t->elfsize, &t->count)) &&
|
||||
sizeof(struct SymbolTable) + sizeof(struct Symbol) * t->count <
|
||||
(t->scratch = BIGPAGESIZE)) {
|
||||
unsigned j = 0;
|
||||
getelfvirtualaddressrange(t->elf, t->elfsize, &t->addr_base, &t->addr_end);
|
||||
for (unsigned i = 0; i < t->count; ++i) {
|
||||
const Elf64_Sym *sym = &symtab[i];
|
||||
if (iselfsymbolcontent(sym) &&
|
||||
(sym->st_value >= t->addr_base && sym->st_value <= t->addr_end)) {
|
||||
t->symbols[j].addr_rva = (unsigned)(sym->st_value - t->addr_base);
|
||||
t->symbols[j].name_rva = sym->st_name;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
t->count = j;
|
||||
heapsortcar((int32_t(*)[2])t->symbols, t->count);
|
||||
} else {
|
||||
closesymboltable(&t);
|
||||
}
|
||||
return t == MAP_FAILED ? NULL : t;
|
||||
}
|
33
libc/runtime/peekall.S
Normal file
33
libc/runtime/peekall.S
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Loads all pages from program image into memory.
|
||||
peekall:.leafprologue
|
||||
ezlea _base,si
|
||||
ezlea _end,cx
|
||||
0: mov (%rsi),%eax
|
||||
add $PAGESIZE,%rsi
|
||||
cmp %rcx,%rsi
|
||||
jb 0b
|
||||
.leafepilogue
|
||||
.endfn peekall,globl
|
71
libc/runtime/piro.c
Normal file
71
libc/runtime/piro.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § post-initialization read-only │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define getaddr(section) ((intptr_t)weakaddr(section))
|
||||
|
||||
static textstartup void __piro_protect(intptr_t start, intptr_t end, int prot) {
|
||||
ssize_t len = end - start;
|
||||
if (len > 0 && start && start % PAGESIZE == 0 && len % PAGESIZE == 0) {
|
||||
if (mprotect((void *)(unsigned long)start, len, prot) == -1) abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protects memory initialized at startup.
|
||||
* e.g. function hooks, unpacked data structures, etc.
|
||||
*
|
||||
* This is only performed for executables of nontrivial size. It won't
|
||||
* break the build if the αpε linker script wasn't used. Test code is
|
||||
* protected too, so we don't end up like Knight Capital.
|
||||
*
|
||||
* @param prot can have PROT_{NONE,READ,WRITE,EXEC}
|
||||
* @see ape/ape.lds
|
||||
* @see libc/_start.S
|
||||
*/
|
||||
textstartup void __piro(int prot) {
|
||||
if (getaddr("main") < getaddr("__test_start")) {
|
||||
__piro_protect(getaddr("__test_start"), getaddr("__test_end"), PROT_NONE);
|
||||
}
|
||||
__piro_protect(getaddr("__ro"), getaddr("_etext"), PROT_READ);
|
||||
__piro_protect(getaddr("__piro_start"), getaddr("__piro_end"), prot);
|
||||
}
|
71
libc/runtime/print.greg.c
Normal file
71
libc/runtime/print.greg.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
static privileged void __print$nt(const void *data, size_t len) {
|
||||
int64_t hand;
|
||||
uint32_t wrote;
|
||||
char xmm[256] aligned(16);
|
||||
savexmm(&xmm[128]);
|
||||
hand = __imp_GetStdHandle(kNtStdErrorHandle);
|
||||
__imp_WriteFile(hand, data, len, &wrote, NULL);
|
||||
__imp_FlushFileBuffers(hand);
|
||||
loadxmm(&xmm[128]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints string, by any means necessary.
|
||||
*
|
||||
* This function offers a subset of write(STDERR_FILENO) functionality.
|
||||
* It's designed to work even when the runtime hasn't initialized, e.g.
|
||||
* before _init() gets called.
|
||||
*
|
||||
* @param len can be computed w/ tinystrlen()
|
||||
* @clob nothing except flags
|
||||
* @see PRINT()
|
||||
*/
|
||||
privileged interruptfn void __print(const void *data, size_t len) {
|
||||
int64_t ax, ordinal;
|
||||
LOAD_DEFAULT_RBX();
|
||||
if (NT_HAVE_IMPORT(__imp_WriteFile)) {
|
||||
__print$nt(data, len);
|
||||
} else {
|
||||
ordinal = __NR_write > 0 ? __NR_write : IsXnu() ? 0x2000004 : 4;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
if (ax == -1 && !hostos && !__NR_write) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
}
|
||||
}
|
||||
RESTORE_RBX();
|
||||
}
|
33
libc/runtime/progname.S
Normal file
33
libc/runtime/progname.S
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Provides argv[0] The BSD Way.
|
||||
.initbss 300,_init___progname
|
||||
__progname:
|
||||
.quad 0
|
||||
.endobj __progname,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 300,_init___progname
|
||||
mov %r13,%rax
|
||||
stosq
|
||||
.init.end 300,_init___progname
|
38
libc/runtime/program_invocation_short_name.S
Normal file
38
libc/runtime/program_invocation_short_name.S
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Supplies basename(argv[0]) The GNU Way.
|
||||
.initbss 400,_init_program_invocation_short_name
|
||||
program_invocation_short_name:
|
||||
.quad 0
|
||||
.endobj program_invocation_short_name,globl
|
||||
.previous
|
||||
|
||||
.init.start 400,_init_program_invocation_short_name
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov (%r13),%rdi
|
||||
call basename
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
stosq
|
||||
.init.end 400,_init_program_invocation_short_name
|
34
libc/runtime/quick_exit.c
Normal file
34
libc/runtime/quick_exit.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Terminates process normally, running minimal cleanup.
|
||||
* @noreturn
|
||||
*/
|
||||
noreturn textexit void quick_exit(int rc) {
|
||||
if (weaken(fflush)) {
|
||||
if (weaken(stdout)) weaken(fflush)(*weaken(stdout));
|
||||
if (weaken(stderr)) weaken(fflush)(*weaken(stderr));
|
||||
}
|
||||
_Exit(rc);
|
||||
}
|
21
libc/runtime/rbx.h
Normal file
21
libc/runtime/rbx.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_RBX_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_RBX_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#if 0
|
||||
#ifndef __llvm__
|
||||
register uint8_t *__rbx asm("rbx");
|
||||
#else
|
||||
#define __rbx \
|
||||
({ \
|
||||
register uint8_t *Rbx asm("rbx"); \
|
||||
asm("" : "=r"(Rbx)); \
|
||||
Rbx; \
|
||||
})
|
||||
#endif
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_RBX_H_ */
|
17
libc/runtime/ring.h
Normal file
17
libc/runtime/ring.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_RING_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_RING_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct RingBuffer {
|
||||
void *p;
|
||||
char *_addr;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
void *ringalloc(struct RingBuffer *, size_t);
|
||||
int ringfree(struct RingBuffer *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_RING_H_ */
|
74
libc/runtime/ringalloc.c
Normal file
74
libc/runtime/ringalloc.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/ring.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* Allocates ring buffer.
|
||||
*
|
||||
* Reads/writes wrap around on overflow.
|
||||
*
|
||||
* ┌────────────┐
|
||||
* │ 𝑓₀..𝑓ₙ₋₁ │
|
||||
* └┬┬──────────┘
|
||||
* │└────────────┐
|
||||
* ┌┴────────────┬┴────────────┐
|
||||
* │ 𝑣₀..𝑣ₙ₋₁ │ 𝑣ₙ..𝑣ₙ*₂₋₁ │
|
||||
* └─────────────┴─────────────┘
|
||||
*
|
||||
* @param r is metadata object owned by caller, initialized to zero
|
||||
* @param n is byte length
|
||||
* @return r->p, or NULL w/ errno
|
||||
* @see ringfree(), balloc()
|
||||
*/
|
||||
void *ringalloc(struct RingBuffer *r, size_t n) {
|
||||
void *a2;
|
||||
int fd, rc;
|
||||
size_t grain;
|
||||
assert(!r->p);
|
||||
assert(n > 0);
|
||||
assert(n <= (INT_MAX - FRAMESIZE + 1) / 2);
|
||||
if ((fd = openanon("ring", 0)) != -1) {
|
||||
grain = ROUNDUP(n, FRAMESIZE);
|
||||
rc = ftruncate(fd, grain * 2);
|
||||
assert(rc != -1);
|
||||
r->_size = grain * 2;
|
||||
r->_addr = mmap(NULL, grain, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (r->_addr != MAP_FAILED) {
|
||||
a2 = mmap(r->_addr + grain, grain, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_FIXED, fd, grain - n);
|
||||
assert(a2 != MAP_FAILED);
|
||||
r->p = r->_addr + grain - n;
|
||||
if (IsWindows()) {
|
||||
memset(r->p, 0, n); /* @see ftruncate() */
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = close(fd);
|
||||
assert(rc != -1);
|
||||
return r->p;
|
||||
}
|
35
libc/runtime/ringfree.c
Normal file
35
libc/runtime/ringfree.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/ring.h"
|
||||
|
||||
/**
|
||||
* Frees ring buffer.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int ringfree(struct RingBuffer *r) {
|
||||
if (r->p) {
|
||||
r->p = NULL;
|
||||
return munmap(r->_addr, r->_size);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
83
libc/runtime/runtime.h
Normal file
83
libc/runtime/runtime.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_RUNTIME_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_RUNTIME_H_
|
||||
#include "libc/dce.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § runtime ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
struct StackFrame {
|
||||
struct StackFrame *next;
|
||||
intptr_t addr;
|
||||
};
|
||||
|
||||
typedef long jmp_buf[8] aligned(CACHELINE);
|
||||
|
||||
extern int g_argc; /* CRT */
|
||||
extern char **g_argv; /* CRT */
|
||||
extern char **environ; /* CRT */
|
||||
extern unsigned long *g_auxv; /* CRT */
|
||||
extern jmp_buf g_winmain; /* CRT */
|
||||
extern char *program_invocation_name; /* RII */
|
||||
extern char *program_invocation_short_name; /* RII */
|
||||
extern uint64_t g_syscount; /* RII */
|
||||
extern const uint64_t kStartTsc; /* RII */
|
||||
extern const char kTmpPath[]; /* RII */
|
||||
extern const char kNtSystemDirectory[]; /* RII */
|
||||
extern const char kNtWindowsDirectory[]; /* RII */
|
||||
extern unsigned char _base[] aligned(PAGESIZE); /* αpε */
|
||||
extern char _ehead aligned(PAGESIZE); /* αpε */
|
||||
extern char _ereal; /* αpε */
|
||||
extern char __privileged_start; /* αpε */
|
||||
extern char __test_start; /* αpε */
|
||||
extern char __ro; /* αpε */
|
||||
extern char _etext aligned(PAGESIZE); /* αpε */
|
||||
extern char __piro_start; /* αpε */
|
||||
extern char _edata aligned(PAGESIZE); /* αpε */
|
||||
extern char __piro_end; /* αpε */
|
||||
extern char _end aligned(PAGESIZE); /* αpε */
|
||||
extern uint8_t __zip_start[]; /* αpε */
|
||||
extern uint8_t __zip_end[]; /* αpε */
|
||||
|
||||
long missingno();
|
||||
void mcount(void);
|
||||
unsigned long getauxval(unsigned long);
|
||||
void *mapanon(size_t) vallocesque attributeallocsize((1));
|
||||
int setjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
void longjmp(jmp_buf, int) libcesque noreturn paramsnonnull();
|
||||
void exit(int) noreturn;
|
||||
void quick_exit(int) noreturn;
|
||||
void _exit(int) libcesque noreturn;
|
||||
void _Exit(int) libcesque noreturn;
|
||||
void abort(void) noreturn noinstrument forcealignargpointer;
|
||||
void abort_(void) asm("abort") noreturn noinstrument privileged;
|
||||
void panic(void) noreturn noinstrument privileged;
|
||||
void triplf(void) noreturn noinstrument privileged;
|
||||
int __cxa_atexit(void *, void *, void *) libcesque;
|
||||
int atfork(void *, void *) libcesque;
|
||||
int atexit(void (*)(void)) libcesque;
|
||||
void free_s(void *) paramsnonnull() libcesque;
|
||||
int close_s(int *) paramsnonnull() libcesque;
|
||||
char *getenv(const char *) paramsnonnull() nosideeffect libcesque;
|
||||
int putenv(char *) paramsnonnull();
|
||||
int setenv(const char *, const char *, int) paramsnonnull();
|
||||
int unsetenv(const char *);
|
||||
int clearenv(void);
|
||||
void __fast_math(void);
|
||||
void fpreset(void);
|
||||
void savexmm(void *);
|
||||
void loadxmm(void *);
|
||||
void peekall(void);
|
||||
int issetugid(void);
|
||||
void weakfree(void *) libcesque;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § runtime » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define _exit(RC) _Exit(RC)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_RUNTIME_H_ */
|
84
libc/runtime/runtime.mk
Normal file
84
libc/runtime/runtime.mk
Normal file
|
@ -0,0 +1,84 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan Runtime
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This package exports essential routines for userspace process
|
||||
# initialization.
|
||||
|
||||
PKGS += LIBC_RUNTIME
|
||||
|
||||
LIBC_RUNTIME = $(LIBC_RUNTIME_A_DEPS) $(LIBC_RUNTIME_A)
|
||||
LIBC_RUNTIME_ARTIFACTS += LIBC_RUNTIME_A
|
||||
LIBC_RUNTIME_A = o/$(MODE)/libc/runtime/runtime.a
|
||||
LIBC_RUNTIME_A_FILES := $(wildcard libc/runtime/*)
|
||||
LIBC_RUNTIME_A_HDRS = $(filter %.h,$(LIBC_RUNTIME_A_FILES))
|
||||
LIBC_RUNTIME_A_SRCS_S = $(filter %.S,$(LIBC_RUNTIME_A_FILES))
|
||||
LIBC_RUNTIME_A_SRCS_C = $(filter %.c,$(LIBC_RUNTIME_A_FILES))
|
||||
|
||||
LIBC_RUNTIME_A_SRCS = \
|
||||
$(LIBC_RUNTIME_A_SRCS_S) \
|
||||
$(LIBC_RUNTIME_A_SRCS_C)
|
||||
|
||||
LIBC_RUNTIME_A_OBJS = \
|
||||
$(LIBC_RUNTIME_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_RUNTIME_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_RUNTIME_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_RUNTIME_A_CHECKS = \
|
||||
$(LIBC_RUNTIME_A).pkg \
|
||||
$(LIBC_RUNTIME_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_RUNTIME_A_DIRECTDEPS = \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_RAND \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS
|
||||
|
||||
LIBC_RUNTIME_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_RUNTIME_A): \
|
||||
libc/runtime/ \
|
||||
$(LIBC_RUNTIME_A).pkg \
|
||||
$(LIBC_RUNTIME_A_OBJS)
|
||||
|
||||
$(LIBC_RUNTIME_A).pkg: \
|
||||
$(LIBC_RUNTIME_A_OBJS) \
|
||||
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/runtime/asan.greg.o \
|
||||
o/$(MODE)/libc/runtime/shadowargs.o \
|
||||
o/$(MODE)/libc/runtime/__stack_chk_fail.o \
|
||||
o/$(MODE)/libc/runtime/__stack_chk_guard.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
$(NO_MAGIC)
|
||||
|
||||
# @see ape/ape.s for tuning parameters that make this safe
|
||||
o/$(MODE)/libc/runtime/winmain.greg.o: \
|
||||
DEFAULT_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
LIBC_RUNTIME_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)))
|
||||
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_RUNTIME_BINS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_RUNTIME_CHECKS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_RUNTIME_OBJS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_OBJS))
|
||||
LIBC_RUNTIME_TESTS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_TESTS))
|
||||
$(LIBC_RUNTIME_OBJS): $(BUILD_FILES) libc/runtime/runtime.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/runtime
|
||||
o/$(MODE)/libc/runtime: $(LIBC_RUNTIME_CHECKS)
|
61
libc/runtime/stackchkfail.c
Normal file
61
libc/runtime/stackchkfail.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/config.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
#define STACK_SMASH_MESSAGE "stack smashed\n"
|
||||
|
||||
/**
|
||||
* Aborts program under enemy fire to avoid being taken alive.
|
||||
*/
|
||||
void __stack_chk_fail(void) {
|
||||
if (!IsWindows()) {
|
||||
const char *const msg = STACK_SMASH_MESSAGE;
|
||||
const size_t len = pushpop(sizeof(STACK_SMASH_MESSAGE) - 1);
|
||||
if (!IsMetal()) {
|
||||
unsigned ax;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_write), "D"(pushpop(STDERR_FILENO)), "S"(msg),
|
||||
"d"(len)
|
||||
: "rcx", "r11", "cc", "memory");
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_exit), "D"(pushpop(88))
|
||||
: "rcx", "r11", "cc", "memory");
|
||||
}
|
||||
short(*ttys)[4] = (short(*)[4])XLM(BIOS_DATA_AREA);
|
||||
unsigned long si;
|
||||
unsigned cx;
|
||||
asm volatile("rep outsb"
|
||||
: "=S"(si), "=c"(cx)
|
||||
: "0"(msg), "1"(len), "d"((*ttys)[1 /*COM2*/])
|
||||
: "memory");
|
||||
triplf();
|
||||
}
|
||||
NT_TERMINATE_PROCESS();
|
||||
for (;;) TerminateProcess(GetCurrentProcess(), 42);
|
||||
}
|
22
libc/runtime/stackchkfaillocal.c
Normal file
22
libc/runtime/stackchkfaillocal.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/internal.h"
|
||||
|
||||
void __stack_chk_fail_local(void) { __stack_chk_fail(); }
|
148
libc/runtime/startmain.S
Normal file
148
libc/runtime/startmain.S
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
.text.startup
|
||||
.yoink __FILE__
|
||||
|
||||
/ Cosmopolitan process entrypoint.
|
||||
/
|
||||
/ @param r12 is argc
|
||||
/ @param r13 is argv
|
||||
/ @param r14 is environ
|
||||
/ @param r15 is auxv
|
||||
/ @noreturn
|
||||
__executive:
|
||||
.frame0
|
||||
ezlea _base,bx
|
||||
|
||||
#ifdef __FAST_MATH__
|
||||
call __fast_math
|
||||
#endif
|
||||
call _init
|
||||
#if IsModeDbg()
|
||||
call _init # _init() is idempotent
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if !IsTiny()
|
||||
/ “Memory obfuscation for glibc, not for we”
|
||||
/
|
||||
/ 64kb stack w/ 4kb guard alongside tuning in libc/integral/c.inc
|
||||
/ e.g. -Werror=frame-larger-than=4096 is intended to guarantee no
|
||||
/ stack overflow possible. We like malloc and only cleverly avoid
|
||||
/ its use at the lowest levels of the runtime stack, without MMU.
|
||||
/ We like this practicee because it's how Google runs production.
|
||||
mov $kStackCeiling-STACKSIZE,%rdi
|
||||
mov $STACKSIZE,%esi
|
||||
mov $PROT_READ|PROT_WRITE,%edx
|
||||
mov MAP_ANONYMOUS,%ecx
|
||||
or MAP_FIXED,%ecx
|
||||
or MAP_PRIVATE,%ecx
|
||||
mov $-1,%r8d
|
||||
xor %r9d,%r9d
|
||||
call mmap
|
||||
cmp $-1,%eax
|
||||
je abort
|
||||
lea STACKSIZE(%rax),%rsp
|
||||
xor %ebp,%ebp
|
||||
mov %rax,%rdi
|
||||
mov $PAGESIZE,%esi
|
||||
mov $PROT_NONE,%edx
|
||||
call mprotect
|
||||
cmp $-1,%eax
|
||||
je abort
|
||||
#endif
|
||||
*/
|
||||
|
||||
orl $RUNSTATE_INITIALIZED,g_runstate(%rip)
|
||||
ezlea __init_array_start,ax # static ctors in forward order
|
||||
.weak __init_array_start # could be called multiple times
|
||||
ezlea __init_array_end,cx # idempotency recommended
|
||||
.weak __init_array_end # @see ape/ape.lds
|
||||
1: cmp %rax,%rcx
|
||||
je 2f
|
||||
push %rax
|
||||
push %rcx
|
||||
call *(%rax)
|
||||
pop %rcx
|
||||
pop %rax
|
||||
add $8,%rax
|
||||
jmp 1b
|
||||
2: nop
|
||||
#if !IsTrustworthy()
|
||||
mov $PROT_READ,%edi
|
||||
call __piro
|
||||
#endif
|
||||
mov %r12,%rdi
|
||||
mov %r13,%rsi
|
||||
mov %r14,%rdx
|
||||
.weak main
|
||||
call main
|
||||
mov %eax,%edi
|
||||
call exit
|
||||
.endfn __executive,weak,hidden
|
||||
|
||||
#ifdef __PG__
|
||||
/ Enables plaintext function tracing if --ftrace flag passed.
|
||||
/
|
||||
/ The --ftrace CLI arg is removed before main() is called. This
|
||||
/ code is intended for diagnostic purposes and assumes binaries
|
||||
/ are trustworthy and stack isn't corrupted. Logging plain text
|
||||
/ allows program structure to easily be visualized and hotspots
|
||||
/ identified w/ sed | sort | uniq -c | sort. A compressed trace
|
||||
/ can be made by appending --ftrace 2>&1 | gzip -4 >trace.gz to
|
||||
/ the CLI arguments. Have fun.
|
||||
/
|
||||
/ @see libc/runtime/ftrace.greg.c
|
||||
/ @see libc/crt/crt.S
|
||||
.init.start 800,_init_ftrace
|
||||
push %rdi
|
||||
push %rsi
|
||||
xor %edx,%edx
|
||||
loadstr "--ftrace",di
|
||||
xor %ecx,%ecx
|
||||
0: inc %ecx
|
||||
mov (%r13,%rcx,8),%rsi
|
||||
test %edx,%edx
|
||||
jz 1f
|
||||
mov %rsi,-8(%r13,%rcx,8)
|
||||
1: test %rsi,%rsi
|
||||
jz 2f
|
||||
test %edx,%edx
|
||||
jnz 0b
|
||||
call tinystrcmp
|
||||
test %eax,%eax
|
||||
setz %dl
|
||||
jmp 0b
|
||||
2: sub %rdx,%r12
|
||||
test %edx,%edx
|
||||
jz 2f
|
||||
call ftrace_init
|
||||
2: pop %rsi
|
||||
pop %rdi
|
||||
.init.end 800,_init_ftrace
|
||||
#endif /* -pg */
|
14
libc/runtime/symbolic.h
Normal file
14
libc/runtime/symbolic.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_SYMBOLIC_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_SYMBOLIC_H_
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
/* clang-format off */
|
||||
#define SYMBOLIC(NAME) NAME(%rip)
|
||||
#define LITERALLY(NAME) $NAME
|
||||
/* clang-format on */
|
||||
#else
|
||||
#define SYMBOLIC(NAME) NAME
|
||||
#define LITERALLY(NAME) NAME
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_SYMBOLIC_H_ */
|
59
libc/runtime/symbols.h
Normal file
59
libc/runtime/symbols.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_SYMBOLS_H_
|
||||
#define COSMOPOLITAN_LIBC_SYMBOLS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/runtime/ezmap.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct Symbol {
|
||||
unsigned addr_rva;
|
||||
unsigned name_rva;
|
||||
};
|
||||
|
||||
struct SymbolTable {
|
||||
union {
|
||||
struct MappedFile mf;
|
||||
struct {
|
||||
int64_t fd;
|
||||
struct Elf64_Ehdr *elf;
|
||||
size_t elfsize;
|
||||
};
|
||||
};
|
||||
size_t scratch;
|
||||
size_t count;
|
||||
intptr_t addr_base;
|
||||
intptr_t addr_end;
|
||||
const char *name_base;
|
||||
struct Symbol symbols[];
|
||||
};
|
||||
|
||||
struct SymbolTable *getsymboltable(void);
|
||||
const char *findcombinary(void);
|
||||
const char *finddebugbinary(void);
|
||||
struct SymbolTable *opensymboltable(const char *) nodiscard;
|
||||
int closesymboltable(struct SymbolTable **);
|
||||
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
|
||||
const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYMBOLS_H_ */
|
26
libc/runtime/sysconf.c
Normal file
26
libc/runtime/sysconf.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/sysconf.h"
|
||||
|
||||
/**
|
||||
* Returns configuration value about system.
|
||||
* @param thing can be _SC_XXX
|
||||
*/
|
||||
long(sysconf)(int thing) { return __sysconf(thing); }
|
37
libc/runtime/sysconf.h
Normal file
37
libc/runtime/sysconf.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
#define _SC_ARG_MAX 0
|
||||
#define _SC_CLK_TCK 2
|
||||
#define _SC_PAGESIZE 30
|
||||
#define _SC_PAGE_SIZE 30
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
long sysconf(int);
|
||||
|
||||
#define sysconf(X) __sysconf(X)
|
||||
|
||||
forceinline long __sysconf(int thing) {
|
||||
switch (thing) {
|
||||
case _SC_ARG_MAX:
|
||||
return ARG_MAX;
|
||||
case _SC_CLK_TCK: {
|
||||
extern const long __AT_CLKTCK asm("AT_CLKTCK");
|
||||
long res = getauxval(__AT_CLKTCK);
|
||||
if (!res) res = 100;
|
||||
return res;
|
||||
}
|
||||
case _SC_PAGESIZE:
|
||||
return FRAMESIZE;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_ */
|
43
libc/runtime/unsetenv.c
Normal file
43
libc/runtime/unsetenv.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Removes environment variable.
|
||||
*/
|
||||
int unsetenv(const char *name) {
|
||||
if (isempty(name) || strchr(name, '=')) return einval();
|
||||
if (environ) {
|
||||
char **ep = environ;
|
||||
size_t removed = 0;
|
||||
size_t namelen = strlen(name);
|
||||
do {
|
||||
if (*ep && strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
|
||||
--removed;
|
||||
} else if (removed) {
|
||||
ep[removed] = *ep;
|
||||
}
|
||||
} while (*ep++);
|
||||
}
|
||||
return 0;
|
||||
}
|
36
libc/runtime/weakfree.S
Normal file
36
libc/runtime/weakfree.S
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Thunks free() if it's linked, otherwise do nothing.
|
||||
/
|
||||
/ @see free_s() which can ignore static/stack and clear refs
|
||||
weakfree:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.weak free
|
||||
ezlea free,ax
|
||||
test %rax,%rax
|
||||
jz 1f
|
||||
call free
|
||||
1: pop %rbp
|
||||
ret
|
||||
.endfn weakfree,globl
|
62
libc/runtime/winmain.greg.c
Normal file
62
libc/runtime/winmain.greg.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/loadlibrarysearch.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/getdosenviron.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
||||
static void LoadFasterAndPreventHijacking(void) {
|
||||
unsigned wrote;
|
||||
if (!SetDefaultDllDirectories(kNtLoadLibrarySearchSearchSystem32)) {
|
||||
WriteFile(GetStdHandle(kNtStdErrorHandle), "nodll\n", 6, &wrote, NULL);
|
||||
ExitProcess(1);
|
||||
}
|
||||
}
|
||||
|
||||
noreturn textwindows int WinMain(void *hInstance, void *hPrevInstance,
|
||||
const char *lpCmdLine, int nCmdShow) {
|
||||
int i, count;
|
||||
const char16_t *cmd16, *env16;
|
||||
long auxarray[][2] = {{pushpop(0L), pushpop(0L)}};
|
||||
char envblock[ENV_MAX], *envarray[512], argblock[ARG_MAX], *argarray[512];
|
||||
LoadFasterAndPreventHijacking();
|
||||
*(/*unconst*/ int *)&__hostos = pushpop(WINDOWS);
|
||||
cmd16 = GetCommandLine();
|
||||
env16 = GetEnvironmentStrings();
|
||||
count = getdosargv(cmd16, argblock, ARG_MAX, argarray, 512);
|
||||
for (i = 0; argarray[0][i]; ++i) {
|
||||
if (argarray[0][i] == '\\') argarray[0][i] = '/';
|
||||
}
|
||||
getdosenviron(env16, envblock, ENV_MAX, envarray, 512);
|
||||
FreeEnvironmentStrings(env16);
|
||||
register int argc asm("r12") = count;
|
||||
register char **argv asm("r13") = argarray;
|
||||
register char **envp asm("r14") = envarray;
|
||||
register long(*auxv)[2] asm("r15") = auxarray;
|
||||
asm volatile("jmp\t__executive"
|
||||
: /* no outputs */
|
||||
: "r"(argc), "r"(argv), "r"(envp), "r"(auxv)
|
||||
: "memory", "cc");
|
||||
unreachable;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue