diff --git a/ape/ape.S b/ape/ape.S index 2521ac30c..412a03626 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -35,6 +35,7 @@ #include "ape/macros.internal.h" #include "ape/notice.inc" #include "ape/relocations.h" +#include "libc/calls/metalfile.internal.h" #include "libc/dce.h" #include "libc/elf/def.h" #include "libc/macho.internal.h" @@ -1565,19 +1566,19 @@ kernel: movabs $ape_stack_vaddr,%rsp #endif push $_HOSTMETAL # sets __hostos in crt.S pop %rcx - push $0 + pushq .Lenv0(%rip) # envp[0][0] mov %rsp,%rbp - mov .Lenv0(%rip),%rax - mov %rax,(%rbp) # envp[0][0] - push $0 # argv[0][0] + pushq .Largv0+8(%rip) # argv[0][8] + pushq .Largv0(%rip) # argv[0][0] + mov %rsp,%rax push $0 # auxv[1][1] push $0 # auxv[1][0] - push %rbp # auxv[0][1] + push %rax # auxv[0][1] push $31 # auxv[0][0] AT_EXECFN push $0 # envp[1] - push $.Lenv0 # envp[0] + push %rbp # envp[0] push $0 # argv[1] - push %rbp # argv[0] + push %rax # argv[0] push $1 # argc xor %ebp,%ebp xor %eax,%eax @@ -1593,6 +1594,9 @@ kernel: movabs $ape_stack_vaddr,%rsp .rodata .Lenv0: .asciz "METAL=1" +.Largv0: + .asciz APE_COM_NAME + .org .Largv0+16 .previous #endif /* SupportsMetal() */ diff --git a/libc/calls/metalfile.internal.h b/libc/calls/metalfile.internal.h index 236fed09d..a74a7cd3b 100644 --- a/libc/calls/metalfile.internal.h +++ b/libc/calls/metalfile.internal.h @@ -11,4 +11,7 @@ struct MetalFile { COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ + +#define APE_COM_NAME "/ape.com" + #endif /* COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_ */ diff --git a/libc/calls/openat-metal.c b/libc/calls/openat-metal.c index 7611c3473..a3889e377 100644 --- a/libc/calls/openat-metal.c +++ b/libc/calls/openat-metal.c @@ -20,18 +20,34 @@ #include "libc/calls/internal.h" #include "libc/calls/metalfile.internal.h" #include "libc/intrin/weaken.h" +#include "libc/macros.internal.h" #include "libc/mem/mem.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/sysv/consts/at.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/prot.h" #include "libc/sysv/errfuns.h" int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) { int fd; struct MetalFile *state; - if (strcmp(file, "ape.com")) return enoent(); - if (!_weaken(calloc)) return enomem(); + if (dirfd != AT_FDCWD || strcmp(file, APE_COM_NAME)) return enoent(); + if (flags != O_RDONLY) return eacces(); if ((fd = __reservefd(-1)) == -1) return -1; - state = _weaken(calloc)(1, sizeof(struct MetalFile)); + if (!_weaken(calloc) || !_weaken(free)) { + struct DirectMap dm; + dm = sys_mmap_metal(NULL, ROUNDUP(sizeof(struct MetalFile), 4096), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, + -1, 0); + state = dm.addr; + if (state == (void *)-1) return -1; + } else { + state = _weaken(calloc)(1, sizeof(struct MetalFile)); + if (!state) return -1; + } state->base = (char *)_base; state->size = _end - _base; g_fds.p[fd].kind = kFdFile;