14a49301eSmrg/************************************************************************** 24a49301eSmrg * 34a49301eSmrg * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 94a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the 104a49301eSmrg * Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice shall be included 134a49301eSmrg * in all copies or substantial portions of the Software. 144a49301eSmrg * 154a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 164a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 174a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 224a49301eSmrg * 234a49301eSmrg **************************************************************************/ 244a49301eSmrg 254a49301eSmrg 264a49301eSmrg/** 274a49301eSmrg * \file exemem.c 284a49301eSmrg * Functions for allocating executable memory. 294a49301eSmrg * 304a49301eSmrg * \author Keith Whitwell 314a49301eSmrg */ 324a49301eSmrg 334a49301eSmrg 344a49301eSmrg#include "pipe/p_compiler.h" 354a49301eSmrg#include "util/u_debug.h" 36cdc920a0Smrg#include "os/os_thread.h" 374a49301eSmrg#include "util/u_memory.h" 384a49301eSmrg 394a49301eSmrg#include "rtasm_execmem.h" 404a49301eSmrg 41af69d88dSmrg#ifndef MAP_ANONYMOUS 424a49301eSmrg#define MAP_ANONYMOUS MAP_ANON 434a49301eSmrg#endif 444a49301eSmrg 454a49301eSmrg#if defined(PIPE_OS_WINDOWS) 464a49301eSmrg#ifndef WIN32_LEAN_AND_MEAN 474a49301eSmrg#define WIN32_LEAN_AND_MEAN 1 484a49301eSmrg#endif 494a49301eSmrg#include <windows.h> 504a49301eSmrg#endif 514a49301eSmrg 5201e04c3fSmrg#if defined(PIPE_OS_UNIX) 534a49301eSmrg 544a49301eSmrg 554a49301eSmrg/* 564a49301eSmrg * Allocate a large block of memory which can hold code then dole it out 574a49301eSmrg * in pieces by means of the generic memory manager code. 584a49301eSmrg */ 594a49301eSmrg 604a49301eSmrg#include <unistd.h> 614a49301eSmrg#include <sys/mman.h> 624a49301eSmrg#include "util/u_mm.h" 634a49301eSmrg 644a49301eSmrg#define EXEC_HEAP_SIZE (10*1024*1024) 654a49301eSmrg 6601e04c3fSmrgstatic mtx_t exec_mutex = _MTX_INITIALIZER_NP; 674a49301eSmrg 684a49301eSmrgstatic struct mem_block *exec_heap = NULL; 694a49301eSmrgstatic unsigned char *exec_mem = NULL; 704a49301eSmrg 714a49301eSmrg 72af69d88dSmrgstatic int 734a49301eSmrginit_heap(void) 744a49301eSmrg{ 754a49301eSmrg if (!exec_heap) 764a49301eSmrg exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE ); 774a49301eSmrg 784a49301eSmrg if (!exec_mem) 794a49301eSmrg exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE, 804a49301eSmrg PROT_EXEC | PROT_READ | PROT_WRITE, 814a49301eSmrg MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 82af69d88dSmrg 83af69d88dSmrg return (exec_mem != MAP_FAILED); 844a49301eSmrg} 854a49301eSmrg 864a49301eSmrg 874a49301eSmrgvoid * 884a49301eSmrgrtasm_exec_malloc(size_t size) 894a49301eSmrg{ 904a49301eSmrg struct mem_block *block = NULL; 914a49301eSmrg void *addr = NULL; 924a49301eSmrg 9301e04c3fSmrg mtx_lock(&exec_mutex); 944a49301eSmrg 95af69d88dSmrg if (!init_heap()) 96af69d88dSmrg goto bail; 974a49301eSmrg 984a49301eSmrg if (exec_heap) { 994a49301eSmrg size = (size + 31) & ~31; /* next multiple of 32 bytes */ 1004a49301eSmrg block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */ 1014a49301eSmrg } 1024a49301eSmrg 1034a49301eSmrg if (block) 1044a49301eSmrg addr = exec_mem + block->ofs; 1054a49301eSmrg else 1064a49301eSmrg debug_printf("rtasm_exec_malloc failed\n"); 107af69d88dSmrg 108af69d88dSmrgbail: 10901e04c3fSmrg mtx_unlock(&exec_mutex); 1104a49301eSmrg 1114a49301eSmrg return addr; 1124a49301eSmrg} 1134a49301eSmrg 1144a49301eSmrg 1154a49301eSmrgvoid 1164a49301eSmrgrtasm_exec_free(void *addr) 1174a49301eSmrg{ 11801e04c3fSmrg mtx_lock(&exec_mutex); 1194a49301eSmrg 1204a49301eSmrg if (exec_heap) { 1214a49301eSmrg struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); 1224a49301eSmrg 1234a49301eSmrg if (block) 1244a49301eSmrg u_mmFreeMem(block); 1254a49301eSmrg } 1264a49301eSmrg 12701e04c3fSmrg mtx_unlock(&exec_mutex); 1284a49301eSmrg} 1294a49301eSmrg 1304a49301eSmrg 1314a49301eSmrg#elif defined(PIPE_OS_WINDOWS) 1324a49301eSmrg 1334a49301eSmrg 1344a49301eSmrg/* 1354a49301eSmrg * Avoid Data Execution Prevention. 1364a49301eSmrg */ 1374a49301eSmrg 1384a49301eSmrgvoid * 1394a49301eSmrgrtasm_exec_malloc(size_t size) 1404a49301eSmrg{ 1414a49301eSmrg return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 1424a49301eSmrg} 1434a49301eSmrg 1444a49301eSmrg 1454a49301eSmrgvoid 1464a49301eSmrgrtasm_exec_free(void *addr) 1474a49301eSmrg{ 1484a49301eSmrg VirtualFree(addr, 0, MEM_RELEASE); 1494a49301eSmrg} 1504a49301eSmrg 1514a49301eSmrg 1524a49301eSmrg#else 1534a49301eSmrg 1544a49301eSmrg 1554a49301eSmrg/* 1564a49301eSmrg * Just use regular memory. 1574a49301eSmrg */ 1584a49301eSmrg 1594a49301eSmrgvoid * 1604a49301eSmrgrtasm_exec_malloc(size_t size) 1614a49301eSmrg{ 1624a49301eSmrg return MALLOC( size ); 1634a49301eSmrg} 1644a49301eSmrg 1654a49301eSmrg 1664a49301eSmrgvoid 1674a49301eSmrgrtasm_exec_free(void *addr) 1684a49301eSmrg{ 1694a49301eSmrg FREE(addr); 1704a49301eSmrg} 1714a49301eSmrg 1724a49301eSmrg 1734a49301eSmrg#endif 174