1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice shall be included 13848b8605Smrg * in all copies or substantial portions of the Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 22848b8605Smrg * 23848b8605Smrg **************************************************************************/ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file exemem.c 28848b8605Smrg * Functions for allocating executable memory. 29848b8605Smrg * 30848b8605Smrg * \author Keith Whitwell 31848b8605Smrg */ 32848b8605Smrg 33848b8605Smrg 34848b8605Smrg#include "pipe/p_compiler.h" 35848b8605Smrg#include "util/u_debug.h" 36848b8605Smrg#include "os/os_thread.h" 37848b8605Smrg#include "util/u_memory.h" 38848b8605Smrg 39848b8605Smrg#include "rtasm_execmem.h" 40848b8605Smrg 41848b8605Smrg#ifndef MAP_ANONYMOUS 42848b8605Smrg#define MAP_ANONYMOUS MAP_ANON 43848b8605Smrg#endif 44848b8605Smrg 45848b8605Smrg#if defined(PIPE_OS_WINDOWS) 46848b8605Smrg#ifndef WIN32_LEAN_AND_MEAN 47848b8605Smrg#define WIN32_LEAN_AND_MEAN 1 48848b8605Smrg#endif 49848b8605Smrg#include <windows.h> 50848b8605Smrg#endif 51848b8605Smrg 52b8e80941Smrg#if defined(PIPE_OS_UNIX) 53848b8605Smrg 54848b8605Smrg 55848b8605Smrg/* 56848b8605Smrg * Allocate a large block of memory which can hold code then dole it out 57848b8605Smrg * in pieces by means of the generic memory manager code. 58848b8605Smrg */ 59848b8605Smrg 60848b8605Smrg#include <unistd.h> 61848b8605Smrg#include <sys/mman.h> 62848b8605Smrg#include "util/u_mm.h" 63848b8605Smrg 64848b8605Smrg#define EXEC_HEAP_SIZE (10*1024*1024) 65848b8605Smrg 66b8e80941Smrgstatic mtx_t exec_mutex = _MTX_INITIALIZER_NP; 67848b8605Smrg 68848b8605Smrgstatic struct mem_block *exec_heap = NULL; 69848b8605Smrgstatic unsigned char *exec_mem = NULL; 70848b8605Smrg 71848b8605Smrg 72848b8605Smrgstatic int 73848b8605Smrginit_heap(void) 74848b8605Smrg{ 75848b8605Smrg if (!exec_heap) 76848b8605Smrg exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE ); 77848b8605Smrg 78848b8605Smrg if (!exec_mem) 79848b8605Smrg exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE, 80848b8605Smrg PROT_EXEC | PROT_READ | PROT_WRITE, 81848b8605Smrg MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 82848b8605Smrg 83848b8605Smrg return (exec_mem != MAP_FAILED); 84848b8605Smrg} 85848b8605Smrg 86848b8605Smrg 87848b8605Smrgvoid * 88848b8605Smrgrtasm_exec_malloc(size_t size) 89848b8605Smrg{ 90848b8605Smrg struct mem_block *block = NULL; 91848b8605Smrg void *addr = NULL; 92848b8605Smrg 93b8e80941Smrg mtx_lock(&exec_mutex); 94848b8605Smrg 95848b8605Smrg if (!init_heap()) 96848b8605Smrg goto bail; 97848b8605Smrg 98848b8605Smrg if (exec_heap) { 99848b8605Smrg size = (size + 31) & ~31; /* next multiple of 32 bytes */ 100848b8605Smrg block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */ 101848b8605Smrg } 102848b8605Smrg 103848b8605Smrg if (block) 104848b8605Smrg addr = exec_mem + block->ofs; 105848b8605Smrg else 106848b8605Smrg debug_printf("rtasm_exec_malloc failed\n"); 107848b8605Smrg 108848b8605Smrgbail: 109b8e80941Smrg mtx_unlock(&exec_mutex); 110848b8605Smrg 111848b8605Smrg return addr; 112848b8605Smrg} 113848b8605Smrg 114848b8605Smrg 115848b8605Smrgvoid 116848b8605Smrgrtasm_exec_free(void *addr) 117848b8605Smrg{ 118b8e80941Smrg mtx_lock(&exec_mutex); 119848b8605Smrg 120848b8605Smrg if (exec_heap) { 121848b8605Smrg struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); 122848b8605Smrg 123848b8605Smrg if (block) 124848b8605Smrg u_mmFreeMem(block); 125848b8605Smrg } 126848b8605Smrg 127b8e80941Smrg mtx_unlock(&exec_mutex); 128848b8605Smrg} 129848b8605Smrg 130848b8605Smrg 131848b8605Smrg#elif defined(PIPE_OS_WINDOWS) 132848b8605Smrg 133848b8605Smrg 134848b8605Smrg/* 135848b8605Smrg * Avoid Data Execution Prevention. 136848b8605Smrg */ 137848b8605Smrg 138848b8605Smrgvoid * 139848b8605Smrgrtasm_exec_malloc(size_t size) 140848b8605Smrg{ 141848b8605Smrg return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 142848b8605Smrg} 143848b8605Smrg 144848b8605Smrg 145848b8605Smrgvoid 146848b8605Smrgrtasm_exec_free(void *addr) 147848b8605Smrg{ 148848b8605Smrg VirtualFree(addr, 0, MEM_RELEASE); 149848b8605Smrg} 150848b8605Smrg 151848b8605Smrg 152848b8605Smrg#else 153848b8605Smrg 154848b8605Smrg 155848b8605Smrg/* 156848b8605Smrg * Just use regular memory. 157848b8605Smrg */ 158848b8605Smrg 159848b8605Smrgvoid * 160848b8605Smrgrtasm_exec_malloc(size_t size) 161848b8605Smrg{ 162848b8605Smrg return MALLOC( size ); 163848b8605Smrg} 164848b8605Smrg 165848b8605Smrg 166848b8605Smrgvoid 167848b8605Smrgrtasm_exec_free(void *addr) 168848b8605Smrg{ 169848b8605Smrg FREE(addr); 170848b8605Smrg} 171848b8605Smrg 172848b8605Smrg 173848b8605Smrg#endif 174