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 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 jlong load_address, | 440 jlong load_address, |
441 jobject lib_info_obj) { | 441 jobject lib_info_obj) { |
442 String zipfile_name_str(env, zipfile_name); | 442 String zipfile_name_str(env, zipfile_name); |
443 String lib_name(env, library_name); | 443 String lib_name(env, library_name); |
444 ZipLibraryOpener opener(zipfile_name_str.c_str()); | 444 ZipLibraryOpener opener(zipfile_name_str.c_str()); |
445 return GenericLoadLibrary( | 445 return GenericLoadLibrary( |
446 env, lib_name.c_str(), | 446 env, lib_name.c_str(), |
447 static_cast<size_t>(load_address), lib_info_obj, opener); | 447 static_cast<size_t>(load_address), lib_info_obj, opener); |
448 } | 448 } |
449 | 449 |
450 // Enable the fallback due to lack of support for mapping the APK file with | |
451 // executable permission in the crazy linker. | |
452 // | |
453 // |env| is the current JNI environment handle and is ignored here. | |
454 // |clazz| is the static class handle for org.chromium.base.Linker, | |
455 // and is ignored here. | |
456 void EnableNoMapExecSupportFallback(JNIEnv* env, jclass clazz) { | |
457 crazy_context_t* context = GetCrazyContext(); | |
458 crazy_context_set_no_map_exec_support_fallback_enabled(context, true); | |
459 } | |
460 | |
461 // Class holding the Java class and method ID for the Java side Linker | 450 // Class holding the Java class and method ID for the Java side Linker |
462 // postCallbackOnMainThread method. | 451 // postCallbackOnMainThread method. |
463 struct JavaCallbackBindings_class { | 452 struct JavaCallbackBindings_class { |
464 jclass clazz; | 453 jclass clazz; |
465 jmethodID method_id; | 454 jmethodID method_id; |
466 | 455 |
467 // Initialize an instance. | 456 // Initialize an instance. |
468 bool Init(JNIEnv* env, jclass linker_class) { | 457 bool Init(JNIEnv* env, jclass linker_class) { |
469 clazz = reinterpret_cast<jclass>(env->NewGlobalRef(linker_class)); | 458 clazz = reinterpret_cast<jclass>(env->NewGlobalRef(linker_class)); |
470 return InitStaticMethodId(env, | 459 return InitStaticMethodId(env, |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 char buffer[kMaxFilePathLengthInZip + 1]; | 652 char buffer[kMaxFilePathLengthInZip + 1]; |
664 if (crazy_library_file_path_in_zip_file( | 653 if (crazy_library_file_path_in_zip_file( |
665 lib_name_c_str, buffer, sizeof(buffer)) == CRAZY_STATUS_FAILURE) { | 654 lib_name_c_str, buffer, sizeof(buffer)) == CRAZY_STATUS_FAILURE) { |
666 LOG_ERROR("%s: Failed to get full filename for library '%s'", | 655 LOG_ERROR("%s: Failed to get full filename for library '%s'", |
667 __FUNCTION__, lib_name_c_str); | 656 __FUNCTION__, lib_name_c_str); |
668 buffer[0] = '\0'; | 657 buffer[0] = '\0'; |
669 } | 658 } |
670 return env->NewStringUTF(buffer); | 659 return env->NewStringUTF(buffer); |
671 } | 660 } |
672 | 661 |
673 // Check whether the device supports mapping the APK file with executable | |
674 // permission. | |
675 // | |
676 // |env| is the current JNI environment handle. | |
677 // |clazz| is the static class handle which is not used here. | |
678 // |apkfile_name| is the filename of the APK. | |
679 // Returns true if supported. | |
680 jboolean CheckMapExecSupport(JNIEnv* env, jclass clazz, jstring apkfile_name) { | |
681 String apkfile_name_str(env, apkfile_name); | |
682 const char* apkfile_name_c_str = apkfile_name_str.c_str(); | |
683 | |
684 int fd = open(apkfile_name_c_str, O_RDONLY); | |
685 if (fd == -1) { | |
686 LOG_ERROR("%s: Failed to open %s\n", __FUNCTION__, apkfile_name_c_str); | |
687 return false; | |
688 } | |
689 | |
690 LOG_INFO( | |
691 "%s: Memory mapping the first page of %s with executable permissions\n", | |
692 __FUNCTION__, apkfile_name_c_str); | |
693 void* address = mmap(NULL, PAGE_SIZE, PROT_EXEC, MAP_PRIVATE, fd, 0); | |
694 | |
695 jboolean status; | |
696 if (address == MAP_FAILED) { | |
697 status = false; | |
698 } else { | |
699 status = true; | |
700 munmap(address, PAGE_SIZE); | |
701 } | |
702 | |
703 close(fd); | |
704 | |
705 LOG_INFO("%s: %s\n", __FUNCTION__, status ? "Supported" : "NOT supported"); | |
706 return status; | |
707 } | |
708 | |
709 // Check whether a library is page aligned and uncompressed in the APK file. | 662 // Check whether a library is page aligned and uncompressed in the APK file. |
710 // | 663 // |
711 // |env| is the current JNI environment handle. | 664 // |env| is the current JNI environment handle. |
712 // |clazz| is the static class handle which is not used here. | 665 // |clazz| is the static class handle which is not used here. |
713 // |apkfile_name| is the filename of the APK. | 666 // |apkfile_name| is the filename of the APK. |
714 // |library_name| is the library base name. | 667 // |library_name| is the library base name. |
715 // Returns true if page aligned and uncompressed. | 668 // Returns true if page aligned and uncompressed. |
716 jboolean CheckLibraryIsMappableInApk(JNIEnv* env, jclass clazz, | 669 jboolean CheckLibraryIsMappableInApk(JNIEnv* env, jclass clazz, |
717 jstring apkfile_name, | 670 jstring apkfile_name, |
718 jstring library_name) { | 671 jstring library_name) { |
(...skipping 22 matching lines...) Expand all Loading... |
741 reinterpret_cast<void*>(&LoadLibrary)}, | 694 reinterpret_cast<void*>(&LoadLibrary)}, |
742 {"nativeLoadLibraryInZipFile", | 695 {"nativeLoadLibraryInZipFile", |
743 "(" | 696 "(" |
744 "Ljava/lang/String;" | 697 "Ljava/lang/String;" |
745 "Ljava/lang/String;" | 698 "Ljava/lang/String;" |
746 "J" | 699 "J" |
747 "Lorg/chromium/base/library_loader/Linker$LibInfo;" | 700 "Lorg/chromium/base/library_loader/Linker$LibInfo;" |
748 ")" | 701 ")" |
749 "Z", | 702 "Z", |
750 reinterpret_cast<void*>(&LoadLibraryInZipFile)}, | 703 reinterpret_cast<void*>(&LoadLibraryInZipFile)}, |
751 {"nativeEnableNoMapExecSupportFallback", | |
752 "(" | |
753 ")" | |
754 "V", | |
755 reinterpret_cast<void*>(&EnableNoMapExecSupportFallback)}, | |
756 {"nativeRunCallbackOnUiThread", | 704 {"nativeRunCallbackOnUiThread", |
757 "(" | 705 "(" |
758 "J" | 706 "J" |
759 ")" | 707 ")" |
760 "V", | 708 "V", |
761 reinterpret_cast<void*>(&RunCallbackOnUiThread)}, | 709 reinterpret_cast<void*>(&RunCallbackOnUiThread)}, |
762 {"nativeCreateSharedRelro", | 710 {"nativeCreateSharedRelro", |
763 "(" | 711 "(" |
764 "Ljava/lang/String;" | 712 "Ljava/lang/String;" |
765 "J" | 713 "J" |
(...skipping 18 matching lines...) Expand all Loading... |
784 "J" | 732 "J" |
785 ")" | 733 ")" |
786 "J", | 734 "J", |
787 reinterpret_cast<void*>(&GetRandomBaseLoadAddress)}, | 735 reinterpret_cast<void*>(&GetRandomBaseLoadAddress)}, |
788 {"nativeGetLibraryFilePathInZipFile", | 736 {"nativeGetLibraryFilePathInZipFile", |
789 "(" | 737 "(" |
790 "Ljava/lang/String;" | 738 "Ljava/lang/String;" |
791 ")" | 739 ")" |
792 "Ljava/lang/String;", | 740 "Ljava/lang/String;", |
793 reinterpret_cast<void*>(&GetLibraryFilePathInZipFile)}, | 741 reinterpret_cast<void*>(&GetLibraryFilePathInZipFile)}, |
794 {"nativeCheckMapExecSupport", | |
795 "(" | |
796 "Ljava/lang/String;" | |
797 ")" | |
798 "Z", | |
799 reinterpret_cast<void*>(&CheckMapExecSupport)}, | |
800 {"nativeCheckLibraryIsMappableInApk", | 742 {"nativeCheckLibraryIsMappableInApk", |
801 "(" | 743 "(" |
802 "Ljava/lang/String;" | 744 "Ljava/lang/String;" |
803 "Ljava/lang/String;" | 745 "Ljava/lang/String;" |
804 ")" | 746 ")" |
805 "Z", | 747 "Z", |
806 reinterpret_cast<void*>(&CheckLibraryIsMappableInApk)}, }; | 748 reinterpret_cast<void*>(&CheckLibraryIsMappableInApk)}, }; |
807 | 749 |
808 } // namespace | 750 } // namespace |
809 | 751 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 crazy_context_t* context = GetCrazyContext(); | 794 crazy_context_t* context = GetCrazyContext(); |
853 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); | 795 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); |
854 | 796 |
855 // Register the function that the crazy linker can call to post code | 797 // Register the function that the crazy linker can call to post code |
856 // for later execution. | 798 // for later execution. |
857 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL); | 799 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL); |
858 | 800 |
859 LOG_INFO("%s: Done", __FUNCTION__); | 801 LOG_INFO("%s: Done", __FUNCTION__); |
860 return JNI_VERSION_1_4; | 802 return JNI_VERSION_1_4; |
861 } | 803 } |
OLD | NEW |