Commit | Line | Data |
---|---|---|
d42e7319 JB |
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 | ||
80 | Note: this is generally stored in a .fini_array section | |
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) | |
90 | in the executable or any of its libraries. | |
91 | ||
92 | Note: this is generally stored in a .preinit_array section | |
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 | |
107 | must be called explicitly from the DT_INIT_ARRAY, and each one of them | |
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 | |
114 | are in charge of calling them explicitly. | |
115 | ||
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 | |
144 | LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h". |