Get redbean -X running in blinkenlights again

This change improves the loading of APE executables in Blinkenlights and
adds some system call wrappers that were previous missing.
This commit is contained in:
Justine Tunney 2022-07-16 11:51:26 -07:00
parent 4700984456
commit 866b21a151
3 changed files with 120 additions and 5 deletions

View file

@ -115,8 +115,15 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
j += uint64toarray_radix16(addr - 1, buf + j) + 1; j += uint64toarray_radix16(addr - 1, buf + j) + 1;
} }
argv[i++] = NULL; argv[i++] = NULL;
if (sys_pipe(pipefds) == -1) return -1; if (sys_pipe(pipefds) == -1) {
if (!(pid = vfork())) { return -1;
}
if ((pid = vfork()) == -1) {
sys_close(pipefds[0]);
sys_close(pipefds[1]);
return -1;
}
if (!pid) {
sys_dup2(pipefds[1], 1); sys_dup2(pipefds[1], 1);
if (pipefds[0] != 1) sys_close(pipefds[0]); if (pipefds[0] != 1) sys_close(pipefds[0]);
if (pipefds[1] != 1) sys_close(pipefds[1]); if (pipefds[1] != 1) sys_close(pipefds[1]);

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/bits.h"
#include "libc/bits/popcnt.h" #include "libc/bits/popcnt.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
@ -28,6 +29,7 @@
#include "libc/runtime/pc.internal.h" #include "libc/runtime/pc.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
@ -135,11 +137,53 @@ static void BootProgram(struct Machine *m, struct Elf *elf, size_t codesize) {
} }
} }
static int GetElfHeader(char ehdr[hasatleast 64], const char *prog,
const char *image) {
char *p;
int c, i;
for (p = image; p < image + 4096; ++p) {
if (READ64LE(p) != READ64LE("printf '")) continue;
for (i = 0, p += 8; p + 3 < image + 4096 && (c = *p++) != '\'';) {
if (c == '\\') {
if ('0' <= *p && *p <= '7') {
c = *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
}
}
}
}
if (i < 64) {
ehdr[i++] = c;
} else {
WARNF("%s: ape printf elf header too long\n", prog);
return -1;
}
}
if (i != 64) {
WARNF("%s: ape printf elf header too short\n", prog);
return -1;
}
if (READ32LE(ehdr) != READ32LE("\177ELF")) {
WARNF("%s: ape printf elf header didn't have elf magic\n", prog);
return -1;
}
return 0;
}
WARNF("%s: printf statement not found in first 4096 bytes\n", prog);
return -1;
}
void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars, void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
struct Elf *elf) { struct Elf *elf) {
int fd; int fd;
ssize_t rc; ssize_t rc;
int64_t sp; int64_t sp;
char ehdr[64];
struct stat st; struct stat st;
size_t i, mappedsize; size_t i, mappedsize;
DCHECK_NOTNULL(prog); DCHECK_NOTNULL(prog);
@ -169,6 +213,12 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
elf->ehdr = (void *)elf->map; elf->ehdr = (void *)elf->map;
elf->size = elf->mapsize; elf->size = elf->mapsize;
LoadElf(m, elf); LoadElf(m, elf);
} else if (READ64LE(elf->map) == READ64LE("MZqFpD='") &&
!GetElfHeader(ehdr, prog, elf->map)) {
memcpy(elf->map, ehdr, 64);
elf->ehdr = (void *)elf->map;
elf->size = elf->mapsize;
LoadElf(m, elf);
} else { } else {
elf->base = IMAGE_BASE_VIRTUAL; elf->base = IMAGE_BASE_VIRTUAL;
elf->ehdr = NULL; elf->ehdr = NULL;

View file

@ -212,7 +212,11 @@ static int XlatSocketOptname(int x) {
XLAT(5, SO_DONTROUTE); XLAT(5, SO_DONTROUTE);
XLAT(7, SO_SNDBUF); XLAT(7, SO_SNDBUF);
XLAT(8, SO_RCVBUF); XLAT(8, SO_RCVBUF);
XLAT(1, TCP_NODELAY);
XLAT(12, TCP_QUICKACK);
XLAT(13, SO_LINGER); XLAT(13, SO_LINGER);
XLAT(23, TCP_FASTOPEN);
XLAT(30, TCP_FASTOPEN_CONNECT);
default: default:
return einval(); return einval();
} }
@ -764,6 +768,60 @@ static int OpSetsockopt(struct Machine *m, int fd, int level, int optname,
return rc; return rc;
} }
static int OpGetsockopt(struct Machine *m, int fd, int level, int optname,
int64_t optvaladdr, int64_t optsizeaddr) {
int rc;
void *optval;
uint32_t optsize;
if ((level = XlatSocketLevel(level)) == -1) return -1;
if ((optname = XlatSocketOptname(optname)) == -1) return -1;
if ((fd = XlatFd(m, fd)) == -1) return -1;
if (!optvaladdr) {
rc = getsockopt(fd, level, optname, 0, 0);
} else {
VirtualSendRead(m, &optsize, optsizeaddr, sizeof(optsize));
if (!(optval = malloc(optsize))) return -1;
if ((rc = getsockopt(fd, level, optname, optval, &optsize)) != -1) {
VirtualRecvWrite(m, optvaladdr, optval, optsize);
VirtualRecvWrite(m, optsizeaddr, &optsize, sizeof(optsize));
}
free(optval);
}
return rc;
}
static int OpGetsockname(struct Machine *m, int fd, int64_t addraddr,
int64_t addrlenaddr) {
int rc;
void *addr;
uint32_t addrlen;
if ((fd = XlatFd(m, fd)) == -1) return -1;
VirtualSendRead(m, &addrlen, addrlenaddr, sizeof(addrlen));
if (!(addr = malloc(addrlen))) return -1;
if ((rc = getsockname(fd, addr, &addrlen)) != -1) {
VirtualRecvWrite(m, addraddr, addr, addrlen);
VirtualRecvWrite(m, addrlenaddr, &addrlen, sizeof(addrlen));
}
free(addr);
return rc;
}
static int OpGetpeername(struct Machine *m, int fd, int64_t addraddr,
int64_t addrlenaddr) {
int rc;
void *addr;
uint32_t addrlen;
if ((fd = XlatFd(m, fd)) == -1) return -1;
VirtualSendRead(m, &addrlen, addrlenaddr, sizeof(addrlen));
if (!(addr = malloc(addrlen))) return -1;
if ((rc = getpeername(fd, addr, &addrlen)) != -1) {
VirtualRecvWrite(m, addraddr, addr, addrlen);
VirtualRecvWrite(m, addrlenaddr, &addrlen, sizeof(addrlen));
}
free(addr);
return rc;
}
static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) { static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
ssize_t rc; ssize_t rc;
struct Iovs iv; struct Iovs iv;
@ -1402,10 +1460,10 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x030, OpShutdown(m, di, si)); SYSCALL(0x030, OpShutdown(m, di, si));
SYSCALL(0x031, OpBind(m, di, si, dx)); SYSCALL(0x031, OpBind(m, di, si, dx));
SYSCALL(0x032, OpListen(m, di, si)); SYSCALL(0x032, OpListen(m, di, si));
SYSCALL(0x033, getsockname(di, PNN(si), PNN(dx))); SYSCALL(0x033, OpGetsockname(m, di, si, dx));
SYSCALL(0x034, getpeername(di, PNN(si), PNN(dx))); SYSCALL(0x034, OpGetpeername(m, di, si, dx));
SYSCALL(0x036, OpSetsockopt(m, di, si, dx, r0, r8)); SYSCALL(0x036, OpSetsockopt(m, di, si, dx, r0, r8));
SYSCALL(0x037, getsockopt(di, si, dx, PNN(r0), PNN(r8))); SYSCALL(0x037, OpGetsockopt(m, di, si, dx, r0, r8));
SYSCALL(0x039, OpFork(m)); SYSCALL(0x039, OpFork(m));
SYSCALL(0x03B, OpExecve(m, di, si, dx)); SYSCALL(0x03B, OpExecve(m, di, si, dx));
SYSCALL(0x03D, OpWait4(m, di, si, dx, r0)); SYSCALL(0x03D, OpWait4(m, di, si, dx, r0));