1b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines/* 2b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Copyright 2011, The Android Open Source Project 3b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * 4b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 5b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * you may not use this file except in compliance with the License. 6b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * You may obtain a copy of the License at 7b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * 8b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * http://www.apache.org/licenses/LICENSE-2.0 9b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * 10b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Unless required by applicable law or agreed to in writing, software 11b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 12b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * See the License for the specific language governing permissions and 14b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * limitations under the License. 15b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines */ 16b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 17b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "MemChunk.h" 18b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 19b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "utils/flush_cpu_cache.h" 20b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "utils/helper.h" 21b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 22b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <llvm/Support/raw_ostream.h> 23b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 241033b5974b02238c2413119963408a1ad65d5c93Raphael Moll#ifndef USE_MINGW /* TODO create a proper HAVE_MMAN_H */ 25b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/mman.h> 261033b5974b02238c2413119963408a1ad65d5c93Raphael Moll#else 271033b5974b02238c2413119963408a1ad65d5c93Raphael Moll#include "mmanWindows.h" 281033b5974b02238c2413119963408a1ad65d5c93Raphael Moll#endif 29b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 30b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdlib.h> 31b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 32b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#ifndef MAP_32BIT 33b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#define MAP_32BIT 0 34b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines// Note: If the <sys/mman.h> does not come with MAP_32BIT, then we 35b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines// define it as zero, so that it won't manipulate the flags. 36b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#endif 37b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 38b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines//#define USE_FIXED_ADDR_MEM_CHUNK 1 39b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 40b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#if USE_FIXED_ADDR_MEM_CHUNK 41b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesstatic uintptr_t StartAddr = 0x7e000000UL; 42b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#endif 43b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 44a221f569d741a425beca4f111931e12177e3a3f3Stephen HinesAllocFunc MemChunk::VendorAlloc = NULL; 45a221f569d741a425beca4f111931e12177e3a3f3Stephen HinesFreeFunc MemChunk::VendorFree = NULL; 46a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines 47a221f569d741a425beca4f111931e12177e3a3f3Stephen HinesMemChunk::MemChunk() : buf(NULL), buf_size(0), bVendorBuf(true) { 48b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines} 49b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 50b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen HinesMemChunk::~MemChunk() { 51a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (!invalidBuf() && bVendorBuf && VendorFree) { 52a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines (*VendorFree)(buf); 53a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines return; 54a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines } 55a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (!invalidBuf()) { 56b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines munmap(buf, buf_size); 57b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 58b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines} 59b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 60a221f569d741a425beca4f111931e12177e3a3f3Stephen Hinesbool MemChunk::invalidBuf() const { 61a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines return (buf == 0 || buf == (unsigned char *)MAP_FAILED); 62a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines} 63a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines 64b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesbool MemChunk::allocate(size_t size) { 65b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines if (size == 0) { 66b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines return true; 67b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 68a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (VendorAlloc) { 69a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines buf = (unsigned char*)(*VendorAlloc)(size, 0); 70a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines } 71a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (invalidBuf()) { 72a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines bVendorBuf = false; 73b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#if USE_FIXED_ADDR_MEM_CHUNK 74a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines buf = (unsigned char *)mmap((void *)StartAddr, size, 75a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines PROT_READ | PROT_WRITE, 76a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines MAP_PRIVATE | MAP_ANON | MAP_32BIT, 77a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines -1, 0); 78b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#else 79a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines buf = (unsigned char *)mmap(0, size, 80a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines PROT_READ | PROT_WRITE, 81a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines MAP_PRIVATE | MAP_ANON | MAP_32BIT, 82a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines -1, 0); 83b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#endif 84a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines } 85b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 86a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (invalidBuf()) { 87b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines return false; 88b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 89b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 90b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#if USE_FIXED_ADDR_MEM_CHUNK 91b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines StartAddr += (size + 4095) / 4096 * 4096; 92b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#endif 93b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 94b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines buf_size = size; 95b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines return true; 96b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines} 97b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 98b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid MemChunk::print() const { 99a221f569d741a425beca4f111931e12177e3a3f3Stephen Hines if (!invalidBuf()) { 100b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines dump_hex(buf, buf_size, 0, buf_size); 101b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 102b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines} 103b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 104b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesbool MemChunk::protect(int prot) { 105b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines if (buf_size > 0) { 106b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines int ret = mprotect((void *)buf, buf_size, prot); 107b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines if (ret == -1) { 108b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines llvm::errs() << "Error: Can't mprotect.\n"; 109b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines return false; 110b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 111b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 112b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines if (prot & PROT_EXEC) { 113b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines FLUSH_CPU_CACHE(buf, buf + buf_size); 114b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 115b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines } 116b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines 117b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines return true; 118b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines} 119