native_relocations.md: Add info about win and cros

Change-Id: I12bcf5d208b4f272bc5e3e538093ebe968e2f538
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1914552
Commit-Queue: Andrew Grieve <[email protected]>
Reviewed-by: Bruce Dawson <[email protected]>
Cr-Commit-Position: refs/heads/master@{#718811}
diff --git a/docs/native_relocations.md b/docs/native_relocations.md
index 0910e6f9..aeb85f9 100644
--- a/docs/native_relocations.md
+++ b/docs/native_relocations.md
@@ -1,12 +1,8 @@
 # Native Relocations
 
-*** note
-Information here is mostly Android & Linux-specific and may not be 100% accurate.
-***
+[TOC]
 
 ## What are they?
- * For ELF files, they are sections of type REL, RELA, or RELR. They generally
-   have the name ".rel.dyn" and ".rel.plt".
  * 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"
@@ -14,45 +10,81 @@
    initialized with the address of something.
    * This includes vtables, function pointers, and string literals, but not
      `char[]`.
- * Each relocation is stored as either 2 or 3 words, based on the architecture.
-   * On Android, they are compressed, which trades off runtime performance for
-     smaller file size.
- * As of Oct 2019, Chrome on Android has about 390000 of them.
-   * Windows and Mac have them as well, but I don't know how they differ.
+
+### 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.
+
+[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
+
+### Windows Relocations (PE Format)
+ * For PE files, relocaitons are stored in per-code-page
+   [`.reloc` sections][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
+   RIP-relative (instruction-relative) addressing.
+
+[win_relocs]: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only
 
 ## Why do they matter?
- * **Binary Size:** Except on Android, relocations are stored very
-   inefficiently.
-   * Chrome on Linux has a `.rela.dyn` section of more than 14MiB!
-   * Android uses a [custom compression scheme][android_relro1] to shrink them
-     down to ~300kb.
-   * There is an even better [RELR][RELR] encoding available on Android P+, but
-     not widely available on Linux yet. It makes relocations ~60kb.
- * **Memory Overhead:** Symbols 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 that *would* have been put into `.rodata` and mapped
-   read-only if not for the required relocations. It does not get written to
-   after it's relocated, so the linker makes it read-only once relocations are
-   applied (but by that point the damage is done and we have the dirty pages).
+### Binary Size
+ * On Linux, relocations are stored very inefficiently.
+   * As of Oct 2019:
+     * Chrome on Linux has a `.rela.dyn` section of more than 14MiB!
+     * Chrome on Android uses [`APS2`] to compress these down to ~300kb.
+     * Chrome on Android with [`RELR`] would require only 60kb, but is
+       [not yet enabled][relr_bug].
+     * Chrome on Windows (x64) has `.relocs` sections that sum to 620KiB.
+
+[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 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
+   that *would* have been put into `.rodata` and mapped read-only if not for the
+   required relocations. The memory does not get written to after it's
+   relocated, so the linker makes it read-only once relocations are applied (but
+   by that point the damage is done and we have the dirty pages).
    * On Linux, we share this overhead between processes via the [zygote].
-   * [On Android][android_relro2], we share this overhead between processes by
+   * [On Android][relro_sharing], we share this overhead between processes by
      loading the shared library at the same address in all processes, and then
      `mremap` onto shared memory to dedupe after-the-fact.
- * **Start-up Time** The runtime linker applies relocations when loading the
-   executable. On low-end Android, it can take ~100ms (measured on a first-gen
-   Android Go devices with APS2 relocations). On Linux, it's
-   [closer to 20ms][zygote].
 
+[almost no memory overhead]: https://devblogs.microsoft.com/oldnewthing/20160413-00/?p=93301
 [zygote]: linux_zygote.md
-[RELR]: https://reviews.llvm.org/D48247
-[android_relro1]: android_native_libraries.md#Packed-Relocations
-[android_relro2]: android_native_libraries.md#relro-sharing
+[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 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 Linux, it's [closer to 20ms][zygote].
 
 ## How do I see them?
 
 ```sh
+# For ELF files:
 third_party/llvm-build/Release+Asserts/bin/llvm-readelf --relocs out/Release/libmonochrome.so
+
+# For PE files:
+python tools\win\pe_summarize.py out\Release\chrome.dll
 ```
 
 ## Can I avoid them?
@@ -61,22 +93,36 @@
 
 For Example:
 ```c++
-// Wastes 2 bytes for each smaller string but creates no relocations.
+// The following uses 2 bytes of padding for each smaller string but creates no relocations.
 // Total size overhead: 4 * 5 = 20 bytes.
 const char kArr[][5] = {"as", "ab", "asdf", "fi"};
 
-// String data stored optimally, but uses 4 relocatable pointers.
+// The following requires no string padding, but uses 4 relocatable pointers.
 // Total size overhead:
-//   64-bit: 8 bytes per pointer + 24 bytes per relocation + 14 bytes of char = 142 bytes
-//   32-bit: 4 bytes per pointer + 8 bytes per relocation + 14 bytes of char = 62 bytes
-const char *kArr2[] = {"as", "ab", "asdf", "fi"};
+//   Linux 64-bit: (8 bytes per pointer + 24 bytes per relocation) * 4 entries + 14 bytes of char = 142 bytes
+//   Windows 64-bit: (8 bytes per pointer + 2 bytes per relocation) * 4 entries + 14 bytes of char = 54 bytes
+//   CrOS 64-bit: (8 bytes per pointer + ~0 bytes per relocation) * 4 entries + 14 bytes of char = ~46 bytes
+//   Android 32-bit: (4 bytes per pointer + ~0 bytes per relocation) * 4 entries + 14 bytes of char = ~30 bytes
+const char * const kArr2[] = {"as", "ab", "asdf", "fi"};
 ```
 
-Note:
-* String literals are de-duped with others in the binary, so it's possible that
-  the second example above might use 14 fewer bytes.
-* Not all string literals require relocations. Only those that are stored into
-  global variables require them.
+Notes:
+* String literals (but not char arrays) are de-duped with others in the binary,
+  so it is possible that the second example above might use 14 fewer bytes.
+* Not all string literals require relocations. Which ones require them depends
+  on the ABI. Generally, All global variables that are initialized to the
+  address of something require them.
+
+Here's a simpler example:
+
+```c++
+// No pointer, no relocation. Just 5 bytes of character data.
+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";
+```
 
 Another thing to look out for:
  * Large data structures with relocations that you don't need random access to,