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

@ -41,14 +41,14 @@ int sys_accept4(int server, struct sockaddr_storage *addr, int flags) {
if ((client = __sys_accept(server, addr, &size, 0)) != -1) {
// __sys_accept() has inconsistent flag inheritence across platforms
// this is one of the issues that accept4() was invented for solving
_unassert((file_mode = __sys_fcntl(client, F_GETFD)) != -1);
_unassert(!__sys_fcntl(client, F_SETFD,
((file_mode & ~FD_CLOEXEC) |
(flags & SOCK_CLOEXEC ? FD_CLOEXEC : 0))));
_unassert((file_mode = __sys_fcntl(client, F_GETFL)) != -1);
_unassert(!__sys_fcntl(client, F_SETFL,
((file_mode & ~O_NONBLOCK) |
(flags & SOCK_NONBLOCK ? O_NONBLOCK : 0))));
unassert((file_mode = __sys_fcntl(client, F_GETFD)) != -1);
unassert(!__sys_fcntl(client, F_SETFD,
((file_mode & ~FD_CLOEXEC) |
(flags & SOCK_CLOEXEC ? FD_CLOEXEC : 0))));
unassert((file_mode = __sys_fcntl(client, F_GETFL)) != -1);
unassert(!__sys_fcntl(client, F_SETFL,
((file_mode & ~O_NONBLOCK) |
(flags & SOCK_NONBLOCK ? O_NONBLOCK : 0))));
}
}
return client;

View file

@ -25,7 +25,7 @@
textwindows int sys_bind_nt(struct Fd *fd, const void *addr,
uint32_t addrsize) {
_npassert(fd->kind == kFdSocket);
npassert(fd->kind == kFdSocket);
if (__sys_bind_nt(fd->handle, addr, addrsize) != -1) {
return 0;
} else {

View file

@ -28,7 +28,7 @@ textwindows int sys_connect_nt(struct Fd *fd, const void *addr,
uint32_t addrsize) {
struct SockFd *sockfd;
sockfd = (struct SockFd *)fd->extra;
_npassert(fd->kind == kFdSocket);
npassert(fd->kind == kFdSocket);
return __winsockblock(
fd->handle, _bsr(kNtFdConnect),
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),

View file

@ -383,7 +383,7 @@ static textwindows int afd_poll(int64_t afd_device_handle,
struct NtIoStatusBlock *io_status_block) {
NtStatus status;
/* Blocking operation is not supported.*/
_npassert(io_status_block);
npassert(io_status_block);
io_status_block->Status = kNtStatusPending;
status =
NtDeviceIoControlFile(afd_device_handle, 0, NULL, io_status_block,
@ -563,7 +563,7 @@ static textwindows int ts_tree_add(struct TsTree *ts_tree,
}
static textwindows void port__free(struct PortState *port) {
_npassert(port);
npassert(port);
free(port);
}
@ -591,7 +591,7 @@ err1:
}
static textwindows int sock__cancel_poll(struct SockState *sock_state) {
_npassert(sock_state->poll_status == kPollPending);
npassert(sock_state->poll_status == kPollPending);
if (afd_cancel_poll(poll_group_get_afd_device_handle(sock_state->poll_group),
&sock_state->io_status_block) < 0) {
return -1;
@ -707,13 +707,13 @@ static textwindows void reflock__await_event(void *address) {
static textwindows void reflock_ref(struct RefLock *reflock) {
long state = InterlockedAdd(&reflock->state, REFLOCK__REF);
/* Verify that the counter didn 't overflow and the lock isn' t destroyed.*/
_npassert((state & REFLOCK__DESTROY_MASK) == 0);
npassert((state & REFLOCK__DESTROY_MASK) == 0);
}
static textwindows void reflock_unref(struct RefLock *reflock) {
long state = InterlockedAdd(&reflock->state, -REFLOCK__REF);
/* Verify that the lock was referenced and not already destroyed.*/
_npassert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0);
npassert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0);
if (state == REFLOCK__DESTROY) reflock__signal_event(reflock);
}
@ -749,10 +749,10 @@ static textwindows void reflock_unref_and_destroy(struct RefLock *reflock) {
state = InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF);
ref_count = state & REFLOCK__REF_MASK;
/* Verify that the lock was referenced and not already destroyed. */
_npassert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY);
npassert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY);
if (ref_count != 0) reflock__await_event(reflock);
state = InterlockedExchange(&reflock->state, REFLOCK__POISON);
_npassert(state == REFLOCK__DESTROY);
npassert(state == REFLOCK__DESTROY);
}
static textwindows void ts_tree_node_unref_and_destroy(
@ -780,13 +780,13 @@ static textwindows void poll_group_release(struct PollGroup *poll_group) {
struct PortState *port_state = poll_group->port_state;
struct Queue *poll_group_queue = port_get_poll_group_queue(port_state);
poll_group->group_size--;
_npassert(poll_group->group_size < MAX_GROUP_SIZE);
npassert(poll_group->group_size < MAX_GROUP_SIZE);
queue_move_to_end(poll_group_queue, &poll_group->queue_node);
/* Poll groups are currently only freed when the epoll port is closed. */
}
static textwindows void sock__free(struct SockState *sock_state) {
_npassert(sock_state != NULL);
npassert(sock_state != NULL);
free(sock_state);
}
@ -832,7 +832,7 @@ static textwindows void sock_force_delete(struct PortState *port_state,
}
static textwindows void poll_group_delete(struct PollGroup *poll_group) {
_npassert(poll_group->group_size == 0);
npassert(poll_group->group_size == 0);
CloseHandle(poll_group->afd_device_handle);
queue_remove(&poll_group->queue_node);
free(poll_group);
@ -844,7 +844,7 @@ static textwindows int port_delete(struct PortState *port_state) {
struct SockState *sock_state;
struct PollGroup *poll_group;
/* At this point the IOCP port should have been closed.*/
_npassert(!port_state->iocp_handle);
npassert(!port_state->iocp_handle);
while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) {
sock_state = sock_state_from_tree_node(tree_node);
sock_force_delete(port_state, sock_state);
@ -857,14 +857,14 @@ static textwindows int port_delete(struct PortState *port_state) {
poll_group = poll_group_from_queue_node(queue_node);
poll_group_delete(poll_group);
}
_npassert(queue_is_empty(&port_state->sock_update_queue));
npassert(queue_is_empty(&port_state->sock_update_queue));
DeleteCriticalSection(&port_state->lock);
port__free(port_state);
return 0;
}
static textwindows int64_t port_get_iocp_handle(struct PortState *port_state) {
_npassert(port_state->iocp_handle);
npassert(port_state->iocp_handle);
return port_state->iocp_handle;
}
@ -938,7 +938,7 @@ static textwindows uint32_t sock__afd_events_to_epoll_events(uint32_t a) {
static textwindows int sock_update(struct PortState *port_state,
struct SockState *sock_state) {
_npassert(!sock_state->delete_pending);
npassert(!sock_state->delete_pending);
if ((sock_state->poll_status == kPollPending) &&
!(sock_state->user_events & KNOWN_EVENTS & ~sock_state->pending_events)) {
/* All the events the user is interested in are already being

View file

@ -36,7 +36,7 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
uint32_t in_optlen;
struct SockFd *sockfd;
struct linger_nt linger;
_npassert(fd->kind == kFdSocket);
npassert(fd->kind == kFdSocket);
sockfd = (struct SockFd *)fd->extra;
if (out_opt_optval && inout_optlen) {

View file

@ -30,7 +30,7 @@
/**
* Information about underlying Windows Sockets implementation.
*
* Cosmopolitan automatically calls YOINK() on this symbol when its
* Cosmopolitan automatically calls __yoink() on this symbol when its
* Berkeley Socket wrappers are linked. The latest version of Winsock
* was introduced alongside x64, so this should never fail.
*/
@ -43,7 +43,7 @@ static textwindows void WinSockCleanup(void) {
NTTRACE("WSACleanup() → %d% lm", rc);
}
textwindows noasan void WinSockInit(void) {
textwindows dontasan void WinSockInit(void) {
int rc;
atexit(WinSockCleanup);
NTTRACE("WSAStartup()");

View file

@ -22,7 +22,7 @@
#include "libc/sock/syscall_fd.internal.h"
textwindows int sys_listen_nt(struct Fd *fd, int backlog) {
_npassert(fd->kind == kFdSocket);
npassert(fd->kind == kFdSocket);
if (__sys_listen_nt(fd->handle, backlog) != -1) {
return 0;
} else {

View file

@ -323,7 +323,7 @@ int nointernet(void) {
sigprocmask(SIG_SETMASK, &old, 0);
return eperm();
}
_npassert(WIFSTOPPED(ws));
npassert(WIFSTOPPED(ws));
// parent process becomes monitor of subprocess tree. all signals
// continue to be blocked since we assume they'll also be sent to

View file

@ -49,6 +49,6 @@ textwindows ssize_t sys_recv_nt(struct Fd *fd, const struct iovec *iov,
sockfd = (struct SockFd *)fd->extra;
rc = __wsablock(fd, &overlapped, &flags, true, sockfd->rcvtimeo);
}
_unassert(WSACloseEvent(overlapped.hEvent));
unassert(WSACloseEvent(overlapped.hEvent));
return rc;
}

View file

@ -110,9 +110,9 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
if (rc != -1) {
if (opt_in_out_inoffset) {
*opt_in_out_inoffset = offset + rc;
_npassert(SetFilePointerEx(ih, pos, 0, SEEK_SET));
npassert(SetFilePointerEx(ih, pos, 0, SEEK_SET));
} else {
_npassert(SetFilePointerEx(ih, offset + rc, 0, SEEK_SET));
npassert(SetFilePointerEx(ih, offset + rc, 0, SEEK_SET));
}
}
WSACloseEvent(ov.hEvent);
@ -141,7 +141,7 @@ static ssize_t sys_sendfile_bsd(int outfd, int infd,
if (opt_in_out_inoffset) {
*opt_in_out_inoffset += sbytes;
} else {
_npassert(lseek(infd, offset + sbytes, SEEK_SET) == offset + sbytes);
npassert(lseek(infd, offset + sbytes, SEEK_SET) == offset + sbytes);
}
return sbytes;
} else {

View file

@ -35,9 +35,9 @@
* functions through weak reference. This ensure those symbols are not
* stripped during final link.
*/
STATIC_YOINK("GetAdaptersAddresses");
STATIC_YOINK("tprecode16to8");
STATIC_YOINK("_dupsockfd");
__static_yoink("GetAdaptersAddresses");
__static_yoink("tprecode16to8");
__static_yoink("_dupsockfd");
textwindows int sys_socket_nt(int family, int type, int protocol) {
int64_t h;

View file

@ -47,8 +47,8 @@ textwindows int __wsablock(struct Fd *fd, struct NtOverlapped *overlapped,
}
if (fd->flags & O_NONBLOCK) {
e = errno;
_unassert(CancelIoEx(fd->handle, overlapped) ||
WSAGetLastError() == kNtErrorNotFound);
unassert(CancelIoEx(fd->handle, overlapped) ||
WSAGetLastError() == kNtErrorNotFound);
errno = e;
} else {
if (_check_interrupts(restartable, g_fds.p)) {

View file

@ -1,5 +1,5 @@
STATIC_YOINK("kNtWsaData"); // for winmain
STATIC_YOINK("WSAGetLastError"); // for kprintf
STATIC_YOINK("sys_closesocket_nt"); // for close
STATIC_YOINK("sys_recv_nt"); // for readv
STATIC_YOINK("sys_send_nt"); // for writev
__static_yoink("kNtWsaData"); // for winmain
__static_yoink("WSAGetLastError"); // for kprintf
__static_yoink("sys_closesocket_nt"); // for close
__static_yoink("sys_recv_nt"); // for readv
__static_yoink("sys_send_nt"); // for writev