SysUtil.cpp revision 99409883d9c4c0ffb49b070ce307bb33a9dfe9f1
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * System utilities.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "SysUtil.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/mman.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <limits.h>
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Having trouble finding a portable way to get this.  sysconf(_SC_PAGE_SIZE)
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * seems appropriate, but we don't have that on the device.  Some systems
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have getpagesize(2), though the linux man page has some odd cautions.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEFAULT_PAGE_SIZE   4096
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an anonymous shared memory segment large enough to hold "length"
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bytes.  The actual segment may be larger because mmap() operates on
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * page boundaries (usually 4K).
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* sysCreateAnonShmem(size_t length)
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* ptr;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr = mmap(NULL, length, PROT_READ | PROT_WRITE,
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            MAP_SHARED | MAP_ANON, -1, 0);
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ptr == MAP_FAILED) {
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("mmap(%d, RW, SHARED|ANON) failed: %s\n", (int) length,
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strerror(errno));
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ptr;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGE("sysCreateAnonShmem not implemented.\n");
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Create a private anonymous storage area.
7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectint sysCreatePrivateMap(size_t length, MemMapping* pMap)
7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    void* memPtr;
7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    memPtr = sysCreateAnonShmem(length);
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (memPtr == NULL)
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        return -1;
7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    pMap->addr = pMap->baseAddr = memPtr;
8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    pMap->length = pMap->baseLength = length;
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    return 0;
8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project}
8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
8599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Determine the current offset and remaining length of the open file.
8699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int getFileStartAndLength(int fd, off_t *start_, size_t *length_)
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t start, end;
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(start_ != NULL);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(length_ != NULL);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    start = lseek(fd, 0L, SEEK_CUR);
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    end = lseek(fd, 0L, SEEK_END);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    (void) lseek(fd, start, SEEK_SET);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start == (off_t) -1 || end == (off_t) -1) {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("could not determine length of file\n");
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    length = end - start;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (length == 0) {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("file is empty\n");
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *start_ = start;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *length_ = length;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pull the contents of a file into an new shared memory segment.  We grab
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * everything from fd's current offset on.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to know the length ahead of time so we can allocate a segment
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of sufficient size.
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint sysLoadFileInShmem(int fd, MemMapping* pMap)
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t start;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length, actual;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* memPtr;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pMap != NULL);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getFileStartAndLength(fd, &start, &length) < 0)
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memPtr = sysCreateAnonShmem(length);
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (memPtr == NULL)
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = read(fd, memPtr, length);
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual != length) {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("only read %d of %d bytes\n", (int) actual, (int) length);
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sysReleaseShmem(pMap);
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseAddr = pMap->addr = memPtr;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseLength = pMap->length = length;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGE("sysLoadFileInShmem not implemented.\n");
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Map a file (from fd's current offset) into a shared, read-only memory
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * segment.  The file offset must be a multiple of the page size.
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On success, returns 0 and fills out "pMap".  On failure, returns a nonzero
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value and does not disturb "pMap".
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint sysMapFileInShmem(int fd, MemMapping* pMap)
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t start;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* memPtr;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pMap != NULL);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getFileStartAndLength(fd, &start, &length) < 0)
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start);
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (memPtr == MAP_FAILED) {
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", (int) length,
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fd, (int) start, strerror(errno));
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseAddr = pMap->addr = memPtr;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseLength = pMap->length = length;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* No MMAP, just fake it by copying the bits.
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       For Win32 we could use MapViewOfFile if really necessary
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project       (see libs/utils/FileMap.cpp).
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    */
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t start;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* memPtr;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pMap != NULL);
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getFileStartAndLength(fd, &start, &length) < 0)
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memPtr = malloc(length);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (read(fd, memPtr, length) < 0) {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("read(fd=%d, start=%d, length=%d) failed: %s\n", (int) length,
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fd, (int) start, strerror(errno));
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseAddr = pMap->addr = memPtr;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseLength = pMap->length = length;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Map part of a file (from fd's current offset) into a shared, read-only
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * memory segment.
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On success, returns 0 and fills out "pMap".  On failure, returns a nonzero
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value and does not disturb "pMap".
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint sysMapFileSegmentInShmem(int fd, off_t start, long length,
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MemMapping* pMap)
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t dummy;
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t fileLength, actualLength;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t actualStart;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int adjust;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* memPtr;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pMap != NULL);
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getFileStartAndLength(fd, &dummy, &fileLength) < 0)
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start + length > (long)fileLength) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("bad segment: st=%d len=%ld flen=%d\n",
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (int) start, length, (int) fileLength);
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* adjust to be page-aligned */
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    adjust = start % DEFAULT_PAGE_SIZE;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actualStart = start - adjust;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actualLength = length + adjust;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED,
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fd, actualStart);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (memPtr == MAP_FAILED) {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n",
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (int) actualLength, fd, (int) actualStart, strerror(errno));
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseAddr = memPtr;
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseLength = actualLength;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->addr = (char*)memPtr + adjust;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->length = length;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d\n",
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (int) start, (int) length,
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMap->baseAddr, (int) pMap->baseLength,
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMap->addr, (int) pMap->length);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGE("sysMapFileSegmentInShmem not implemented.\n");
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release a memory mapping.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sysReleaseShmem(MemMapping* pMap)
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_FILEMAP
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pMap->baseAddr == NULL && pMap->baseLength == 0)
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (munmap(pMap->baseAddr, pMap->baseLength) < 0) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("munmap(%p, %d) failed: %s\n",
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pMap->baseAddr, (int)pMap->baseLength, strerror(errno));
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("munmap(%p, %d) succeeded\n", pMap->baseAddr, pMap->baseLength);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMap->baseAddr = NULL;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMap->baseLength = 0;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Free the bits allocated by sysMapFileInShmem. */
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pMap->baseAddr != NULL) {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      free(pMap->baseAddr);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      pMap->baseAddr = NULL;
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMap->baseLength = 0;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make a copy of a MemMapping.
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid sysCopyMap(MemMapping* dst, const MemMapping* src)
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(dst, src, sizeof(MemMapping));
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307