Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1646)

Unified Diff: third_party/crazy_linker/crazy_linker/DESIGN.TXT

Issue 23717023: Android: Add chrome-specific dynamic linker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to fix build. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/crazy_linker/crazy_linker/DESIGN.TXT
diff --git a/third_party/crazy_linker/crazy_linker/DESIGN.TXT b/third_party/crazy_linker/crazy_linker/DESIGN.TXT
new file mode 100644
index 0000000000000000000000000000000000000000..ea4482da1548ec3f4b93b4ad15b9c4f5fe67be95
--- /dev/null
+++ b/third_party/crazy_linker/crazy_linker/DESIGN.TXT
@@ -0,0 +1,205 @@
+The design of crazy_linker:
+===========================
+
+Introduction:
+-------------
+
+A system linker (e.g. ld.so on Linux, or /system/bin/linker on Android), is a
+particularly sophisticated piece of code because it is used to load and start
+_executables_ on the system. This requires dealing with really low-level
+details like:
+
+ - The way the kernel loads and initializes binaries into a new process.
+
+ - The way it passes initialization data (e.g. command-line arguments) to
+ the process being launched.
+
+ - Setting up the C runtime library, thread-local storage, and others properly
+ before calling main().
+
+ - Be very careful in the way it operates, due to the fact that it will be used
+ to load set-uid programs.
+
+ - Need to support a flurry of exotic flags and environment variables that
+ affect runtime behaviour in "interesting" but mostly unpredictable ways
+ (see the manpages for dlopen, dlsym and ld.so for details).
+
+Add to this that most of this must be done without the C library being loaded or
+initialized yet. No wonder this code is really complex.
+
+By contrast, crazy_linker is a static library whose only purpose is to load
+ELF shared libraries, inside an _existing_ executable process. This makes it
+considerably simpler:
+
+ - The runtime environment (C library, libstdc++) is available and properly
+ initialized.
+
+ - No need to care about kernel interfaces. Everything uses mmap() and simple
+ file accesses.
+
+ - The API is simple, and straightforward (no hidden behaviour changes due to
+ environment variables).
+
+This document explains how the crazy_linker works. A good understanding of the
+ELF file format is recommended, though not necessary.
+
+
+I. ELF Loading Basics:
+----------------------
+
+When it comes to loading shared libraries, an ELF file mainly consists in the
+following parts:
+
+ - A fixed-size header that identifies the file as an ELF file and gives
+ offsets/sizes to other tables.
+
+ - A table (called the "program header table"), containing entries describing
+ 'segments' of interest in the ELF file.
+
+ - A table (called the "dynamic table"), containing entries describing
+ properties of the ELF library. The most interesting ones are the list
+ of libraries the current one depends on.
+
+ - A table describing the symbols (function or global names) that the library
+ references or exports.
+
+ - One or more tables containing 'relocations'. Because libraries can be loaded
+ at any page-aligned address in memory, numerical pointers they contain must
+ be adjusted after load. That's what the relocation entries do. They can
+ also reference symbols to be found in other libraries.
+
+The process of loading a given ELF shared library can be decomposed into 4 steps:
+
+ 1) Map loadable segments into memory.
+
+ This step parses the program header table to identify 'loadable' segments,
+ reserve the corresponding address space, then map them directly into
+ memory with mmap().
+
+ Related: src/crazy_linker_elf_loader.cpp
+
+
+ 2) Load library dependencies.
+
+ This step parses the dynamic table to identify all the other shared
+ libraries the current one depends on, then will _recursively_ load them.
+
+ Related: src/crazy_linker_library_list.cpp
+ (crazy::LibraryList::LoadLibrary())
+
+ 3) Apply all relocations.
+
+ This steps adjusts all pointers within the library for the actual load
+ address. This can also reference symbols that appear in other libraries
+ loaded in step 2).
+
+ Related: src/crazy_linker_elf_relocator.cpp
+
+ 4) Run constructors.
+
+ Libraries include a list of functions to be run at load time, typically
+ to perform static C++ initialization.
+
+ Related: src/crazy_linker_shared_library.cpp
+ (SharedLibrary::RunConstructors())
+
+Unloading a library is similar, but in reverse order:
+
+ 1) Run destructors.
+ 2) Unload dependencies recursively.
+ 3) Unmap loadable segments.
+
+
+II. Managing the list of libraries:
+-----------------------------------
+
+It is crucial to avoid loading the same library twice in the same process,
+otherwise some really bad undefined behaviour may happen.
+
+This implies that, inside an Android application process, all system libraries
+should be loaded by the system linker (because otherwise, the Dalvik-based
+framework might load the same library on demand, at an unpredictable time).
+
+To handle this, the crazy_linker uses a custom class (crazy::LibraryList) where
+each entry (crazy::LibraryView) is reference-counted, and either references:
+
+ - An application shared libraries, loaded by the crazy_linker itself.
+ - A system shared libraries, loaded through the system dlopen().
+
+Libraries loaded by the crazy_linker are modelled by a crazy::SharedLibrary
+object. The source code comments often refer to these objects as
+"crazy libraries", as opposed to "system libraries".
+
+As an example, here's a diagram that shows the list after loading a library
+'libfoo.so' that depends on the system libraries 'libc.so', 'libm.so' and
+'libOpenSLES.so'.
+
+ +-------------+
+ | LibraryList |
+ +-------------+
+ |
+ | +-------------+
+ +----| LibraryView | ----> libc.so
+ | +-------------+
+ |
+ | +-------------+
+ +----| LibraryView | ----> libm.so
+ | +-------------+
+ |
+ | +-------------+
+ +----| LibraryView | ----> libOpenSLES.so
+ | +-------------+
+ |
+ | +-------------+ +-------------+
+ +----| LibraryView |----->|SharedLibrary| ---> libfoo.so
+ | +-------------+ +-------------+
+ |
+ ___
+ _
+
+System libraries are identified by name. Only the official NDK-official system
+libraries are listed. It is likely that using crazy_linker to load non-NDK
+system libraries will not work correctly, so don't do it.
+
+
+III. Wrapping of linker symbols within crazy ones:
+--------------------------------------------------
+
+Libraries loaded by the crazy linker are not visible to the system linker.
+
+This means that directly calling the system dlopen() or dlsym() from a library
+code loaded by the crazy_linker will not work properly.
+
+To work-around this, crazy_linker redirects all linker symbols to its own
+wrapper implementation. This redirection happens transparently.
+
+ Related: src/crazy_linker_wrappers.cpp
+
+This also includes a few "hidden" dynamic linker symbols which are used for
+stack-unwinding. This guarantees that C++ exception propagation works.
+
+
+IV. GDB support:
+----------------
+
+The crazy_linker contains support code to ensure that libraries loaded with it
+are visible through GDB at runtime. For more details, see the extensive comments
+in src/crazy_linker_rdebug.h
+
+
+V. Other Implementation details:
+--------------------------------
+
+The crazy_linker is written in C++, but its API is completely C-based.
+
+The implementation doesn't require any C++ STL feature (except for new
+and delete).
+
+Very little of the code is actually Android-specific. The target system's
+bitness is abstracted through a C++ traits class (see src/elf_traits.h).
+
+Written originally for Chrome, so follows the Chromium coding style. Which can
+be enforced by using the 'clang-format' tool with:
+
+ cd /path/to/crazy_linker/
+ find . -name "*.h" -o -name "*.cpp" | xargs clang-format -style Chromium -i

Powered by Google App Engine
This is Rietveld 408576698