Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: base/android/linker/legacy_linker_jni.cc

Issue 1647803004: Move base to DEPS (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/android/linker/config.gni ('k') | base/android/locale_utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
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
7 // real Chromium libraries (e.g. libcontentshell.so).
8
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
11 // renderer process.
12
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.
15
16 #include <android/log.h>
17 #include <crazy_linker.h>
18 #include <fcntl.h>
19 #include <jni.h>
20 #include <limits.h>
21 #include <stdlib.h>
22 #include <sys/mman.h>
23 #include <unistd.h>
24
25 // See commentary in crazy_linker_elf_loader.cpp for the effect of setting
26 // this. If changing there, change here also.
27 //
28 // For more, see:
29 // https://crbug.com/504410
30 #define RESERVE_BREAKPAD_GUARD_REGION 1
31
32 // Set this to 1 to enable debug traces to the Android log.
33 // Note that LOG() from "base/logging.h" cannot be used, since it is
34 // in base/ which hasn't been loaded yet.
35 #define DEBUG 0
36
37 #define TAG "chromium_android_linker"
38
39 #if DEBUG
40 #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
41 #else
42 #define LOG_INFO(...) ((void)0)
43 #endif
44 #define LOG_ERROR(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
45
46 #define UNUSED __attribute__((unused))
47
48 namespace {
49
50 // A simply scoped UTF String class that can be initialized from
51 // a Java jstring handle. Modeled like std::string, which cannot
52 // be used here.
53 class String {
54 public:
55 String(JNIEnv* env, jstring str);
56
57 ~String() {
58 if (ptr_)
59 ::free(ptr_);
60 }
61
62 const char* c_str() const { return ptr_ ? ptr_ : ""; }
63 size_t size() const { return size_; }
64
65 private:
66 char* ptr_;
67 size_t size_;
68 };
69
70 String::String(JNIEnv* env, jstring str) {
71 size_ = env->GetStringUTFLength(str);
72 ptr_ = static_cast<char*>(::malloc(size_ + 1));
73
74 // Note: the result contains Java "modified UTF-8" bytes.
75 // Good enough for the linker though.
76 const char* bytes = env->GetStringUTFChars(str, NULL);
77 ::memcpy(ptr_, bytes, size_);
78 ptr_[size_] = '\0';
79
80 env->ReleaseStringUTFChars(str, bytes);
81 }
82
83 // Return true iff |address| is a valid address for the target CPU.
84 bool IsValidAddress(jlong address) {
85 return static_cast<jlong>(static_cast<size_t>(address)) == address;
86 }
87
88 // Find the jclass JNI reference corresponding to a given |class_name|.
89 // |env| is the current JNI environment handle.
90 // On success, return true and set |*clazz|.
91 bool InitClassReference(JNIEnv* env, const char* class_name, jclass* clazz) {
92 *clazz = env->FindClass(class_name);
93 if (!*clazz) {
94 LOG_ERROR("Could not find class for %s", class_name);
95 return false;
96 }
97 return true;
98 }
99
100 // Initialize a jfieldID corresponding to the field of a given |clazz|,
101 // with name |field_name| and signature |field_sig|.
102 // |env| is the current JNI environment handle.
103 // On success, return true and set |*field_id|.
104 bool InitFieldId(JNIEnv* env,
105 jclass clazz,
106 const char* field_name,
107 const char* field_sig,
108 jfieldID* field_id) {
109 *field_id = env->GetFieldID(clazz, field_name, field_sig);
110 if (!*field_id) {
111 LOG_ERROR("Could not find ID for field '%s'", field_name);
112 return false;
113 }
114 LOG_INFO("%s: Found ID %p for field '%s'", __FUNCTION__, *field_id,
115 field_name);
116 return true;
117 }
118
119 // Initialize a jmethodID corresponding to the static method of a given
120 // |clazz|, with name |method_name| and signature |method_sig|.
121 // |env| is the current JNI environment handle.
122 // On success, return true and set |*method_id|.
123 bool InitStaticMethodId(JNIEnv* env,
124 jclass clazz,
125 const char* method_name,
126 const char* method_sig,
127 jmethodID* method_id) {
128 *method_id = env->GetStaticMethodID(clazz, method_name, method_sig);
129 if (!*method_id) {
130 LOG_ERROR("Could not find ID for static method '%s'", method_name);
131 return false;
132 }
133 LOG_INFO("%s: Found ID %p for static method '%s'", __FUNCTION__, *method_id,
134 method_name);
135 return true;
136 }
137
138 // Initialize a jfieldID corresponding to the static field of a given |clazz|,
139 // with name |field_name| and signature |field_sig|.
140 // |env| is the current JNI environment handle.
141 // On success, return true and set |*field_id|.
142 bool InitStaticFieldId(JNIEnv* env,
143 jclass clazz,
144 const char* field_name,
145 const char* field_sig,
146 jfieldID* field_id) {
147 *field_id = env->GetStaticFieldID(clazz, field_name, field_sig);
148 if (!*field_id) {
149 LOG_ERROR("Could not find ID for static field '%s'", field_name);
150 return false;
151 }
152 LOG_INFO("%s: Found ID %p for static field '%s'", __FUNCTION__, *field_id,
153 field_name);
154 return true;
155 }
156
157 // Initialize a jint corresponding to the static integer field of a class
158 // with class name |class_name| and field name |field_name|.
159 // |env| is the current JNI environment handle.
160 // On success, return true and set |*value|.
161 bool InitStaticInt(JNIEnv* env,
162 const char* class_name,
163 const char* field_name,
164 jint* value) {
165 jclass clazz;
166 if (!InitClassReference(env, class_name, &clazz))
167 return false;
168
169 jfieldID field_id;
170 if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id))
171 return false;
172
173 *value = env->GetStaticIntField(clazz, field_id);
174 LOG_INFO("%s: Found value %d for class '%s', static field '%s'", __FUNCTION__,
175 *value, class_name, field_name);
176
177 return true;
178 }
179
180 // A class used to model the field IDs of the org.chromium.base.Linker
181 // LibInfo inner class, used to communicate data with the Java side
182 // of the linker.
183 struct LibInfo_class {
184 jfieldID load_address_id;
185 jfieldID load_size_id;
186 jfieldID relro_start_id;
187 jfieldID relro_size_id;
188 jfieldID relro_fd_id;
189
190 // Initialize an instance.
191 bool Init(JNIEnv* env) {
192 jclass clazz;
193 if (!InitClassReference(
194 env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) {
195 return false;
196 }
197
198 return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) &&
199 InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) &&
200 InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) &&
201 InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) &&
202 InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id);
203 }
204
205 void SetLoadInfo(JNIEnv* env,
206 jobject library_info_obj,
207 size_t load_address,
208 size_t load_size) {
209 env->SetLongField(library_info_obj, load_address_id, load_address);
210 env->SetLongField(library_info_obj, load_size_id, load_size);
211 }
212
213 // Use this instance to convert a RelroInfo reference into
214 // a crazy_library_info_t.
215 void GetRelroInfo(JNIEnv* env,
216 jobject library_info_obj,
217 size_t* relro_start,
218 size_t* relro_size,
219 int* relro_fd) {
220 *relro_start = static_cast<size_t>(
221 env->GetLongField(library_info_obj, relro_start_id));
222
223 *relro_size =
224 static_cast<size_t>(env->GetLongField(library_info_obj, relro_size_id));
225
226 *relro_fd = env->GetIntField(library_info_obj, relro_fd_id);
227 }
228
229 void SetRelroInfo(JNIEnv* env,
230 jobject library_info_obj,
231 size_t relro_start,
232 size_t relro_size,
233 int relro_fd) {
234 env->SetLongField(library_info_obj, relro_start_id, relro_start);
235 env->SetLongField(library_info_obj, relro_size_id, relro_size);
236 env->SetIntField(library_info_obj, relro_fd_id, relro_fd);
237 }
238 };
239
240 static LibInfo_class s_lib_info_fields;
241
242 // Retrieve the SDK build version and pass it into the crazy linker. This
243 // needs to be done early in initialization, before any other crazy linker
244 // code is run.
245 // |env| is the current JNI environment handle.
246 // On success, return true.
247 bool InitSDKVersionInfo(JNIEnv* env) {
248 jint value = 0;
249 if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value))
250 return false;
251
252 crazy_set_sdk_build_version(static_cast<int>(value));
253 LOG_INFO("%s: Set SDK build version to %d", __FUNCTION__,
254 static_cast<int>(value));
255
256 return true;
257 }
258
259 // The linker uses a single crazy_context_t object created on demand.
260 // There is no need to protect this against concurrent access, locking
261 // is already handled on the Java side.
262 static crazy_context_t* s_crazy_context;
263
264 crazy_context_t* GetCrazyContext() {
265 if (!s_crazy_context) {
266 // Create new context.
267 s_crazy_context = crazy_context_create();
268
269 // Ensure libraries located in the same directory as the linker
270 // can be loaded before system ones.
271 crazy_context_add_search_path_for_address(
272 s_crazy_context, reinterpret_cast<void*>(&s_crazy_context));
273 }
274
275 return s_crazy_context;
276 }
277
278 // A scoped crazy_library_t that automatically closes the handle
279 // on scope exit, unless Release() has been called.
280 class ScopedLibrary {
281 public:
282 ScopedLibrary() : lib_(NULL) {}
283
284 ~ScopedLibrary() {
285 if (lib_)
286 crazy_library_close_with_context(lib_, GetCrazyContext());
287 }
288
289 crazy_library_t* Get() { return lib_; }
290
291 crazy_library_t** GetPtr() { return &lib_; }
292
293 crazy_library_t* Release() {
294 crazy_library_t* ret = lib_;
295 lib_ = NULL;
296 return ret;
297 }
298
299 private:
300 crazy_library_t* lib_;
301 };
302
303 namespace {
304
305 template <class LibraryOpener>
306 bool GenericLoadLibrary(JNIEnv* env,
307 const char* library_name,
308 jlong load_address,
309 jobject lib_info_obj,
310 const LibraryOpener& opener) {
311 crazy_context_t* context = GetCrazyContext();
312
313 if (!IsValidAddress(load_address)) {
314 LOG_ERROR("%s: Invalid address 0x%llx", __FUNCTION__, load_address);
315 return false;
316 }
317
318 // Set the desired load address (0 means randomize it).
319 crazy_context_set_load_address(context, static_cast<size_t>(load_address));
320
321 ScopedLibrary library;
322 if (!opener.Open(library.GetPtr(), library_name, context)) {
323 return false;
324 }
325
326 crazy_library_info_t info;
327 if (!crazy_library_get_info(library.Get(), context, &info)) {
328 LOG_ERROR("%s: Could not get library information for %s: %s", __FUNCTION__,
329 library_name, crazy_context_get_error(context));
330 return false;
331 }
332
333 // Release library object to keep it alive after the function returns.
334 library.Release();
335
336 s_lib_info_fields.SetLoadInfo(env, lib_info_obj, info.load_address,
337 info.load_size);
338 LOG_INFO("%s: Success loading library %s", __FUNCTION__, library_name);
339 return true;
340 }
341
342 // Used for opening the library in a regular file.
343 class FileLibraryOpener {
344 public:
345 bool Open(crazy_library_t** library,
346 const char* library_name,
347 crazy_context_t* context) const;
348 };
349
350 bool FileLibraryOpener::Open(crazy_library_t** library,
351 const char* library_name,
352 crazy_context_t* context) const {
353 if (!crazy_library_open(library, library_name, context)) {
354 LOG_ERROR("%s: Could not open %s: %s", __FUNCTION__, library_name,
355 crazy_context_get_error(context));
356 return false;
357 }
358 return true;
359 }
360
361 // Used for opening the library in a zip file.
362 class ZipLibraryOpener {
363 public:
364 explicit ZipLibraryOpener(const char* zip_file) : zip_file_(zip_file) {}
365 bool Open(crazy_library_t** library,
366 const char* library_name,
367 crazy_context_t* context) const;
368
369 private:
370 const char* zip_file_;
371 };
372
373 bool ZipLibraryOpener::Open(crazy_library_t** library,
374 const char* library_name,
375 crazy_context_t* context) const {
376 if (!crazy_library_open_in_zip_file(library, zip_file_, library_name,
377 context)) {
378 LOG_ERROR("%s: Could not open %s in zip file %s: %s", __FUNCTION__,
379 library_name, zip_file_, crazy_context_get_error(context));
380 return false;
381 }
382 return true;
383 }
384
385 } // unnamed namespace
386
387 // Load a library with the chromium linker. This will also call its
388 // JNI_OnLoad() method, which shall register its methods. Note that
389 // lazy native method resolution will _not_ work after this, because
390 // Dalvik uses the system's dlsym() which won't see the new library,
391 // so explicit registration is mandatory.
392 // |env| is the current JNI environment handle.
393 // |clazz| is the static class handle for org.chromium.base.Linker,
394 // and is ignored here.
395 // |library_name| is the library name (e.g. libfoo.so).
396 // |load_address| is an explicit load address.
397 // |library_info| is a LibInfo handle used to communicate information
398 // with the Java side.
399 // Return true on success.
400 jboolean LoadLibrary(JNIEnv* env,
401 jclass clazz,
402 jstring library_name,
403 jlong load_address,
404 jobject lib_info_obj) {
405 String lib_name(env, library_name);
406 FileLibraryOpener opener;
407 return GenericLoadLibrary(env, lib_name.c_str(),
408 static_cast<size_t>(load_address), lib_info_obj,
409 opener);
410 }
411
412 // Load a library from a zipfile with the chromium linker. The
413 // library in the zipfile must be uncompressed and page aligned.
414 // The basename of the library is given. The library is expected
415 // to be lib/<abi_tag>/crazy.<basename>. The <abi_tag> used will be the
416 // same as the abi for this linker. The "crazy." prefix is included
417 // so that the Android Package Manager doesn't extract the library into
418 // /data/app-lib.
419 //
420 // Loading the library will also call its JNI_OnLoad() method, which
421 // shall register its methods. Note that lazy native method resolution
422 // will _not_ work after this, because Dalvik uses the system's dlsym()
423 // which won't see the new library, so explicit registration is mandatory.
424 //
425 // |env| is the current JNI environment handle.
426 // |clazz| is the static class handle for org.chromium.base.Linker,
427 // and is ignored here.
428 // |zipfile_name| is the filename of the zipfile containing the library.
429 // |library_name| is the library base name (e.g. libfoo.so).
430 // |load_address| is an explicit load address.
431 // |library_info| is a LibInfo handle used to communicate information
432 // with the Java side.
433 // Returns true on success.
434 jboolean LoadLibraryInZipFile(JNIEnv* env,
435 jclass clazz,
436 jstring zipfile_name,
437 jstring library_name,
438 jlong load_address,
439 jobject lib_info_obj) {
440 String zipfile_name_str(env, zipfile_name);
441 String lib_name(env, library_name);
442 ZipLibraryOpener opener(zipfile_name_str.c_str());
443 return GenericLoadLibrary(env, lib_name.c_str(),
444 static_cast<size_t>(load_address), lib_info_obj,
445 opener);
446 }
447
448 // Class holding the Java class and method ID for the Java side Linker
449 // postCallbackOnMainThread method.
450 struct JavaCallbackBindings_class {
451 jclass clazz;
452 jmethodID method_id;
453
454 // Initialize an instance.
455 bool Init(JNIEnv* env, jclass linker_class) {
456 clazz = reinterpret_cast<jclass>(env->NewGlobalRef(linker_class));
457 return InitStaticMethodId(env, linker_class, "postCallbackOnMainThread",
458 "(J)V", &method_id);
459 }
460 };
461
462 static JavaCallbackBindings_class s_java_callback_bindings;
463
464 // Designated receiver function for callbacks from Java. Its name is known
465 // to the Java side.
466 // |env| is the current JNI environment handle and is ignored here.
467 // |clazz| is the static class handle for org.chromium.base.Linker,
468 // and is ignored here.
469 // |arg| is a pointer to an allocated crazy_callback_t, deleted after use.
470 void RunCallbackOnUiThread(JNIEnv* env, jclass clazz, jlong arg) {
471 crazy_callback_t* callback = reinterpret_cast<crazy_callback_t*>(arg);
472
473 LOG_INFO("%s: Called back from java with handler %p, opaque %p", __FUNCTION__,
474 callback->handler, callback->opaque);
475
476 crazy_callback_run(callback);
477 delete callback;
478 }
479
480 // Request a callback from Java. The supplied crazy_callback_t is valid only
481 // for the duration of this call, so we copy it to a newly allocated
482 // crazy_callback_t and then call the Java side's postCallbackOnMainThread.
483 // This will call back to to our RunCallbackOnUiThread some time
484 // later on the UI thread.
485 // |callback_request| is a crazy_callback_t.
486 // |poster_opaque| is unused.
487 // Returns true if the callback request succeeds.
488 static bool PostForLaterExecution(crazy_callback_t* callback_request,
489 void* poster_opaque UNUSED) {
490 crazy_context_t* context = GetCrazyContext();
491
492 JavaVM* vm;
493 int minimum_jni_version;
494 crazy_context_get_java_vm(context, reinterpret_cast<void**>(&vm),
495 &minimum_jni_version);
496
497 // Do not reuse JNIEnv from JNI_OnLoad, but retrieve our own.
498 JNIEnv* env;
499 if (JNI_OK !=
500 vm->GetEnv(reinterpret_cast<void**>(&env), minimum_jni_version)) {
501 LOG_ERROR("Could not create JNIEnv");
502 return false;
503 }
504
505 // Copy the callback; the one passed as an argument may be temporary.
506 crazy_callback_t* callback = new crazy_callback_t();
507 *callback = *callback_request;
508
509 LOG_INFO("%s: Calling back to java with handler %p, opaque %p", __FUNCTION__,
510 callback->handler, callback->opaque);
511
512 jlong arg = static_cast<jlong>(reinterpret_cast<uintptr_t>(callback));
513
514 env->CallStaticVoidMethod(s_java_callback_bindings.clazz,
515 s_java_callback_bindings.method_id, arg);
516
517 // Back out and return false if we encounter a JNI exception.
518 if (env->ExceptionCheck() == JNI_TRUE) {
519 env->ExceptionDescribe();
520 env->ExceptionClear();
521 delete callback;
522 return false;
523 }
524
525 return true;
526 }
527
528 jboolean CreateSharedRelro(JNIEnv* env,
529 jclass clazz,
530 jstring library_name,
531 jlong load_address,
532 jobject lib_info_obj) {
533 String lib_name(env, library_name);
534
535 LOG_INFO("%s: Called for %s", __FUNCTION__, lib_name.c_str());
536
537 if (!IsValidAddress(load_address)) {
538 LOG_ERROR("%s: Invalid address 0x%llx", __FUNCTION__, load_address);
539 return false;
540 }
541
542 ScopedLibrary library;
543 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
544 LOG_ERROR("%s: Could not find %s", __FUNCTION__, lib_name.c_str());
545 return false;
546 }
547
548 crazy_context_t* context = GetCrazyContext();
549 size_t relro_start = 0;
550 size_t relro_size = 0;
551 int relro_fd = -1;
552
553 if (!crazy_library_create_shared_relro(
554 library.Get(), context, static_cast<size_t>(load_address),
555 &relro_start, &relro_size, &relro_fd)) {
556 LOG_ERROR("%s: Could not create shared RELRO sharing for %s: %s\n",
557 __FUNCTION__, lib_name.c_str(), crazy_context_get_error(context));
558 return false;
559 }
560
561 s_lib_info_fields.SetRelroInfo(env, lib_info_obj, relro_start, relro_size,
562 relro_fd);
563 return true;
564 }
565
566 jboolean UseSharedRelro(JNIEnv* env,
567 jclass clazz,
568 jstring library_name,
569 jobject lib_info_obj) {
570 String lib_name(env, library_name);
571
572 LOG_INFO("%s: called for %s, lib_info_ref=%p", __FUNCTION__, lib_name.c_str(),
573 lib_info_obj);
574
575 ScopedLibrary library;
576 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
577 LOG_ERROR("%s: Could not find %s", __FUNCTION__, lib_name.c_str());
578 return false;
579 }
580
581 crazy_context_t* context = GetCrazyContext();
582 size_t relro_start = 0;
583 size_t relro_size = 0;
584 int relro_fd = -1;
585 s_lib_info_fields.GetRelroInfo(env, lib_info_obj, &relro_start, &relro_size,
586 &relro_fd);
587
588 LOG_INFO("%s: library=%s relro start=%p size=%p fd=%d", __FUNCTION__,
589 lib_name.c_str(), (void*)relro_start, (void*)relro_size, relro_fd);
590
591 if (!crazy_library_use_shared_relro(library.Get(), context, relro_start,
592 relro_size, relro_fd)) {
593 LOG_ERROR("%s: Could not use shared RELRO for %s: %s", __FUNCTION__,
594 lib_name.c_str(), crazy_context_get_error(context));
595 return false;
596 }
597
598 LOG_INFO("%s: Library %s using shared RELRO section!", __FUNCTION__,
599 lib_name.c_str());
600
601 return true;
602 }
603
604 jboolean CanUseSharedRelro(JNIEnv* env, jclass clazz) {
605 return crazy_system_can_share_relro();
606 }
607
608 jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz, jlong bytes) {
609 #if RESERVE_BREAKPAD_GUARD_REGION
610 // Add a Breakpad guard region. 16Mb should be comfortably larger than
611 // the largest relocation packer saving we expect to encounter.
612 static const size_t kBreakpadGuardRegionBytes = 16 * 1024 * 1024;
613 bytes += kBreakpadGuardRegionBytes;
614 #endif
615
616 void* address =
617 mmap(NULL, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
618 if (address == MAP_FAILED) {
619 LOG_INFO("%s: Random base load address not determinable\n", __FUNCTION__);
620 return 0;
621 }
622 munmap(address, bytes);
623
624 #if RESERVE_BREAKPAD_GUARD_REGION
625 // Allow for a Breakpad guard region ahead of the returned address.
626 address = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) +
627 kBreakpadGuardRegionBytes);
628 #endif
629
630 LOG_INFO("%s: Random base load address is %p\n", __FUNCTION__, address);
631 return static_cast<jlong>(reinterpret_cast<uintptr_t>(address));
632 }
633
634 const JNINativeMethod kNativeMethods[] = {
635 {"nativeLoadLibrary",
636 "("
637 "Ljava/lang/String;"
638 "J"
639 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
640 ")"
641 "Z",
642 reinterpret_cast<void*>(&LoadLibrary)},
643 {"nativeLoadLibraryInZipFile",
644 "("
645 "Ljava/lang/String;"
646 "Ljava/lang/String;"
647 "J"
648 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
649 ")"
650 "Z",
651 reinterpret_cast<void*>(&LoadLibraryInZipFile)},
652 {"nativeRunCallbackOnUiThread",
653 "("
654 "J"
655 ")"
656 "V",
657 reinterpret_cast<void*>(&RunCallbackOnUiThread)},
658 {"nativeCreateSharedRelro",
659 "("
660 "Ljava/lang/String;"
661 "J"
662 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
663 ")"
664 "Z",
665 reinterpret_cast<void*>(&CreateSharedRelro)},
666 {"nativeUseSharedRelro",
667 "("
668 "Ljava/lang/String;"
669 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
670 ")"
671 "Z",
672 reinterpret_cast<void*>(&UseSharedRelro)},
673 {"nativeCanUseSharedRelro",
674 "("
675 ")"
676 "Z",
677 reinterpret_cast<void*>(&CanUseSharedRelro)},
678 {"nativeGetRandomBaseLoadAddress",
679 "("
680 "J"
681 ")"
682 "J",
683 reinterpret_cast<void*>(&GetRandomBaseLoadAddress)},
684 };
685
686 } // namespace
687
688 // JNI_OnLoad() hook called when the linker library is loaded through
689 // the regular System.LoadLibrary) API. This shall save the Java VM
690 // handle and initialize LibInfo fields.
691 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
692 LOG_INFO("%s: Entering", __FUNCTION__);
693 // Get new JNIEnv
694 JNIEnv* env;
695 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) {
696 LOG_ERROR("Could not create JNIEnv");
697 return -1;
698 }
699
700 // Initialize SDK version info.
701 LOG_INFO("%s: Retrieving SDK version info", __FUNCTION__);
702 if (!InitSDKVersionInfo(env))
703 return -1;
704
705 // Register native methods.
706 jclass linker_class;
707 if (!InitClassReference(env, "org/chromium/base/library_loader/LegacyLinker",
708 &linker_class))
709 return -1;
710
711 LOG_INFO("%s: Registering native methods", __FUNCTION__);
712 env->RegisterNatives(linker_class, kNativeMethods,
713 sizeof(kNativeMethods) / sizeof(kNativeMethods[0]));
714
715 // Find LibInfo field ids.
716 LOG_INFO("%s: Caching field IDs", __FUNCTION__);
717 if (!s_lib_info_fields.Init(env)) {
718 return -1;
719 }
720
721 // Resolve and save the Java side Linker callback class and method.
722 LOG_INFO("%s: Resolving callback bindings", __FUNCTION__);
723 if (!s_java_callback_bindings.Init(env, linker_class)) {
724 return -1;
725 }
726
727 // Save JavaVM* handle into context.
728 crazy_context_t* context = GetCrazyContext();
729 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
730
731 // Register the function that the crazy linker can call to post code
732 // for later execution.
733 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL);
734
735 LOG_INFO("%s: Done", __FUNCTION__);
736 return JNI_VERSION_1_4;
737 }
OLDNEW
« no previous file with comments | « base/android/linker/config.gni ('k') | base/android/locale_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698