#include #include #include #include #include #include #include #include #include #include "zircon_impl.h" #include "threads_impl.h" #include "stdio_impl.h" static const char mmap_vmo_name[] = "mmap-anonymous"; void* __mmap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) { if (fd_off & (PAGE_SIZE - 1)) { errno = EINVAL; return MAP_FAILED; } if (len == 0) { errno = EINVAL; return MAP_FAILED; } if (len >= PTRDIFF_MAX) { errno = ENOMEM; return MAP_FAILED; } if (!(flags & (MAP_PRIVATE | MAP_SHARED)) || (flags & MAP_PRIVATE && flags & MAP_SHARED)) { errno = EINVAL; return MAP_FAILED; } // round up to page size len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); // build zircon flags for this zx_vm_option_t zx_options = 0; zx_options |= (prot & PROT_READ) ? ZX_VM_PERM_READ : 0; zx_options |= (prot & PROT_WRITE) ? ZX_VM_PERM_WRITE : 0; zx_options |= (prot & PROT_EXEC) ? ZX_VM_PERM_EXECUTE : 0; size_t offset = 0; zx_status_t status = ZX_OK; if (flags & MAP_FIXED) { zx_options |= ZX_VM_SPECIFIC; zx_info_vmar_t info; status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info, sizeof(info), NULL, NULL); if (status < 0 || (uintptr_t)start < info.base) { goto fail; } offset = (uintptr_t)start - info.base; } zx_handle_t vmo; uintptr_t ptr = 0; if (flags & MAP_ANON) { if (_zx_vmo_create(len, 0, &vmo) < 0) { errno = ENOMEM; return MAP_FAILED; } _zx_object_set_property(vmo, ZX_PROP_NAME, mmap_vmo_name, strlen(mmap_vmo_name)); } else { status = _mmap_file(offset, len, zx_options, flags, fd, fd_off, &ptr); if (status < 0) { goto fail; } return (void*) ptr; } status = _zx_vmar_map(_zx_vmar_root_self(), zx_options, offset, vmo, fd_off, len, &ptr); _zx_handle_close(vmo); // TODO: map this as shared if we ever implement forking if (status < 0) { goto fail; } return (void*)ptr; fail: switch(status) { case ZX_ERR_BAD_HANDLE: errno = EBADF; break; case ZX_ERR_NOT_SUPPORTED: errno = ENODEV; break; case ZX_ERR_ACCESS_DENIED: errno = EACCES; break; case ZX_ERR_NO_MEMORY: errno = ENOMEM; break; case ZX_ERR_INVALID_ARGS: case ZX_ERR_BAD_STATE: default: errno = EINVAL; } return MAP_FAILED; } weak_alias(__mmap, mmap);