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

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