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:
Justine Tunney 2023-07-26 13:54:49 -07:00
parent 6843150e0c
commit 7e0a09feec
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
510 changed files with 1783 additions and 1483 deletions

View file

@ -18,8 +18,8 @@ void __assert_fail(const char *, const char *, int) relegated;
#ifdef COSMO
extern bool __assert_disable;
#ifndef NDEBUG
#define _unassert(x) __assert_macro(x, #x)
#define _npassert(x) __assert_macro(x, #x)
#define unassert(x) __assert_macro(x, #x)
#define npassert(x) __assert_macro(x, #x)
#define __assert_macro(x, s) \
({ \
if (__builtin_expect(!(x), 0)) { \
@ -29,14 +29,14 @@ extern bool __assert_disable;
(void)0; \
})
#else
#define _npassert(x) \
#define npassert(x) \
({ \
if (__builtin_expect(!(x), 0)) { \
__builtin_trap(); \
} \
(void)0; \
})
#define _unassert(x) \
#define unassert(x) \
({ \
if (__builtin_expect(!(x), 0)) { \
__builtin_unreachable(); \

View file

@ -35,7 +35,7 @@ unsigned alarm(unsigned seconds) {
struct itimerval it;
bzero(&it, sizeof(it));
it.it_value.tv_sec = seconds;
_npassert(!setitimer(ITIMER_REAL, &it, &it));
npassert(!setitimer(ITIMER_REAL, &it, &it));
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
return 0;
} else {

View file

@ -80,11 +80,11 @@ static struct timespec GetNanosleepLatency(void) {
if (!(nanos = g_nanosleep_latency)) {
BLOCK_CANCELLATIONS;
for (cgt = __clock_gettime_get(0);;) {
_npassert(!cgt(CLOCK_REALTIME_PRECISE, &x));
npassert(!cgt(CLOCK_REALTIME_PRECISE, &x));
rc = sys_clock_nanosleep(CLOCK_REALTIME, 0, &w, 0);
_npassert(!rc || rc == EINTR);
npassert(!rc || rc == EINTR);
if (!rc) {
_npassert(!cgt(CLOCK_REALTIME_PRECISE, &y));
npassert(!cgt(CLOCK_REALTIME_PRECISE, &y));
nanos = timespec_tonanos(timespec_sub(y, x));
g_nanosleep_latency = nanos;
break;
@ -115,10 +115,10 @@ static errno_t SpinNanosleep(int clock, int flags, const struct timespec *req,
return rc;
}
cgt = __clock_gettime_get(0);
_npassert(!cgt(CLOCK_REALTIME, &start));
npassert(!cgt(CLOCK_REALTIME, &start));
for (;;) {
sched_yield();
_npassert(!cgt(CLOCK_REALTIME, &now));
npassert(!cgt(CLOCK_REALTIME, &now));
if (flags & TIMER_ABSTIME) {
if (timespec_cmp(now, *req) >= 0) {
return 0;

View file

@ -31,7 +31,7 @@
// Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
int64_t rc, proc, handle;
_unassert(!(flags & ~O_CLOEXEC));
unassert(!(flags & ~O_CLOEXEC));
__fds_lock();

View file

@ -45,9 +45,9 @@ static void sys_dup3_test(void) {
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
int how;
_unassert(oldfd >= 0);
_unassert(newfd >= 0);
_unassert(!(flags & ~O_CLOEXEC));
unassert(oldfd >= 0);
unassert(newfd >= 0);
unassert(!(flags & ~O_CLOEXEC));
if (IsFreebsd()) {
if (flags & O_CLOEXEC) {

View file

@ -85,8 +85,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
(CanExecute((ape = "/usr/bin/ape")) ||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
firstnonnull(getenv("HOME"), ".")),
".ape-1.4", buf))) ||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.4",
".ape-1.5", buf))) ||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.5",
buf))))) {
shargs[0] = ape;
shargs[1] = "-";

View file

@ -52,7 +52,7 @@ int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
} else {
rc = sys_fadvise_netbsd(fd, offset, offset, len, advice);
}
_npassert(rc >= 0);
npassert(rc >= 0);
if (rc) {
errno = rc;
rc = -1;

View file

@ -158,7 +158,7 @@ static int fd_to_mem_fd(const int infd, char *path) {
if (path) {
FormatInt32(stpcpy(path, "COSMOPOLITAN_INIT_ZIPOS="), fd);
}
_unassert(readRc == st.st_size);
unassert(readRc == st.st_size);
return fd;
} else if (!success) {
errno = e;

View file

@ -29,12 +29,12 @@ int __fixupnewfd(int fd, int flags) {
int file_mode;
if (fd != -1) {
if (flags & O_CLOEXEC) {
_unassert((file_mode = __sys_fcntl(fd, F_GETFD)) != -1);
_unassert(!__sys_fcntl(fd, F_SETFD, file_mode | FD_CLOEXEC));
unassert((file_mode = __sys_fcntl(fd, F_GETFD)) != -1);
unassert(!__sys_fcntl(fd, F_SETFD, file_mode | FD_CLOEXEC));
}
if (flags & O_NONBLOCK) {
_unassert((file_mode = __sys_fcntl(fd, F_GETFL)) != -1);
_unassert(!__sys_fcntl(fd, F_SETFL, file_mode | O_NONBLOCK));
unassert((file_mode = __sys_fcntl(fd, F_GETFL)) != -1);
unassert(!__sys_fcntl(fd, F_SETFL, file_mode | O_NONBLOCK));
}
}
return fd;

View file

@ -31,7 +31,7 @@ textwindows int sys_ftruncate_nt(int64_t handle, uint64_t length) {
if ((ok = SetFilePointerEx(handle, 0, &tell, kNtFileCurrent))) {
ok = SetFilePointerEx(handle, length, NULL, kNtFileBegin) &&
SetEndOfFile(handle);
_npassert(SetFilePointerEx(handle, tell, NULL, kNtFileBegin));
npassert(SetFilePointerEx(handle, tell, NULL, kNtFileBegin));
}
if (ok) {
return 0;

View file

@ -52,7 +52,7 @@ char *getcwd(char *buf, size_t size) {
return 0;
}
} else if (_weaken(malloc)) {
_unassert(!__vforked);
unassert(!__vforked);
if (!size) size = PATH_MAX;
if (!(p = _weaken(malloc)(size))) {
STRACE("getcwd(%p, %'zu) %m", buf, size);
@ -60,7 +60,7 @@ char *getcwd(char *buf, size_t size) {
}
} else {
einval();
STRACE("getcwd() needs buf≠0 or STATIC_YOINK(\"malloc\")");
STRACE("getcwd() needs buf≠0 or __static_yoink(\"malloc\")");
return 0;
}
*p = '\0';

View file

@ -44,7 +44,7 @@ int getppid(void) {
} else {
rc = sys_getppid_nt();
}
_npassert(rc >= 0);
npassert(rc >= 0);
STRACE("%s() → %d", "getppid", rc);
return rc;
}

View file

@ -63,7 +63,7 @@ uint32_t getuid(void) {
} else {
rc = GetUserNameHash();
}
_npassert(rc >= 0);
npassert(rc >= 0);
STRACE("%s() → %d", "getuid", rc);
return rc;
}
@ -88,7 +88,7 @@ uint32_t getgid(void) {
} else {
rc = GetUserNameHash();
}
_npassert(rc >= 0);
npassert(rc >= 0);
STRACE("%s() → %d", "getgid", rc);
return rc;
}

View file

@ -291,7 +291,7 @@ static textwindows int createHostInfo(
char name[IFNAMSIZ];
int count, i;
/* __hostInfo must be empty */
_unassert(__hostInfo == NULL);
unassert(__hostInfo == NULL);
for (aa = firstAdapter; aa; aa = aa->Next) {
/* Skip all the interfaces with no address and the ones that are not AF_INET
*/

View file

@ -47,12 +47,12 @@
#define MAP_FIXED_linux 0x00000010
#define MAP_SHARED_linux 0x00000001
STATIC_YOINK("_init_metalfile");
__static_yoink("_init_metalfile");
void *__ape_com_base;
size_t __ape_com_size = 0;
textstartup noasan void InitializeMetalFile(void) {
textstartup dontasan void InitializeMetalFile(void) {
if (IsMetal()) {
/*
* Copy out a pristine image of the program before the program might
@ -61,7 +61,7 @@ textstartup noasan void InitializeMetalFile(void) {
* This code is included if a symbol "file:/proc/self/exe" is defined
* (see libc/calls/metalfile.internal.h & libc/calls/metalfile_init.S).
* The zipos code will automatically arrange to do this. Alternatively,
* user code can STATIC_YOINK this symbol.
* user code can __static_yoink this symbol.
*/
size_t size = ROUNDUP(_ezip - __executable_start, 4096);
// TODO(jart): Restore support for ZIPOS on metal.
@ -70,7 +70,7 @@ textstartup noasan void InitializeMetalFile(void) {
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
copied_base = dm.addr;
_npassert(copied_base != (void *)-1);
npassert(copied_base != (void *)-1);
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
__ape_com_base = copied_base;
__ape_com_size = size;

View file

@ -20,7 +20,7 @@
#include "libc/runtime/pc.internal.h"
#ifdef __x86_64__
noasan int sys_munmap_metal(void *addr, size_t size) {
dontasan int sys_munmap_metal(void *addr, size_t size) {
size_t i;
uint64_t *e, paddr;
struct mman *mm = __get_mm();

View file

@ -92,7 +92,7 @@ static long double nowl_art(void) {
static long double nowl_vdso(void) {
long double secs;
struct timespec tv;
_unassert(__gettime);
unassert(__gettime);
__gettime(CLOCK_REALTIME_PRECISE, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9L;

View file

@ -53,7 +53,7 @@ static textwindows int sys_open_nt_console(int dirfd,
-1) {
g_fds.p[fd].extra = sys_open_nt_impl(dirfd, mp->conout,
(flags & ~O_ACCMODE) | O_WRONLY, mode);
_npassert(g_fds.p[fd].extra != -1);
npassert(g_fds.p[fd].extra != -1);
} else {
return -1;
}

View file

@ -54,7 +54,7 @@
*
* If your main() source file has this statement:
*
* STATIC_YOINK("zipos");
* __static_yoink("zipos");
*
* Then you can read zip assets by adding a `"/zip/..."` prefix to `file`, e.g.
*

View file

@ -66,8 +66,8 @@ static int openpty_impl(int *mfd, int *sfd, char *name,
*mfd = m;
*sfd = s;
if (name) strcpy(name, t.sname);
if (tio) _npassert(!tcsetattr(s, TCSAFLUSH, tio));
if (wsz) _npassert(!tcgetwinsize(s, wsz));
if (tio) npassert(!tcsetattr(s, TCSAFLUSH, tio));
if (wsz) npassert(!tcgetwinsize(s, wsz));
return 0;
OnError:
if (m != -1) sys_close(m);

View file

@ -51,10 +51,10 @@ errno_t posix_fadvise(int fd, int64_t offset, int64_t len, int advice) {
rc = sys_fadvise(fd, offset, len, advice);
} else if (IsFreebsd()) {
rc = sys_fadvise(fd, offset, len, advice);
_unassert(rc >= 0);
unassert(rc >= 0);
} else if (IsNetbsd()) {
rc = sys_fadvise_netbsd(fd, offset, offset, len, advice);
_unassert(rc >= 0);
unassert(rc >= 0);
} else if (IsWindows()) {
rc = sys_fadvise_nt(fd, offset, len, advice);
} else {

View file

@ -76,7 +76,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
} else {
rc = ebadf();
}
_npassert(rc == -1 || (size_t)rc <= size);
npassert(rc == -1 || (size_t)rc <= size);
END_CANCELLATION_POINT;
DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,

View file

@ -69,9 +69,9 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
if (rc != -1) {
wrote = (size_t)rc;
if (!wrote) {
_npassert(size == 0);
npassert(size == 0);
} else {
_npassert(wrote <= size);
npassert(wrote <= size);
}
}

View file

@ -31,7 +31,7 @@ static textwindows inline bool HasWorkingConsole(void) {
return !!(__ntconsolemode[0] | __ntconsolemode[1] | __ntconsolemode[2]);
}
static noubsan void RaiseSigFpe(void) {
static dontubsan void RaiseSigFpe(void) {
volatile int x = 0;
x = 1 / x;
}

View file

@ -81,7 +81,7 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
if (ok) ok = GetOverlappedResult(fd->handle, &overlap, &got, true);
// restore file pointer which windows clobbers, even on error
_unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET));
unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET));
}
if (ok) {
return got;

View file

@ -181,7 +181,7 @@ skip_readlink:
continue;
}
k = rc;
_npassert(k <= p);
npassert(k <= p);
if (k==p)
goto toolong;
if (!k) {

View file

@ -49,13 +49,13 @@
#include "libc/sysv/errfuns.h"
#ifdef SYSDEBUG
STATIC_YOINK("strsignal"); // for kprintf()
__static_yoink("strsignal"); // for kprintf()
#endif
#if SupportsWindows()
STATIC_YOINK("_init_onntconsoleevent");
STATIC_YOINK("_check_sigwinch");
STATIC_YOINK("_init_wincrash");
__static_yoink("_init_onntconsoleevent");
__static_yoink("_check_sigwinch");
__static_yoink("_init_wincrash");
#endif
#define SA_RESTORER 0x04000000

View file

@ -28,7 +28,7 @@ sigset_t _sigsetmask(sigset_t neu) {
if (IsMetal() || IsWindows()) {
__sig_mask(SIG_SETMASK, &neu, &res);
} else {
_npassert(!sys_sigprocmask(SIG_SETMASK, &neu, &res));
npassert(!sys_sigprocmask(SIG_SETMASK, &neu, &res));
}
return res;
}

View file

@ -42,7 +42,7 @@ unsigned sleep(unsigned seconds) {
struct timespec tv = {seconds};
if (!(rc = clock_nanosleep(CLOCK_REALTIME, 0, &tv, &tv))) return 0;
if (rc == ECANCELED) return -1u;
_npassert(rc == EINTR);
npassert(rc == EINTR);
unslept = tv.tv_sec;
if (tv.tv_nsec && unslept < UINT_MAX) {
++unslept;

View file

@ -29,6 +29,6 @@
*/
struct timespec timespec_mono(void) {
struct timespec ts;
_npassert(!clock_gettime(CLOCK_MONOTONIC, &ts));
npassert(!clock_gettime(CLOCK_MONOTONIC, &ts));
return ts;
}

View file

@ -31,6 +31,6 @@
*/
struct timespec timespec_real(void) {
struct timespec ts;
_npassert(!clock_gettime(CLOCK_REALTIME, &ts));
npassert(!clock_gettime(CLOCK_REALTIME, &ts));
return ts;
}

View file

@ -34,7 +34,7 @@ struct timespec timespec_sleep(struct timespec delay) {
BLOCK_CANCELLATIONS;
bzero(&remain, sizeof(remain));
if ((rc = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
_npassert(rc == EINTR);
npassert(rc == EINTR);
}
ALLOW_CANCELLATIONS;
return remain;

View file

@ -33,6 +33,6 @@
errno_t timespec_sleep_until(struct timespec abs_deadline) {
errno_t rc;
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
_npassert(!rc || rc == EINTR || rc == ECANCELED);
npassert(!rc || rc == EINTR || rc == ECANCELED);
return rc;
}

View file

@ -26,6 +26,6 @@
*/
struct timeval timeval_real(void) {
struct timeval tv;
_npassert(!gettimeofday(&tv, 0));
npassert(!gettimeofday(&tv, 0));
return tv;
}

View file

@ -76,15 +76,15 @@ static textwindows void GetNtName(char *name, int kind) {
}
}
static inline textwindows noasan int GetNtMajorVersion(void) {
static inline textwindows dontasan int GetNtMajorVersion(void) {
return NtGetPeb()->OSMajorVersion;
}
static inline textwindows noasan int GetNtMinorVersion(void) {
static inline textwindows dontasan int GetNtMinorVersion(void) {
return NtGetPeb()->OSMinorVersion;
}
static inline textwindows noasan int GetNtBuildNumber(void) {
static inline textwindows dontasan int GetNtBuildNumber(void) {
return NtGetPeb()->OSBuildNumber;
}

View file

@ -473,10 +473,10 @@ int unveil(const char *path, const char *permissions) {
if (permissions) return einval();
if (IsOpenbsd()) return 0;
if (landlock_abi_version != -1) {
_unassert(landlock_abi_version >= 1);
unassert(landlock_abi_version >= 1);
return landlock_abi_version;
} else {
_unassert(landlock_abi_errno);
unassert(landlock_abi_errno);
errno = landlock_abi_errno;
return -1;
}

View file

@ -60,7 +60,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
if (ok) ok = GetOverlappedResult(handle, &overlap, &sent, true);
// restore file pointer which windows clobbers, even on error
_unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
}
if (ok) {
return sent;

View file

@ -55,6 +55,6 @@
* @see unbing() for inverse
*/
int bing(int b, int intent) {
_unassert(0 <= b && b < 256);
unassert(0 <= b && b < 256);
return kCp437[b & 0xff];
}

View file

@ -21,7 +21,7 @@
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
char *p;
_unassert(k <= 64 && !(k & 3));
unassert(k <= 64 && !(k & 3));
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
*p = '\0';
return p - b;

View file

@ -194,19 +194,22 @@ typedef struct {
#endif
#ifndef privileged
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__visibility__) || defined(__GNUC__))
#define privileged _Section(".privileged")
#else
#define privileged _Section(".privileged")
#endif
#define privileged \
_Section(".privileged") dontinline dontinstrument dontubsan dontasan
#endif
#ifndef dontinstrument
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__no_instrument_function__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204)
#if ((__GNUC__ + 0) >= 7 && !defined(__chibicc__)) || \
__has_attribute(__patchable_function_entry__)
#define dontinstrument \
__attribute__((__no_instrument_function__, \
__patchable_function_entry__(0, 0)))
#else
#define dontinstrument __attribute__((__no_instrument_function__))
#endif
#else
#define dontinstrument
#endif
@ -569,17 +572,17 @@ typedef struct {
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
__has_attribute(__no_sanitize_address__)) && \
!defined(__STRICT_ANSI__)
#define noasan __attribute__((__no_sanitize_address__))
#define dontasan __attribute__((__no_sanitize_address__))
#else
#define noasan
#define dontasan
#endif
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
__has_attribute(__no_sanitize_undefined__)) && \
!defined(__STRICT_ANSI__)
#define noubsan __attribute__((__no_sanitize_undefined__))
#define dontubsan __attribute__((__no_sanitize_undefined__))
#else
#define noubsan
#define dontubsan
#endif
#ifdef __STRICT_ANSI__
@ -645,11 +648,7 @@ void abort(void) wontreturn;
#endif
#ifndef _Section
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define _Section(s) __attribute__((__section__(s)))
#else
#define _Section(s)
#endif
#endif
#if defined(__x86_64__) && !defined(__llvm__)
@ -772,69 +771,69 @@ void abort(void) wontreturn;
#endif
#ifndef __STRICT_ANSI__
#define VEIL(CONSTRAINT, EXPRESSION) \
#define __veil(CONSTRAINT, EXPRESSION) \
({ \
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
asm("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
VeiledValue; \
})
#else
#define VEIL(CONSTRAINT, EXPRESSION) (EXPRESSION)
#define __veil(CONSTRAINT, EXPRESSION) (EXPRESSION)
#endif
#ifndef __STRICT_ANSI__
#define CONCEAL(CONSTRAINT, EXPRESSION) \
#define __conceal(CONSTRAINT, EXPRESSION) \
({ \
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
asm volatile("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
VeiledValue; \
})
#else
#define CONCEAL(CONSTRAINT, EXPRESSION) (EXPRESSION)
#define __conceal(CONSTRAINT, EXPRESSION) (EXPRESSION)
#endif
#ifndef __STRICT_ANSI__
#define EXPROPRIATE(EXPRESSION) \
#define __expropriate(EXPRESSION) \
({ \
asm volatile("" ::"g"(EXPRESSION) : "memory"); \
0; \
})
#else
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
#define __expropriate(EXPRESSION) (EXPRESSION)
#endif
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
#define YOINK(SYMBOL) \
#define __yoink(SYMBOL) \
asm(".section .yoink\n\tnopl\t%0\n\t.previous" : : "m"(SYMBOL))
#elif defined(__aarch64__)
#define YOINK(SYMBOL) \
#define __yoink(SYMBOL) \
asm(".section .yoink\n\tb\t%0\n\t.previous" : : "m"(SYMBOL))
#else
#define YOINK(SYMBOL) (void)0
#define __yoink(SYMBOL) (void)0
#endif
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
#define STATIC_YOINK(SYMBOLSTR) \
#define __static_yoink(SYMBOLSTR) \
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
#elif defined(__aarch64__)
#define STATIC_YOINK(SYMBOLSTR) \
#define __static_yoink(SYMBOLSTR) \
asm(".section .yoink\n\tb\t\"" SYMBOLSTR "\"\n\t.previous")
#else
#define STATIC_YOINK(SYMBOLSTR)
#define __static_yoink(SYMBOLSTR)
#endif
#if !defined(IM_FEELING_NAUGHTY)
#define STATIC_YOINK_SOURCE(PATH) STATIC_YOINK(PATH)
#define __static_yoink_source(PATH) __static_yoink(PATH)
#else
#define STATIC_YOINK_SOURCE(PATH)
#define __static_yoink_source(PATH)
#endif
#define __strong_reference(sym, aliassym) \
extern typeof(sym) aliassym __attribute__((__alias__(#sym)))
#define __weak_reference(sym, alias) \
asm(".weak\t" #alias "\n\t" \
".equ\t" #alias ", " #sym "\n\t" \
".type\t" #alias ",@notype")
extern __typeof(sym) aliassym __attribute__((__alias__(#sym)))
#define __weak_reference(sym, alias) \
__asm__(".weak\t" #alias "\n\t" \
".equ\t" #alias ", " #sym "\n\t" \
".type\t" #alias ",@notype")
#define __funline \
extern __inline \

View file

@ -82,8 +82,7 @@
#else
#define APE_STACKSIZE 4194304 /* default 4mb stack */
#endif
#define APE_PAGESIZE 0x10000 /* i386+ */
#define APE_GUARDSIZE 0x4000 /* b/c apple m1 */
#define APE_PAGESIZE 0x10000 /* i386+ */
#define BUFSIZ 0x1000 /* best stdio default */
#define CHAR_BIT 8 /* b/c von neumann */

View file

@ -20,19 +20,15 @@
#include "libc/runtime/runtime.h"
/**
* Returns auxiliary value, or zero if kernel didn't provide it.
*
* This function is typically regarded as a libc implementation detail;
* thus, the source code is the documentation.
* Returns auxiliary value better.
*
* @param at is `AT_...` search key
* @return true if value was found
* @see libc/sysv/consts.sh
* @see System Five Application Binary Interface § 3.4.3
* @error ENOENT when value not found
* @asyncsignalsafe
*/
struct AuxiliaryValue _getauxval(unsigned long at) {
dontasan struct AuxiliaryValue _getauxval(unsigned long at) {
unsigned long *ap;
for (ap = __auxv; ap[0]; ap += 2) {
if (at == ap[0]) {

View file

@ -19,7 +19,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/memtrack.internal.h"
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
dontasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
/* asan runtime depends on this function */
int i;
size_t wantsize;

View file

@ -52,7 +52,7 @@
#include "third_party/dlmalloc/dlmalloc.h"
#ifdef __x86_64__
STATIC_YOINK("_init_asan");
__static_yoink("_init_asan");
#if IsModeDbg()
// MODE=dbg
@ -342,7 +342,7 @@ static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
static void __asan_exit(void) {
kprintf("your asan runtime needs\n"
"\tSTATIC_YOINK(\"__die\");\n"
"\t__static_yoink(\"__die\");\n"
"in order to show you backtraces\n");
_Exitr(99);
}
@ -457,7 +457,7 @@ static struct AsanFault __asan_checka(const signed char *s, long ndiv8) {
* This is normally abstracted by the compiler. In some cases, it may be
* desirable to perform an ASAN memory safety check explicitly, e.g. for
* system call wrappers that need to vet memory passed to the kernel, or
* string library routines that use the `noasan` keyword due to compiler
* string library routines that use the `dontasan` keyword due to compiler
* generated ASAN being too costly. This function is fast especially for
* large memory ranges since this takes a few picoseconds for each byte.
*
@ -766,11 +766,11 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG\n");
}
} else {
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");\n");
kprintf("\tunknown please __static_yoink(\"GetSymbolTable\");\n");
}
}
static noasan void __asan_onmemory(void *x, void *y, size_t n, void *a) {
static dontasan void __asan_onmemory(void *x, void *y, size_t n, void *a) {
const unsigned char *p = x;
struct ReportOriginHeap *t = a;
if ((p <= t->a && t->a < p + n) ||
@ -790,7 +790,7 @@ static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
t.z = z;
_weaken(malloc_inspect_all)(__asan_onmemory, &t);
} else {
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");\n");
kprintf("\tunknown please __static_yoink(\"malloc_inspect_all\");\n");
}
}
@ -1117,7 +1117,7 @@ int __asan_print_trace(void *p) {
kprintf("\n%*lx %s", 12, e->bt.p[i],
_weaken(GetSymbolByAddr)
? _weaken(GetSymbolByAddr)(e->bt.p[i])
: "please STATIC_YOINK(\"GetSymbolByAddr\")");
: "please __static_yoink(\"GetSymbolByAddr\")");
}
return 0;
}
@ -1482,7 +1482,8 @@ static textstartup void __asan_shadow_mapping(struct MemoryIntervals *m,
static textstartup void __asan_shadow_existing_mappings(void) {
__asan_shadow_mapping(&_mmi, 0);
__asan_map_shadow(GetStackAddr(), GetStackSize());
__asan_poison((void *)GetStackAddr(), APE_GUARDSIZE, kAsanStackOverflow);
__asan_poison((void *)GetStackAddr(), getauxval(AT_PAGESZ),
kAsanStackOverflow);
}
forceinline ssize_t __write_str(const char *s) {
@ -1509,7 +1510,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
__asan_shadow_existing_mappings();
__asan_map_shadow((uintptr_t)__executable_start, _end - __executable_start);
__asan_map_shadow(0, 4096);
__asan_poison(0, APE_GUARDSIZE, kAsanNullPage);
__asan_poison(0, getauxval(AT_PAGESZ), kAsanNullPage);
if (!IsWindows()) {
sys_mprotect((void *)0x7fff8000, 0x10000, PROT_READ);
}

View file

@ -49,7 +49,7 @@ void _bt(const char *fmt, ...) {
errno = e;
} else {
kprintf("_bt() can't show backtrace because you need:\n"
"\tSTATIC_YOINK(\"ShowBacktrace\");\n"
"\t__static_yoink(\"ShowBacktrace\");\n"
"to be linked.\n");
if (_weaken(PrintBacktraceUsingSymbols) && _weaken(GetSymbolTable)) {
e = errno;
@ -58,8 +58,8 @@ void _bt(const char *fmt, ...) {
errno = e;
} else {
kprintf("_bt() can't show backtrace because you need:\n"
"\tSTATIC_YOINK(\"PrintBacktraceUsingSymbols\");\n"
"\tSTATIC_YOINK(\"GetSymbolTable\");\n"
"\t__static_yoink(\"PrintBacktraceUsingSymbols\");\n"
"\t__static_yoink(\"GetSymbolTable\");\n"
"to be linked.\n");
}
}

View file

@ -26,7 +26,7 @@
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
STATIC_YOINK("__cxa_finalize");
__static_yoink("__cxa_finalize");
/**
* Adds global destructor.
@ -42,7 +42,7 @@ STATIC_YOINK("__cxa_finalize");
* @return 0 on success or nonzero w/ errno
* @note folks have forked libc in past just to unbloat atexit()
*/
noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
dontasan int __cxa_atexit(void *fp, void *arg, void *pred) {
/* asan runtime depends on this function */
unsigned i;
struct CxaAtexitBlock *b, *b2;
@ -61,7 +61,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
}
}
i = _bsr(~b->mask);
_unassert(i < ARRAYLEN(b->p));
unassert(i < ARRAYLEN(b->p));
b->mask |= 1u << i;
b->p[i].fp = fp;
b->p[i].arg = arg;

View file

@ -60,7 +60,7 @@ StartOverLocked:
if (!pred) {
b2 = b->next;
if (b2) {
_unassert(b != &__cxa_blocks.root);
unassert(b != &__cxa_blocks.root);
if (_weaken(free)) {
_weaken(free)(b);
}

View file

@ -32,15 +32,15 @@
static uint64_t sys_mmap_metal_break;
noasan static struct DirectMap bad_mmap(void) {
dontasan static struct DirectMap bad_mmap(void) {
struct DirectMap res;
res.addr = (void *)-1;
res.maphandle = -1;
return res;
}
noasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
int flags, int fd, int64_t off) {
dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
int flags, int fd, int64_t off) {
/* asan runtime depends on this function */
size_t i;
struct mman *mm;

View file

@ -72,7 +72,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
}
}
} else {
_unassert(flags & MAP_ANONYMOUS);
unassert(flags & MAP_ANONYMOUS);
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
kNtFileMapWrite | kNtFileMapExecute};
}

View file

@ -43,11 +43,11 @@ static void *_mapframe(void *p, int f) {
if (!rc) {
return p;
} else {
_unassert(errno == ENOMEM);
unassert(errno == ENOMEM);
return 0;
}
} else {
_unassert(errno == ENOMEM);
unassert(errno == ENOMEM);
return 0;
}
}
@ -71,14 +71,14 @@ static void *_mapframe(void *p, int f) {
* @return new value for `e` or null w/ errno
* @raise ENOMEM if we require more vespene gas
*/
noasan void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
dontasan void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
char *q;
_unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
_unassert((uintptr_t)p + (G << kAsanScale) <= h);
unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
unassert((uintptr_t)p + (G << kAsanScale) <= h);
// TODO(jart): Make this spin less in non-ASAN mode.
for (q = e; q < ((char *)p + n); q += 8) {
if (!((uintptr_t)q & (G - 1))) {
_unassert(q + G <= (char *)h);
unassert(q + G <= (char *)h);
if (!_mapframe(q, f)) return 0;
if (IsAsan()) {
if (!((uintptr_t)SHADOW(q) & (G - 1))) {

View file

@ -19,7 +19,7 @@
#include "libc/assert.h"
#include "libc/runtime/memtrack.internal.h"
noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
dontasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
unsigned l, m, r;
l = 0;
r = mm->i;
@ -31,6 +31,6 @@ noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
r = m;
}
}
_unassert(l == mm->i || x <= mm->p[l].y);
unassert(l == mm->i || x <= mm->p[l].y);
return l;
}

View file

@ -31,7 +31,7 @@
#include "libc/thread/thread.h"
#ifdef __x86_64__
STATIC_YOINK("_init_g_fds");
__static_yoink("_init_g_fds");
#endif
struct Fds g_fds;
@ -49,7 +49,7 @@ static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
textstartup void __init_fds(void) {
struct Fds *fds;
__fds_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
fds = VEIL("r", &g_fds);
fds = __veil("r", &g_fds);
fds->n = 4;
atomic_store_explicit(&fds->f, 3, memory_order_relaxed);
if (_weaken(_extend)) {
@ -73,9 +73,9 @@ textstartup void __init_fds(void) {
fds->p[1].kind = pushpop(kFdSerial);
fds->p[2].kind = pushpop(kFdSerial);
}
fds->p[0].handle = VEIL("r", 0x3F8ull);
fds->p[1].handle = VEIL("r", 0x3F8ull);
fds->p[2].handle = VEIL("r", 0x3F8ull);
fds->p[0].handle = __veil("r", 0x3F8ull);
fds->p[1].handle = __veil("r", 0x3F8ull);
fds->p[2].handle = __veil("r", 0x3F8ull);
} else if (IsWindows()) {
SetupWinStd(fds, 0, kNtStdInputHandle);
SetupWinStd(fds, 1, kNtStdOutputHandle);

View file

@ -16,28 +16,33 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/intrin/_getauxval.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
#include "libc/sysv/consts/auxv.h"
/**
* Returns auxiliary value, or zero if kernel didn't provide it.
* Returns auxiliary value.
*
* This function is typically regarded as a libc implementation detail;
* thus, the source code is the documentation.
*
* @return auxiliary value or 0 if `at` not found
* @return auxiliary value or 0 if `key` not found
* @see libc/sysv/consts.sh
* @see System Five Application Binary Interface § 3.4.3
* @error ENOENT when value not found
* @asyncsignalsafe
*/
unsigned long getauxval(unsigned long at) {
unsigned long res, *ap;
for (ap = __auxv; ap[0]; ap += 2) {
if (at == ap[0]) {
return ap[1];
unsigned long getauxval(unsigned long key) {
struct AuxiliaryValue x;
x = _getauxval(key);
if (key == AT_PAGESZ) {
if (!x.isfound) {
x.value = 16384;
}
x.isfound = true;
}
if (x.isfound) {
return x.value;
} else {
errno = ENOENT;
return 0;
}
enoent();
return 0;
}

View file

@ -31,7 +31,7 @@
#define kBufSize 1024
#define kPid "TracerPid:\t"
static textwindows noasan bool IsBeingDebugged(void) {
static textwindows dontasan bool IsBeingDebugged(void) {
return !!NtGetPeb()->BeingDebugged;
}

View file

@ -38,9 +38,9 @@ bool IsWsl1(void) {
if (res) return res & 1;
if (!IsLinux()) return res = 2, false;
int e = errno;
_unassert(__sys_mmap((void *)1, 4096, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | ANONYMOUS | GROWSDOWN, -1, 0,
0) == MAP_FAILED);
unassert(__sys_mmap((void *)1, 4096, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | ANONYMOUS | GROWSDOWN, -1, 0,
0) == MAP_FAILED);
bool tmp = errno == ENOTSUP;
errno = e;
res = 2 | tmp;

View file

@ -82,7 +82,7 @@ void *kmalloc(size_t size) {
}
__kmalloc_unlock();
if (p) {
_unassert(!((intptr_t)(p + i) & (KMALLOC_ALIGN - 1)));
unassert(!((intptr_t)(p + i) & (KMALLOC_ALIGN - 1)));
if (IsAsan()) __asan_poison(p + i + size, n - size, kAsanHeapOverrun);
return p + i;
} else {

View file

@ -57,6 +57,7 @@
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "libc/str/utf16.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/tls.h"
@ -187,7 +188,7 @@ privileged bool kisdangerous(const void *p) {
if (IsStackFrame(frame)) return false;
if (kismapped(frame)) return false;
}
if (GetStackAddr() + APE_GUARDSIZE <= (uintptr_t)p &&
if (GetStackAddr() + 16384 <= (uintptr_t)p &&
(uintptr_t)p < GetStackAddr() + GetStackSize()) {
return false;
}

View file

@ -4,7 +4,7 @@
COSMOPOLITAN_C_START_
#define IGNORE_LEAKS(FUNC) \
STATIC_YOINK("_leaky_start"); \
__static_yoink("_leaky_start"); \
void *_leaky_##FUNC[] _Section(".piro.relo.sort.leaky.2." #FUNC \
",\"aw\",@init_array #") = {FUNC}

View file

@ -36,9 +36,9 @@ static inline const unsigned char *memchr_pure(const unsigned char *s,
}
#ifdef __x86_64__
noasan static inline const unsigned char *memchr_sse(const unsigned char *s,
unsigned char c,
size_t n) {
dontasan static inline const unsigned char *memchr_sse(const unsigned char *s,
unsigned char c,
size_t n) {
size_t i;
unsigned k;
unsigned m;

View file

@ -36,9 +36,9 @@ static inline const unsigned char *memrchr_pure(const unsigned char *s,
}
#ifdef __x86_64__
noasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
unsigned char c,
size_t n) {
dontasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
unsigned char c,
size_t n) {
size_t i;
unsigned k, m;
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};

View file

@ -50,7 +50,7 @@
static void *MoveMemoryIntervals(struct MemoryInterval *d,
const struct MemoryInterval *s, int n) {
int i;
_unassert(n >= 0);
unassert(n >= 0);
if (d > s) {
for (i = n; i--;) {
d[i] = s[i];
@ -64,8 +64,8 @@ static void *MoveMemoryIntervals(struct MemoryInterval *d,
}
static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
_unassert(i >= 0);
_unassert(i + n <= mm->i);
unassert(i >= 0);
unassert(i + n <= mm->i);
MoveMemoryIntervals(mm->p + i, mm->p + i + n, mm->i - (i + n));
mm->i -= n;
}
@ -109,9 +109,9 @@ static bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
}
int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
_unassert(i >= 0);
_unassert(i <= mm->i);
_unassert(mm->n >= 0);
unassert(i >= 0);
unassert(i <= mm->i);
unassert(mm->n >= 0);
if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
return 0;
@ -130,7 +130,7 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
void wf(struct MemoryIntervals *, int, int)) {
unsigned l, r;
ASSERT_MEMTRACK();
_unassert(y >= x);
unassert(y >= x);
if (!mm->i) return 0;
// binary search for the lefthand side
l = FindMemoryInterval(mm, x);
@ -140,8 +140,8 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// binary search for the righthand side
r = FindMemoryInterval(mm, y);
if (r == mm->i || (r > l && y < mm->p[r].x)) --r;
_unassert(r >= l);
_unassert(x <= mm->p[r].y);
unassert(r >= l);
unassert(x <= mm->p[r].y);
// remove the middle of an existing map
//
@ -162,11 +162,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// ----|mmmm|----------------- after
//
if (x > mm->p[l].x && x <= mm->p[l].y) {
_unassert(y >= mm->p[l].y);
unassert(y >= mm->p[l].y);
if (IsWindows()) return einval();
mm->p[l].size -= (size_t)(mm->p[l].y - (x - 1)) * FRAMESIZE;
mm->p[l].y = x - 1;
_unassert(mm->p[l].x <= mm->p[l].y);
unassert(mm->p[l].x <= mm->p[l].y);
++l;
}
@ -177,11 +177,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// ---------------|mm|-------- after
//
if (y >= mm->p[r].x && y < mm->p[r].y) {
_unassert(x <= mm->p[r].x);
unassert(x <= mm->p[r].x);
if (IsWindows()) return einval();
mm->p[r].size -= (size_t)((y + 1) - mm->p[r].x) * FRAMESIZE;
mm->p[r].x = y + 1;
_unassert(mm->p[r].x <= mm->p[r].y);
unassert(mm->p[r].x <= mm->p[r].y);
--r;
}
@ -199,7 +199,7 @@ int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
long offset, long size) {
unsigned i;
ASSERT_MEMTRACK();
_unassert(y >= x);
unassert(y >= x);
i = FindMemoryInterval(mm, x);
// try to extend the righthand side of the lefthand entry

View file

@ -54,14 +54,14 @@ struct ReclaimedPage {
/**
* Allocates new page of physical memory.
*/
noasan texthead uint64_t __new_page(struct mman *mm) {
dontasan texthead uint64_t __new_page(struct mman *mm) {
uint64_t p = mm->frp;
if (p != NOPAGE) {
uint64_t q;
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
_unassert(p == (p & PAGE_TA));
unassert(p == (p & PAGE_TA));
q = rp->next;
_unassert(q == (q & PAGE_TA) || q == NOPAGE);
unassert(q == (q & PAGE_TA) || q == NOPAGE);
mm->frp = q;
return p;
}
@ -81,8 +81,8 @@ noasan texthead uint64_t __new_page(struct mman *mm) {
* Returns pointer to page table entry for page at virtual address.
* Additional page tables are allocated if needed as a side-effect.
*/
noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
int64_t vaddr, bool maketables) {
dontasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
int64_t vaddr, bool maketables) {
uint64_t *e, p;
unsigned char h;
for (h = 39;; h -= 9) {
@ -101,7 +101,7 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
/**
* Sorts, rounds, and filters BIOS memory map.
*/
static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
static dontasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
uint64_t a, b;
uint64_t x, y;
unsigned i, j, n;
@ -134,9 +134,10 @@ static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
/**
* Identity maps an area of physical memory to its negative address.
*/
noasan textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
uint64_t ps, uint64_t size,
uint64_t pte_flags) {
dontasan textreal uint64_t *__invert_memory_area(struct mman *mm,
uint64_t *pml4t, uint64_t ps,
uint64_t size,
uint64_t pte_flags) {
uint64_t pe = ps + size, p, *m = NULL;
ps = ROUNDDOWN(ps, 4096);
pe = ROUNDUP(pe, 4096);
@ -152,7 +153,7 @@ noasan textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
/**
* Increments the reference count for a page of physical memory.
*/
noasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
dontasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
uint64_t *m, e;
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
if (m) {
@ -167,8 +168,8 @@ noasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
/**
* Increments the reference counts for an area of physical memory.
*/
noasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
uint64_t size) {
dontasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
uint64_t size) {
uint64_t p = ROUNDDOWN(ps, 4096), e = ROUNDUP(ps + size, 4096);
while (p != e) {
__ref_page(mm, pml4t, p);
@ -179,9 +180,9 @@ noasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
/**
* Reclaims a page of physical memory for later use.
*/
static noasan void __reclaim_page(struct mman *mm, uint64_t p) {
static dontasan void __reclaim_page(struct mman *mm, uint64_t p) {
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
_unassert(p == (p & PAGE_TA));
unassert(p == (p & PAGE_TA));
rp->next = mm->frp;
mm->frp = p;
}
@ -191,7 +192,7 @@ static noasan void __reclaim_page(struct mman *mm, uint64_t p) {
* page if there are no virtual addresses (excluding the negative space)
* referring to it.
*/
noasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
dontasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
uint64_t *m, e;
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
if (m) {
@ -207,7 +208,8 @@ noasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
/**
* Identity maps all usable physical memory to its negative address.
*/
static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
static dontasan textreal void __invert_memory(struct mman *mm,
uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
uint64_t ps = mm->e820[i].addr, size = mm->e820[i].size;
@ -230,8 +232,8 @@ static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
: "i"(offsetof(type, member))); \
} while (0)
noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
uint64_t top) {
dontasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
uint64_t top) {
export_offsetof(struct mman, pc_drive_base_table);
export_offsetof(struct mman, pc_drive_last_sector);
export_offsetof(struct mman, pc_drive_last_head);
@ -257,8 +259,8 @@ noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
/**
* Maps APE-defined ELF program headers into memory and clears BSS.
*/
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
uint64_t top) {
dontasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
uint64_t top) {
struct Elf64_Phdr *p;
uint64_t i, f, v, m, *e;
extern char ape_phdrs[] __attribute__((__weak__));
@ -292,8 +294,9 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
* Reclaims memory pages which were used at boot time but which can now be
* made available for the application.
*/
noasan textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
uint64_t skip_end) {
dontasan textreal void __reclaim_boot_pages(struct mman *mm,
uint64_t skip_start,
uint64_t skip_end) {
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e;
for (i = 0; i < n; ++i) {
b = mm->e820[i].addr;

View file

@ -21,7 +21,7 @@
#include "libc/thread/thread.h"
#ifdef __x86_64__
STATIC_YOINK("_init__mmi");
__static_yoink("_init__mmi");
#endif
struct MemoryIntervals _mmi;

View file

@ -48,9 +48,9 @@
*/
bool __nocolor;
optimizesize textstartup noasan void __nocolor_init(int argc, char **argv,
char **envp,
intptr_t *auxv) {
optimizesize textstartup dontasan void __nocolor_init(int argc, char **argv,
char **envp,
intptr_t *auxv) {
char *s;
__nocolor = (IsWindows() && !IsAtLeastWindows10()) ||
((s = getenv("TERM")) && IsDumb(s));

View file

@ -27,7 +27,7 @@
*
* @see IsAtLeastWindows10()
*/
textwindows noasan int NtGetVersion(void) {
textwindows dontasan int NtGetVersion(void) {
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
}

View file

@ -24,7 +24,7 @@
void(pthread_cleanup_pop)(struct _pthread_cleanup_buffer *cb, int execute) {
struct PosixThread *pt;
if (__tls_enabled && (pt = (struct PosixThread *)__get_tls()->tib_pthread)) {
_unassert(cb == pt->cleanup);
unassert(cb == pt->cleanup);
pt->cleanup = cb->__prev;
}
if (execute) {

View file

@ -35,7 +35,7 @@ void *pthread_getspecific(pthread_key_t k) {
// pthread_key_create() or after key has been deleted with
// pthread_key_delete() is undefined."
// ──Quoth POSIX.1-2017
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
return __get_tls()->tib_keys[k];
}

View file

@ -35,8 +35,8 @@
*/
int pthread_key_delete(pthread_key_t k) {
uint64_t mask;
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
atomic_store_explicit(_pthread_key_dtor + k, 0, memory_order_release);
return 0;
}

View file

@ -35,8 +35,8 @@ int pthread_setspecific(pthread_key_t k, const void *val) {
// pthread_key_create() or after key has been deleted with
// pthread_key_delete() is undefined."
// ──Quoth POSIX.1-2017
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
__get_tls()->tib_keys[k] = val;
return 0;
}

View file

@ -48,14 +48,14 @@ errno_t(pthread_spin_lock)(pthread_spinlock_t *spin) {
LOCKTRACE("pthread_spin_lock(%t)", spin);
break;
}
_unassert(x == 1);
unassert(x == 1);
LOCKTRACE("pthread_spin_lock(%t) trying...", spin);
}
#else
for (;;) {
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
if (!x) break;
_unassert(x == 1);
unassert(x == 1);
}
#endif
return 0;

View file

@ -34,6 +34,6 @@ errno_t(pthread_spin_trylock)(pthread_spinlock_t *spin) {
int x;
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
if (!x) return 0;
_unassert(x == 1);
unassert(x == 1);
return EBUSY;
}

View file

@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return pointer to nul byte
* @asyncsignalsafe
*/
noasan char *stpcpy(char *d, const char *s) {
dontasan char *stpcpy(char *d, const char *s) {
size_t i = 0;
if (IsAsan()) {
__asan_verify(d, strlen(s) + 1);

View file

@ -32,7 +32,7 @@ static inline const char *strchr_pure(const char *s, int c) {
#ifdef __x86_64__
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
noasan static inline const char *strchr_sse(const char *s, unsigned char c) {
dontasan static inline const char *strchr_sse(const char *s, unsigned char c) {
unsigned k;
unsigned m;
xmm_t v, *p;
@ -55,7 +55,7 @@ noasan static inline const char *strchr_sse(const char *s, unsigned char c) {
}
#endif
static noasan inline const char *strchr_x64(const char *p, uint64_t c) {
static dontasan inline const char *strchr_x64(const char *p, uint64_t c) {
unsigned a, b;
uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) {
@ -103,7 +103,7 @@ char *strchr(const char *s, int c) {
} else {
r = strchr_pure(s, c);
}
_unassert(!r || *r || !(c & 255));
unassert(!r || *r || !(c & 255));
return (char *)r;
#else
char *r;
@ -112,7 +112,7 @@ char *strchr(const char *s, int c) {
if (!*s) return NULL;
}
r = strchr_x64(s, c);
_unassert(!r || *r || !c);
unassert(!r || *r || !c);
return r;
#endif
}

View file

@ -32,7 +32,8 @@ static inline const char *strchrnul_pure(const char *s, int c) {
#ifdef __x86_64__
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
noasan static inline const char *strchrnul_sse(const char *s, unsigned char c) {
dontasan static inline const char *strchrnul_sse(const char *s,
unsigned char c) {
unsigned k;
unsigned m;
xmm_t v, *p;
@ -52,7 +53,7 @@ noasan static inline const char *strchrnul_sse(const char *s, unsigned char c) {
}
#endif
noasan static const char *strchrnul_x64(const char *p, uint64_t c) {
dontasan static const char *strchrnul_x64(const char *p, uint64_t c) {
unsigned a, b;
uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) {
@ -101,7 +102,7 @@ char *strchrnul(const char *s, int c) {
} else {
r = strchrnul_pure(s, c);
}
_unassert((*r & 255) == (c & 255) || !*r);
unassert((*r & 255) == (c & 255) || !*r);
return (char *)r;
#else
char *r;

View file

@ -29,7 +29,7 @@
* @return is <0, 0, or >0 based on uint8_t comparison
* @asyncsignalsafe
*/
noasan int strcmp(const char *a, const char *b) {
dontasan int strcmp(const char *a, const char *b) {
int c;
size_t i = 0;
uint64_t v, w, d;

View file

@ -34,7 +34,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return original dest
* @asyncsignalsafe
*/
noasan char *strcpy(char *d, const char *s) {
dontasan char *strcpy(char *d, const char *s) {
size_t i = 0;
if (IsAsan()) {
__asan_verify(d, strlen(s) + 1);

View file

@ -28,7 +28,7 @@
* @return number of bytes (excluding NUL)
* @asyncsignalsafe
*/
noasan size_t strlen(const char *s) {
dontasan size_t strlen(const char *s) {
if (IsAsan()) __asan_verify_str(s);
#ifdef __x86_64__
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));

View file

@ -23,7 +23,7 @@
#include "libc/str/str.h"
#ifndef __aarch64__
static noasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
static dontasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
uint64_t w;
for (; i + 8 < n; i += 8) {
w = *(uint64_t *)(s + i);
@ -43,7 +43,7 @@ static noasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
* @return byte length
* @asyncsignalsafe
*/
noasan size_t strnlen(const char *s, size_t n) {
dontasan size_t strnlen(const char *s, size_t n) {
size_t i;
if (IsAsan() && n) __asan_verify(s, 1);
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
@ -53,7 +53,7 @@ noasan size_t strnlen(const char *s, size_t n) {
for (;; ++i) {
if (i == n || !s[i]) break;
}
_unassert(i == n || (i < n && !s[i]));
unassert(i == n || (i < n && !s[i]));
if (IsAsan()) __asan_verify(s, i);
return i;
}

View file

@ -204,7 +204,7 @@ static wontreturn void __ubsan_unreachable(void) {
static void __ubsan_exit(void) {
kprintf("your ubsan runtime needs\n"
"\tSTATIC_YOINK(\"__die\");\n"
"\t__static_yoink(\"__die\");\n"
"in order to show you backtraces\n");
_Exitr(99);
}

View file

@ -44,7 +44,7 @@ textwindows int WSARecv(
// Use NULL for this parameter if the lpOverlapped parameter is not
// NULL to avoid potentially erroneous results. This parameter can
// be NULL only if the lpOverlapped parameter is not NULL.
_unassert(!opt_out_lpNumberOfBytesRecvd);
unassert(!opt_out_lpNumberOfBytesRecvd);
}
#if defined(SYSDEBUG) && _NTTRACE
uint32_t NumberOfBytesRecvd;

View file

@ -45,7 +45,7 @@
* @param st is open symbol table for current executable
* @return -1 w/ errno if error happened
*/
dontinstrument noasan int PrintBacktraceUsingSymbols(
dontinstrument dontasan int PrintBacktraceUsingSymbols(
int fd, const struct StackFrame *bp, struct SymbolTable *st) {
bool ok;
size_t gi;

View file

@ -31,7 +31,7 @@
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
STATIC_YOINK("strerror_wr");
__static_yoink("strerror_wr");
/**
* Handles failure of CHECK_xx() macros.

View file

@ -53,7 +53,7 @@ static void PrintHistogram(const long *h, size_t n, long t) {
unsigned long logos;
for (i = 0; i < n; ++i) {
p = (h[i] * 10000 + (t >> 1)) / t;
_unassert(0 <= p && p <= 10000);
unassert(0 <= p && p <= 10000);
if (p) {
for (j = 0; j < p / 100; ++j) s[j] = '#';
s[j] = 0;

View file

@ -32,7 +32,7 @@
#include "libc/thread/thread.h"
#if SupportsMetal()
STATIC_YOINK("_idt");
__static_yoink("_idt");
#endif
/**

View file

@ -28,14 +28,14 @@
#include "libc/runtime/runtime.h"
#include "libc/testlib/testlib.h"
STATIC_YOINK("GetSymbolByAddr");
__static_yoink("GetSymbolByAddr");
#define MAXLEAKS 1000
static bool once;
static bool hasleaks;
static noasan void CheckLeak(void *x, void *y, size_t n, void *a) {
static dontasan void CheckLeak(void *x, void *y, size_t n, void *a) {
if (n) {
if (IsAsan()) {
if (__asan_get_heap_size(x) && !__asan_is_leaky(x)) {
@ -47,7 +47,7 @@ static noasan void CheckLeak(void *x, void *y, size_t n, void *a) {
}
}
static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
static dontasan void OnMemory(void *x, void *y, size_t n, void *a) {
static int i;
if (n) {
if (MAXLEAKS) {
@ -67,7 +67,7 @@ static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
}
}
static noasan bool HasLeaks(void) {
static dontasan bool HasLeaks(void) {
malloc_inspect_all(CheckLeak, 0);
return hasleaks;
}
@ -79,7 +79,7 @@ static noasan bool HasLeaks(void) {
* services that depend on malloc() cannot be used, after calling this
* function.
*/
noasan void CheckForMemoryLeaks(void) {
dontasan void CheckForMemoryLeaks(void) {
struct mallinfo mi;
if (!IsAsan()) return; // we need traces to exclude leaky
if (!_cmpxchg(&once, false, true)) {

View file

@ -35,7 +35,7 @@
*
* If you put the following in your main file:
*
* STATIC_YOINK("enable_memory_log");
* __static_yoink("enable_memory_log");
*
* Then memory allocations with constant backtraces will be logged to
* standard error. The columns printed are
@ -146,7 +146,7 @@ static void __memlog_update(void *p2, void *p) {
__memlog.usage += n - __memlog.allocs.p[i].size;
__memlog.allocs.p[i].addr = p2;
__memlog.allocs.p[i].size = n;
_unassert(__memlog.usage >= 0);
unassert(__memlog.usage >= 0);
return;
}
}
@ -170,20 +170,20 @@ static void __memlog_free(void *p) {
__memlog.allocs.p[i].addr = 0;
__memlog.usage -= __memlog.allocs.p[i].size;
__memlog.allocs.f = MIN(__memlog.allocs.f, i);
_unassert(__memlog.usage >= 0);
unassert(__memlog.usage >= 0);
} else {
kprintf("memlog could not find %p\n", p);
notpossible;
}
__memlog_unlock();
_unassert(__memlog.free);
unassert(__memlog.free);
__memlog.free(p);
__memlog_log(__builtin_frame_address(0), "free", 0, p, n);
}
static void *__memlog_malloc(size_t n) {
void *res;
_unassert(__memlog.malloc);
unassert(__memlog.malloc);
if ((res = __memlog.malloc(n))) {
__memlog_lock();
__memlog_insert(res);
@ -195,7 +195,7 @@ static void *__memlog_malloc(size_t n) {
static void *__memlog_calloc(size_t n, size_t z) {
void *res;
_unassert(__memlog.calloc);
unassert(__memlog.calloc);
if ((res = __memlog.calloc(n, z))) {
__memlog_lock();
__memlog_insert(res);
@ -207,7 +207,7 @@ static void *__memlog_calloc(size_t n, size_t z) {
static void *__memlog_memalign(size_t l, size_t n) {
void *res;
_unassert(__memlog.memalign);
unassert(__memlog.memalign);
if ((res = __memlog.memalign(l, n))) {
__memlog_lock();
__memlog_insert(res);
@ -221,7 +221,7 @@ static void *__memlog_realloc_impl(void *p, size_t n,
void *(*f)(void *, size_t),
struct StackFrame *frame) {
void *res;
_unassert(f);
unassert(f);
if ((res = f(p, n))) {
__memlog_lock();
if (p) {

View file

@ -45,13 +45,14 @@
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#ifdef __x86_64__
STATIC_YOINK("strerror_wr"); // for kprintf %m
STATIC_YOINK("strsignal_r"); // for kprintf %G
__static_yoink("strerror_wr"); // for kprintf %m
__static_yoink("strsignal_r"); // for kprintf %G
static const char kGregOrder[17] forcealign(1) = {
13, 11, 8, 14, 12, 9, 10, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7,
@ -219,7 +220,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
uname(&names);
errno = err;
// TODO(jart): Buffer the WHOLE crash report with backtrace for atomic write.
_npassert((p = buf = kmalloc((n = 1024 * 1024))));
npassert((p = buf = kmalloc((n = 1024 * 1024))));
p += ksnprintf(
p, n,
"\n%serror%s: Uncaught %G (%s) on %s pid %d tid %d\n"
@ -227,8 +228,9 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
" %s\n"
" %s %s %s %s\n",
!__nocolor ? "\e[30;101m" : "", !__nocolor ? "\e[0m" : "", sig,
(ctx && (ctx->uc_mcontext.rsp >= GetStaticStackAddr(0) &&
ctx->uc_mcontext.rsp <= GetStaticStackAddr(0) + APE_GUARDSIZE))
(ctx &&
(ctx->uc_mcontext.rsp >= GetStaticStackAddr(0) &&
ctx->uc_mcontext.rsp <= GetStaticStackAddr(0) + getauxval(AT_PAGESZ)))
? "Stack Overflow"
: GetSiCodeName(sig, si->si_code),
host, getpid(), gettid(), program_invocation_name, strerror(err),

View file

@ -39,12 +39,13 @@
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/thread.h"
#ifdef __aarch64__
STATIC_YOINK("strerror_wr"); // for kprintf %m
STATIC_YOINK("strsignal_r"); // for kprintf %G
__static_yoink("strerror_wr"); // for kprintf %m
__static_yoink("strsignal_r"); // for kprintf %G
#define RESET "\e[0m"
#define BOLD "\e[1m"
@ -197,7 +198,8 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) {
gethostname(host, sizeof(host));
reset = !__nocolor ? RESET : "";
strong = !__nocolor ? STRONG : "";
if (ctx && (ctx->uc_mcontext.sp & (GetStackSize() - 1)) <= APE_GUARDSIZE) {
if (ctx &&
(ctx->uc_mcontext.sp & (GetStackSize() - 1)) <= getauxval(AT_PAGESZ)) {
kind = "Stack Overflow";
} else {
kind = GetSiCodeName(sig, si->si_code);

View file

@ -37,13 +37,13 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/ss.h"
STATIC_YOINK("zipos"); // for symtab
STATIC_YOINK("__die"); // for backtracing
STATIC_YOINK("ShowBacktrace"); // for backtracing
STATIC_YOINK("GetSymbolTable"); // for backtracing
STATIC_YOINK("PrintBacktraceUsingSymbols"); // for backtracing
STATIC_YOINK("malloc_inspect_all"); // for asan memory origin
STATIC_YOINK("GetSymbolByAddr"); // for asan memory origin
__static_yoink("zipos"); // for symtab
__static_yoink("__die"); // for backtracing
__static_yoink("ShowBacktrace"); // for backtracing
__static_yoink("GetSymbolTable"); // for backtracing
__static_yoink("PrintBacktraceUsingSymbols"); // for backtracing
__static_yoink("malloc_inspect_all"); // for asan memory origin
__static_yoink("GetSymbolByAddr"); // for asan memory origin
struct CrashHandler {
int sig;
@ -147,8 +147,8 @@ void ShowCrashReports(void) {
ss.ss_size = GetStackSize();
// FreeBSD sigaltstack() will EFAULT if we use MAP_STACK here
// OpenBSD sigaltstack() auto-applies MAP_STACK to the memory
_npassert((ss.ss_sp = _mapanon(GetStackSize())));
_npassert(!sigaltstack(&ss, 0));
npassert((ss.ss_sp = _mapanon(GetStackSize())));
npassert(!sigaltstack(&ss, 0));
}
InstallCrashHandler(SIGQUIT, __got_sigquit, ef); // ctrl+\ aka ctrl+break
InstallCrashHandler(SIGFPE, __got_sigfpe, ef); // 1 / 0

View file

@ -22,7 +22,7 @@
// there's a crash in a constructor, this will help with
// troubleshooting it. You need to add:
//
// STATIC_YOINK("ShowCrashReportsEarly");
// __static_yoink("ShowCrashReportsEarly");
//
// To the top of your main module to use this.

View file

@ -64,12 +64,12 @@ static wontreturn void __arena_die(void) {
}
forceinline void __arena_check(void) {
_unassert(__arena.depth);
unassert(__arena.depth);
}
forceinline void __arena_check_pointer(void *p) {
_unassert(BASE + __arena.offset[__arena.depth - 1] <= (uintptr_t)p &&
(uintptr_t)p < BASE + __arena.offset[__arena.depth]);
unassert(BASE + __arena.offset[__arena.depth - 1] <= (uintptr_t)p &&
(uintptr_t)p < BASE + __arena.offset[__arena.depth]);
}
forceinline bool __arena_is_arena_pointer(void *p) {
@ -322,7 +322,7 @@ void __arena_push(void) {
if (!__arena.depth) {
__arena_install();
} else {
_unassert(__arena.depth < ARRAYLEN(__arena.offset) - 1);
unassert(__arena.depth < ARRAYLEN(__arena.offset) - 1);
}
__arena.offset[__arena.depth + 1] = __arena.offset[__arena.depth];
++__arena.depth;

View file

@ -93,8 +93,8 @@ static void DeferFunction(struct StackFrame *frame, void *fn, void *arg) {
void __defer(void *rbp, void *fn, void *arg) {
struct StackFrame *f, *frame = rbp;
f = __builtin_frame_address(0);
_unassert(f->next == frame);
_unassert(PointerNotOwnedByParentStackFrame(f, frame, arg));
unassert(f->next == frame);
unassert(PointerNotOwnedByParentStackFrame(f, frame, arg));
DeferFunction(frame, fn, arg);
}

View file

@ -51,8 +51,8 @@ int LeftmostInt(const struct SortedInts *t, int k) {
r = m;
}
}
_unassert(l == 0 || k >= t->p[l - 1]);
_unassert(l == t->n || k <= t->p[l]);
unassert(l == 0 || k >= t->p[l - 1]);
unassert(l == t->n || k <= t->p[l]);
return l;
}
@ -70,8 +70,8 @@ int CountInt(const struct SortedInts *t, int k) {
bool InsertInt(struct SortedInts *t, int k, bool u) {
int l;
_unassert(t->n >= 0);
_unassert(t->n <= t->c);
unassert(t->n >= 0);
unassert(t->n <= t->c);
if (t->n == t->c) {
++t->c;
if (!IsModeDbg()) {

View file

@ -23,7 +23,7 @@
// If you want to support Raspberry Pi by embedding an emulator
// in your APE binary that runs automatically, then put this:
//
// STATIC_YOINK("blink_linux_aarch64");
// __static_yoink("blink_linux_aarch64");
//
// In your main.c file, to pull it into linkage from the static
// archive. Alternatively, you may simply add blink_linux_aarch64.o

View file

@ -23,7 +23,7 @@
// If you want to support Apple M1 by embedding an emulator in
// your APE binary that runs automatically, then put this:
//
// STATIC_YOINK("blink_xnu_aarch64");
// __static_yoink("blink_xnu_aarch64");
//
// In your main.c file, to pull it into linkage from the static
// archive. Alternatively, you may simply add blink_xnu_aarch64.o

View file

@ -3,14 +3,60 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct NtImageSectionHeader {
uint8_t Name[8];
union {
uint32_t PhysicalAddress;
/*
* The total size of the section when loaded into memory. If this
* value is greater than SizeOfRawData, the section is zero-padded.
* This field is valid only for executable images and should be set
* to zero for object files.
*/
uint32_t VirtualSize;
} Misc;
/*
* In an image file, the VAs for sections must be assigned by the
* linker so that they are in ascending order and adjacent, and they
* must be a multiple of the SectionAlignment value in the optional
* header.
*
* For executable images, the address of the first byte of the section
* relative to the image base when the section is loaded into memory.
* For object files, this field is the address of the first byte
* before relocation is applied; for simplicity, compilers should set
* this to zero. Otherwise, it is an arbitrary value that is
* subtracted from offsets during relocation.
*/
uint32_t VirtualAddress;
/*
* The size of the section (for object files) or the size of the
* initialized data on disk (for image files). For executable images,
* this must be a multiple of FileAlignment from the optional header.
* If this is less than VirtualSize, the remainder of the section is
* zero-filled. Because the SizeOfRawData field is rounded but the
* VirtualSize field is not, it is possible for SizeOfRawData to be
* greater than VirtualSize as well. When a section contains only
* uninitialized data, this field should be zero.
*/
uint32_t SizeOfRawData;
/*
* The file pointer to the first page of the section within the COFF
* file. For executable images, this must be a multiple of
* FileAlignment from the optional header. For object files, the value
* should be aligned on a 4-byte boundary for best performance. When a
* section contains only uninitialized data, this field should be
* zero.
*/
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;

View file

@ -7,7 +7,7 @@
/*
* These macros address directly into NT's TEB a.k.a. TIB
* Any function that does this needs the `noasan` keyword
* Any function that does this needs the `dontasan` keyword
*/
#define NtGetPeb() gs((struct NtPeb **)(0x60ULL))
#define NtGetTeb() gs((void **)(0x30)) /* %gs:0 linear address */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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];
}
}

Some files were not shown because too many files have changed in this diff Show more