blob: 1af4a6b04cd1ed7948ee066e90b54a7d461cf0b0 [file] [log] [blame] [view]
Andrew Grieve0cb64c22019-10-10 14:45:391# Native Relocations
2
Andrew Grieve0eeb5fd2019-11-25 21:04:263[TOC]
Andrew Grieve0cb64c22019-10-10 14:45:394
5## What are they?
Andrew Grieve0cb64c22019-10-10 14:45:396 * They tell the runtime linker a list of addresses to post-process after
7 loading the executable into memory.
8 * There are several types of relocations, but >99% of them are "relative"
Andrew Grieve9534b162022-11-16 03:54:019 relocations and are created any time a global symbol or compile-time
10 initialized static local is initialized with the address of something, and
11 the compiler cannot optimize away the relocation (e.g. for pointers where
12 not all uses are visible, or for values that are passed to functions that
13 are not inlined).
14
15
16Examples of things that require relative relocations:
17
18```C++
19// Pointer to yourself.
20extern const void* const kUserDataKey = &kUserDataKey;
21// Array of pointers.
22extern const char* const kMemoryDumpAllowedArgs[] = {"dumps", nullptr};
23// Array of structs that contain one or more pointers.
24extern const StringPiece kStrings[] = {"one, "two"};
25```
26
27Vtables are arrays of function pointers, and so require relative relocations.
28However, on some Chrome platforms we use a non-standard ABI that uses offsets
29rather than pointers in order to remove the relocations overhead
30([crbug/589384]).
31
32[crbug/589384]: https://crbug.com/589384
Andrew Grieve0eeb5fd2019-11-25 21:04:2633
34### Linux & Android Relocations (ELF Format)
Andrew Grieve0eeb5fd2019-11-25 21:04:2635 * Relocations are stored in sections named: `.rel.dyn`, `.rel.plt`,
36 `.rela.dyn`, or `.rela.plt`.
Andrew Grieve9534b162022-11-16 03:54:0137 * Relocations are stored in sections of type: `REL`, `RELA`, [`APS2`][APS2], or
38 [`RELR`][RELR].
39 * `REL` is default for arm32. It uses two words to per relocation: `address`,
40 `flags`.
41 * `RELA` is default for arm64. It uses three words per relocation: `address`,
42 `flags`, `addend`.
43 * [`APS2`][APS2] is what Chrome for Android uses. It stores the same fields
44 as REL` / `RELA`, but uses variable length ints (LEB128) and run-length
45 encoding.
46 * [`RELR`][RELR] is what [Chrome OS uses], and is supported in Android P+
47 ([tracking bug for enabling]). It encodes only relative relocations and
48 uses a bitmask to do so (which works well since all symbols that require
49 relocations live in `.data.rel.ro`).
50
Andrew Grieve0eeb5fd2019-11-25 21:04:2651[APS2]: android_native_libraries.md#Packed-Relocations
Andrew Grieve9534b162022-11-16 03:54:0152[RELR]: https://maskray.me/blog/2021-10-31-relative-relocations-and-relr
53[tracking bug for enabling]: https://bugs.chromium.org/p/chromium/issues/detail?id=895194
54[Chrome OS uses]: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/1210982
Andrew Grieve0eeb5fd2019-11-25 21:04:2655
56### Windows Relocations (PE Format)
Andrew Grieve9534b162022-11-16 03:54:0157 * For PE files, relocations are stored in the [`.reloc` section][win_relocs].
Andrew Grieve0eeb5fd2019-11-25 21:04:2658 * Each relocation is stored using 2 bytes. Each `.reloc` section has a small
59 overhead as well.
60 * 64-bit executables have fewer relocations thanks to the ability to use
61 RIP-relative (instruction-relative) addressing.
62
63[win_relocs]: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only
Andrew Grieve0cb64c22019-10-10 14:45:3964
65## Why do they matter?
Andrew Grieve0eeb5fd2019-11-25 21:04:2666### Binary Size
67 * On Linux, relocations are stored very inefficiently.
68 * As of Oct 2019:
69 * Chrome on Linux has a `.rela.dyn` section of more than 14MiB!
70 * Chrome on Android uses [`APS2`] to compress these down to ~300kb.
71 * Chrome on Android with [`RELR`] would require only 60kb, but is
72 [not yet enabled][relr_bug].
73 * Chrome on Windows (x64) has `.relocs` sections that sum to 620KiB.
74
75[relr_bug]: https://bugs.chromium.org/p/chromium/issues/detail?id=895194
76
77### Memory Overhead
Andrew Grieve9534b162022-11-16 03:54:0178 * On Windows, relocations are applied by the kernel during page faults. There
79 is therefore [almost no memory overhead] from relocations, as the memory they
80 are applied to is still considered "clean" memory and shared between
81 processes.
Andrew Grieve0eeb5fd2019-11-25 21:04:2682 * On Linux and Android, memory with relocations cannot be loaded read-only and
83 result in dirty memory. 99% of these symbols live in `.data.rel.ro`, which as
84 of Oct 2019 is ~6.5MiB on Linux and ~2MiB on Android. `.data.rel.ro` is data
85 that *would* have been put into `.rodata` and mapped read-only if not for the
86 required relocations. The memory does not get written to after it's
87 relocated, so the linker makes it read-only once relocations are applied (but
88 by that point the damage is done and we have the dirty pages).
Andrew Grieve0cb64c22019-10-10 14:45:3989 * On Linux, we share this overhead between processes via the [zygote].
Andrew Grieve0eeb5fd2019-11-25 21:04:2690 * [On Android][relro_sharing], we share this overhead between processes by
Andrew Grieve0cb64c22019-10-10 14:45:3991 loading the shared library at the same address in all processes, and then
92 `mremap` onto shared memory to dedupe after-the-fact.
Andrew Grieve0cb64c22019-10-10 14:45:3993
Andrew Grieve0eeb5fd2019-11-25 21:04:2694[almost no memory overhead]: https://devblogs.microsoft.com/oldnewthing/20160413-00/?p=93301
Tom Anderson93e49e492019-12-23 19:55:3795[zygote]: linux/zygote.md
Andrew Grieve0eeb5fd2019-11-25 21:04:2696[relro_sharing]: android_native_libraries.md#relro-sharing
97
98### Start-up Time
Andrew Grieve9534b162022-11-16 03:54:0199 * On Windows, relocations are applied just-in-time, and so their overhead is
100 both small and difficult to measure.
Andrew Grieve0eeb5fd2019-11-25 21:04:26101 * On other platforms, the runtime linker applies all relocations upfront.
102 * On low-end Android, it can take ~100ms (measured on a first-gen Android Go
103 devices with APS2 relocations).
Andrew Grieve9534b162022-11-16 03:54:01104 * On a Pixel 4a, it's ~50ms, and with RELR relocations, it's closer to 15ms.
Andrew Grieve0eeb5fd2019-11-25 21:04:26105 * On Linux, it's [closer to 20ms][zygote].
Andrew Grieve0cb64c22019-10-10 14:45:39106
107## How do I see them?
108
109```sh
Andrew Grieve0eeb5fd2019-11-25 21:04:26110# For ELF files:
Andrew Grieve0cb64c22019-10-10 14:45:39111third_party/llvm-build/Release+Asserts/bin/llvm-readelf --relocs out/Release/libmonochrome.so
Andrew Grieve0eeb5fd2019-11-25 21:04:26112
113# For PE files:
114python tools\win\pe_summarize.py out\Release\chrome.dll
Andrew Grieve0cb64c22019-10-10 14:45:39115```
116
117## Can I avoid them?
118It's not practical to avoid them altogether, but there are times when you can be
119smart about them.
120
121For Example:
122```c++
Andrew Grieve0eeb5fd2019-11-25 21:04:26123// The following uses 2 bytes of padding for each smaller string but creates no relocations.
Andrew Grieve0cb64c22019-10-10 14:45:39124// Total size overhead: 4 * 5 = 20 bytes.
125const char kArr[][5] = {"as", "ab", "asdf", "fi"};
126
Andrew Grieve0eeb5fd2019-11-25 21:04:26127// The following requires no string padding, but uses 4 relocatable pointers.
Andrew Grieve0cb64c22019-10-10 14:45:39128// Total size overhead:
Andrew Grieve0eeb5fd2019-11-25 21:04:26129// Linux 64-bit: (8 bytes per pointer + 24 bytes per relocation) * 4 entries + 14 bytes of char = 142 bytes
130// Windows 64-bit: (8 bytes per pointer + 2 bytes per relocation) * 4 entries + 14 bytes of char = 54 bytes
131// CrOS 64-bit: (8 bytes per pointer + ~0 bytes per relocation) * 4 entries + 14 bytes of char = ~46 bytes
132// Android 32-bit: (4 bytes per pointer + ~0 bytes per relocation) * 4 entries + 14 bytes of char = ~30 bytes
133const char * const kArr2[] = {"as", "ab", "asdf", "fi"};
Andrew Grieve0cb64c22019-10-10 14:45:39134```
135
Andrew Grieve0eeb5fd2019-11-25 21:04:26136Notes:
137* String literals (but not char arrays) are de-duped with others in the binary,
138 so it is possible that the second example above might use 14 fewer bytes.
139* Not all string literals require relocations. Which ones require them depends
140 on the ABI. Generally, All global variables that are initialized to the
141 address of something require them.
142
143Here's a simpler example:
144
145```c++
146// No pointer, no relocation. Just 5 bytes of character data.
Andrew Grieve9534b162022-11-16 03:54:01147extern const char kText[] = "asdf";
Andrew Grieve0eeb5fd2019-11-25 21:04:26148
149// Requires pointer, relocation, and character data.
150// In most cases there is no advantage to pointers for strings.
Andrew Grieve9534b162022-11-16 03:54:01151// When not "extern", the compiler can often figure out how to avoid the relocation.
152extern const char* const kText = "asdf";
Andrew Grieve0eeb5fd2019-11-25 21:04:26153```
Andrew Grieve0cb64c22019-10-10 14:45:39154
155Another thing to look out for:
156 * Large data structures with relocations that you don't need random access to,
157 or which are seldom needed.
158 * For such cases, it might be better to store the data encoded and then
159 decode when required.