linker_jni.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // This is the Android-specific Chromium linker, a tiny shared library
  5. // implementing a custom dynamic linker that can be used to load the
  6. // real Chromium libraries.
  7. // The main point of this linker is to be able to share the RELRO
  8. // section of libcontentshell.so (or equivalent) between the browser and
  9. // renderer process.
  10. // This source code *cannot* depend on anything from base/ or the C++
  11. // STL, to keep the final library small, and avoid ugly dependency issues.
  12. #ifndef BASE_ANDROID_LINKER_LINKER_JNI_H_
  13. #define BASE_ANDROID_LINKER_LINKER_JNI_H_
  14. #include <android/log.h>
  15. #include <jni.h>
  16. #include <stddef.h>
  17. #include <stdlib.h>
  18. #include "build/build_config.h"
  19. // Set this to 1 to enable debug traces to the Android log.
  20. // Note that LOG() from "base/logging.h" cannot be used, since it is
  21. // in base/ which hasn't been loaded yet.
  22. #define DEBUG 0
  23. #define TAG "cr_ChromiumAndroidLinker"
  24. #if DEBUG
  25. #define LOG_INFO(FORMAT, ...) \
  26. __android_log_print(ANDROID_LOG_INFO, TAG, "%s: " FORMAT, __FUNCTION__, \
  27. ##__VA_ARGS__)
  28. #else
  29. #define LOG_INFO(FORMAT, ...) ((void)0)
  30. #endif
  31. #define LOG_ERROR(FORMAT, ...) \
  32. __android_log_print(ANDROID_LOG_ERROR, TAG, "%s: " FORMAT, __FUNCTION__, \
  33. ##__VA_ARGS__)
  34. #define UNUSED __attribute__((unused))
  35. #if defined(ARCH_CPU_X86)
  36. // Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
  37. // x86 - use force_align_arg_pointer to realign the stack at the JNI
  38. // boundary. https://crbug.com/655248
  39. #define JNI_GENERATOR_EXPORT \
  40. extern "C" __attribute__((visibility("default"), force_align_arg_pointer))
  41. #else
  42. #define JNI_GENERATOR_EXPORT extern "C" __attribute__((visibility("default")))
  43. #endif
  44. #if defined(__arm__) && defined(__ARM_ARCH_7A__)
  45. #define CURRENT_ABI "armeabi-v7a"
  46. #elif defined(__arm__)
  47. #define CURRENT_ABI "armeabi"
  48. #elif defined(__i386__)
  49. #define CURRENT_ABI "x86"
  50. #elif defined(__mips__)
  51. #define CURRENT_ABI "mips"
  52. #elif defined(__x86_64__)
  53. #define CURRENT_ABI "x86_64"
  54. #elif defined(__aarch64__)
  55. #define CURRENT_ABI "arm64-v8a"
  56. #else
  57. #error "Unsupported target abi"
  58. #endif
  59. namespace chromium_android_linker {
  60. // Larger than the largest library we might attempt to load.
  61. static const size_t kAddressSpaceReservationSize = 192 * 1024 * 1024;
  62. // A simple scoped UTF String class that can be initialized from
  63. // a Java jstring handle. Modeled like std::string, which cannot
  64. // be used here.
  65. class String {
  66. public:
  67. String(JNIEnv* env, jstring str);
  68. inline ~String() { ::free(ptr_); }
  69. inline const char* c_str() const { return ptr_ ? ptr_ : ""; }
  70. inline size_t size() const { return size_; }
  71. private:
  72. char* ptr_;
  73. size_t size_;
  74. };
  75. // Return true iff |address| is a valid address for the target CPU.
  76. inline bool IsValidAddress(jlong address) {
  77. return static_cast<jlong>(static_cast<size_t>(address)) == address;
  78. }
  79. // Find the jclass JNI reference corresponding to a given |class_name|.
  80. // |env| is the current JNI environment handle.
  81. // On success, return true and set |*clazz|.
  82. extern bool InitClassReference(JNIEnv* env,
  83. const char* class_name,
  84. jclass* clazz);
  85. // Initialize a jfieldID corresponding to the field of a given |clazz|,
  86. // with name |field_name| and signature |field_sig|.
  87. // |env| is the current JNI environment handle.
  88. // On success, return true and set |*field_id|.
  89. extern bool InitFieldId(JNIEnv* env,
  90. jclass clazz,
  91. const char* field_name,
  92. const char* field_sig,
  93. jfieldID* field_id);
  94. // Initialize a jfieldID corresponding to the static field of a given |clazz|,
  95. // with name |field_name| and signature |field_sig|.
  96. // |env| is the current JNI environment handle.
  97. // On success, return true and set |*field_id|.
  98. extern bool InitStaticFieldId(JNIEnv* env,
  99. jclass clazz,
  100. const char* field_name,
  101. const char* field_sig,
  102. jfieldID* field_id);
  103. // Use Android ASLR to create a random library load address.
  104. // |env| is the current JNI environment handle, and |clazz| a class.
  105. // Returns the address selected by ASLR.
  106. extern jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz);
  107. // A class used to model the field IDs of the org.chromium.base.Linker
  108. // LibInfo inner class, used to communicate data with the Java side
  109. // of the linker.
  110. struct LibInfo_class {
  111. jfieldID load_address_id;
  112. jfieldID load_size_id;
  113. jfieldID relro_start_id;
  114. jfieldID relro_size_id;
  115. jfieldID relro_fd_id;
  116. // Initialize an instance.
  117. bool Init(JNIEnv* env) {
  118. jclass clazz;
  119. if (!InitClassReference(
  120. env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) {
  121. return false;
  122. }
  123. return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) &&
  124. InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) &&
  125. InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) &&
  126. InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) &&
  127. InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id);
  128. }
  129. void SetLoadInfo(JNIEnv* env,
  130. jobject library_info_obj,
  131. size_t load_address,
  132. size_t load_size) {
  133. env->SetLongField(library_info_obj, load_address_id, load_address);
  134. env->SetLongField(library_info_obj, load_size_id, load_size);
  135. }
  136. void SetRelroInfo(JNIEnv* env,
  137. jobject library_info_obj,
  138. size_t relro_start,
  139. size_t relro_size,
  140. int relro_fd) {
  141. env->SetLongField(library_info_obj, relro_start_id, relro_start);
  142. env->SetLongField(library_info_obj, relro_size_id, relro_size);
  143. env->SetIntField(library_info_obj, relro_fd_id, relro_fd);
  144. }
  145. // Use this instance to convert a RelroInfo reference into
  146. // a crazy_library_info_t.
  147. void GetRelroInfo(JNIEnv* env,
  148. jobject library_info_obj,
  149. size_t* relro_start,
  150. size_t* relro_size,
  151. int* relro_fd) {
  152. if (relro_start) {
  153. *relro_start = static_cast<size_t>(
  154. env->GetLongField(library_info_obj, relro_start_id));
  155. }
  156. if (relro_size) {
  157. *relro_size = static_cast<size_t>(
  158. env->GetLongField(library_info_obj, relro_size_id));
  159. }
  160. if (relro_fd) {
  161. *relro_fd = env->GetIntField(library_info_obj, relro_fd_id);
  162. }
  163. }
  164. };
  165. // Variable containing LibInfo for the loaded library.
  166. extern LibInfo_class s_lib_info_fields;
  167. } // namespace chromium_android_linker
  168. #endif // BASE_ANDROID_LINKER_LINKER_JNI_H_