0

native_relocation.md: 2022 update

Change-Id: Ie50ff8bf852f78cdeb60c791bac0a43fd3cb1722
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4020905
Reviewed-by: Nico Weber <thakis@chromium.org>
Reviewed-by: Bruce Dawson <brucedawson@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1072035}
This commit is contained in:
Andrew Grieve
2022-11-16 03:54:01 +00:00
committed by Chromium LUCI CQ
parent 646ea5e0a9
commit 9534b16025

@ -6,32 +6,55 @@
* They tell the runtime linker a list of addresses to post-process after
loading the executable into memory.
* There are several types of relocations, but >99% of them are "relative"
relocations and are created any time a global variable or constant is
initialized with the address of something.
* This includes vtables, function pointers, and string literals, but not
`char[]`.
relocations and are created any time a global symbol or compile-time
initialized static local is initialized with the address of something, and
the compiler cannot optimize away the relocation (e.g. for pointers where
not all uses are visible, or for values that are passed to functions that
are not inlined).
Examples of things that require relative relocations:
```C++
// Pointer to yourself.
extern const void* const kUserDataKey = &kUserDataKey;
// Array of pointers.
extern const char* const kMemoryDumpAllowedArgs[] = {"dumps", nullptr};
// Array of structs that contain one or more pointers.
extern const StringPiece kStrings[] = {"one, "two"};
```
Vtables are arrays of function pointers, and so require relative relocations.
However, on some Chrome platforms we use a non-standard ABI that uses offsets
rather than pointers in order to remove the relocations overhead
([crbug/589384]).
[crbug/589384]: https://crbug.com/589384
### Linux & Android Relocations (ELF Format)
* Relocations are stored in sections of type: `REL`, `RELA`, [`APS2`][APS2], or
[`RELR`][RELR].
* Relocations are stored in sections named: `.rel.dyn`, `.rel.plt`,
`.rela.dyn`, or `.rela.plt`.
* For `REL` and `RELA`, each relocation is stored using either 2 or 3 words,
based on the architecture.
* For `RELR` and `APS2`, relative relocations are compressed.
* [`APS2`][APS2]: Somewhat involved compression which trades off runtime
performance for smaller file size.
* [`RELR`][RELR]: Supported in Android P+. Smaller and simpler than `APS2`.
* `RELR` is [used by default][cros] on Chrome OS.
* As of Oct 2019, Chrome on Android (arm32) has about 390,000 of them.
* Relocations are stored in sections of type: `REL`, `RELA`, [`APS2`][APS2], or
[`RELR`][RELR].
* `REL` is default for arm32. It uses two words to per relocation: `address`,
`flags`.
* `RELA` is default for arm64. It uses three words per relocation: `address`,
`flags`, `addend`.
* [`APS2`][APS2] is what Chrome for Android uses. It stores the same fields
as REL` / `RELA`, but uses variable length ints (LEB128) and run-length
encoding.
* [`RELR`][RELR] is what [Chrome OS uses], and is supported in Android P+
([tracking bug for enabling]). It encodes only relative relocations and
uses a bitmask to do so (which works well since all symbols that require
relocations live in `.data.rel.ro`).
[APS2]: android_native_libraries.md#Packed-Relocations
[RELR]: https://reviews.llvm.org/D48247
[cros]: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/1210982
[RELR]: https://maskray.me/blog/2021-10-31-relative-relocations-and-relr
[tracking bug for enabling]: https://bugs.chromium.org/p/chromium/issues/detail?id=895194
[Chrome OS uses]: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/1210982
### Windows Relocations (PE Format)
* For PE files, relocations are stored in per-code-page
[`.reloc` sections][win_relocs].
* For PE files, relocations are stored in the [`.reloc` section][win_relocs].
* Each relocation is stored using 2 bytes. Each `.reloc` section has a small
overhead as well.
* 64-bit executables have fewer relocations thanks to the ability to use
@ -52,7 +75,10 @@
[relr_bug]: https://bugs.chromium.org/p/chromium/issues/detail?id=895194
### Memory Overhead
* On Windows, there is [almost no memory overhead] from relocations.
* On Windows, relocations are applied by the kernel during page faults. There
is therefore [almost no memory overhead] from relocations, as the memory they
are applied to is still considered "clean" memory and shared between
processes.
* On Linux and Android, memory with relocations cannot be loaded read-only and
result in dirty memory. 99% of these symbols live in `.data.rel.ro`, which as
of Oct 2019 is ~6.5MiB on Linux and ~2MiB on Android. `.data.rel.ro` is data
@ -70,11 +96,12 @@
[relro_sharing]: android_native_libraries.md#relro-sharing
### Start-up Time
* On Windows, relocations are applied just-in-time on page faults, and are
backed by the PE file (not the pagefile).
* On Windows, relocations are applied just-in-time, and so their overhead is
both small and difficult to measure.
* On other platforms, the runtime linker applies all relocations upfront.
* On low-end Android, it can take ~100ms (measured on a first-gen Android Go
devices with APS2 relocations).
* On a Pixel 4a, it's ~50ms, and with RELR relocations, it's closer to 15ms.
* On Linux, it's [closer to 20ms][zygote].
## How do I see them?
@ -117,11 +144,12 @@ Here's a simpler example:
```c++
// No pointer, no relocation. Just 5 bytes of character data.
const char kText[] = "asdf";
extern const char kText[] = "asdf";
// Requires pointer, relocation, and character data.
// In most cases there is no advantage to pointers for strings.
const char* const kText = "asdf";
// When not "extern", the compiler can often figure out how to avoid the relocation.
extern const char* const kText = "asdf";
```
Another thing to look out for: