blob: 4fe5e5de28c62363b77afeda4a18f11d616ad77e [file] [log] [blame] [view]
Andrew Grieve860b1552017-09-06 14:50:061# Static Initializers
2
3[TOC]
4
5Some background on the original decision to ban static initializers:
6
7http://neugierig.org/software/chromium/notes/2011/08/static-initializers.html
8
Andrew Grieve5e704682021-02-19 23:35:249Note: Another name for static initializers is "global constructors".
10
Andrew Grieve860b1552017-09-06 14:50:0611# How Static Initializers are Checked
12
13* For Linux and Mac:
Matthew Denton43cafd52021-05-26 15:42:1414 * The expected count is stored in [//testing/scripts/check_static_initializers.py](https://source.chromium.org/chromium/chromium/src/+/main:testing/scripts/check_static_initializers.py)
Andrew Grieve860b1552017-09-06 14:50:0615* For Android:
16 * The expected count is stored in the build target [//chrome/android:monochrome_static_initializers](https://cs.chromium.org/chromium/src/chrome/android/BUILD.gn)
17
18## Removing Static Initializers
19
20Common fixes include:
21
Lei Zhangfafa2b72020-09-29 21:58:4622* Add constexpr.
23* Move global variable to be a static variable within a function that returns
24 it, often wrapped in `base::NoDestructor`.
Andrew Grieve860b1552017-09-06 14:50:0625
26## Listing Static Initializers
27
Andrew Grieve5e704682021-02-19 23:35:2428### Step 1 - Use objdump to report them
Andrew Grieve860b1552017-09-06 14:50:0629For Linux:
30
31 tools/linux/dump-static-initializers.py out/Release/chrome
32
Andrew Grieve3c2c4202020-04-16 01:55:0533For Android (from easiest to hardest):
Andrew Grieve860b1552017-09-06 14:50:0634
Andrew Grieve3c2c4202020-04-16 01:55:0535 # Build with: is_official_build=true is_chrome_branded=true
36 # This will dump the list of SI's only when they don't match the expected
37 # number in static_initializers.gni (this is what the bots use).
38 ninja chrome/android:monochrome_static_initializers
39 # or:
40 tools/binary_size/diagnose_bloat.py HEAD # See README.md for flags.
Andrew Grieve5e704682021-02-19 23:35:2441 # or (the other two use this under the hood):
42 tools/linux/dump-static-initializers.py --toolchain-prefix third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi- out/Release/lib.unstripped/libmonochrome.so
43 # arm32 ^^ vv arm64
44 tools/linux/dump-static-initializers.py --toolchain-prefix third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android- out/Release/lib.unstripped/libmonochrome.so
45 # Note: For arm64, having use_thin_lto=true seems to dump a couple extra
46 # initializers that don't actually exist.
47
48The last one may actually be the easiest if you've already properly built
49`libmonochrome.so` with `is_official_build=true`.
50
51### Step 2 - Ask compiler to report them
52
Adenilson Cavalcanti9b156832021-10-27 00:50:1453If the source of the new initializers is not obvious from Step 1, you can ask the
Andrew Grieve5e704682021-02-19 23:35:2454compiler to pinpoint the exact source line.
55
561. Edit [//build/config/BUILDCONFIG.gn](https://cs.chromium.org/chromium/src/build/config/BUILDCONFIG.gn)
57and add `"//build/config/compiler:wglobal_constructors"` to `default_compiler_configs`
582. Remove the config from the `configs` in `//base:base`
593. Set GN arg `treat_warnings_as_errors=false`
604. Compile and look for warnings **from the files identified by step 1** (may want to pipe ninja output to a file).
61
62*** note
63The compiler warning triggers for every static initializer that exists
64*before optimization*. We care only about those that survive optimization.
65More details in [crbug/1136086](https://bugs.chromium.org/p/chromium/issues/detail?id=1136086).
66***
Andrew Grieve860b1552017-09-06 14:50:0667
Andrew Grieve3c2c4202020-04-16 01:55:0568* For more information about `diagnose_bloat.py`, refer to its [README.md](/tools/binary_size/README.md#diagnose_bloat.py)
69* List of existing static initializers documented in [static_initializers.gni](/chrome/android/static_initializers.gni)
Adenilson Cavalcanti9b156832021-10-27 00:50:1470
Andrew Grieve7c58e2e2022-04-22 02:00:1071### Step 3 - Manual Verification
Adenilson Cavalcanti9b156832021-10-27 00:50:1472
73If the source of the new initializers is not revealed with
74`dump-static-initializers.py` (e.g. for static initializers introduced in
75compiler-rt), there's a manual option.
76
Andrew Grieve7c58e2e2022-04-22 02:00:10771. Locate the address range of the .init_array section with:
Adenilson Cavalcanti9b156832021-10-27 00:50:1478```
Andrew Grieve7c58e2e2022-04-22 02:00:1079$ third_party/llvm-build/Release+Asserts/bin/llvm-readelf \
80 --hex-dump=.init_array out/Release/lib.unstripped/libmonochrome.so
81Hex dump of section '.init_array':
820x04064624 294a1a02 154acb00 79d3be01 894c1a02 )J...J..y....L..
Adenilson Cavalcanti9b156832021-10-27 00:50:1483```
Andrew Grieve7c58e2e2022-04-22 02:00:1084
85* `0x04064624` is the location of `.init_array`.
86* The other four entries are addresses of functions **in little endian**.
87
882. Convert the address into a function name with:
89
Adenilson Cavalcanti9b156832021-10-27 00:50:1490```
Andrew Grieve7c58e2e2022-04-22 02:00:1091# Reverse hex pairs to account for endianness.
92$ third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer \
93 --functions -e out/Release/lib.unstripped/libmonochrome.so 0x021a4a29
94_GLOBAL__I_000101
95./../../buildtools/third_party/libc++/trunk/src/iostream.cpp:0:0
96```
97
983. If any `.init_array` slots are zero, that means they their address is exists
99within the relocation table. To find the address:
100
101```
102# Use the location of ".init_array" printed in step 1, plus an offset for subsequent slots.
103$ third_party/llvm-build/Release+Asserts/bin/llvm-readelf \
104 --relocations out/Release/lib.unstripped/libmonochrome.so | grep 0x04064624
10503dfb7b0 00000017 R_ARM_RELATIVE 0
106```
107
108### Step 4 - Compiler Naming Heuristics
109
110You might be able to find the static initialzer functions by listing symbols:
111
112```sh
113nm out/Release/lib.unstripped/libmonochrome.so | grep " _GLOBAL__"
114```
115
116This currently yields:
117```
1180214ea45 t _GLOBAL__I_000101
11900cb2315 t _GLOBAL__sub_I_base_logging.cc
1200214eca5 t _GLOBAL__sub_I_iostream.cpp
12101c01219 t _GLOBAL__sub_I_token.cc
Adenilson Cavalcanti9b156832021-10-27 00:50:14122```