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