David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 1 | Android Dynamic Linker Design Notes |
| 2 | =================================== |
| 3 | |
| 4 | Introduction: |
| 5 | ------------- |
| 6 | |
| 7 | This document provides several notes related to the design of the Android |
| 8 | dynamic linker. |
| 9 | |
| 10 | |
| 11 | Prelinking: |
| 12 | ----------- |
| 13 | |
| 14 | System libraries in Android are internally prelinked, which means that |
| 15 | any internal relocations within them are stripped from the corresponding |
| 16 | shared object, in order to reduce size and speed up loading. |
| 17 | |
| 18 | Such libraries can only be loaded at the very specific virtual memory address |
| 19 | they have been prelinked to (during the build process). The list of prelinked |
| 20 | system libraries and their corresponding virtual memory address is found in |
| 21 | the file: |
| 22 | |
| 23 | build/core/prelink-linux-<arch>.map |
| 24 | |
| 25 | It should be updated each time a new system library is added to the |
| 26 | system. |
| 27 | |
| 28 | The prelink step happens at build time, and uses the 'soslim' and 'apriori' |
| 29 | tools: |
| 30 | |
| 31 | - 'apriori' is the real prelink tool which removes relocations from the |
| 32 | shared object, however, it must be given a list of symbols to remove |
| 33 | from the file. |
| 34 | |
| 35 | - 'soslim' is used to find symbols in an executable ELF file |
| 36 | and generate a list that can be passed to 'apriori'. |
| 37 | |
| 38 | By default, these tools are only used to remove internal symbols from |
| 39 | libraries, though they have been designed to allow more aggressive |
| 40 | optimizations (e.g. 'global' prelinking and symbol stripping, which |
| 41 | prevent replacing individual system libraries though). |
| 42 | |
| 43 | You can disable prelinking at build time by modifying your Android.mk with |
| 44 | a line like: |
| 45 | |
| 46 | LOCAL_PRELINK_MODULE := false |
| 47 | |
| 48 | |
| 49 | Initialization and Termination functions: |
| 50 | ----------------------------------------- |
| 51 | |
| 52 | The Unix Sys V Binary Interface standard states that an |
| 53 | executable can have the following entries in its .dynamic |
| 54 | section: |
| 55 | |
| 56 | DT_INIT |
| 57 | Points to the address of an initialization function |
| 58 | that must be called when the file is loaded. |
| 59 | |
| 60 | DT_INIT_ARRAY |
| 61 | Points to an array of function addresses that must be |
| 62 | called, in-order, to perform initialization. Some of |
| 63 | the entries in the array can be 0 or -1, and should |
| 64 | be ignored. |
| 65 | |
| 66 | Note: this is generally stored in a .init_array section |
| 67 | |
| 68 | DT_INIT_ARRAYSZ |
| 69 | The size of the DT_INITARRAY, if any |
| 70 | |
| 71 | DT_FINI |
| 72 | Points to the address of a finalization function which |
| 73 | must be called when the file is unloaded or the process |
| 74 | terminated. |
| 75 | |
| 76 | DT_FINI_ARRAY |
| 77 | Same as DT_INITARRAY but for finalizers. Note that the |
| 78 | functions must be called in reverse-order though |
| 79 | |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 80 | Note: this is generally stored in a .fini_array section |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 81 | |
| 82 | DT_FINI_ARRAYSZ |
| 83 | Size of FT_FINIARRAY |
| 84 | |
| 85 | DT_PREINIT_ARRAY |
| 86 | An array similar to DT_INIT_ARRAY which must *only* be |
| 87 | present in executables, not shared libraries, which contains |
| 88 | a list of functions that need to be called before any other |
| 89 | initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY) |
Evgeniy Stepanov | e83c56d | 2011-12-21 13:03:54 +0400 | [diff] [blame^] | 90 | in the executable or any of its libraries. |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 91 | |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 92 | Note: this is generally stored in a .preinit_array section |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 93 | |
| 94 | DT_PREINIT_ARRAYSZ |
| 95 | The size of DT_PREINIT_ARRAY |
| 96 | |
| 97 | If both a DT_INIT and DT_INITARRAY entry are present, the DT_INIT |
| 98 | function must be called before the DT_INITARRAY functions. |
| 99 | |
| 100 | Consequently, the DT_FINIARRAY must be parsed in reverse order before |
| 101 | the DT_FINI function, if both are available. |
| 102 | |
| 103 | Note that the implementation of static C++ constructors is very |
| 104 | much processor dependent, and may use different ELF sections. |
| 105 | |
| 106 | On the ARM (see "C++ ABI for ARM" document), the static constructors |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 107 | must be called explicitly from the DT_INIT_ARRAY, and each one of them |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 108 | shall register a destructor by calling the special __eabi_atexit() |
| 109 | function (provided by the C library). The DT_FINI_ARRAY is not used |
| 110 | by static C++ destructors. |
| 111 | |
| 112 | On x86, the lists of constructors and destructors are placed in special |
| 113 | sections named ".ctors" and ".dtors", and the DT_INIT / DT_FINI functions |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 114 | are in charge of calling them explicitly. |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 115 | |
David 'Digit' Turner | 5c73464 | 2010-01-20 12:36:51 -0800 | [diff] [blame] | 116 | |
| 117 | Debugging: |
| 118 | ---------- |
| 119 | |
| 120 | It is possible to enable debug output in the dynamic linker. To do so, |
| 121 | follow these steps: |
| 122 | |
| 123 | 1/ Modify the line in Android.mk that says: |
| 124 | |
| 125 | LOCAL_CFLAGS += -DLINKER_DEBUG=0 |
| 126 | |
| 127 | Into the following: |
| 128 | |
| 129 | LOCAL_CFLAGS += -DLINKER_DEBUG=1 |
| 130 | |
| 131 | 2/ Force-rebuild the dynamic linker: |
| 132 | |
| 133 | cd bionic/linker |
| 134 | mm -B |
| 135 | |
| 136 | 3/ Rebuild a new system image. |
| 137 | |
| 138 | You can increase the verbosity of debug traces by defining the DEBUG |
| 139 | environment variable to a numeric value from 0 to 2. This will only |
| 140 | affect new processes being launched. |
| 141 | |
| 142 | By default, traces are sent to logcat, with the "linker" tag. You can |
| 143 | change this to go to stdout instead by setting the definition of |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 144 | LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h". |