1#include <errno.h> 2#include <limits.h> 3#include <zircon/process.h> 4#include <zircon/syscalls.h> 5#include <zircon/syscalls/object.h> 6#include <stdint.h> 7#include <string.h> 8#include <sys/mman.h> 9#include <unistd.h> 10 11#include "zircon_impl.h" 12#include "threads_impl.h" 13#include "stdio_impl.h" 14 15static const char mmap_vmo_name[] = "mmap-anonymous"; 16 17void* __mmap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) { 18 if (fd_off & (PAGE_SIZE - 1)) { 19 errno = EINVAL; 20 return MAP_FAILED; 21 } 22 if (len == 0) { 23 errno = EINVAL; 24 return MAP_FAILED; 25 } 26 if (len >= PTRDIFF_MAX) { 27 errno = ENOMEM; 28 return MAP_FAILED; 29 } 30 if (!(flags & (MAP_PRIVATE | MAP_SHARED)) || 31 (flags & MAP_PRIVATE && flags & MAP_SHARED)) { 32 errno = EINVAL; 33 return MAP_FAILED; 34 } 35 36 // round up to page size 37 len = (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 38 39 // build zircon flags for this 40 zx_vm_option_t zx_options = 0; 41 zx_options |= (prot & PROT_READ) ? ZX_VM_PERM_READ : 0; 42 zx_options |= (prot & PROT_WRITE) ? ZX_VM_PERM_WRITE : 0; 43 zx_options |= (prot & PROT_EXEC) ? ZX_VM_PERM_EXECUTE : 0; 44 45 size_t offset = 0; 46 zx_status_t status = ZX_OK; 47 if (flags & MAP_FIXED) { 48 zx_options |= ZX_VM_SPECIFIC; 49 50 zx_info_vmar_t info; 51 status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info, 52 sizeof(info), NULL, NULL); 53 if (status < 0 || (uintptr_t)start < info.base) { 54 goto fail; 55 } 56 offset = (uintptr_t)start - info.base; 57 } 58 59 zx_handle_t vmo; 60 uintptr_t ptr = 0; 61 if (flags & MAP_ANON) { 62 if (_zx_vmo_create(len, 0, &vmo) < 0) { 63 errno = ENOMEM; 64 return MAP_FAILED; 65 } 66 _zx_object_set_property(vmo, ZX_PROP_NAME, mmap_vmo_name, strlen(mmap_vmo_name)); 67 } else { 68 status = _mmap_file(offset, len, zx_options, flags, fd, fd_off, &ptr); 69 if (status < 0) { 70 goto fail; 71 } 72 return (void*) ptr; 73 } 74 75 status = _zx_vmar_map(_zx_vmar_root_self(), zx_options, offset, vmo, fd_off, len, &ptr); 76 _zx_handle_close(vmo); 77 // TODO: map this as shared if we ever implement forking 78 if (status < 0) { 79 goto fail; 80 } 81 82 return (void*)ptr; 83 84fail: 85 switch(status) { 86 case ZX_ERR_BAD_HANDLE: 87 errno = EBADF; 88 break; 89 case ZX_ERR_NOT_SUPPORTED: 90 errno = ENODEV; 91 break; 92 case ZX_ERR_ACCESS_DENIED: 93 errno = EACCES; 94 break; 95 case ZX_ERR_NO_MEMORY: 96 errno = ENOMEM; 97 break; 98 case ZX_ERR_INVALID_ARGS: 99 case ZX_ERR_BAD_STATE: 100 default: 101 errno = EINVAL; 102 } 103 return MAP_FAILED; 104} 105 106weak_alias(__mmap, mmap); 107