mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +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
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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] = "-";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -181,7 +181,7 @@ skip_readlink:
|
|||
continue;
|
||||
}
|
||||
k = rc;
|
||||
_npassert(k <= p);
|
||||
npassert(k <= p);
|
||||
if (k==p)
|
||||
goto toolong;
|
||||
if (!k) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
struct timeval timeval_real(void) {
|
||||
struct timeval tv;
|
||||
_npassert(!gettimeofday(&tv, 0));
|
||||
npassert(!gettimeofday(&tv, 0));
|
||||
return tv;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue