OLD | NEW |
(Empty) | |
| 1 Introduction: |
| 2 ------------- |
| 3 |
| 4 A custom dynamic linker for Android programs that adds a few interesting |
| 5 features compared to /system/bin/linker: |
| 6 |
| 7 - Support changing the library search path. The system linker, when used |
| 8 inside Android applications, is limited to the value of LD_LIBRARY_PATH |
| 9 at boot time, that only looks into system directories, not application |
| 10 ones. |
| 11 |
| 12 This linker allows the client to add application paths before the |
| 13 default system ones, this has two benefits: |
| 14 |
| 15 - Library dependencies are loaded automatically in the right order. |
| 16 |
| 17 - Libraries from the application paths are favored over system ones. |
| 18 This avoids conflicts when one of your application's libraries |
| 19 has the same name than a system one (which happens randomly |
| 20 on certain devices due to system application bundling). |
| 21 |
| 22 (Note: The system linker issue above has been fixed in Android 4.3). |
| 23 |
| 24 - Supports any number of shared libraries. On older Android platforms, |
| 25 the system linker will refuse to load more than 64 or 128 libraries |
| 26 in a single process (Note: Fixed in Android 4.3). |
| 27 |
| 28 - Supports loading a library at an explicit (page-aligned) memory |
| 29 address. The system linker always randomizes the address. Note that |
| 30 this is generally a _bad_ idea for security reasons. Consider using |
| 31 this only when using shared RELROs (see below). |
| 32 |
| 33 - Supports loading a library from an explicit (page-aligned) file |
| 34 offset. This can be useful to load a library directly from an .apk, |
| 35 provided that it is uncompressed and at a page-aligned offset. |
| 36 |
| 37 - Support sharing of RELRO sections. When two processes load the same |
| 38 library at exactly the same address, the content of its RELRO section |
| 39 is identical. By default, each instance uses private RAM pages to host |
| 40 it, but it is possible to use a single ashmem region to share the same |
| 41 data instead. |
| 42 |
| 43 WARNING: This feature will not work on certain older kernels. See |
| 44 the documentation for crazy_system_can_share_relro() for |
| 45 more details. |
| 46 |
| 47 See include/crazy_linker.h for the API and its documentation. |
| 48 |
| 49 See LICENSE file for full licensing details (hint: BSD) |
| 50 |
| 51 A few notes: |
| 52 |
| 53 - Do not use this if you don't know what you're doing. Read the API |
| 54 documentation first, and look at the test programs for usage examples. |
| 55 |
| 56 - The crazy linker will always use the system linker to load NDK-exposed |
| 57 system libraries (e.g. liblog.so and others). This avoids having two |
| 58 instances of the same library in the same process, and correctly |
| 59 resolving any symbols from system libraries. |
| 60 |
| 61 - Any library loaded by the crazy linker, and which uses functions of |
| 62 libdl.so will continue to work. However, calls to dlopen(), dlsym(), |
| 63 et al will be redirected to the crazy linker's own wrappers. |
| 64 |
| 65 This ensures that if a library is loaded by the crazy linker, any of |
| 66 its dependencies will be loaded by it too. |
| 67 |
| 68 - Libraries loaded with the crazy linker are visible to GDB, or Breakpad, |
| 69 and stack unwinding / C++ exception propagation should just work. |
| 70 |
| 71 |
| 72 Caveats: |
| 73 -------- |
| 74 |
| 75 You can't call the crazy_linker code directly from Java in your Android |
| 76 application (it's a static library). You need to put it into your own |
| 77 shared library, loaded with System.loadLibrary() instead (or alternatively, |
| 78 inside your NativeActivity's shared library). |
| 79 |
| 80 Also, libraries loaded with the crazy linker are not visible to the system |
| 81 one. In practice, it means that lazy native method lookup will not work. I.e.: |
| 82 |
| 83 The first time you call a native method like: |
| 84 |
| 85 'mypackage.MyClass.myNativeMethod()' |
| 86 |
| 87 The VM will look into existing native libraries with dlsym() for a |
| 88 function symbol named like: |
| 89 |
| 90 Java_mypackage_MyClass_myNativeMethod |
| 91 |
| 92 This will not work if the symbol is inside a library loaded with the |
| 93 crazy_linker. |
| 94 |
| 95 To work-around this, register the native methods explicitely |
| 96 in your JNI_OnLoad() by calling env->RegisterNatives() with the |
| 97 appropriate parameters. |
| 98 |
| 99 |
| 100 Usage instructions: |
| 101 ------------------- |
| 102 |
| 103 1/ Add the following to your module definition in your project's Android.mk: |
| 104 |
| 105 LOCAL_STATIC_LIBRARIES := crazy_linker |
| 106 |
| 107 2/ Also Include the top-level crazy_linker Android.mk, as in: |
| 108 |
| 109 include /path/to/crazy_linker/Android.mk |
| 110 |
| 111 3/ In your C or C++ source: |
| 112 |
| 113 #include <crazy_linker.h> |
| 114 |
| 115 Read the header for API documentation. |
| 116 |
| 117 If your library implements native methods, it must explicitely register |
| 118 them with env->RegisterNatives() before they become usable. |
| 119 |
| 120 BUGS & TODOs: |
| 121 ------------- |
| 122 |
| 123 - Libraries loaded by the crazy linker are not automatically closed when |
| 124 the process exits. |
| 125 |
| 126 - dlopen() when called inside a library loaded by the crazy linker doesn't |
| 127 support RTLD_MAIN or RTLD_NEXT. |
| 128 |
| 129 Testing: |
| 130 -------- |
| 131 |
| 132 If you modify this code, check your changes by running the test suite using: |
| 133 |
| 134 cd $NDK |
| 135 tests/run-tests.sh crazy_linker |
| 136 |
| 137 See DESIGN.TXT for an overview of the library's design. |
OLD | NEW |