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

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

Issue 228023005: Additions to support crazy linker callbacks from the UI thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tidy up style. Created 6 years, 8 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
OLDNEW
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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 *field_id = env->GetFieldID(clazz, field_name, field_sig); 133 *field_id = env->GetFieldID(clazz, field_name, field_sig);
134 if (!*field_id) { 134 if (!*field_id) {
135 LOG_ERROR("Could not find ID for field '%s'", field_name); 135 LOG_ERROR("Could not find ID for field '%s'", field_name);
136 return false; 136 return false;
137 } 137 }
138 LOG_INFO( 138 LOG_INFO(
139 "%s: Found ID %p for field '%s'", __FUNCTION__, *field_id, field_name); 139 "%s: Found ID %p for field '%s'", __FUNCTION__, *field_id, field_name);
140 return true; 140 return true;
141 } 141 }
142 142
143 // Initialize a jmethodID corresponding to the static method of a given
144 // |clazz|, with name |method_name| and signature |method_sig|.
145 // |env| is the current JNI environment handle.
146 // On success, return true and set |*method_id|.
147 bool InitStaticMethodId(JNIEnv* env,
148 jclass clazz,
149 const char* method_name,
150 const char* method_sig,
151 jmethodID* method_id) {
152 *method_id = env->GetStaticMethodID(clazz, method_name, method_sig);
153 if (!*method_id) {
154 LOG_ERROR("Could not find ID for static method '%s'", method_name);
155 return false;
156 }
157 LOG_INFO("%s: Found ID %p for static method '%s'",
158 __FUNCTION__, *method_id, method_name);
159 return true;
160 }
161
143 // A class used to model the field IDs of the org.chromium.base.Linker 162 // A class used to model the field IDs of the org.chromium.base.Linker
144 // LibInfo inner class, used to communicate data with the Java side 163 // LibInfo inner class, used to communicate data with the Java side
145 // of the linker. 164 // of the linker.
146 struct LibInfo_class { 165 struct LibInfo_class {
147 jfieldID load_address_id; 166 jfieldID load_address_id;
148 jfieldID load_size_id; 167 jfieldID load_size_id;
149 jfieldID relro_start_id; 168 jfieldID relro_start_id;
150 jfieldID relro_size_id; 169 jfieldID relro_size_id;
151 jfieldID relro_fd_id; 170 jfieldID relro_fd_id;
152 171
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 294
276 // Release library object to keep it alive after the function returns. 295 // Release library object to keep it alive after the function returns.
277 library.Release(); 296 library.Release();
278 297
279 s_lib_info_fields.SetLoadInfo( 298 s_lib_info_fields.SetLoadInfo(
280 env, lib_info_obj, info.load_address, info.load_size); 299 env, lib_info_obj, info.load_address, info.load_size);
281 LOG_INFO("%s: Success loading library %s", __FUNCTION__, lib_basename); 300 LOG_INFO("%s: Success loading library %s", __FUNCTION__, lib_basename);
282 return true; 301 return true;
283 } 302 }
284 303
304 // Class to support simple callbacks from the Java side. Hold a pointer
305 // to a function taking a single void* argument, and an argument value.
306 struct callback_t {
307 public:
308 callback_t() : handler(NULL), opaque(NULL) { }
309
310 void (*handler)(void*);
311 void* opaque;
312 };
313
314 // Designated receiver function for callbacks from Java. Its name is known
315 // to the Java side.
316 // |env| is the current JNI environment handle and is ignored here.
317 // |clazz| is the static class handle for org.chromium.base.Linker,
318 // and is ignored here.
319 // |arg| is a pointer to an allocated callback_t.
320 void ReceiveCallbackFromMainThread(JNIEnv* env, jclass clazz, jlong arg) {
321 callback_t* callback = reinterpret_cast<callback_t*>(arg);
322
323 LOG_INFO("%s: Called back from java with handler %p, opaque %p",
324 __FUNCTION__, callback->handler, callback->opaque);
325
326 (*callback->handler)(callback->opaque);
327 delete callback;
328 }
329
330 // Class holding the Java class and method ID for the Java side Linker
331 // PostCallbackOnMainThread method. Like crazy_context_t, there is
332 // only one of these, requiring no locking.
333 struct callback_refs_t {
334 public:
335 callback_refs_t() : clazz(NULL), method_id(NULL) { }
336
337 jclass clazz;
338 jmethodID method_id;
339 };
340
341 static callback_refs_t s_callback_refs;
342
343 // Request a callback from Java. Constructs a new callback_t and calls
344 // the Java side's PostCallbackOnMainThread, which will some time later
345 // call back to our ReceiveCallbackFromMainThread.
346 // |handler| is a handler function, taking a single void* argument.
347 // |opaque| is the argument to supply to the handler when run in the callback.
348 // Returns true if the callback request succeeded.
349 static bool PostForLaterExecution(void (*handler)(void*), void *opaque) {
bulach 2014/04/15 13:58:14 nit: s/void *opaque/void* opaque/
simonb1 2014/04/17 14:45:43 Done.
350 crazy_context_t* context = GetCrazyContext();
351
352 JavaVM* vm;
353 int minimum_jni_version;
354 crazy_context_get_java_vm(context,
355 reinterpret_cast<void**>(&vm),
356 &minimum_jni_version);
357
358 // Do not reuse JNIEnv from JNI_OnLoad, but retrieve our own.
359 JNIEnv* env;
360 if (JNI_OK != vm->GetEnv(
361 reinterpret_cast<void**>(&env), minimum_jni_version)) {
362 LOG_ERROR("Could not create JNIEnv");
363 return false;
364 }
365
366 callback_t* callback = new callback_t();
367 callback->handler = handler;
368 callback->opaque = opaque;
369
370 LOG_INFO("%s: Calling back to java with handler %p, opaque %p",
371 __FUNCTION__, callback->handler, callback->opaque);
372
373 jlong arg = static_cast<jlong>(reinterpret_cast<intptr_t>(callback));
374 env->CallStaticVoidMethod(
375 s_callback_refs.clazz, s_callback_refs.method_id, arg);
bulach 2014/04/15 13:58:14 need to clear any java exception (assuming it's sa
simonb1 2014/04/17 14:45:43 Done.
376 return true;
377 }
378
285 jboolean CreateSharedRelro(JNIEnv* env, 379 jboolean CreateSharedRelro(JNIEnv* env,
286 jclass clazz, 380 jclass clazz,
287 jstring library_name, 381 jstring library_name,
288 jlong load_address, 382 jlong load_address,
289 jobject lib_info_obj) { 383 jobject lib_info_obj) {
290 String lib_name(env, library_name); 384 String lib_name(env, library_name);
291 385
292 LOG_INFO("%s: Called for %s", __FUNCTION__, lib_name.c_str()); 386 LOG_INFO("%s: Called for %s", __FUNCTION__, lib_name.c_str());
293 387
294 if (!IsValidAddress(load_address)) { 388 if (!IsValidAddress(load_address)) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 478
385 const JNINativeMethod kNativeMethods[] = { 479 const JNINativeMethod kNativeMethods[] = {
386 {"nativeLoadLibrary", 480 {"nativeLoadLibrary",
387 "(" 481 "("
388 "Ljava/lang/String;" 482 "Ljava/lang/String;"
389 "J" 483 "J"
390 "Lorg/chromium/base/library_loader/Linker$LibInfo;" 484 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
391 ")" 485 ")"
392 "Z", 486 "Z",
393 reinterpret_cast<void*>(&LoadLibrary)}, 487 reinterpret_cast<void*>(&LoadLibrary)},
488 {"nativeReceiveCallbackFromMainThread",
489 "("
490 "J"
491 ")"
492 "V",
493 reinterpret_cast<void*>(&ReceiveCallbackFromMainThread)},
394 {"nativeCreateSharedRelro", 494 {"nativeCreateSharedRelro",
395 "(" 495 "("
396 "Ljava/lang/String;" 496 "Ljava/lang/String;"
397 "J" 497 "J"
398 "Lorg/chromium/base/library_loader/Linker$LibInfo;" 498 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
399 ")" 499 ")"
400 "Z", 500 "Z",
401 reinterpret_cast<void*>(&CreateSharedRelro)}, 501 reinterpret_cast<void*>(&CreateSharedRelro)},
402 {"nativeUseSharedRelro", 502 {"nativeUseSharedRelro",
403 "(" 503 "("
404 "Ljava/lang/String;" 504 "Ljava/lang/String;"
405 "Lorg/chromium/base/library_loader/Linker$LibInfo;" 505 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
406 ")" 506 ")"
407 "Z", 507 "Z",
408 reinterpret_cast<void*>(&UseSharedRelro)}, 508 reinterpret_cast<void*>(&UseSharedRelro)},
409 {"nativeCanUseSharedRelro", 509 {"nativeCanUseSharedRelro",
410 "(" 510 "("
411 ")" 511 ")"
412 "Z", 512 "Z",
413 reinterpret_cast<void*>(&CanUseSharedRelro)}, 513 reinterpret_cast<void*>(&CanUseSharedRelro)},
414 {"nativeGetPageSize", 514 {"nativeGetPageSize",
415 "(" 515 "("
416 ")" 516 ")"
417 "J", 517 "J",
418 reinterpret_cast<void*>(&GetPageSize)}, }; 518 reinterpret_cast<void*>(&GetPageSize)}, };
419
420 } // namespace 519 } // namespace
421 520
422 // JNI_OnLoad() hook called when the linker library is loaded through 521 // JNI_OnLoad() hook called when the linker library is loaded through
423 // the regular System.LoadLibrary) API. This shall save the Java VM 522 // the regular System.LoadLibrary) API. This shall save the Java VM
424 // handle and initialize LibInfo fields. 523 // handle and initialize LibInfo fields.
425 jint JNI_OnLoad(JavaVM* vm, void* reserved) { 524 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
426 LOG_INFO("%s: Entering", __FUNCTION__); 525 LOG_INFO("%s: Entering", __FUNCTION__);
427 // Get new JNIEnv 526 // Get new JNIEnv
428 JNIEnv* env; 527 JNIEnv* env;
429 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { 528 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) {
430 LOG_ERROR("Could not create JNIEnv"); 529 LOG_ERROR("Could not create JNIEnv");
431 return -1; 530 return -1;
432 } 531 }
433 532
434 // Register native methods. 533 // Register native methods.
435 jclass linker_class; 534 jclass linker_class;
436 if (!InitClassReference( 535 if (!InitClassReference(env,
437 env, "org/chromium/base/library_loader/Linker", &linker_class)) 536 "org/chromium/base/library_loader/Linker",
537 &linker_class))
438 return -1; 538 return -1;
439 539
440 LOG_INFO("%s: Registering native methods", __FUNCTION__); 540 LOG_INFO("%s: Registering native methods", __FUNCTION__);
441 env->RegisterNatives(linker_class, 541 env->RegisterNatives(linker_class,
442 kNativeMethods, 542 kNativeMethods,
443 sizeof(kNativeMethods) / sizeof(kNativeMethods[0])); 543 sizeof(kNativeMethods) / sizeof(kNativeMethods[0]));
444 544
445 // Find LibInfo field ids. 545 // Find LibInfo field ids.
446 LOG_INFO("%s: Caching field IDs", __FUNCTION__); 546 LOG_INFO("%s: Caching field IDs", __FUNCTION__);
447 if (!s_lib_info_fields.Init(env)) { 547 if (!s_lib_info_fields.Init(env)) {
448 return -1; 548 return -1;
449 } 549 }
450 550
451 // Save JavaVM* handle into context. 551 // Save JavaVM* handle into context.
452 crazy_context_t* context = GetCrazyContext(); 552 crazy_context_t* context = GetCrazyContext();
453 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); 553 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
454 554
555 // Resolve the Java side Linker callback method.
556 jmethodID method_id;
557 if (!InitStaticMethodId(env,
558 linker_class,
559 "PostCallbackOnMainThread",
560 "(J)V",
561 &method_id))
562 return -1;
563
564 // Save the callback class and method, and register the function that
565 // the crazy linker can call to post code for later execution.
566 s_callback_refs.clazz = linker_class;
567 s_callback_refs.method_id = method_id;
568 crazy_context_set_post_for_later_execution(context, &PostForLaterExecution);
569
455 LOG_INFO("%s: Done", __FUNCTION__); 570 LOG_INFO("%s: Done", __FUNCTION__);
456 return JNI_VERSION_1_4; 571 return JNI_VERSION_1_4;
457 } 572 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698