blob: 0910e6f91f95122447f044765ba1b7bd0dbfb5d6 [file] [log] [blame] [view]
Andrew Grieve0cb64c22019-10-10 14:45:391# Native Relocations
2
3*** note
4Information here is mostly Android & Linux-specific and may not be 100% accurate.
5***
6
7## What are they?
8 * For ELF files, they are sections of type REL, RELA, or RELR. They generally
9 have the name ".rel.dyn" and ".rel.plt".
10 * They tell the runtime linker a list of addresses to post-process after
11 loading the executable into memory.
12 * There are several types of relocations, but >99% of them are "relative"
13 relocations and are created any time a global variable or constant is
14 initialized with the address of something.
15 * This includes vtables, function pointers, and string literals, but not
16 `char[]`.
17 * Each relocation is stored as either 2 or 3 words, based on the architecture.
18 * On Android, they are compressed, which trades off runtime performance for
19 smaller file size.
20 * As of Oct 2019, Chrome on Android has about 390000 of them.
21 * Windows and Mac have them as well, but I don't know how they differ.
22
23## Why do they matter?
24 * **Binary Size:** Except on Android, relocations are stored very
25 inefficiently.
26 * Chrome on Linux has a `.rela.dyn` section of more than 14MiB!
27 * Android uses a [custom compression scheme][android_relro1] to shrink them
28 down to ~300kb.
29 * There is an even better [RELR][RELR] encoding available on Android P+, but
30 not widely available on Linux yet. It makes relocations ~60kb.
31 * **Memory Overhead:** Symbols with relocations cannot be loaded read-only
32 and result in "dirty" memory. 99% of these symbols live in `.data.rel.ro`,
33 which as of Oct 2019 is ~6.5MiB on Linux and ~2MiB on Android.
34 `.data.rel.ro` is data that *would* have been put into `.rodata` and mapped
35 read-only if not for the required relocations. It does not get written to
36 after it's relocated, so the linker makes it read-only once relocations are
37 applied (but by that point the damage is done and we have the dirty pages).
38 * On Linux, we share this overhead between processes via the [zygote].
39 * [On Android][android_relro2], we share this overhead between processes by
40 loading the shared library at the same address in all processes, and then
41 `mremap` onto shared memory to dedupe after-the-fact.
42 * **Start-up Time** The runtime linker applies relocations when loading the
43 executable. On low-end Android, it can take ~100ms (measured on a first-gen
44 Android Go devices with APS2 relocations). On Linux, it's
45 [closer to 20ms][zygote].
46
47[zygote]: linux_zygote.md
48[RELR]: https://reviews.llvm.org/D48247
49[android_relro1]: android_native_libraries.md#Packed-Relocations
50[android_relro2]: android_native_libraries.md#relro-sharing
51
52## How do I see them?
53
54```sh
55third_party/llvm-build/Release+Asserts/bin/llvm-readelf --relocs out/Release/libmonochrome.so
56```
57
58## Can I avoid them?
59It's not practical to avoid them altogether, but there are times when you can be
60smart about them.
61
62For Example:
63```c++
64// Wastes 2 bytes for each smaller string but creates no relocations.
65// Total size overhead: 4 * 5 = 20 bytes.
66const char kArr[][5] = {"as", "ab", "asdf", "fi"};
67
68// String data stored optimally, but uses 4 relocatable pointers.
69// Total size overhead:
70// 64-bit: 8 bytes per pointer + 24 bytes per relocation + 14 bytes of char = 142 bytes
71// 32-bit: 4 bytes per pointer + 8 bytes per relocation + 14 bytes of char = 62 bytes
72const char *kArr2[] = {"as", "ab", "asdf", "fi"};
73```
74
75Note:
76* String literals are de-duped with others in the binary, so it's possible that
77 the second example above might use 14 fewer bytes.
78* Not all string literals require relocations. Only those that are stored into
79 global variables require them.
80
81Another thing to look out for:
82 * Large data structures with relocations that you don't need random access to,
83 or which are seldom needed.
84 * For such cases, it might be better to store the data encoded and then
85 decode when required.