Merge change I117408b2
* changes:
Restore support for DEX on FAT.
diff --git a/libdex/CmdUtils.c b/libdex/CmdUtils.c
index 7dfee87..102664c 100644
--- a/libdex/CmdUtils.c
+++ b/libdex/CmdUtils.c
@@ -162,7 +162,7 @@
goto bail;
}
- if (sysMapFileInShmem(fd, pMap) != 0) {
+ if (sysMapFileInShmemReadOnly(fd, pMap) != 0) {
fprintf(stderr, "ERROR: Unable to map %s\n", fileName);
close(fd);
goto bail;
diff --git a/libdex/SysUtil.c b/libdex/SysUtil.c
index 08dc67c..eaa612b 100644
--- a/libdex/SysUtil.c
+++ b/libdex/SysUtil.c
@@ -160,7 +160,7 @@
* On success, returns 0 and fills out "pMap". On failure, returns a nonzero
* value and does not disturb "pMap".
*/
-int sysMapFileInShmem(int fd, MemMapping* pMap)
+int sysMapFileInShmemReadOnly(int fd, MemMapping* pMap)
{
#ifdef HAVE_POSIX_FILEMAP
off_t start;
@@ -172,32 +172,72 @@
if (getFileStartAndLength(fd, &start, &length) < 0)
return -1;
- /*
- * This was originally (PROT_READ, MAP_SHARED), but we want to be able
- * to make local edits for verification errors and debugger breakpoints.
- * So we map it read-write and private, but use mprotect to mark the
- * pages read-only. This should yield identical results so long as the
- * pages are left read-only.
- */
- memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
- fd, start);
+ memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start);
if (memPtr == MAP_FAILED) {
- LOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s\n", (int) length,
+ LOGW("mmap(%d, RO, FILE|SHARED, %d, %d) failed: %s\n", (int) length,
fd, (int) start, strerror(errno));
return -1;
}
- if (mprotect(memPtr, length, PROT_READ) < 0) {
- LOGW("mprotect(%p, %d, PROT_READ) failed: %s\n",
- memPtr, length, strerror(errno));
- (void) munmap(memPtr, length);
- return -1;
- }
pMap->baseAddr = pMap->addr = memPtr;
pMap->baseLength = pMap->length = length;
return 0;
#else
+ sysFakeMapFile(fd, pMap);
+#endif
+}
+
+/*
+ * Map a file (from fd's current offset) into a private, read-write memory
+ * segment that will be marked read-only (a/k/a "writable read-only"). The
+ * file offset must be a multiple of the system page size.
+ *
+ * In some cases the mapping will be fully writable (e.g. for files on
+ * FAT filesystems).
+ *
+ * On success, returns 0 and fills out "pMap". On failure, returns a nonzero
+ * value and does not disturb "pMap".
+ */
+int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap)
+{
+#ifdef HAVE_POSIX_FILEMAP
+ off_t start;
+ size_t length;
+ void* memPtr;
+
+ assert(pMap != NULL);
+
+ if (getFileStartAndLength(fd, &start, &length) < 0)
+ return -1;
+
+ memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
+ fd, start);
+ if (memPtr == MAP_FAILED) {
+ LOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s\n", (int) length,
+ fd, (int) start, strerror(errno));
+ return -1;
+ }
+ if (mprotect(memPtr, length, PROT_READ) < 0) {
+ /* this fails with EACCESS on FAT filesystems, e.g. /sdcard */
+ int err = errno;
+ LOGV("mprotect(%p, %d, PROT_READ) failed: %s\n",
+ memPtr, length, strerror(err));
+ LOGD("mprotect(RO) failed (%d), file will remain read-write\n", err);
+ }
+
+ pMap->baseAddr = pMap->addr = memPtr;
+ pMap->baseLength = pMap->length = length;
+
+ return 0;
+#else
+ sysFakeMapFile(fd, pMap);
+#endif
+}
+
+#ifndef HAVE_POSIX_FILEMAP
+int sysFakeMapFile(int fd, MemMapping* pMap)
+{
/* No MMAP, just fake it by copying the bits.
For Win32 we could use MapViewOfFile if really necessary
(see libs/utils/FileMap.cpp).
@@ -222,8 +262,8 @@
pMap->baseLength = pMap->length = length;
return 0;
-#endif
}
+#endif
/*
* Map part of a file (from fd's current offset) into a shared, read-only
@@ -314,7 +354,7 @@
int prot = wantReadWrite ? (PROT_READ|PROT_WRITE) : (PROT_READ);
if (mprotect(alignAddr, alignLength, prot) != 0) {
int err = errno;
- LOGW("mprotect (%p,%zd,%d) failed: %s\n",
+ LOGV("mprotect (%p,%zd,%d) failed: %s\n",
alignAddr, alignLength, prot, strerror(errno));
return (errno != 0) ? errno : -1;
}
diff --git a/libdex/SysUtil.h b/libdex/SysUtil.h
index 6ee352b..b300a7b 100644
--- a/libdex/SysUtil.h
+++ b/libdex/SysUtil.h
@@ -66,10 +66,19 @@
*
* On success, "pMap" is filled in, and zero is returned.
*/
-int sysMapFileInShmem(int fd, MemMapping* pMap);
+int sysMapFileInShmemReadOnly(int fd, MemMapping* pMap);
/*
- * Like sysMapFileInShmem, but on only part of a file.
+ * Map a file (from fd's current offset) into a shared, read-only memory
+ * segment that can be made writable. (In some cases, such as when
+ * mapping a file on a FAT filesystem, the result may be fully writable.)
+ *
+ * On success, "pMap" is filled in, and zero is returned.
+ */
+int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap);
+
+/*
+ * Like sysMapFileInShmemReadOnly, but on only part of a file.
*/
int sysMapFileSegmentInShmem(int fd, off_t start, long length,
MemMapping* pMap);
diff --git a/libdex/ZipArchive.c b/libdex/ZipArchive.c
index 3f88e7d..7c7e18e 100644
--- a/libdex/ZipArchive.c
+++ b/libdex/ZipArchive.c
@@ -310,7 +310,7 @@
pArchive->mFd = fd;
- if (sysMapFileInShmem(pArchive->mFd, &map) != 0) {
+ if (sysMapFileInShmemReadOnly(pArchive->mFd, &map) != 0) {
err = -1;
LOGW("Map of '%s' failed\n", debugFileName);
goto bail;
diff --git a/tests/071-dexfile/expected.txt b/tests/071-dexfile/expected.txt
index 8aa4061..b7af75e 100644
--- a/tests/071-dexfile/expected.txt
+++ b/tests/071-dexfile/expected.txt
@@ -1,4 +1,3 @@
-My path is: test-ex.jar
Constructing another
Got expected ULE
done
diff --git a/vm/DvmDex.c b/vm/DvmDex.c
index 20a4376..258d768 100644
--- a/vm/DvmDex.c
+++ b/vm/DvmDex.c
@@ -130,7 +130,7 @@
goto bail;
}
- if (sysMapFileInShmem(fd, &memMap) != 0) {
+ if (sysMapFileInShmemWritableReadOnly(fd, &memMap) != 0) {
LOGE("Unable to map file\n");
goto bail;
}
@@ -245,16 +245,16 @@
}
LOGV("+++ change byte at %p from 0x%02x to 0x%02x\n", addr, *addr, newVal);
- if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) < 0) {
- LOGE("access change failed\n");
- return false;
+ if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) != 0) {
+ LOGD("NOTE: DEX page access change (->RW) failed\n");
+ /* expected on files mounted from FAT; keep going (may crash) */
}
*addr = newVal;
- if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) < 0) {
- LOGW("WARNING: unable to restore read-only access on mapping\n");
- /* not fatal, keep going */
+ if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) != 0) {
+ LOGD("NOTE: DEX page access change (->RO) failed\n");
+ /* expected on files mounted from FAT; keep going */
}
return true;
@@ -274,16 +274,16 @@
}
LOGV("+++ change 2byte at %p from 0x%04x to 0x%04x\n", addr, *addr, newVal);
- if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) < 0) {
- LOGE("access change failed\n");
- return false;
+ if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) != 0) {
+ LOGD("NOTE: DEX page access change (->RW) failed\n");
+ /* expected on files mounted from FAT; keep going (may crash) */
}
*addr = newVal;
- if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) < 0) {
- LOGW("WARNING: unable to restore read-only access on mapping\n");
- /* not fatal, keep going */
+ if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) != 0) {
+ LOGD("NOTE: DEX page access change (->RO) failed\n");
+ /* expected on files mounted from FAT; keep going */
}
return true;