LLVM API Documentation
00001 //===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by Reid Spencer and is distributed under the 00006 // University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines some functions for various memory management utilities. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "Unix.h" 00015 #include "llvm/System/Process.h" 00016 00017 #ifdef HAVE_SYS_MMAN_H 00018 #include <sys/mman.h> 00019 #endif 00020 00021 /// AllocateRWXMemory - Allocate a slab of memory with read/write/execute 00022 /// permissions. This is typically used for JIT applications where we want 00023 /// to emit code to the memory then jump to it. Getting this type of memory 00024 /// is very OS specific. 00025 /// 00026 llvm::sys::MemoryBlock 00027 llvm::sys::Memory::AllocateRWX(unsigned NumBytes, const MemoryBlock* NearBlock, 00028 std::string *ErrMsg) { 00029 if (NumBytes == 0) return MemoryBlock(); 00030 00031 long pageSize = Process::GetPageSize(); 00032 unsigned NumPages = (NumBytes+pageSize-1)/pageSize; 00033 00034 int fd = -1; 00035 #ifdef NEED_DEV_ZERO_FOR_MMAP 00036 static int zero_fd = open("/dev/zero", O_RDWR); 00037 if (zero_fd == -1) { 00038 GetErrno("Can't open /dev/zero device", ErrMsg); 00039 return MemoryBlock(); 00040 } 00041 fd = zero_fd; 00042 #endif 00043 00044 int flags = MAP_PRIVATE | 00045 #ifdef HAVE_MMAP_ANONYMOUS 00046 MAP_ANONYMOUS 00047 #else 00048 MAP_ANON 00049 #endif 00050 ; 00051 00052 void* start = NearBlock ? (unsigned char*)NearBlock->base() + 00053 NearBlock->size() : 0; 00054 00055 void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, 00056 flags, fd, 0); 00057 if (pa == MAP_FAILED) { 00058 if (NearBlock) //Try again without a near hint 00059 return AllocateRWX(NumBytes, 0); 00060 00061 GetErrno("Can't allocate RWX Memory", ErrMsg); 00062 return MemoryBlock(); 00063 } 00064 MemoryBlock result; 00065 result.Address = pa; 00066 result.Size = NumPages*pageSize; 00067 return result; 00068 } 00069 00070 bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { 00071 if (M.Address == 0 || M.Size == 0) return false; 00072 if (0 != ::munmap(M.Address, M.Size)) 00073 return GetErrno("Can't release RWX Memory", ErrMsg); 00074 return false; 00075 } 00076