summaryrefslogtreecommitdiffstats
path: root/base/android/linker
diff options
context:
space:
mode:
authoranton@chromium.org <anton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-27 18:57:23 +0000
committeranton@chromium.org <anton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-27 18:57:23 +0000
commit168e6aef26389443a846447a65761575c8601c8e (patch)
tree40f284b67851da1c641cfe3eb92f385c702bfa35 /base/android/linker
parentb1d07cbc3a605392482a488dbdd6180789a3c45b (diff)
downloadchromium_src-168e6aef26389443a846447a65761575c8601c8e.zip
chromium_src-168e6aef26389443a846447a65761575c8601c8e.tar.gz
chromium_src-168e6aef26389443a846447a65761575c8601c8e.tar.bz2
Chromium Linker support for loading lib*.so from within an APK file
Split from https://codereview.chromium.org/301223005/ BUG= Review URL: https://codereview.chromium.org/358813002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280370 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/android/linker')
-rw-r--r--base/android/linker/linker_jni.cc166
1 files changed, 129 insertions, 37 deletions
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index bd03e02..28ed75a 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -70,14 +70,6 @@ String::String(JNIEnv* env, jstring str) {
env->ReleaseStringUTFChars(str, bytes);
}
-// Return a pointer to the base name from an input |path| string.
-const char* GetBaseNamePtr(const char* path) {
- const char* p = strrchr(path, '/');
- if (p)
- return p + 1;
- return path;
-}
-
// Return true iff |address| is a valid address for the target CPU.
bool IsValidAddress(jlong address) {
return static_cast<jlong>(static_cast<size_t>(address)) == address;
@@ -239,27 +231,13 @@ class ScopedLibrary {
crazy_library_t* lib_;
};
-// Load a library with the chromium linker. This will also call its
-// JNI_OnLoad() method, which shall register its methods. Note that
-// lazy native method resolution will _not_ work after this, because
-// Dalvik uses the system's dlsym() which won't see the new library,
-// so explicit registration is mandatory.
-// |env| is the current JNI environment handle.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// |library_name| is the library name (e.g. libfoo.so).
-// |load_address| is an explicit load address.
-// |library_info| is a LibInfo handle used to communicate information
-// with the Java side.
-// Return true on success.
-jboolean LoadLibrary(JNIEnv* env,
- jclass clazz,
- jstring library_name,
- jlong load_address,
- jobject lib_info_obj) {
- String lib_name(env, library_name);
- const char* UNUSED lib_basename = GetBaseNamePtr(lib_name.c_str());
+namespace {
+template <class LibraryOpener>
+bool GenericLoadLibrary(
+ JNIEnv* env,
+ const char* library_name, jlong load_address, jobject lib_info_obj,
+ const LibraryOpener& opener) {
crazy_context_t* context = GetCrazyContext();
if (!IsValidAddress(load_address)) {
@@ -270,15 +248,8 @@ jboolean LoadLibrary(JNIEnv* env,
// Set the desired load address (0 means randomize it).
crazy_context_set_load_address(context, static_cast<size_t>(load_address));
- // Open the library now.
- LOG_INFO("%s: Opening shared library: %s", __FUNCTION__, lib_name.c_str());
-
ScopedLibrary library;
- if (!crazy_library_open(library.GetPtr(), lib_name.c_str(), context)) {
- LOG_ERROR("%s: Could not open %s: %s",
- __FUNCTION__,
- lib_basename,
- crazy_context_get_error(context));
+ if (!opener.Open(library.GetPtr(), library_name, context)) {
return false;
}
@@ -286,7 +257,7 @@ jboolean LoadLibrary(JNIEnv* env,
if (!crazy_library_get_info(library.Get(), context, &info)) {
LOG_ERROR("%s: Could not get library information for %s: %s",
__FUNCTION__,
- lib_basename,
+ library_name,
crazy_context_get_error(context));
return false;
}
@@ -300,6 +271,118 @@ jboolean LoadLibrary(JNIEnv* env,
return true;
}
+// Used for opening the library in a regular file.
+class FileLibraryOpener {
+ public:
+ bool Open(
+ crazy_library_t** library,
+ const char* library_name,
+ crazy_context_t* context) const;
+};
+
+bool FileLibraryOpener::Open(
+ crazy_library_t** library,
+ const char* library_name,
+ crazy_context_t* context) const {
+ if (!crazy_library_open(library, library_name, context)) {
+ LOG_ERROR("%s: Could not open %s: %s",
+ __FUNCTION__,
+ library_name,
+ crazy_context_get_error(context));
+ return false;
+ }
+ return true;
+}
+
+// Used for opening the library in a zip file.
+class ZipLibraryOpener {
+ public:
+ ZipLibraryOpener(const char* zip_file) : zip_file_(zip_file) {}
+ bool Open(
+ crazy_library_t** library,
+ const char* library_name,
+ crazy_context_t* context) const;
+ private:
+ const char* zip_file_;
+};
+
+bool ZipLibraryOpener::Open(
+ crazy_library_t** library,
+ const char* library_name,
+ crazy_context_t* context) const {
+ if (!crazy_library_open_in_zip_file(
+ library, zip_file_, library_name, context)) {
+ LOG_ERROR("%s: Could not open %s in zip file %s: %s",
+ __FUNCTION__, library_name, zip_file_,
+ crazy_context_get_error(context));
+ return false;
+ }
+ return true;
+}
+
+} // unnamed namespace
+
+// Load a library with the chromium linker. This will also call its
+// JNI_OnLoad() method, which shall register its methods. Note that
+// lazy native method resolution will _not_ work after this, because
+// Dalvik uses the system's dlsym() which won't see the new library,
+// so explicit registration is mandatory.
+// |env| is the current JNI environment handle.
+// |clazz| is the static class handle for org.chromium.base.Linker,
+// and is ignored here.
+// |library_name| is the library name (e.g. libfoo.so).
+// |load_address| is an explicit load address.
+// |library_info| is a LibInfo handle used to communicate information
+// with the Java side.
+// Return true on success.
+jboolean LoadLibrary(JNIEnv* env,
+ jclass clazz,
+ jstring library_name,
+ jlong load_address,
+ jobject lib_info_obj) {
+ String lib_name(env, library_name);
+ FileLibraryOpener opener;
+ return GenericLoadLibrary(
+ env, lib_name.c_str(),
+ static_cast<size_t>(load_address), lib_info_obj, opener);
+}
+
+// Load a library from a zipfile with the chromium linker. The
+// library in the zipfile must be uncompressed and page aligned.
+// The basename of the library is given. The library is expected
+// to be lib/<abi_tag>/crazy.<basename>. The <abi_tag> used will be the
+// same as the abi for this linker. The "crazy." prefix is included
+// so that the Android Package Manager doesn't extract the library into
+// /data/app-lib.
+//
+// Loading the library will also call its JNI_OnLoad() method, which
+// shall register its methods. Note that lazy native method resolution
+// will _not_ work after this, because Dalvik uses the system's dlsym()
+// which won't see the new library, so explicit registration is mandatory.
+//
+// |env| is the current JNI environment handle.
+// |clazz| is the static class handle for org.chromium.base.Linker,
+// and is ignored here.
+// |zipfile_name| is the filename of the zipfile containing the library.
+// |library_name| is the library base name (e.g. libfoo.so).
+// |load_address| is an explicit load address.
+// |library_info| is a LibInfo handle used to communicate information
+// with the Java side.
+// Returns true on success.
+jboolean LoadLibraryInZipFile(JNIEnv* env,
+ jclass clazz,
+ jstring zipfile_name,
+ jstring library_name,
+ jlong load_address,
+ jobject lib_info_obj) {
+ String zipfile_name_str(env, zipfile_name);
+ String lib_name(env, library_name);
+ ZipLibraryOpener opener(zipfile_name_str.c_str());
+ return GenericLoadLibrary(
+ env, lib_name.c_str(),
+ static_cast<size_t>(load_address), lib_info_obj, opener);
+}
+
// Class holding the Java class and method ID for the Java side Linker
// postCallbackOnMainThread method.
struct JavaCallbackBindings_class {
@@ -492,6 +575,15 @@ const JNINativeMethod kNativeMethods[] = {
")"
"Z",
reinterpret_cast<void*>(&LoadLibrary)},
+ {"nativeLoadLibraryInZipFile",
+ "("
+ "Ljava/lang/String;"
+ "Ljava/lang/String;"
+ "J"
+ "Lorg/chromium/base/library_loader/Linker$LibInfo;"
+ ")"
+ "Z",
+ reinterpret_cast<void*>(&LoadLibraryInZipFile)},
{"nativeRunCallbackOnUiThread",
"("
"J"