mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 23:08:31 +00:00
Mint APE Loader v1.5
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
This commit is contained in:
parent
6843150e0c
commit
7e0a09feec
510 changed files with 1783 additions and 1483 deletions
|
@ -28,7 +28,7 @@ int __sigsetjmp_tail(sigjmp_buf jb, int rc) {
|
|||
sizeof(sigjmp_buf) == sizeof(jmp_buf) + 8 + 8 + sizeof(sigset_t),
|
||||
"please recompute sigjmp_buf w.r.t. sigset_t");
|
||||
void *p = (char *)jb + sizeof(jmp_buf) + 8 + 8;
|
||||
_npassert(!sigprocmask(SIG_SETMASK, rc ? p : 0, rc ? 0 : p));
|
||||
npassert(!sigprocmask(SIG_SETMASK, rc ? p : 0, rc ? 0 : p));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,11 +113,11 @@ int WinThreadLaunch(void *arg, // rdi
|
|||
// 2. windows owns the stack memory right now
|
||||
// we need win32 raw imports because:
|
||||
// 1. generated thunks are function logged
|
||||
noasan dontinstrument static textwindows wontreturn void //
|
||||
WinThreadEntry(int rdi, // rcx
|
||||
int rsi, // rdx
|
||||
int rdx, // r8
|
||||
struct CloneArgs *wt) { // r9
|
||||
dontasan dontinstrument static textwindows wontreturn void //
|
||||
WinThreadEntry(int rdi, // rcx
|
||||
int rsi, // rdx
|
||||
int rdx, // r8
|
||||
struct CloneArgs *wt) { // r9
|
||||
int rc;
|
||||
if (wt->tls) __set_tls_win32(wt->tls);
|
||||
*wt->ctid = wt->tid;
|
||||
|
@ -143,7 +143,7 @@ static textwindows errno_t CloneWindows(int (*func)(void *, int), char *stk,
|
|||
wt->func = func;
|
||||
wt->arg = arg;
|
||||
wt->tls = flags & CLONE_SETTLS ? tls : 0;
|
||||
if ((h = CreateThread(0, 4096, (void *)WinThreadEntry, wt, 0, &wt->utid))) {
|
||||
if ((h = CreateThread(0, 65536, (void *)WinThreadEntry, wt, 0, &wt->utid))) {
|
||||
CloseHandle(h);
|
||||
if (flags & CLONE_PARENT_SETTID) {
|
||||
*ptid = wt->tid;
|
||||
|
@ -216,7 +216,7 @@ static errno_t CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
|
|||
static bool once;
|
||||
struct CloneArgs *wt;
|
||||
if (!once) {
|
||||
_npassert(sys_bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) != -1);
|
||||
npassert(sys_bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) != -1);
|
||||
once = true;
|
||||
}
|
||||
wt = AllocateCloneArgs(stk, stksz);
|
||||
|
@ -286,7 +286,7 @@ static errno_t CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
|
|||
|
||||
// we can't use address sanitizer because:
|
||||
// 1. __asan_handle_no_return wipes stack [todo?]
|
||||
noasan static wontreturn void OpenbsdThreadMain(void *p) {
|
||||
dontasan static wontreturn void OpenbsdThreadMain(void *p) {
|
||||
struct CloneArgs *wt = p;
|
||||
*wt->ctid = wt->tid;
|
||||
wt->func(wt->arg, wt->tid);
|
||||
|
@ -325,7 +325,7 @@ static errno_t CloneOpenbsd(int (*func)(void *, int), char *stk, size_t stksz,
|
|||
tf->tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
||||
tf->tf_tid = &wt->tid;
|
||||
if ((rc = __tfork_thread(tf, sizeof(*tf), OpenbsdThreadMain, wt)) >= 0) {
|
||||
_npassert(rc);
|
||||
npassert(rc);
|
||||
if (flags & CLONE_PARENT_SETTID) {
|
||||
*ptid = rc;
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
|
|||
: CFLAG_CONSTRAINT(failed), "=a"(ax)
|
||||
: "1"(__NR_getcontext_netbsd), "D"(&netbsd_clone_template)
|
||||
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
|
||||
_npassert(!failed);
|
||||
npassert(!failed);
|
||||
once = true;
|
||||
}
|
||||
sp = (intptr_t)(stk + stksz);
|
||||
|
@ -425,7 +425,7 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
|
|||
: "1"(__NR__lwp_create), "D"(ctx), "S"(LWP_DETACHED), "2"(tid)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||
if (!failed) {
|
||||
_npassert(*tid);
|
||||
npassert(*tid);
|
||||
if (flags & CLONE_PARENT_SETTID) {
|
||||
*ptid = *tid;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ static void UnsetEnv(char **p, const char *k) {
|
|||
}
|
||||
|
||||
static void Append(int c) {
|
||||
_npassert(q + 1 < argbuf + sizeof(argbuf));
|
||||
npassert(q + 1 < argbuf + sizeof(argbuf));
|
||||
*q++ = c;
|
||||
}
|
||||
|
||||
|
@ -234,6 +234,54 @@ static int Echo(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int Cat(void) {
|
||||
int i, fd;
|
||||
ssize_t rc;
|
||||
char buf[512];
|
||||
if (n < 2) {
|
||||
for (;;) {
|
||||
rc = read(0, buf, sizeof(buf));
|
||||
if (rc == -1) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
if (!rc) break;
|
||||
rc = write(1, buf, rc);
|
||||
if (rc == -1) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if ((fd = open(args[i], O_RDONLY)) == -1) {
|
||||
perror(args[i]);
|
||||
return 1;
|
||||
}
|
||||
for (;;) {
|
||||
rc = read(fd, buf, sizeof(buf));
|
||||
if (rc == -1) {
|
||||
perror(args[i]);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (!rc) break;
|
||||
rc = write(1, buf, rc);
|
||||
if (rc == -1) {
|
||||
perror("write");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (close(fd)) {
|
||||
perror(args[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Read(void) {
|
||||
unsigned char c;
|
||||
int i, j, rc = 1;
|
||||
|
@ -522,6 +570,7 @@ static int TryBuiltin(void) {
|
|||
if (!strcmp(args[0], "cd")) return Cd();
|
||||
if (!strcmp(args[0], "rm")) return Rm();
|
||||
if (!strcmp(args[0], "[")) return Test();
|
||||
if (!strcmp(args[0], "cat")) return Cat();
|
||||
if (!strcmp(args[0], "env")) return Env();
|
||||
if (!strcmp(args[0], "exec")) return Exec();
|
||||
if (!strcmp(args[0], "wait")) return Wait();
|
||||
|
@ -562,14 +611,14 @@ static void Pipe(void) {
|
|||
_Exit(127);
|
||||
}
|
||||
if (!pid) {
|
||||
_unassert(dup2(pfds[1], 1) == 1);
|
||||
unassert(dup2(pfds[1], 1) == 1);
|
||||
// we can't rely on cloexec because builtins
|
||||
if (pfds[0] != 1) _unassert(!close(pfds[0]));
|
||||
if (pfds[1] != 1) _unassert(!close(pfds[1]));
|
||||
if (pfds[0] != 1) unassert(!close(pfds[0]));
|
||||
if (pfds[1] != 1) unassert(!close(pfds[1]));
|
||||
_Exit(ShellExec());
|
||||
}
|
||||
_unassert(!dup2(pfds[0], 0));
|
||||
if (pfds[1]) _unassert(!close(pfds[1]));
|
||||
unassert(!dup2(pfds[0], 0));
|
||||
if (pfds[1]) unassert(!close(pfds[1]));
|
||||
n = 0;
|
||||
}
|
||||
|
||||
|
@ -619,7 +668,7 @@ static const char *GetVar(const char *key) {
|
|||
} else if (key[0] == '?' && !key[1]) {
|
||||
return IntToStr(exitstatus);
|
||||
} else if (!strcmp(key, "PWD")) {
|
||||
_npassert(getcwd(vbuf, sizeof(vbuf)));
|
||||
npassert(getcwd(vbuf, sizeof(vbuf)));
|
||||
return vbuf;
|
||||
} else if (!strcmp(key, "UID")) {
|
||||
FormatInt32(vbuf, getuid());
|
||||
|
@ -644,14 +693,14 @@ static bool CopyVar(void) {
|
|||
size_t j;
|
||||
const char *s;
|
||||
if (IsVarName(*p)) {
|
||||
_npassert(vari + 1 < sizeof(var));
|
||||
npassert(vari + 1 < sizeof(var));
|
||||
var[vari++] = *p;
|
||||
var[vari] = 0;
|
||||
return false;
|
||||
}
|
||||
if ((s = GetVar(var))) {
|
||||
if ((j = strlen(s))) {
|
||||
_npassert(q + j < argbuf + sizeof(argbuf));
|
||||
npassert(q + j < argbuf + sizeof(argbuf));
|
||||
q = mempcpy(q, s, j);
|
||||
}
|
||||
}
|
||||
|
@ -855,7 +904,7 @@ int _cocmd(int argc, char **argv, char **envp) {
|
|||
int envi = 0;
|
||||
if (envp) {
|
||||
for (; envp[envi]; ++envi) {
|
||||
_npassert(envi + 1 < ARRAYLEN(envs));
|
||||
npassert(envi + 1 < ARRAYLEN(envs));
|
||||
envs[envi] = envp[envi];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,15 +52,15 @@ int daemon(int nochdir, int noclose) {
|
|||
}
|
||||
|
||||
if (!nochdir) {
|
||||
_unassert(!chdir("/"));
|
||||
unassert(!chdir("/"));
|
||||
}
|
||||
|
||||
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
|
||||
_unassert(dup2(fd, 0) == 0);
|
||||
_unassert(dup2(fd, 1) == 1);
|
||||
_unassert(dup2(fd, 2) == 2);
|
||||
unassert(dup2(fd, 0) == 0);
|
||||
unassert(dup2(fd, 1) == 1);
|
||||
unassert(dup2(fd, 2) == 2);
|
||||
if (fd > 2) {
|
||||
_unassert(!close(fd));
|
||||
unassert(!close(fd));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ static void EfiInitVga(struct mman *mm, EFI_SYSTEM_TABLE *SystemTable) {
|
|||
* So if you want to trade away Windows so that you can use
|
||||
* UEFI instead of the normal BIOS boot process, do this:
|
||||
*
|
||||
* STATIC_YOINK("EfiMain");
|
||||
* __static_yoink("EfiMain");
|
||||
* int main() { ... }
|
||||
*
|
||||
* You can use QEMU to test this, but please note that UEFI
|
||||
|
@ -141,8 +141,8 @@ static void EfiInitVga(struct mman *mm, EFI_SYSTEM_TABLE *SystemTable) {
|
|||
*
|
||||
* @see libc/dce.h
|
||||
*/
|
||||
__msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable) {
|
||||
__msabi dontasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable) {
|
||||
int type, x87cw = 0x037f;
|
||||
struct mman *mm;
|
||||
uint32_t DescVersion;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
extern int __threadcalls_end[] __attribute__((__weak__));
|
||||
extern int __threadcalls_start[] __attribute__((__weak__));
|
||||
|
||||
static privileged dontinline void FixupLockNops(void) {
|
||||
static privileged void FixupLockNops(void) {
|
||||
__morph_begin();
|
||||
/*
|
||||
* _NOPL("__threadcalls", func)
|
||||
|
|
|
@ -116,8 +116,8 @@ textstartup void __enable_tls(void) {
|
|||
// _tbss_start + _tbss_size:
|
||||
// _tdata_start + _tls_size:
|
||||
//
|
||||
_unassert(_tbss_start == _tdata_start + I(_tbss_offset));
|
||||
_unassert(_tbss_start + I(_tbss_size) == _tdata_start + I(_tls_size));
|
||||
unassert(_tbss_start == _tdata_start + I(_tbss_offset));
|
||||
unassert(_tbss_start + I(_tbss_size) == _tdata_start + I(_tls_size));
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
|
@ -130,12 +130,12 @@ textstartup void __enable_tls(void) {
|
|||
} else {
|
||||
// if this binary needs a hefty tls block then we'll bank on
|
||||
// malloc() being linked, which links _mapanon(). otherwise
|
||||
// if you exceed this, you need to STATIC_YOINK("_mapanon").
|
||||
// if you exceed this, you need to __static_yoink("_mapanon").
|
||||
// please note that it's probably too early to call calloc()
|
||||
_npassert(_weaken(_mapanon));
|
||||
npassert(_weaken(_mapanon));
|
||||
siz = ROUNDUP(siz, FRAMESIZE);
|
||||
mem = _weaken(_mapanon)(siz);
|
||||
_npassert(mem);
|
||||
npassert(mem);
|
||||
}
|
||||
|
||||
if (IsAsan()) {
|
||||
|
@ -154,10 +154,10 @@ textstartup void __enable_tls(void) {
|
|||
if (siz <= sizeof(__static_tls)) {
|
||||
mem = __static_tls;
|
||||
} else {
|
||||
_npassert(_weaken(_mapanon));
|
||||
npassert(_weaken(_mapanon));
|
||||
siz = ROUNDUP(siz, FRAMESIZE);
|
||||
mem = _weaken(_mapanon)(siz);
|
||||
_npassert(mem);
|
||||
npassert(mem);
|
||||
}
|
||||
|
||||
if (IsAsan()) {
|
||||
|
@ -205,7 +205,7 @@ textstartup void __enable_tls(void) {
|
|||
_pthread_main.tib = tib;
|
||||
_pthread_main.flags = PT_STATIC;
|
||||
_pthread_main.list.prev = _pthread_main.list.next = //
|
||||
_pthread_list = VEIL("r", &_pthread_main.list);
|
||||
_pthread_list = __veil("r", &_pthread_main.list);
|
||||
atomic_store_explicit(&_pthread_main.ptid, tid, memory_order_relaxed);
|
||||
|
||||
// copy in initialized data section
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
#ifdef __x86_64__
|
||||
|
||||
STATIC_YOINK("_check_sigchld");
|
||||
__static_yoink("_check_sigchld");
|
||||
|
||||
extern int64_t __wincrashearly;
|
||||
bool32 __onntconsoleevent_nt(uint32_t);
|
||||
|
@ -231,7 +231,7 @@ textwindows void WinMainForked(void) {
|
|||
|
||||
// rewrap the stdin named pipe hack
|
||||
// since the handles closed on fork
|
||||
struct Fds *fds = VEIL("r", &g_fds);
|
||||
struct Fds *fds = __veil("r", &g_fds);
|
||||
fds->p[0].handle = GetStdHandle(kNtStdInputHandle);
|
||||
fds->p[1].handle = GetStdHandle(kNtStdOutputHandle);
|
||||
fds->p[2].handle = GetStdHandle(kNtStdErrorHandle);
|
||||
|
|
|
@ -30,7 +30,7 @@ struct DosArgv {
|
|||
wint_t wc;
|
||||
};
|
||||
|
||||
textwindows noasan void DecodeDosArgv(int ignore, struct DosArgv *st) {
|
||||
textwindows dontasan void DecodeDosArgv(int ignore, struct DosArgv *st) {
|
||||
wint_t x, y;
|
||||
for (;;) {
|
||||
if (!(x = *st->s++)) break;
|
||||
|
@ -46,7 +46,7 @@ textwindows noasan void DecodeDosArgv(int ignore, struct DosArgv *st) {
|
|||
st->wc = x;
|
||||
}
|
||||
|
||||
static textwindows noasan void AppendDosArgv(wint_t wc, struct DosArgv *st) {
|
||||
static textwindows dontasan void AppendDosArgv(wint_t wc, struct DosArgv *st) {
|
||||
uint64_t w;
|
||||
w = _tpenc(wc);
|
||||
do {
|
||||
|
@ -55,7 +55,7 @@ static textwindows noasan void AppendDosArgv(wint_t wc, struct DosArgv *st) {
|
|||
} while (w >>= 8);
|
||||
}
|
||||
|
||||
static textwindows noasan int Count(int c, struct DosArgv *st) {
|
||||
static textwindows dontasan int Count(int c, struct DosArgv *st) {
|
||||
int ignore, n = 0;
|
||||
asm("" : "=g"(ignore));
|
||||
while (st->wc == c) {
|
||||
|
@ -82,8 +82,8 @@ static textwindows noasan int Count(int c, struct DosArgv *st) {
|
|||
// @see test/libc/dosarg_test.c
|
||||
// @see libc/runtime/ntspawn.c
|
||||
// @note kudos to Simon Tatham for figuring out quoting behavior
|
||||
textwindows noasan int GetDosArgv(const char16_t *cmdline, char *buf,
|
||||
size_t size, char **argv, size_t max) {
|
||||
textwindows dontasan int GetDosArgv(const char16_t *cmdline, char *buf,
|
||||
size_t size, char **argv, size_t max) {
|
||||
bool inquote;
|
||||
int i, argc, slashes, quotes, ignore;
|
||||
static struct DosArgv st_;
|
||||
|
|
|
@ -36,7 +36,7 @@ forceinline char *MemChr(const char *s, unsigned char c, unsigned long n) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static textwindows noasan dontinstrument axdx_t
|
||||
static textwindows dontasan dontinstrument axdx_t
|
||||
Recode16to8(char *dst, size_t dstsize, const char16_t *src) {
|
||||
bool v;
|
||||
axdx_t r;
|
||||
|
@ -70,7 +70,7 @@ Recode16to8(char *dst, size_t dstsize, const char16_t *src) {
|
|||
return r;
|
||||
}
|
||||
|
||||
textwindows dontinstrument noasan void FixPath(char *path) {
|
||||
textwindows dontinstrument dontasan void FixPath(char *path) {
|
||||
char *p;
|
||||
size_t i;
|
||||
|
||||
|
@ -110,9 +110,9 @@ textwindows dontinstrument noasan void FixPath(char *path) {
|
|||
// @param envp stores NULL-terminated string pointer list (optional)
|
||||
// @param max is the pointer count capacity of envp
|
||||
// @return number of variables decoded, excluding NULL-terminator
|
||||
textwindows noasan dontinstrument int GetDosEnviron(const char16_t *env,
|
||||
char *buf, size_t size,
|
||||
char **envp, size_t max) {
|
||||
textwindows dontasan dontinstrument int GetDosEnviron(const char16_t *env,
|
||||
char *buf, size_t size,
|
||||
char **envp, size_t max) {
|
||||
int i;
|
||||
char *p;
|
||||
axdx_t r;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
noasan size_t GetMemtrackSize(struct MemoryIntervals *mm) {
|
||||
dontasan size_t GetMemtrackSize(struct MemoryIntervals *mm) {
|
||||
size_t i, n;
|
||||
for (n = i = 0; i < mm->i; ++i) {
|
||||
n += ((size_t)(mm->p[i].y - mm->p[i].x) + 1) << 16;
|
||||
|
|
|
@ -27,7 +27,7 @@ extern struct SymbolTable *__symtab;
|
|||
* @param t if null will be auto-populated only if already open
|
||||
* @return index or -1 if nothing found
|
||||
*/
|
||||
dontinstrument privileged int __get_symbol(struct SymbolTable *t, intptr_t a) {
|
||||
privileged int __get_symbol(struct SymbolTable *t, intptr_t a) {
|
||||
// we need privileged because:
|
||||
// kprintf is privileged and it depends on this
|
||||
// we don't want function tracing because:
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
/**
|
||||
* Returns name of symbol at address.
|
||||
*/
|
||||
noasan char *GetSymbolByAddr(int64_t addr) {
|
||||
dontasan char *GetSymbolByAddr(int64_t addr) {
|
||||
/* asan runtime depends on this function */
|
||||
int i;
|
||||
struct SymbolTable *st;
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
||||
privileged dontinstrument noasan noubsan char *__get_symbol_name(
|
||||
struct SymbolTable *t, int s) {
|
||||
privileged char *__get_symbol_name(struct SymbolTable *t, int s) {
|
||||
/* asan runtime depends on this function */
|
||||
if (t && s != -1) {
|
||||
return t->name_base + t->names[s];
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/puff/puff.h"
|
||||
|
||||
STATIC_YOINK("__get_symbol");
|
||||
__static_yoink("__get_symbol");
|
||||
|
||||
static pthread_spinlock_t g_lock;
|
||||
struct SymbolTable *__symtab; // for kprintf
|
||||
|
@ -111,7 +111,7 @@ static struct SymbolTable *GetSymbolTableFromElf(void) {
|
|||
* This uses multiple strategies to find the symbol table. The first
|
||||
* strategy, depends on whether or not the following is linked:
|
||||
*
|
||||
* STATIC_YOINK("__zipos_get");
|
||||
* __static_yoink("__zipos_get");
|
||||
*
|
||||
* In that case, the symbol table may be read from `/zip/.symtab` which
|
||||
* is generated by `o//tool/build/symtab.com`. The second strategy is to
|
||||
|
|
|
@ -38,9 +38,9 @@ bool __grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
|
|||
size_t t1, t2;
|
||||
extra += GUARANTEE_TERMINATOR;
|
||||
p = (void **)pp;
|
||||
_unassert(itemsize);
|
||||
_unassert((*p && *capacity) || (!*p && !*capacity));
|
||||
_unassert(!_isheap(*p) || ((intptr_t)*p & 15) == 0);
|
||||
unassert(itemsize);
|
||||
unassert((*p && *capacity) || (!*p && !*capacity));
|
||||
unassert(!_isheap(*p) || ((intptr_t)*p & 15) == 0);
|
||||
p1 = _isheap(*p) ? *p : NULL;
|
||||
p2 = NULL;
|
||||
n1 = *capacity;
|
||||
|
|
|
@ -106,8 +106,7 @@ static privileged void HookFunction(code_t *func, void *dest) {
|
|||
* @param st can be obtained using `GetSymbolTable()`
|
||||
* @see ape/ape.lds
|
||||
*/
|
||||
privileged dontinstrument noasan int __hook(void *dest,
|
||||
struct SymbolTable *st) {
|
||||
privileged int __hook(void *dest, struct SymbolTable *st) {
|
||||
long i;
|
||||
code_t *p, *pe;
|
||||
intptr_t lowest;
|
||||
|
|
|
@ -48,8 +48,8 @@ int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t);
|
|||
bool __intercept_flag(int *, char *[], const char *);
|
||||
int sys_mprotect_nt(void *, size_t, int);
|
||||
int __inflate(void *, size_t, const void *, size_t);
|
||||
noasan void *_Mmap(void *, size_t, int, int, int, int64_t);
|
||||
noasan int _Munmap(char *, size_t);
|
||||
void *_Mmap(void *, size_t, int, int, int, int64_t) dontasan;
|
||||
int _Munmap(char *, size_t) dontasan;
|
||||
void __on_arithmetic_overflow(void);
|
||||
void __init_fds(void);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* @assume stack addresses are always greater than heap addresses
|
||||
* @assume stack memory isn't stored beneath %rsp (-mno-red-zone)
|
||||
*/
|
||||
optimizesize noasan bool _isheap(void *p) {
|
||||
optimizesize dontasan bool _isheap(void *p) {
|
||||
intptr_t x, y;
|
||||
x = kAutomapStart;
|
||||
y = x + kAutomapSize;
|
||||
|
|
|
@ -23,14 +23,14 @@
|
|||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
static inline noasan void *GetFrameAddr(int f) {
|
||||
static inline dontasan void *GetFrameAddr(int f) {
|
||||
intptr_t a;
|
||||
a = f;
|
||||
a *= FRAMESIZE;
|
||||
return (void *)a;
|
||||
}
|
||||
|
||||
noasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
|
||||
dontasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
|
||||
int i;
|
||||
for (i = l; i <= r; ++i) {
|
||||
UnmapViewOfFile(GetFrameAddr(mm->p[i].x));
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/directmap.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
@ -47,9 +46,11 @@
|
|||
#include "libc/stdckdint.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/ss.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -76,9 +77,9 @@ static wontreturn void OnUnrecoverableMmapError(const char *s) {
|
|||
_Exitr(199);
|
||||
}
|
||||
|
||||
static noasan inline bool OverlapsExistingMapping(char *p, size_t n) {
|
||||
static dontasan inline bool OverlapsExistingMapping(char *p, size_t n) {
|
||||
int a, b, i;
|
||||
_unassert(n > 0);
|
||||
unassert(n > 0);
|
||||
a = FRAME(p);
|
||||
b = FRAME(p + (n - 1));
|
||||
i = FindMemoryInterval(&_mmi, a);
|
||||
|
@ -90,10 +91,10 @@ static noasan inline bool OverlapsExistingMapping(char *p, size_t n) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
|
||||
static dontasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
|
||||
// TODO: improve performance
|
||||
int i, start, end;
|
||||
_unassert(align > 0);
|
||||
unassert(align > 0);
|
||||
if (_mmi.i) {
|
||||
|
||||
// find the start of the automap memory region
|
||||
|
@ -151,14 +152,14 @@ static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
|
|||
return false;
|
||||
}
|
||||
|
||||
noasan static bool Automap(int count, int align, int *res) {
|
||||
dontasan static bool Automap(int count, int align, int *res) {
|
||||
return ChooseMemoryInterval(FRAME(kAutomapStart), count, align, res) &&
|
||||
*res + count <= FRAME(kAutomapStart + (kAutomapSize - 1));
|
||||
}
|
||||
|
||||
static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n,
|
||||
struct DirectMap dm) {
|
||||
static dontasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n,
|
||||
struct DirectMap dm) {
|
||||
if (!IsWindows() && (flags & MAP_FIXED)) {
|
||||
if (UntrackMemoryIntervals(addr, size)) {
|
||||
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
||||
|
@ -177,8 +178,8 @@ static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags,
|
|||
return addr;
|
||||
}
|
||||
|
||||
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n) {
|
||||
static dontasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off, int f, int x, int n) {
|
||||
struct DirectMap dm;
|
||||
dm = sys_mmap(addr, size, prot, f, fd, off);
|
||||
if (VERY_UNLIKELY(dm.addr == MAP_FAILED)) {
|
||||
|
@ -200,17 +201,18 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
|||
* This is useful on Windows since it allows us to partially unmap or
|
||||
* punch holes into existing mappings.
|
||||
*/
|
||||
static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
|
||||
int prot, int flags,
|
||||
int fd, int64_t off,
|
||||
int f, int x, int n) {
|
||||
static textwindows dontinline dontasan void *MapMemories(char *addr,
|
||||
size_t size, int prot,
|
||||
int flags, int fd,
|
||||
int64_t off, int f,
|
||||
int x, int n) {
|
||||
size_t i, m;
|
||||
int64_t oi, sz;
|
||||
struct DirectMap dm;
|
||||
bool iscow, readonlyfile;
|
||||
m = (size_t)(n - 1) << 16;
|
||||
_unassert(m < size);
|
||||
_unassert(m + FRAMESIZE >= size);
|
||||
unassert(m < size);
|
||||
unassert(m + FRAMESIZE >= size);
|
||||
oi = fd == -1 ? 0 : off + m;
|
||||
sz = size - m;
|
||||
dm = sys_mmap(addr + m, sz, prot, f, fd, oi);
|
||||
|
@ -239,12 +241,13 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
|
|||
return addr;
|
||||
}
|
||||
|
||||
noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
||||
int64_t off) {
|
||||
dontasan inline void *_Mmap(void *addr, size_t size, int prot, int flags,
|
||||
int fd, int64_t off) {
|
||||
char *p = addr;
|
||||
struct DirectMap dm;
|
||||
int a, b, i, f, m, n, x;
|
||||
bool needguard, clashes;
|
||||
unsigned long guardsize;
|
||||
size_t virtualused, virtualneed;
|
||||
|
||||
if (VERY_UNLIKELY(!size)) {
|
||||
|
@ -332,6 +335,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
}
|
||||
|
||||
needguard = false;
|
||||
guardsize = getauxval(AT_PAGESZ);
|
||||
p = (char *)ADDR_32_TO_48(x);
|
||||
if ((f & MAP_TYPE) == MAP_STACK) {
|
||||
if (~f & MAP_ANONYMOUS) {
|
||||
|
@ -355,7 +359,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
// make sure there's no existing stuff existing between our stack
|
||||
// starting page and the bottom guard page, since that would stop
|
||||
// our stack page from growing down.
|
||||
_npassert(!sys_munmap(p, size));
|
||||
npassert(!sys_munmap(p, size));
|
||||
// by default MAP_GROWSDOWN will auto-allocate 10mb of pages. it's
|
||||
// supposed to stop growing if an adjacent allocation exists, to
|
||||
// prevent your stacks from overlapping on each other. we're not
|
||||
|
@ -367,12 +371,12 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
// however this 1mb behavior oddly enough is smart enough to not
|
||||
// apply if the mapping is a manually-created guard page.
|
||||
int e = errno;
|
||||
if ((dm = sys_mmap(p + size - APE_GUARDSIZE, APE_GUARDSIZE, prot,
|
||||
if ((dm = sys_mmap(p + size - SIGSTKSZ, SIGSTKSZ, prot,
|
||||
f | MAP_GROWSDOWN_linux, fd, off))
|
||||
.addr != MAP_FAILED) {
|
||||
_npassert(sys_mmap(p, APE_GUARDSIZE, PROT_NONE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
|
||||
.addr == p);
|
||||
npassert(sys_mmap(p, guardsize, PROT_NONE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
|
||||
.addr == p);
|
||||
dm.addr = p;
|
||||
return FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm);
|
||||
} else if (errno == ENOTSUP) {
|
||||
|
@ -398,11 +402,11 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
if (needguard) {
|
||||
if (!IsWindows()) {
|
||||
// make windows fork() code simpler
|
||||
mprotect(p, APE_GUARDSIZE, PROT_NONE);
|
||||
mprotect(p, guardsize, PROT_NONE);
|
||||
}
|
||||
if (IsAsan()) {
|
||||
__repstosb((void *)(((intptr_t)p >> 3) + 0x7fff8000),
|
||||
kAsanStackOverflow, APE_GUARDSIZE / 8);
|
||||
kAsanStackOverflow, guardsize / 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,15 +439,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
* - `MAP_PRIVATE` for copy-on-write behavior of writeable pages
|
||||
* - `MAP_SHARED` to create shared memory between processes
|
||||
* - `MAP_STACK` to create a grows-down alloc, where a guard page
|
||||
* is automatically protected at the bottom: FreeBSD's behavior
|
||||
* is polyfilled across platforms; uses MAP_GROWSDOWN on Linux
|
||||
* too for extra oomph (do not use MAP_GROWSDOWN!) and this is
|
||||
* completely mandatory on OpenBSD but helps perf elsewhere if
|
||||
* you need to create 10,000 threads. This flag is the reason
|
||||
* why `STACK_FRAME_UNLIMITED` toil is important, because this
|
||||
* only allocates a 4096-byte guard page, thus we need the GCC
|
||||
* compile-time checks to ensure some char[8192] vars will not
|
||||
* create an undetectable overflow into another thread's stack
|
||||
* is automatically protected at the bottom, sized as AT_PAGESZ
|
||||
* Your `flags` may optionally bitwise or any of the following:
|
||||
* - `MAP_ANONYMOUS` in which case `fd` and `off` are ignored
|
||||
* - `MAP_FIXED` in which case `addr` becomes more than a hint
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
noasan textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
|
||||
dontasan textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
|
||||
int i, rc = 0;
|
||||
char *a, *b, *x, *y;
|
||||
__mmi_lock();
|
||||
|
|
|
@ -43,7 +43,7 @@ int msync(void *addr, size_t size, int flags) {
|
|||
int rc;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
|
||||
_unassert(((flags & MS_SYNC) ^ (flags & MS_ASYNC)) || !(MS_SYNC && MS_ASYNC));
|
||||
unassert(((flags & MS_SYNC) ^ (flags & MS_ASYNC)) || !(MS_SYNC && MS_ASYNC));
|
||||
if (!IsWindows()) {
|
||||
rc = sys_msync(addr, size, flags);
|
||||
} else {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
|
||||
|
||||
static noasan void MunmapShadow(char *p, size_t n) {
|
||||
static dontasan void MunmapShadow(char *p, size_t n) {
|
||||
intptr_t a, b, x, y;
|
||||
KERNTRACE("MunmapShadow(%p, %'zu)", p, n);
|
||||
a = ((intptr_t)p >> 3) + 0x7fff8000;
|
||||
|
@ -66,7 +66,7 @@ static noasan void MunmapShadow(char *p, size_t n) {
|
|||
// our api supports doing things like munmap(0, 0x7fffffffffff) but some
|
||||
// platforms (e.g. openbsd) require that we know the specific intervals
|
||||
// or else it returns EINVAL. so we munmap a piecewise.
|
||||
static noasan void MunmapImpl(char *p, size_t n) {
|
||||
static dontasan void MunmapImpl(char *p, size_t n) {
|
||||
char *q;
|
||||
size_t m;
|
||||
intptr_t a, b, c;
|
||||
|
@ -102,7 +102,7 @@ static noasan void MunmapImpl(char *p, size_t n) {
|
|||
q = (char *)a;
|
||||
m = MIN(b, c) - a;
|
||||
if (!IsWindows()) {
|
||||
_npassert(!sys_munmap(q, m));
|
||||
npassert(!sys_munmap(q, m));
|
||||
} else {
|
||||
// Handled by UntrackMemoryIntervals() on Windows
|
||||
}
|
||||
|
@ -112,11 +112,11 @@ static noasan void MunmapImpl(char *p, size_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
noasan int _Munmap(char *p, size_t n) {
|
||||
dontasan int _Munmap(char *p, size_t n) {
|
||||
unsigned i;
|
||||
char poison;
|
||||
intptr_t a, b, x, y;
|
||||
_unassert(!__vforked);
|
||||
unassert(!__vforked);
|
||||
if (UNLIKELY(!n)) {
|
||||
STRACE("munmap n is 0");
|
||||
return einval();
|
||||
|
|
|
@ -63,8 +63,8 @@
|
|||
#include "tool/decode/lib/idname.h"
|
||||
#include "tool/decode/lib/x86idnames.h"
|
||||
|
||||
STATIC_YOINK("strerror"); // for kprintf()
|
||||
STATIC_YOINK("strsignal"); // for kprintf()
|
||||
__static_yoink("strerror"); // for kprintf()
|
||||
__static_yoink("strsignal"); // for kprintf()
|
||||
|
||||
#define PRINT(FMT, ...) \
|
||||
do { \
|
||||
|
@ -72,49 +72,6 @@ STATIC_YOINK("strsignal"); // for kprintf()
|
|||
kprintf(FMT "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static const struct AuxiliaryValue {
|
||||
const char *fmt;
|
||||
long *id;
|
||||
const char *name;
|
||||
} kAuxiliaryValues[] = {
|
||||
{"%-14p", &AT_EXECFD, "AT_EXECFD"},
|
||||
{"%-14p", &AT_PHDR, "AT_PHDR"},
|
||||
{"%-14p", &AT_PHENT, "AT_PHENT"},
|
||||
{"%-14p", &AT_PHNUM, "AT_PHNUM"},
|
||||
{"%-14p", &AT_PAGESZ, "AT_PAGESZ"},
|
||||
{"%-14p", &AT_BASE, "AT_BASE"},
|
||||
{"%-14p", &AT_ENTRY, "AT_ENTRY"},
|
||||
{"%-14p", &AT_NOTELF, "AT_NOTELF"},
|
||||
{"%-14d", &AT_UID, "AT_UID"},
|
||||
{"%-14d", &AT_EUID, "AT_EUID"},
|
||||
{"%-14d", &AT_GID, "AT_GID"},
|
||||
{"%-14d", &AT_EGID, "AT_EGID"},
|
||||
{"%-14d", &AT_CLKTCK, "AT_CLKTCK"},
|
||||
{"%-14d", &AT_OSRELDATE, "AT_OSRELDATE"},
|
||||
{"%-14p", &AT_PLATFORM, "AT_PLATFORM"},
|
||||
{"%-14p", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE"},
|
||||
{"%-14p", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE"},
|
||||
{"%-14p", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE"},
|
||||
{"%-14p", &AT_SECURE, "AT_SECURE"},
|
||||
{"%-14s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM"},
|
||||
{"%-14p", &AT_RANDOM, "AT_RANDOM"},
|
||||
{"%-14s", &AT_EXECFN, "AT_EXECFN"},
|
||||
{"%-14p", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR"},
|
||||
{"%-14p", &AT_FLAGS, "AT_FLAGS"},
|
||||
{"%-14p", &AT_HWCAP, "AT_HWCAP"},
|
||||
{"%-14p", &AT_HWCAP2, "AT_HWCAP2"},
|
||||
{"%-14p", &AT_STACKBASE, "AT_STACKBASE"},
|
||||
{"%-14p", &AT_CANARY, "AT_CANARY"},
|
||||
{"%-14p", &AT_CANARYLEN, "AT_CANARYLEN"},
|
||||
{"%-14ld", &AT_NCPUS, "AT_NCPUS"},
|
||||
{"%-14p", &AT_PAGESIZES, "AT_PAGESIZES"},
|
||||
{"%-14d", &AT_PAGESIZESLEN, "AT_PAGESIZESLEN"},
|
||||
{"%-14p", &AT_TIMEKEEP, "AT_TIMEKEEP"},
|
||||
{"%-14p", &AT_STACKPROT, "AT_STACKPROT"},
|
||||
{"%-14p", &AT_EHDRFLAGS, "AT_EHDRFLAGS"},
|
||||
{"%-14d", &AT_MINSIGSTKSZ, "AT_MINSIGSTKSZ"},
|
||||
};
|
||||
|
||||
static const char *FindNameById(const struct IdName *names, unsigned long id) {
|
||||
for (; names->name; names++) {
|
||||
if (names->id == id) {
|
||||
|
@ -124,17 +81,7 @@ static const char *FindNameById(const struct IdName *names, unsigned long id) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
|
||||
if (*kAuxiliaryValues[i].id && x == *kAuxiliaryValues[i].id) {
|
||||
return kAuxiliaryValues + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static noasan void PrintDependencies(const char *prologue) {
|
||||
static dontasan void PrintDependencies(const char *prologue) {
|
||||
struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
|
||||
struct NtLinkedList *ldr = head->Next;
|
||||
do {
|
||||
|
@ -145,7 +92,7 @@ static noasan void PrintDependencies(const char *prologue) {
|
|||
} while ((ldr = ldr->Next) && ldr != head);
|
||||
}
|
||||
|
||||
static noasan void Print(const char *prologue) {
|
||||
static dontasan void Print(const char *prologue) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,6 +105,50 @@ static noasan void Print(const char *prologue) {
|
|||
* @param prologue needs to be a .rodata kprintf string
|
||||
*/
|
||||
textstartup void __printargs(const char *prologue) {
|
||||
|
||||
const struct AuxiliaryValue {
|
||||
const char *fmt;
|
||||
unsigned long id;
|
||||
const char *name;
|
||||
} kAuxiliaryValues[] = {
|
||||
{"%-14p", AT_EXECFD, "AT_EXECFD"},
|
||||
{"%-14p", AT_PHDR, "AT_PHDR"},
|
||||
{"%-14p", AT_PHENT, "AT_PHENT"},
|
||||
{"%-14p", AT_PHNUM, "AT_PHNUM"},
|
||||
{"%-14p", AT_PAGESZ, "AT_PAGESZ"},
|
||||
{"%-14p", AT_BASE, "AT_BASE"},
|
||||
{"%-14p", AT_ENTRY, "AT_ENTRY"},
|
||||
{"%-14p", AT_NOTELF, "AT_NOTELF"},
|
||||
{"%-14d", AT_UID, "AT_UID"},
|
||||
{"%-14d", AT_EUID, "AT_EUID"},
|
||||
{"%-14d", AT_GID, "AT_GID"},
|
||||
{"%-14d", AT_EGID, "AT_EGID"},
|
||||
{"%-14d", AT_CLKTCK, "AT_CLKTCK"},
|
||||
{"%-14d", AT_OSRELDATE, "AT_OSRELDATE"},
|
||||
{"%-14p", AT_PLATFORM, "AT_PLATFORM"},
|
||||
{"%-14p", AT_DCACHEBSIZE, "AT_DCACHEBSIZE"},
|
||||
{"%-14p", AT_ICACHEBSIZE, "AT_ICACHEBSIZE"},
|
||||
{"%-14p", AT_UCACHEBSIZE, "AT_UCACHEBSIZE"},
|
||||
{"%-14p", AT_SECURE, "AT_SECURE"},
|
||||
{"%-14s", AT_BASE_PLATFORM, "AT_BASE_PLATFORM"},
|
||||
{"%-14p", AT_RANDOM, "AT_RANDOM"},
|
||||
{"%-14s", AT_EXECFN, "AT_EXECFN"},
|
||||
{"%-14p", AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR"},
|
||||
{"%-14p", AT_FLAGS, "AT_FLAGS"},
|
||||
{"%-14p", AT_HWCAP, "AT_HWCAP"},
|
||||
{"%-14p", AT_HWCAP2, "AT_HWCAP2"},
|
||||
{"%-14p", AT_STACKBASE, "AT_STACKBASE"},
|
||||
{"%-14p", AT_CANARY, "AT_CANARY"},
|
||||
{"%-14p", AT_CANARYLEN, "AT_CANARYLEN"},
|
||||
{"%-14ld", AT_NCPUS, "AT_NCPUS"},
|
||||
{"%-14p", AT_PAGESIZES, "AT_PAGESIZES"},
|
||||
{"%-14d", AT_PAGESIZESLEN, "AT_PAGESIZESLEN"},
|
||||
{"%-14p", AT_TIMEKEEP, "AT_TIMEKEEP"},
|
||||
{"%-14p", AT_STACKPROT, "AT_STACKPROT"},
|
||||
{"%-14p", AT_EHDRFLAGS, "AT_EHDRFLAGS"},
|
||||
{"%-14d", AT_MINSIGSTKSZ, "AT_MINSIGSTKSZ"},
|
||||
};
|
||||
|
||||
long key;
|
||||
char **env;
|
||||
sigset_t ss;
|
||||
|
@ -412,7 +403,14 @@ textstartup void __printargs(const char *prologue) {
|
|||
if (*__auxv) {
|
||||
if (*__auxv) {
|
||||
for (auxp = __auxv; *auxp; auxp += 2) {
|
||||
if ((auxinfo = DescribeAuxv(auxp[0]))) {
|
||||
auxinfo = 0;
|
||||
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
|
||||
if (kAuxiliaryValues[i].id && auxp[0] == kAuxiliaryValues[i].id) {
|
||||
auxinfo = kAuxiliaryValues + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (auxinfo) {
|
||||
ksnprintf(u.path, sizeof(u.path), auxinfo->fmt, auxp[1]);
|
||||
PRINT(" ☼ %16s[%4ld] = %s", auxinfo->name, auxp[0], u.path);
|
||||
} else {
|
||||
|
|
|
@ -130,8 +130,7 @@ o/$(MODE)/libc/runtime/morph_tls.o: private \
|
|||
CFLAGS += \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector \
|
||||
-fpatchable-function-entry=0,0
|
||||
-fno-stack-protector
|
||||
|
||||
# TODO(jart): We need a way to avoid WinThreadEntry() being hooked.
|
||||
o/$(MODE)/libc/runtime/clone.o: private \
|
||||
|
|
|
@ -36,7 +36,7 @@ textstartup void __set_tls(struct CosmoTib *tib) {
|
|||
int ax, dx;
|
||||
if (IsWindows()) {
|
||||
__tls_index = TlsAlloc();
|
||||
_npassert(0 <= __tls_index && __tls_index < 64);
|
||||
npassert(0 <= __tls_index && __tls_index < 64);
|
||||
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
|
||||
} else if (IsFreebsd()) {
|
||||
sys_set_tls(129 /*AMD64_SET_FSBASE*/, tib);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* If you want to know how much stack your programs needs, then
|
||||
*
|
||||
* STATIC_YOINK("stack_usage_logging");
|
||||
* __static_yoink("stack_usage_logging");
|
||||
*
|
||||
* will install an atexit() handler that appends to `o/$MODE/stack.log`
|
||||
*
|
||||
|
@ -125,7 +125,7 @@ extern char ape_stack_align[] __attribute__((__weak__));
|
|||
* Returns true if at least `n` bytes of stack are available.
|
||||
*/
|
||||
#define HaveStackMemory(n) \
|
||||
((intptr_t)__builtin_frame_address(0) >= GetStackAddr() + APE_GUARDSIZE + (n))
|
||||
((intptr_t)__builtin_frame_address(0) >= GetStackAddr() + 16384 + (n))
|
||||
|
||||
forceinline void CheckLargeStackAllocation(void *p, ssize_t n) {
|
||||
for (; n > 0; n -= 4096) {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static char stacklog[1024];
|
||||
|
||||
noasan size_t GetStackUsage(char *s, size_t n) {
|
||||
dontasan size_t GetStackUsage(char *s, size_t n) {
|
||||
// RHEL5 MAP_GROWSDOWN seems to only grow to 68kb :'(
|
||||
// So we count non-zero bytes down from the top
|
||||
// First clear 64 bytes is considered the end
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
int UntrackMemoryIntervals(void *addr, size_t size) {
|
||||
int a, b;
|
||||
_unassert(size > 0);
|
||||
unassert(size > 0);
|
||||
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||
return ReleaseMemoryIntervals(&_mmi, a, b,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue