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