Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 1 | # Static Initializers |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | Some background on the original decision to ban static initializers: |
| 6 | |
| 7 | http://neugierig.org/software/chromium/notes/2011/08/static-initializers.html |
| 8 | |
Andrew Grieve | 5e70468 | 2021-02-19 23:35:24 | [diff] [blame] | 9 | Note: Another name for static initializers is "global constructors". |
| 10 | |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 11 | # How Static Initializers are Checked |
| 12 | |
Arthur Milchior | 7b39ba2 | 2024-11-14 14:32:57 | [diff] [blame] | 13 | * For Linux, Mac and iOS: |
Matthew Denton | 43cafd5 | 2021-05-26 15:42:14 | [diff] [blame] | 14 | * 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 Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 15 | * For Android: |
David Benjamin | 17fce3e8b | 2022-08-04 19:43:03 | [diff] [blame] | 16 | * The expected count is stored in [//chrome/android/static_initializers.gni](https://cs.chromium.org/chromium/src/chrome/android/static_initializers.gni) |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 17 | |
| 18 | ## Removing Static Initializers |
| 19 | |
| 20 | Common fixes include: |
| 21 | |
Lei Zhang | fafa2b7 | 2020-09-29 21:58:46 | [diff] [blame] | 22 | * Add constexpr. |
| 23 | * Move global variable to be a static variable within a function that returns |
| 24 | it, often wrapped in `base::NoDestructor`. |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 25 | |
| 26 | ## Listing Static Initializers |
| 27 | |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 28 | ### Option 1 - dump-static-initializers.py |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 29 | For Linux: |
| 30 | |
| 31 | tools/linux/dump-static-initializers.py out/Release/chrome |
| 32 | |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 33 | For Android: |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 34 | |
Andrew Grieve | 3c2c420 | 2020-04-16 01:55:05 | [diff] [blame] | 35 | # 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). |
Mohamed Heikal | dbeb522 | 2024-01-15 22:28:01 | [diff] [blame] | 38 | ninja chrome/android:check_chrome_static_initializers |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 39 | # or, to dump directly: |
| 40 | tools/linux/dump-static-initializers.py out/Release/lib.unstripped/libmonochrome.so |
Andrew Grieve | 5e70468 | 2021-02-19 23:35:24 | [diff] [blame] | 41 | |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 42 | ### Option 2 - Ask compiler to report them |
Andrew Grieve | 5e70468 | 2021-02-19 23:35:24 | [diff] [blame] | 43 | |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 44 | If the source of the new initializers is not obvious from Step 1, you can ask the |
Andrew Grieve | 5e70468 | 2021-02-19 23:35:24 | [diff] [blame] | 45 | compiler to pinpoint the exact source line. |
| 46 | |
| 47 | 1. Edit [//build/config/BUILDCONFIG.gn](https://cs.chromium.org/chromium/src/build/config/BUILDCONFIG.gn) |
| 48 | and add `"//build/config/compiler:wglobal_constructors"` to `default_compiler_configs` |
| 49 | 2. Remove the config from the `configs` in `//base:base` |
| 50 | 3. Set GN arg `treat_warnings_as_errors=false` |
| 51 | 4. Compile and look for warnings **from the files identified by step 1** (may want to pipe ninja output to a file). |
| 52 | |
| 53 | *** note |
| 54 | The compiler warning triggers for every static initializer that exists |
| 55 | *before optimization*. We care only about those that survive optimization. |
| 56 | More details in [crbug/1136086](https://bugs.chromium.org/p/chromium/issues/detail?id=1136086). |
| 57 | *** |
Andrew Grieve | 860b155 | 2017-09-06 14:50:06 | [diff] [blame] | 58 | |
Andrew Grieve | 3c2c420 | 2020-04-16 01:55:05 | [diff] [blame] | 59 | * For more information about `diagnose_bloat.py`, refer to its [README.md](/tools/binary_size/README.md#diagnose_bloat.py) |
| 60 | * List of existing static initializers documented in [static_initializers.gni](/chrome/android/static_initializers.gni) |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 61 | |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 62 | ### Option 3 - Manual Verification |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 63 | |
Andrew Grieve | 5d0ac9cf | 2022-10-14 01:12:00 | [diff] [blame] | 64 | You can manually go through the steps that `dump-static-initializers.py` does. |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 65 | |
Andrew Grieve | 7c58e2e | 2022-04-22 02:00:10 | [diff] [blame] | 66 | 1. Locate the address range of the .init_array section with: |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 67 | ``` |
Andrew Grieve | 7c58e2e | 2022-04-22 02:00:10 | [diff] [blame] | 68 | $ third_party/llvm-build/Release+Asserts/bin/llvm-readelf \ |
| 69 | --hex-dump=.init_array out/Release/lib.unstripped/libmonochrome.so |
| 70 | Hex dump of section '.init_array': |
| 71 | 0x04064624 294a1a02 154acb00 79d3be01 894c1a02 )J...J..y....L.. |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 72 | ``` |
Andrew Grieve | 7c58e2e | 2022-04-22 02:00:10 | [diff] [blame] | 73 | |
| 74 | * `0x04064624` is the location of `.init_array`. |
| 75 | * The other four entries are addresses of functions **in little endian**. |
| 76 | |
| 77 | 2. Convert the address into a function name with: |
| 78 | |
Adenilson Cavalcanti | 9b15683 | 2021-10-27 00:50:14 | [diff] [blame] | 79 | ``` |
Andrew Grieve | 7c58e2e | 2022-04-22 02:00:10 | [diff] [blame] | 80 | # Reverse hex pairs to account for endianness. |
| 81 | $ third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer \ |
| 82 | --functions -e out/Release/lib.unstripped/libmonochrome.so 0x021a4a29 |
| 83 | _GLOBAL__I_000101 |
| 84 | ./../../buildtools/third_party/libc++/trunk/src/iostream.cpp:0:0 |
| 85 | ``` |
| 86 | |
| 87 | 3. If any `.init_array` slots are zero, that means they their address is exists |
| 88 | within the relocation table. To find the address: |
| 89 | |
| 90 | ``` |
| 91 | # Use the location of ".init_array" printed in step 1, plus an offset for subsequent slots. |
| 92 | $ third_party/llvm-build/Release+Asserts/bin/llvm-readelf \ |
| 93 | --relocations out/Release/lib.unstripped/libmonochrome.so | grep 0x04064624 |
| 94 | 03dfb7b0 00000017 R_ARM_RELATIVE 0 |
| 95 | ``` |