diff options
author | anton@chromium.org <anton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-27 18:57:23 +0000 |
---|---|---|
committer | anton@chromium.org <anton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-27 18:57:23 +0000 |
commit | 168e6aef26389443a846447a65761575c8601c8e (patch) | |
tree | 40f284b67851da1c641cfe3eb92f385c702bfa35 /base/android/linker | |
parent | b1d07cbc3a605392482a488dbdd6180789a3c45b (diff) | |
download | chromium_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.cc | 166 |
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" |