| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This is the Android-specific content linker, a tiny shared library | 5 // This is the Android-specific Chromium linker, a tiny shared library |
| 6 // implementing a custom dynamic linker that can be used to load the | 6 // implementing a custom dynamic linker that can be used to load the |
| 7 // real content-based libraries (e.g. libcontentshell.so). | 7 // real Chromium libraries (e.g. libcontentshell.so). |
| 8 | 8 |
| 9 // The main point of this linker is to be able to share the RELRO | 9 // The main point of this linker is to be able to share the RELRO |
| 10 // section of libcontentshell.so (or equivalent) between the browser and | 10 // section of libcontentshell.so (or equivalent) between the browser and |
| 11 // renderer process. | 11 // renderer process. |
| 12 | 12 |
| 13 // This source code *cannot* depend on anything from base/ or the C++ | 13 // This source code *cannot* depend on anything from base/ or the C++ |
| 14 // STL, to keep the final library small, and avoid ugly dependency issues. | 14 // STL, to keep the final library small, and avoid ugly dependency issues. |
| 15 | 15 |
| 16 #include <android/log.h> | 16 #include <android/log.h> |
| 17 #include <crazy_linker.h> | 17 #include <crazy_linker.h> |
| 18 #include <jni.h> | 18 #include <jni.h> |
| 19 #include <stdlib.h> | 19 #include <stdlib.h> |
| 20 #include <unistd.h> | 20 #include <unistd.h> |
| 21 | 21 |
| 22 // Set this to 1 to enable debug traces to the Android log. | 22 // Set this to 1 to enable debug traces to the Android log. |
| 23 // Note that LOG() from "base/logging.h" cannot be used, since it is | 23 // Note that LOG() from "base/logging.h" cannot be used, since it is |
| 24 // in base/ which hasn't been loaded yet. | 24 // in base/ which hasn't been loaded yet. |
| 25 #define DEBUG 0 | 25 #define DEBUG 0 |
| 26 | 26 |
| 27 #define TAG "content_android_linker" | 27 #define TAG "chromium_android_linker" |
| 28 | 28 |
| 29 #if DEBUG | 29 #if DEBUG |
| 30 #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) | 30 #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) |
| 31 #define LOG_ERROR(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) | 31 #define LOG_ERROR(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) |
| 32 #else | 32 #else |
| 33 #define LOG_INFO(...) ((void)0) | 33 #define LOG_INFO(...) ((void)0) |
| 34 #define LOG_ERROR(...) ((void)0) | 34 #define LOG_ERROR(...) ((void)0) |
| 35 #endif | 35 #endif |
| 36 | 36 |
| 37 #define UNUSED __attribute__((unused)) | 37 #define UNUSED __attribute__((unused)) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 jfieldID load_address_id; | 147 jfieldID load_address_id; |
| 148 jfieldID load_size_id; | 148 jfieldID load_size_id; |
| 149 jfieldID relro_start_id; | 149 jfieldID relro_start_id; |
| 150 jfieldID relro_size_id; | 150 jfieldID relro_size_id; |
| 151 jfieldID relro_fd_id; | 151 jfieldID relro_fd_id; |
| 152 | 152 |
| 153 // Initialize an instance. | 153 // Initialize an instance. |
| 154 bool Init(JNIEnv* env) { | 154 bool Init(JNIEnv* env) { |
| 155 jclass clazz; | 155 jclass clazz; |
| 156 if (!InitClassReference( | 156 if (!InitClassReference( |
| 157 env, "org/chromium/content/app/Linker$LibInfo", &clazz)) { | 157 env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) { |
| 158 return false; | 158 return false; |
| 159 } | 159 } |
| 160 | 160 |
| 161 return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) && | 161 return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) && |
| 162 InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) && | 162 InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) && |
| 163 InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) && | 163 InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) && |
| 164 InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) && | 164 InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) && |
| 165 InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id); | 165 InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id); |
| 166 } | 166 } |
| 167 | 167 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 | 214 |
| 215 // Ensure libraries located in the same directory as the linker | 215 // Ensure libraries located in the same directory as the linker |
| 216 // can be loaded before system ones. | 216 // can be loaded before system ones. |
| 217 crazy_context_add_search_path_for_address( | 217 crazy_context_add_search_path_for_address( |
| 218 s_crazy_context, reinterpret_cast<void*>(&s_crazy_context)); | 218 s_crazy_context, reinterpret_cast<void*>(&s_crazy_context)); |
| 219 } | 219 } |
| 220 | 220 |
| 221 return s_crazy_context; | 221 return s_crazy_context; |
| 222 } | 222 } |
| 223 | 223 |
| 224 // Load a library with the content linker. This will also call its | 224 // Load a library with the chromium linker. This will also call its |
| 225 // JNI_OnLoad() method, which shall register its methods. Note that | 225 // JNI_OnLoad() method, which shall register its methods. Note that |
| 226 // lazy native method resolution will _not_ work after this, because | 226 // lazy native method resolution will _not_ work after this, because |
| 227 // Dalvik uses the system's dlsym() which won't see the new library, | 227 // Dalvik uses the system's dlsym() which won't see the new library, |
| 228 // so explicit registration is mandatory. | 228 // so explicit registration is mandatory. |
| 229 // |env| is the current JNI environment handle. | 229 // |env| is the current JNI environment handle. |
| 230 // |clazz| is the static class handle for org.chromium.base.Linker, | 230 // |clazz| is the static class handle for org.chromium.base.Linker, |
| 231 // and is ignored here. | 231 // and is ignored here. |
| 232 // |library_name| is the library name (e.g. libfoo.so). | 232 // |library_name| is the library name (e.g. libfoo.so). |
| 233 // |load_address| is an explicit load address. | 233 // |load_address| is an explicit load address. |
| 234 // |library_info| is a LibInfo handle used to communicate information | 234 // |library_info| is a LibInfo handle used to communicate information |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 jlong result = static_cast<jlong>(sysconf(_SC_PAGESIZE)); | 380 jlong result = static_cast<jlong>(sysconf(_SC_PAGESIZE)); |
| 381 LOG_INFO("%s: System page size is %lld bytes\n", __FUNCTION__, result); | 381 LOG_INFO("%s: System page size is %lld bytes\n", __FUNCTION__, result); |
| 382 return result; | 382 return result; |
| 383 } | 383 } |
| 384 | 384 |
| 385 const JNINativeMethod kNativeMethods[] = { | 385 const JNINativeMethod kNativeMethods[] = { |
| 386 {"nativeLoadLibrary", | 386 {"nativeLoadLibrary", |
| 387 "(" | 387 "(" |
| 388 "Ljava/lang/String;" | 388 "Ljava/lang/String;" |
| 389 "J" | 389 "J" |
| 390 "Lorg/chromium/content/app/Linker$LibInfo;" | 390 "Lorg/chromium/base/library_loader/Linker$LibInfo;" |
| 391 ")" | 391 ")" |
| 392 "Z", | 392 "Z", |
| 393 reinterpret_cast<void*>(&LoadLibrary)}, | 393 reinterpret_cast<void*>(&LoadLibrary)}, |
| 394 {"nativeCreateSharedRelro", | 394 {"nativeCreateSharedRelro", |
| 395 "(" | 395 "(" |
| 396 "Ljava/lang/String;" | 396 "Ljava/lang/String;" |
| 397 "J" | 397 "J" |
| 398 "Lorg/chromium/content/app/Linker$LibInfo;" | 398 "Lorg/chromium/base/library_loader/Linker$LibInfo;" |
| 399 ")" | 399 ")" |
| 400 "Z", | 400 "Z", |
| 401 reinterpret_cast<void*>(&CreateSharedRelro)}, | 401 reinterpret_cast<void*>(&CreateSharedRelro)}, |
| 402 {"nativeUseSharedRelro", | 402 {"nativeUseSharedRelro", |
| 403 "(" | 403 "(" |
| 404 "Ljava/lang/String;" | 404 "Ljava/lang/String;" |
| 405 "Lorg/chromium/content/app/Linker$LibInfo;" | 405 "Lorg/chromium/base/library_loader/Linker$LibInfo;" |
| 406 ")" | 406 ")" |
| 407 "Z", | 407 "Z", |
| 408 reinterpret_cast<void*>(&UseSharedRelro)}, | 408 reinterpret_cast<void*>(&UseSharedRelro)}, |
| 409 {"nativeCanUseSharedRelro", | 409 {"nativeCanUseSharedRelro", |
| 410 "(" | 410 "(" |
| 411 ")" | 411 ")" |
| 412 "Z", | 412 "Z", |
| 413 reinterpret_cast<void*>(&CanUseSharedRelro)}, | 413 reinterpret_cast<void*>(&CanUseSharedRelro)}, |
| 414 {"nativeGetPageSize", | 414 {"nativeGetPageSize", |
| 415 "(" | 415 "(" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 427 // Get new JNIEnv | 427 // Get new JNIEnv |
| 428 JNIEnv* env; | 428 JNIEnv* env; |
| 429 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { | 429 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { |
| 430 LOG_ERROR("Could not create JNIEnv"); | 430 LOG_ERROR("Could not create JNIEnv"); |
| 431 return -1; | 431 return -1; |
| 432 } | 432 } |
| 433 | 433 |
| 434 // Register native methods. | 434 // Register native methods. |
| 435 jclass linker_class; | 435 jclass linker_class; |
| 436 if (!InitClassReference( | 436 if (!InitClassReference( |
| 437 env, "org/chromium/content/app/Linker", &linker_class)) | 437 env, "org/chromium/base/library_loader/Linker", &linker_class)) |
| 438 return -1; | 438 return -1; |
| 439 | 439 |
| 440 LOG_INFO("%s: Registering native methods", __FUNCTION__); | 440 LOG_INFO("%s: Registering native methods", __FUNCTION__); |
| 441 env->RegisterNatives(linker_class, | 441 env->RegisterNatives(linker_class, |
| 442 kNativeMethods, | 442 kNativeMethods, |
| 443 sizeof(kNativeMethods) / sizeof(kNativeMethods[0])); | 443 sizeof(kNativeMethods) / sizeof(kNativeMethods[0])); |
| 444 | 444 |
| 445 // Find LibInfo field ids. | 445 // Find LibInfo field ids. |
| 446 LOG_INFO("%s: Caching field IDs", __FUNCTION__); | 446 LOG_INFO("%s: Caching field IDs", __FUNCTION__); |
| 447 if (!s_lib_info_fields.Init(env)) { | 447 if (!s_lib_info_fields.Init(env)) { |
| 448 return -1; | 448 return -1; |
| 449 } | 449 } |
| 450 | 450 |
| 451 // Save JavaVM* handle into context. | 451 // Save JavaVM* handle into context. |
| 452 crazy_context_t* context = GetCrazyContext(); | 452 crazy_context_t* context = GetCrazyContext(); |
| 453 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); | 453 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); |
| 454 | 454 |
| 455 LOG_INFO("%s: Done", __FUNCTION__); | 455 LOG_INFO("%s: Done", __FUNCTION__); |
| 456 return JNI_VERSION_1_4; | 456 return JNI_VERSION_1_4; |
| 457 } | 457 } |
| OLD | NEW |