implement zipos mmap

This commit is contained in:
Gavin Hayes 2023-02-01 01:17:46 -05:00
parent 6d36584ff2
commit 38f876aee7
7 changed files with 80 additions and 2 deletions

View file

@ -50,6 +50,7 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
#include "libc/zipos/zipos.internal.h"
#define MAP_ANONYMOUS_linux 0x00000020
#define MAP_ANONYMOUS_openbsd 0x00001000
@ -485,6 +486,9 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
void *res;
size_t toto;
if (__isfdkind(fd, kFdZip)) {
return _weaken(__zipos_mmap)(addr, size, prot, flags, (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, off);
}
#if defined(SYSDEBUG) && (_KERNTRACE || _NTTRACE)
if (IsWindows()) {
STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size,

58
libc/zipos/mmap.c Normal file
View file

@ -0,0 +1,58 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
void *__zipos_mmap(void *addr, size_t size, int prot, int flags, struct ZiposHandle *h, int64_t off) {
if (VERY_UNLIKELY(!!(flags & MAP_ANONYMOUS))) {
STRACE("fd anonymous mismatch");
return VIP(einval());
}
if (VERY_UNLIKELY(!(!!(prot & PROT_WRITE) ^ !!(flags & MAP_SHARED)))) {
STRACE("PROT_WRITE and MAP_SHARED on zipos");
return VIP(eacces());
}
const int tempProt = !IsXnu() ? prot | PROT_WRITE : PROT_WRITE;
void *outAddr = mmap(addr, size, tempProt, flags | MAP_ANONYMOUS, -1, 0);
if (outAddr == MAP_FAILED) {
return MAP_FAILED;
}
const int64_t beforeOffset = __zipos_lseek(h, 0, SEEK_CUR);
if ((beforeOffset == -1) || (__zipos_read(h, &(struct iovec){outAddr, size}, 1, off) == -1)) {
munmap(outAddr, size);
return MAP_FAILED;
}
__zipos_lseek(h, beforeOffset, SEEK_SET);
if(prot != tempProt) {
mprotect(outAddr, size, prot);
}
return outAddr;
}

View file

@ -48,7 +48,7 @@
static char *mapend;
static size_t maptotal;
static void *__zipos_mmap(size_t mapsize) {
static void *__zipos_mmap_space(size_t mapsize) {
char *start;
size_t offset;
_unassert(mapsize);
@ -78,7 +78,7 @@ StartOver:
ph = &h->next;
}
if (!h) {
h = __zipos_mmap(mapsize);
h = __zipos_mmap_space(mapsize);
}
__zipos_unlock();
if (IsAsan()) {

View file

@ -34,6 +34,7 @@
.yoink __zipos_read
.yoink __zipos_stat
.yoink __zipos_notat
.yoink __zipos_mmap
// TODO(jart): why does corruption happen when zip has no assets?
.yoink .cosmo

View file

@ -48,6 +48,7 @@ ssize_t __zipos_write(struct ZiposHandle *, const struct iovec *, size_t,
int64_t __zipos_lseek(struct ZiposHandle *, int64_t, unsigned) _Hide;
int __zipos_fcntl(int, int, uintptr_t) _Hide;
int __zipos_notat(int, const char *) _Hide;
void *__zipos_mmap(void *, uint64_t, int32_t, int32_t, struct ZiposHandle *, int64_t) _Hide;
#ifdef _NOPL0
#define __zipos_lock() _NOPL0("__threadcalls", __zipos_lock)

View file

@ -46,6 +46,8 @@
#include "libc/x/xspawn.h"
#include "third_party/xed/x86.h"
STATIC_YOINK("zip_uri_support");
char testlib_enable_tmp_setup_teardown;
void SetUpOnce(void) {
@ -219,6 +221,17 @@ TEST(isheap, mallocOffset) {
ASSERT_TRUE(_isheap(p + 100000));
}
TEST(mmap, ziposMapFiles) {
int fd;
const char *lifepath = "/zip/life.elf";
void *p;
ASSERT_NE(-1, (fd = open(lifepath, O_RDONLY), "%s", lifepath));
ASSERT_NE(NULL, (p = mmap(NULL, 0x00010000, PROT_READ, MAP_SHARED, fd, 0)));
EXPECT_STREQN("ELF", ((const char *)p)+1, 3);
close(fd);
}
////////////////////////////////////////////////////////////////////////////////
// NON-SHARED READ-ONLY FILE MEMORY

View file

@ -51,6 +51,7 @@ o/$(MODE)/test/libc/runtime/runtime.pkg: \
o/$(MODE)/test/libc/runtime/%.com.dbg: \
$(TEST_LIBC_RUNTIME_DEPS) \
o/$(MODE)/test/libc/mem/prog/life.elf.zip.o \
o/$(MODE)/test/libc/runtime/%.o \
o/$(MODE)/test/libc/runtime/runtime.pkg \
$(LIBC_TESTMAIN) \