|
| 1 | +This directory contains the sources of the C runtime object files |
| 2 | +required by the Android NDK toolchains. This document explains |
| 3 | +what they are, as well as a few important details about them. |
| 4 | + |
| 5 | +The files are located under the following directories: |
| 6 | + |
| 7 | + android-3/arch-arm/src/ |
| 8 | + android-9/arch-x86/src/ |
| 9 | + android-9/arch-mips/src/ |
| 10 | + |
| 11 | +They are all *assembly* files with an .S extension, which means that |
| 12 | +they'll be sent to the C-preprocessor before being assembled into |
| 13 | +object files. They have the following names and usage: |
| 14 | + |
| 15 | + crtbegin_static.S |
| 16 | + This file contains a tiny ELF startup entry point (named '_start') |
| 17 | + that is linked into every Android _static_ executable. These binaries can |
| 18 | + run on any Linux ARM system, but cannot perform dynamic linking at all. |
| 19 | + |
| 20 | + Note that the kernel calls the '_start' entry point directly when it |
| 21 | + launches such an executable. The _start stub is used to call the |
| 22 | + C library's runtime initialization, passing it the address of the |
| 23 | + 'main' function. |
| 24 | + |
| 25 | + crtbegin_dynamic.S |
| 26 | + This is equivalent to crtbegin_static.S, for for _dynamic_ executables. |
| 27 | + These executables always link to the system C library dynamically. |
| 28 | + |
| 29 | + When the kernel launches such an executable, it actually starts the |
| 30 | + dynamic linker (/system/bin/linker), which loads and relocates the |
| 31 | + executable (possibly loading any dependent system libraries as well), |
| 32 | + then call the _start stub. |
| 33 | + |
| 34 | + crtbegin_so.S |
| 35 | + This is equivalent to crtbegin_dynamic.S, but shall be used for |
| 36 | + shared libraries. One major difference is that there is no _start |
| 37 | + entry point. |
| 38 | + |
| 39 | + crtend_android.S |
| 40 | + This source file shall be used when generating an executable, i.e. used |
| 41 | + in association with either crtbegin_static.S or crtbegin_dynamic.S |
| 42 | + |
| 43 | + crtend.S |
| 44 | + This source file is _strictly_ equivalent to crtend_android.S. |
| 45 | + Actually, it *must* be compiled into an object named 'crtend_android.o' |
| 46 | + because that's the hard-coded name that the toolchain binaries expect. |
| 47 | + |
| 48 | + (the naming difference for this source file is purely historical, it |
| 49 | + could probably be removed in the future). |
| 50 | + |
| 51 | + crtend_so.S |
| 52 | + This source's object file shall be used when generating a shared library, |
| 53 | + i.e. used in association with crtbegin_so.S only. |
| 54 | + |
| 55 | +Content of these files: |
| 56 | + |
| 57 | +ELF section (lists); |
| 58 | + |
| 59 | + crtbegin_static.S + crtbegin_dynamic.S contain a '_start' entry point for |
| 60 | + the corresponding executable. crtbegin_so.S doesn't need any. |
| 61 | + |
| 62 | + all crtbegin_XXX.s files contain the head of various ELF sections, which are |
| 63 | + used to list of ELF constructors and destructors. The sections are: |
| 64 | + |
| 65 | + .init_array: |
| 66 | + Contains a list of function addresses that are run at load time. |
| 67 | + This means they are run *before* 'main', in the case of executables, |
| 68 | + or during 'dlopen()' for shared libraries (either implicit or explicit). |
| 69 | + |
| 70 | + The functions are called in list order (from first to last). |
| 71 | + |
| 72 | + .fini_array: |
| 73 | + Contains a list of destructor addresses that are run at unload time. |
| 74 | + This means they are run *after* 'exit', in the case of executables, |
| 75 | + or during 'dlclose()' for shared libraries (either implicit or explicit). |
| 76 | + |
| 77 | + The functions are called in _reverse_ list order (from last to first). |
| 78 | + |
| 79 | + .preinit_array: |
| 80 | + This section can *only* appear in executables. It contains a list of |
| 81 | + constructors that are run _before_ the ones in .init_array, or those |
| 82 | + of any dependent shared library (if any). |
| 83 | + |
| 84 | + .ctors |
| 85 | + This section shall *not* be used on Android. Used on some GLibc-based |
| 86 | + Linux systems to hold list of constructors. The toolchains should |
| 87 | + place all constructors in .init_array instead. |
| 88 | + |
| 89 | + .dtors |
| 90 | + This section shall *not* be used on Android. Used on some GLibc-based |
| 91 | + Linux systems to hold a list of destructors. The toolchains should |
| 92 | + place all destructors in .fini_array instead. |
| 93 | + |
| 94 | + |
| 95 | +__dso_handle symbol: |
| 96 | + |
| 97 | + To properly support the C++ ABI, a unique *local* *hidden* symbol named |
| 98 | + '__dso_handle' must be defined in each shared library. |
| 99 | + |
| 100 | + This is used to implement static C++ object initialization in a shared |
| 101 | + library, as in: |
| 102 | + |
| 103 | + static Foo foo(10); |
| 104 | + |
| 105 | + The statement above creates a hidden function, which address will be added |
| 106 | + to the .init_array section described above. Its compiler-generated code |
| 107 | + will perform the object construction, and also register static destructor |
| 108 | + using a call that looks like: |
| 109 | + |
| 110 | + __cxa_atexit( Foo::~Foo, &foo, &__dso_handle ); |
| 111 | + |
| 112 | + Where '__cxa_atexit' is a special C++ support function provided by the |
| 113 | + C library. Doing this ensures that the destructor for 'foo' will be |
| 114 | + automatically called when the shared library containing this code is |
| 115 | + unloaded (i.e. either through 'dlclose' or at program exit). |
| 116 | + |
| 117 | + The value of __dso_handle is normally never taken directly. |
| 118 | + |
| 119 | + See http://sourcery.mentor.com/public/cxx-abi/abi.html#dso-dtor |
| 120 | + |
| 121 | + WARNING: There is a big caveat regarding this symbol. Read the section |
| 122 | + named 'IMPORTANT BACKWARDS COMPATIBILITY ISSUES' below. |
| 123 | + |
| 124 | + |
| 125 | +atexit() implementation: |
| 126 | + |
| 127 | + The Posix standard doesn't mandate the program behaviour's when a shared |
| 128 | + library which registered a function with 'atexit' is unloaded explicitely |
| 129 | + (e.g. with 'dlclose()'). |
| 130 | + |
| 131 | + On most BSD systems (including OS X), unloading the library succeeds, but |
| 132 | + the program will crash when it calls exit() or returns from main(). |
| 133 | + |
| 134 | + On Linux, GLibc provides an implementation that automatically unregisters |
| 135 | + such atexit() handlers when the corresponding shared library is unloaded. |
| 136 | + |
| 137 | + However, this requires that the atexit() implementation be part of the |
| 138 | + shared library itself, rather than the C library. |
| 139 | + |
| 140 | + The crtbegin_shared.S and crtbegin_static.S files contain an tiny |
| 141 | + implementation of atexit() in assembler that essentially does: |
| 142 | + |
| 143 | + void atexit(void(*myfunc)(void)) |
| 144 | + { |
| 145 | + __cxa_atexit(myfunc, NULL, &__dso_handle); |
| 146 | + } |
| 147 | + |
| 148 | + Because it references the shared library's hidden __dso_handle symbol, |
| 149 | + this code cannot be in the C library itself. |
| 150 | + |
| 151 | + Note that crtbegin_static.S should *not* provide an atexit() function |
| 152 | + (the latter should be provided by libc.a instead). |
| 153 | + |
| 154 | + See 'BACKWARDS COMPATIBILITY ISSUES' section below. |
| 155 | + |
| 156 | + |
| 157 | + |
| 158 | +BACKWARDS COMPATIBILITY ISSUES: |
| 159 | +------------------------------- |
| 160 | + |
| 161 | +To maintain binary compatibility to all existing NDK-generated machine code, |
| 162 | +the system's C library (i.e. /system/lib/libc.so) needs to exports symbols |
| 163 | +that shall *not* be exported by the NDK-provided link-time libraries (i.e. |
| 164 | +$NDK/platforms/android-$LEVEL/arch-$ARCH/usr/lib/libc.so). |
| 165 | + |
| 166 | +Starting from NDK r7, the NDK libc.so is itself generated by a script |
| 167 | +(gen-platforms.sh) from a list of symbol files (see libc.so.functions.txt |
| 168 | +and libc.so.variables.txt) and does not contain any implementation code. |
| 169 | + |
| 170 | +The NDK libc.a, on the other hand, is a copy of a given version of the system |
| 171 | +C static library, and shall only be used to generate static executables (it |
| 172 | +is also required to build gdbserver). |
| 173 | + |
| 174 | +1. libgcc compatibility symbols: |
| 175 | + |
| 176 | + None of the link-time NDK shared libraries should export any libgcc symbol. |
| 177 | + |
| 178 | + However, on ARM, the system C library needs to export some of them to |
| 179 | + maintain binary compatibility with 'legacy' NDK machine code. Details are |
| 180 | + under bionic/libc/arch-arm/bionic/libgcc_compat.c. |
| 181 | + |
| 182 | + Note that gen-platforms.sh takes care of this by explicitely removing any |
| 183 | + libgcc symbol from the link-time shared libraries it generates. This is done |
| 184 | + by using the lists under: |
| 185 | + |
| 186 | + $NDK/build/tools/toolchain-symbols/$ARCH/libgcc.a.functions.txt |
| 187 | + |
| 188 | + You will need to update these files when the toolchain changes. |
| 189 | + |
| 190 | + Note that all libgcc releases should be backwards-compatible, i.e. newer |
| 191 | + releases always contain all the symbols from previous ones). |
| 192 | + |
| 193 | + |
| 194 | +2. __dso_handle compatibility symbol: |
| 195 | + |
| 196 | + Earlier versions of the C library exported a __dso_handle symbol |
| 197 | + *incorrectly*. As such: |
| 198 | + |
| 199 | + - the system's libc.so shall always export its __dso_handle, as *global* |
| 200 | + and *public* (in ELF visibility terms). A weak symbol definition is ok |
| 201 | + but not necessary. This is only to ensure binary compatibility with |
| 202 | + 'legacy' NDK machine code. |
| 203 | + |
| 204 | + - the NDK link-time libc.so shall *never* export or contain any |
| 205 | + __dso_handle symbol. |
| 206 | + |
| 207 | + - The NDK's crtbegin_dynamic.S and crtbegin_so.S shall provide a *local* |
| 208 | + and *hidden* __dso_handle symbol. |
| 209 | + |
| 210 | + - The NDK's libc.a will containg a *global* and *public* __dso_handle, since |
| 211 | + it is a copy of a release-specific system libc.so. |
| 212 | + |
| 213 | + - crtbegin_static.S shall not provide any __dso_handle symbol, since static |
| 214 | + executables will use the one in libc.a instead. |
| 215 | + |
| 216 | +Note that existing NDK machine code that links against the system libc's |
| 217 | +__dso_handle will not have their C++ destructors run correctly when the |
| 218 | +library is unloaded. However, this bug can be solved by simply recompiling |
| 219 | +/relinking against a newer NDK release, without touching the original |
| 220 | +sources. |
| 221 | + |
| 222 | + |
| 223 | + |
| 224 | +3. atexit compatibility symbol: |
| 225 | + |
| 226 | + Earlier versions of the C library implemented and exported an atexit() |
| 227 | + function. While this is compliant with Posix, this doesn't allow a useful |
| 228 | + GLibc extension which automatically un-registers atexit() handlers when |
| 229 | + a shared library is unloaded with dlclose(). |
| 230 | + |
| 231 | + To support this, while providing binary compatibility, the following |
| 232 | + must apply: |
| 233 | + |
| 234 | + - The platform's /system/lib/libc.so should *always* export a working |
| 235 | + atexit() implementation (used by 'legacy' NDK machine code). |
| 236 | + |
| 237 | + - The NDK link-time libc.so should *never* export atexit() |
| 238 | + |
| 239 | + - crtbegin_shared.S, crtbegin_so.S shall define a *local* *hidden* |
| 240 | + symbol for atexit(), with a tiny implementation that amounts to the |
| 241 | + following code: |
| 242 | + |
| 243 | + void atexit( void(*handler)(void) ) |
| 244 | + { |
| 245 | + __cxa_atexit( handler, NULL, &__dso_handle ); |
| 246 | + } |
| 247 | + |
| 248 | + - The NDK libc.a shall provide an atexit() implementation, and |
| 249 | + crtbegin_static.S shall *not* provide one to avoid conflicts. |
| 250 | + |
| 251 | +Note that existing NDK machine code that links against the system libc's |
| 252 | +atexit symbol will not have their atexit-handler automatically unregistered |
| 253 | +when the library is unloaded. However, this bug can be solved by simply |
| 254 | +recompiling/relinking against a newer NDK release, without touching the |
| 255 | +original sources. |
| 256 | + |
| 257 | +4. __atomic_xxx sompatibility symbols: |
| 258 | + |
| 259 | +This issues is detailed in ndk/docs/ANDROID-ATOMICS.html and |
| 260 | +bionic/libc/arch-arm/bionic/atomics_arm.c. In a nutshell: |
| 261 | + |
| 262 | + - The system C library *shall* always export on *ARM* the __atomic_cmpxchg, |
| 263 | + __atomic_inc and __atomic_dec functions to support legacy NDK machine code. |
| 264 | + Their implementation should have full (i.e. acquire+release) memory ordering |
| 265 | + semantics. |
| 266 | + |
| 267 | + - The system C library for other CPU architectures (e.g. x86 or mips) *shall* |
| 268 | + *not* export any of these symbols. |
| 269 | + |
| 270 | + - The NDK libc.so *shall* *not* export these symbols at all. |
| 271 | + |
| 272 | + - The NDK <sys/atomics.h> header shall provide inlined-static versions of |
| 273 | + these functions that use the built-in GCC atomic functions instead. |
| 274 | + |
0 commit comments