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 | |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 11 | Initialization and Termination functions: |
| 12 | ----------------------------------------- |
| 13 | |
| 14 | The Unix Sys V Binary Interface standard states that an |
| 15 | executable can have the following entries in its .dynamic |
| 16 | section: |
| 17 | |
| 18 | DT_INIT |
| 19 | Points to the address of an initialization function |
| 20 | that must be called when the file is loaded. |
| 21 | |
| 22 | DT_INIT_ARRAY |
| 23 | Points to an array of function addresses that must be |
| 24 | called, in-order, to perform initialization. Some of |
| 25 | the entries in the array can be 0 or -1, and should |
| 26 | be ignored. |
| 27 | |
| 28 | Note: this is generally stored in a .init_array section |
| 29 | |
| 30 | DT_INIT_ARRAYSZ |
| 31 | The size of the DT_INITARRAY, if any |
| 32 | |
| 33 | DT_FINI |
| 34 | Points to the address of a finalization function which |
| 35 | must be called when the file is unloaded or the process |
| 36 | terminated. |
| 37 | |
| 38 | DT_FINI_ARRAY |
| 39 | Same as DT_INITARRAY but for finalizers. Note that the |
| 40 | functions must be called in reverse-order though |
| 41 | |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 42 | Note: this is generally stored in a .fini_array section |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 43 | |
| 44 | DT_FINI_ARRAYSZ |
| 45 | Size of FT_FINIARRAY |
| 46 | |
| 47 | DT_PREINIT_ARRAY |
| 48 | An array similar to DT_INIT_ARRAY which must *only* be |
| 49 | present in executables, not shared libraries, which contains |
| 50 | a list of functions that need to be called before any other |
| 51 | initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY) |
Evgeniy Stepanov | e83c56d | 2011-12-21 13:03:54 +0400 | [diff] [blame] | 52 | in the executable or any of its libraries. |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 53 | |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 54 | Note: this is generally stored in a .preinit_array section |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 55 | |
| 56 | DT_PREINIT_ARRAYSZ |
| 57 | The size of DT_PREINIT_ARRAY |
| 58 | |
| 59 | If both a DT_INIT and DT_INITARRAY entry are present, the DT_INIT |
| 60 | function must be called before the DT_INITARRAY functions. |
| 61 | |
| 62 | Consequently, the DT_FINIARRAY must be parsed in reverse order before |
| 63 | the DT_FINI function, if both are available. |
| 64 | |
| 65 | Note that the implementation of static C++ constructors is very |
| 66 | much processor dependent, and may use different ELF sections. |
| 67 | |
| 68 | On the ARM (see "C++ ABI for ARM" document), the static constructors |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 69 | 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] | 70 | shall register a destructor by calling the special __eabi_atexit() |
| 71 | function (provided by the C library). The DT_FINI_ARRAY is not used |
| 72 | by static C++ destructors. |
| 73 | |
| 74 | On x86, the lists of constructors and destructors are placed in special |
| 75 | sections named ".ctors" and ".dtors", and the DT_INIT / DT_FINI functions |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 76 | are in charge of calling them explicitly. |
David 'Digit' Turner | 8215679 | 2009-05-18 14:37:41 +0200 | [diff] [blame] | 77 | |
David 'Digit' Turner | 5c73464 | 2010-01-20 12:36:51 -0800 | [diff] [blame] | 78 | |
| 79 | Debugging: |
| 80 | ---------- |
| 81 | |
| 82 | It is possible to enable debug output in the dynamic linker. To do so, |
| 83 | follow these steps: |
| 84 | |
| 85 | 1/ Modify the line in Android.mk that says: |
| 86 | |
| 87 | LOCAL_CFLAGS += -DLINKER_DEBUG=0 |
| 88 | |
| 89 | Into the following: |
| 90 | |
| 91 | LOCAL_CFLAGS += -DLINKER_DEBUG=1 |
| 92 | |
| 93 | 2/ Force-rebuild the dynamic linker: |
| 94 | |
| 95 | cd bionic/linker |
| 96 | mm -B |
| 97 | |
| 98 | 3/ Rebuild a new system image. |
| 99 | |
| 100 | You can increase the verbosity of debug traces by defining the DEBUG |
| 101 | environment variable to a numeric value from 0 to 2. This will only |
| 102 | affect new processes being launched. |
| 103 | |
| 104 | By default, traces are sent to logcat, with the "linker" tag. You can |
| 105 | change this to go to stdout instead by setting the definition of |
Glenn Kasten | 1f35382 | 2011-01-18 09:36:38 -0800 | [diff] [blame] | 106 | LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h". |