OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 Chromium 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 Chromium 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 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 *method_id = env->GetStaticMethodID(clazz, method_name, method_sig); | 121 *method_id = env->GetStaticMethodID(clazz, method_name, method_sig); |
122 if (!*method_id) { | 122 if (!*method_id) { |
123 LOG_ERROR("Could not find ID for static method '%s'", method_name); | 123 LOG_ERROR("Could not find ID for static method '%s'", method_name); |
124 return false; | 124 return false; |
125 } | 125 } |
126 LOG_INFO("%s: Found ID %p for static method '%s'", | 126 LOG_INFO("%s: Found ID %p for static method '%s'", |
127 __FUNCTION__, *method_id, method_name); | 127 __FUNCTION__, *method_id, method_name); |
128 return true; | 128 return true; |
129 } | 129 } |
130 | 130 |
| 131 // Initialize a jfieldID corresponding to the static field of a given |clazz|, |
| 132 // with name |field_name| and signature |field_sig|. |
| 133 // |env| is the current JNI environment handle. |
| 134 // On success, return true and set |*field_id|. |
| 135 bool InitStaticFieldId(JNIEnv* env, |
| 136 jclass clazz, |
| 137 const char* field_name, |
| 138 const char* field_sig, |
| 139 jfieldID* field_id) { |
| 140 *field_id = env->GetStaticFieldID(clazz, field_name, field_sig); |
| 141 if (!*field_id) { |
| 142 LOG_ERROR("Could not find ID for static field '%s'", field_name); |
| 143 return false; |
| 144 } |
| 145 LOG_INFO( |
| 146 "%s: Found ID %p for static field '%s'", |
| 147 __FUNCTION__, *field_id, field_name); |
| 148 return true; |
| 149 } |
| 150 |
| 151 // Initialize a jint corresponding to the static integer field of a class |
| 152 // with class name |class_name| and field name |field_name|. |
| 153 // |env| is the current JNI environment handle. |
| 154 // On success, return true and set |*value|. |
| 155 bool InitStaticInt(JNIEnv* env, |
| 156 const char* class_name, |
| 157 const char* field_name, |
| 158 jint* value) { |
| 159 jclass clazz; |
| 160 if (!InitClassReference(env, class_name, &clazz)) |
| 161 return false; |
| 162 |
| 163 jfieldID field_id; |
| 164 if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id)) |
| 165 return false; |
| 166 |
| 167 *value = env->GetStaticIntField(clazz, field_id); |
| 168 LOG_INFO( |
| 169 "%s: Found value %d for class '%s', static field '%s'", |
| 170 __FUNCTION__, *value, class_name, field_name); |
| 171 |
| 172 return true; |
| 173 } |
| 174 |
131 // A class used to model the field IDs of the org.chromium.base.Linker | 175 // A class used to model the field IDs of the org.chromium.base.Linker |
132 // LibInfo inner class, used to communicate data with the Java side | 176 // LibInfo inner class, used to communicate data with the Java side |
133 // of the linker. | 177 // of the linker. |
134 struct LibInfo_class { | 178 struct LibInfo_class { |
135 jfieldID load_address_id; | 179 jfieldID load_address_id; |
136 jfieldID load_size_id; | 180 jfieldID load_size_id; |
137 jfieldID relro_start_id; | 181 jfieldID relro_start_id; |
138 jfieldID relro_size_id; | 182 jfieldID relro_size_id; |
139 jfieldID relro_fd_id; | 183 jfieldID relro_fd_id; |
140 | 184 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 size_t relro_size, | 227 size_t relro_size, |
184 int relro_fd) { | 228 int relro_fd) { |
185 env->SetLongField(library_info_obj, relro_start_id, relro_start); | 229 env->SetLongField(library_info_obj, relro_start_id, relro_start); |
186 env->SetLongField(library_info_obj, relro_size_id, relro_size); | 230 env->SetLongField(library_info_obj, relro_size_id, relro_size); |
187 env->SetIntField(library_info_obj, relro_fd_id, relro_fd); | 231 env->SetIntField(library_info_obj, relro_fd_id, relro_fd); |
188 } | 232 } |
189 }; | 233 }; |
190 | 234 |
191 static LibInfo_class s_lib_info_fields; | 235 static LibInfo_class s_lib_info_fields; |
192 | 236 |
| 237 // Retrieve the SDK build version and pass it into the crazy linker. This |
| 238 // needs to be done early in initialization, before any other crazy linker |
| 239 // code is run. |
| 240 // |env| is the current JNI environment handle. |
| 241 // On success, return true. |
| 242 bool InitSDKVersionInfo(JNIEnv* env) { |
| 243 jint value = 0; |
| 244 if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value)) |
| 245 return false; |
| 246 |
| 247 crazy_set_sdk_build_version(static_cast<int>(value)); |
| 248 LOG_INFO("%s: Set SDK build version to %d", |
| 249 __FUNCTION__, static_cast<int>(value)); |
| 250 |
| 251 return true; |
| 252 } |
| 253 |
193 // The linker uses a single crazy_context_t object created on demand. | 254 // The linker uses a single crazy_context_t object created on demand. |
194 // There is no need to protect this against concurrent access, locking | 255 // There is no need to protect this against concurrent access, locking |
195 // is already handled on the Java side. | 256 // is already handled on the Java side. |
196 static crazy_context_t* s_crazy_context; | 257 static crazy_context_t* s_crazy_context; |
197 | 258 |
198 crazy_context_t* GetCrazyContext() { | 259 crazy_context_t* GetCrazyContext() { |
199 if (!s_crazy_context) { | 260 if (!s_crazy_context) { |
200 // Create new context. | 261 // Create new context. |
201 s_crazy_context = crazy_context_create(); | 262 s_crazy_context = crazy_context_create(); |
202 | 263 |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 // handle and initialize LibInfo fields. | 812 // handle and initialize LibInfo fields. |
752 jint JNI_OnLoad(JavaVM* vm, void* reserved) { | 813 jint JNI_OnLoad(JavaVM* vm, void* reserved) { |
753 LOG_INFO("%s: Entering", __FUNCTION__); | 814 LOG_INFO("%s: Entering", __FUNCTION__); |
754 // Get new JNIEnv | 815 // Get new JNIEnv |
755 JNIEnv* env; | 816 JNIEnv* env; |
756 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { | 817 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { |
757 LOG_ERROR("Could not create JNIEnv"); | 818 LOG_ERROR("Could not create JNIEnv"); |
758 return -1; | 819 return -1; |
759 } | 820 } |
760 | 821 |
| 822 // Initialize SDK version info. |
| 823 LOG_INFO("%s: Retrieving SDK version info", __FUNCTION__); |
| 824 if (!InitSDKVersionInfo(env)) |
| 825 return -1; |
| 826 |
761 // Register native methods. | 827 // Register native methods. |
762 jclass linker_class; | 828 jclass linker_class; |
763 if (!InitClassReference(env, | 829 if (!InitClassReference(env, |
764 "org/chromium/base/library_loader/Linker", | 830 "org/chromium/base/library_loader/Linker", |
765 &linker_class)) | 831 &linker_class)) |
766 return -1; | 832 return -1; |
767 | 833 |
768 LOG_INFO("%s: Registering native methods", __FUNCTION__); | 834 LOG_INFO("%s: Registering native methods", __FUNCTION__); |
769 env->RegisterNatives(linker_class, | 835 env->RegisterNatives(linker_class, |
770 kNativeMethods, | 836 kNativeMethods, |
(...skipping 15 matching lines...) Expand all Loading... |
786 crazy_context_t* context = GetCrazyContext(); | 852 crazy_context_t* context = GetCrazyContext(); |
787 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); | 853 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); |
788 | 854 |
789 // Register the function that the crazy linker can call to post code | 855 // Register the function that the crazy linker can call to post code |
790 // for later execution. | 856 // for later execution. |
791 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL); | 857 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL); |
792 | 858 |
793 LOG_INFO("%s: Done", __FUNCTION__); | 859 LOG_INFO("%s: Done", __FUNCTION__); |
794 return JNI_VERSION_1_4; | 860 return JNI_VERSION_1_4; |
795 } | 861 } |
OLD | NEW |