mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 23:08:31 +00:00
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:
parent
4700984456
commit
866b21a151
3 changed files with 120 additions and 5 deletions
|
@ -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]);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue