Index: base/android/linker/linker_jni.cc |
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc |
index 79dd20103e7add06b2b30dd0550193682cbb7d50..83cc1ada24630ecf525a340bcc588722899ad4a1 100644 |
--- a/base/android/linker/linker_jni.cc |
+++ b/base/android/linker/linker_jni.cc |
@@ -15,7 +15,10 @@ |
#include <android/log.h> |
#include <crazy_linker.h> |
+#include <errno.h> |
+#include <fcntl.h> |
#include <jni.h> |
+#include <limits.h> |
#include <stdlib.h> |
#include <sys/mman.h> |
#include <unistd.h> |
@@ -574,6 +577,44 @@ jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz, jlong bytes) { |
return static_cast<jlong>(reinterpret_cast<uintptr_t>(address)); |
} |
+// Check whether the device supports memory mapping APK files with executable |
+// permissions. |
+// |
+// |env| is the current JNI environment handle and is ignored here. |
rmcilroy
2014/10/10 16:26:08
not ignored - used for string conversion
petrcermak
2014/10/10 17:13:24
Done.
|
+// |clazz| is the static class handle for org.chromium.base.Linker, |
+// and is ignored here. |
rmcilroy
2014/10/10 16:26:08
nit - I would just write "|class| is the static cl
petrcermak
2014/10/10 17:13:24
Done.
|
+// |apkfile_name| is the filename of the APK. |
+// Returns true if supported. |
+jboolean CheckApkMemoryMappingSupport(JNIEnv* env, jclass clazz, |
+ jstring apkfile_name) { |
+ String apkfile_name_str(env, apkfile_name); |
+ const char* apkfile_name_c_str = apkfile_name_str.c_str(); |
+ |
+ int fd = TEMP_FAILURE_RETRY(open(apkfile_name_c_str, O_RDONLY)); |
rmcilroy
2014/10/10 16:26:08
I would avoid the TEMP_FAILURE_RETRY - it's not su
petrcermak
2014/10/10 17:13:24
Done.
|
+ if (fd == -1) { |
+ LOG_ERROR("%s: Failed to open %s\n", __FUNCTION__, apkfile_name_c_str); |
+ return 0; |
+ } |
+ |
+ LOG_INFO("%s: Memory mapping the first page of %s\n", __FUNCTION__, |
+ apkfile_name_c_str); |
+ void* address = mmap(NULL, PAGE_SIZE, PROT_EXEC, MAP_PRIVATE, fd, 0); |
+ |
+ jboolean success; |
+ if (address == MAP_FAILED) { |
+ success = 0; |
rmcilroy
2014/10/10 16:26:08
/s/0/false (and true for '1' below)
petrcermak
2014/10/10 17:13:24
Done.
|
+ } else { |
+ success = 1; |
+ munmap(address, PAGE_SIZE); |
+ } |
+ |
+ TEMP_FAILURE_RETRY(close(fd)); |
rmcilroy
2014/10/10 16:26:08
ditto
petrcermak
2014/10/10 17:13:24
Done.
|
+ |
+ LOG_INFO(" %ssupported\n", success ? "" : "NOT "); |
+ return success; |
+ |
+} |
+ |
const JNINativeMethod kNativeMethods[] = { |
{"nativeLoadLibrary", |
"(" |
@@ -623,7 +664,13 @@ const JNINativeMethod kNativeMethods[] = { |
"J" |
")" |
"J", |
- reinterpret_cast<void*>(&GetRandomBaseLoadAddress)}, }; |
+ reinterpret_cast<void*>(&GetRandomBaseLoadAddress)}, |
+ {"nativeCheckApkMemoryMappingSupport", |
+ "(" |
+ "Ljava/lang/String;" |
+ ")" |
+ "Z", |
+ reinterpret_cast<void*>(&CheckApkMemoryMappingSupport)}, }; |
} // namespace |