• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2022 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import("//build/config/cronet/config.gni")
6import("//build/config/sanitizers/sanitizers.gni")
7import("//build_overrides/partition_alloc.gni")
8
9if (is_apple) {
10  import("//build/config/features.gni")
11}
12
13# PartitionAlloc have limited support for MSVC's cl.exe compiler. It can only
14# access the generate "buildflags" and the "raw_ptr" definitions implemented
15# with RawPtrNoOpImpl. Everything else is considered not supported.
16#
17# Since there are no other good ways to detect MSVC's cl.exe, we are reusing the
18# same definition used by Chrome in //base/BUILD.gn. See
19# https://crbug.com/988071.
20is_clang_or_gcc = is_clang || !is_win
21
22# Whether 64-bit pointers are used.
23# A static_assert in partition_alloc_config.h verifies that.
24if (is_nacl) {
25  # NaCl targets don't use 64-bit pointers.
26  has_64_bit_pointers = false
27} else if (current_cpu == "x64" || current_cpu == "arm64" ||
28           current_cpu == "loong64" || current_cpu == "riscv64") {
29  has_64_bit_pointers = true
30} else if (current_cpu == "x86" || current_cpu == "arm") {
31  has_64_bit_pointers = false
32} else {
33  assert(false, "Unknown CPU: $current_cpu")
34}
35
36declare_args() {
37  # Causes all the allocations to be routed via allocator_shim.cc. Usually,
38  # the allocator shim will, in turn, route them to Partition Alloc, but
39  # other allocators are also supported by the allocator shim.
40  use_allocator_shim = use_allocator_shim_default && is_clang_or_gcc
41
42  # Whether PartitionAlloc should be available for use or not.
43  # true makes PartitionAlloc linked to the executable or shared library and
44  # makes it available for use. It doesn't mean that the default allocator
45  # is PartitionAlloc, which is governed by |use_partition_alloc_as_malloc|.
46  #
47  # N.B. generally, embedders should look at this GN arg and at the
48  # corresponding buildflag to determine whether to interact with PA
49  # source at all (pulling the component in via GN, including headers,
50  # etc.). There is nothing stopping a lazy embedder from ignoring this
51  # and unconditionally using PA, but such a setup is inadvisable.
52  #
53  # In Chromium, this is set true, except:
54  #
55  # 1.  On Cronet bots, because Cronet doesn't use PartitionAlloc at all,
56  #     and doesn't wish to incur the library size increase (crbug.com/674570).
57  # 2.  On NaCl (through this declaration), where PartitionAlloc doesn't
58  #     build at all.
59  use_partition_alloc = !is_nacl && is_clang_or_gcc
60}
61
62if (!is_clang_or_gcc) {
63  assert(!use_partition_alloc,
64         "PartitionAlloc's allocator does not support this compiler")
65  assert(!use_allocator_shim,
66         "PartitionAlloc's allocator shim does not support this compiler")
67}
68
69if (is_nacl) {
70  assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl")
71}
72
73declare_args() {
74  # Turns on compiler optimizations in PartitionAlloc in Debug build.
75  # If enabling PartitionAlloc-Everywhere in Debug build for tests in Debug
76  # build, since all memory allocations and deallocations are executed by
77  # non-optimized PartitionAlloc, chrome (including tests) will be much
78  # slower. This will cause debug trybots' timeouts. If we want to debug
79  # PartitionAlloc itself, use partition_alloc_optimized_debug=false.
80  # Otherwise, use partition_alloc_optimized_debug=true to enable optimized
81  # PartitionAlloc.
82  partition_alloc_optimized_debug = true
83
84  # PartitionAlloc-Everywhere (PA-E). Causes allocator_shim.cc to route
85  # calls to PartitionAlloc, rather than some other platform allocator.
86  use_partition_alloc_as_malloc = use_partition_alloc && use_allocator_shim &&
87                                  use_partition_alloc_as_malloc_default
88}
89
90assert(!use_allocator_shim || (is_android || is_apple || is_chromeos ||
91                                   is_fuchsia || is_linux || is_win),
92       "The allocator shim does not (yet) support the platform.")
93
94if (use_allocator_shim && is_win) {
95  # It's hard to override CRT's malloc family in every case in the component
96  # build, and it's very easy to override it partially and to be inconsistent
97  # among allocations and deallocations. Then, we'll crash when PA deallocates
98  # a memory region allocated by the CRT's malloc or vice versa.
99  assert(!is_component_build,
100         "The allocator shim doesn't work for the component build on Windows.")
101}
102
103declare_args() {
104  use_freeslot_bitmap = false
105
106  # Puts the regular and BRP pools right next to each other, so that we can
107  # check "belongs to one of the two pools" with a single bitmask operation.
108  glue_core_pools = false
109
110  # Introduces pointer compression support in PA. These are 4-byte
111  # pointers that can point within the core pools (regular and BRP).
112  #
113  # This is effective only for memory allocated from PartitionAlloc, so it is
114  # recommended to enable PA-E above, but isn't strictly necessary. Embedders
115  # can create and use PA partitions explicitly.
116  enable_pointer_compression_support = false
117
118  # Enables a bounds check when two pointers (at least one being raw_ptr) are
119  # subtracted (if supported by the underlying implementation).
120  enable_pointer_subtraction_check = false
121
122  # Enables a compile-time check that all raw_ptrs to which arithmetic
123  # operations are to be applied are annotated with the AllowPtrArithmetic
124  # trait,
125  enable_pointer_arithmetic_trait_check = true
126}
127
128declare_args() {
129  # Build support for Use-after-Free protection via BackupRefPtr (BRP),
130  # making the raw_ptr<T> implementation to RawPtrBackupRefImpl if active.
131  #
132  # These are effective only for memory allocated from PartitionAlloc, so it is
133  # recommended to enable PA-E above, but isn't strictly necessary. Embedders
134  # can create and use PA partitions explicitly.
135  #
136  # Note that |enable_backup_ref_ptr_support = true| doesn't necessarily enable
137  # BRP protection. It'll be enabled only for partition created with
138  # partition_alloc::PartitionOptions::kEnabled.
139  enable_backup_ref_ptr_support =
140      use_partition_alloc && enable_backup_ref_ptr_support_default
141
142  # RAW_PTR_EXCLUSION macro is disabled on official builds because it increased
143  # binary size. This flag can be used to enable it for official builds too.
144  force_enable_raw_ptr_exclusion = false
145}
146
147assert(!enable_pointer_compression_support || glue_core_pools,
148       "Pointer compression relies on core pools being contiguous.")
149
150declare_args() {
151  # Make explicit calls to ASAN at runtime, e.g. to mark quarrantined memory
152  # as poisoned. Allows ASAN to tell if a particular memory error is protected
153  # by BRP in its reports.
154  #
155  # The implementation of ASan BRP is purpose-built to inspect Chromium
156  # internals and is entangled with `//base` s.t. it cannot be used
157  # outside of Chromium.
158  use_asan_backup_ref_ptr =
159      build_with_chromium && is_asan &&
160      (is_win || is_android || is_linux || is_mac || is_chromeos)
161
162  # Use probe-on-destruct unowned ptr detection with ASAN.
163  use_asan_unowned_ptr = false
164}
165
166# Use the version of raw_ptr<T> that allows the embedder to implement custom
167# logic.
168use_hookable_raw_ptr = use_asan_backup_ref_ptr
169
170declare_args() {
171  # - put_ref_count_in_previous_slot: place the ref-count at the end of the
172  #   previous slot (or in metadata if a slot starts on the page boundary), as
173  #   opposed to the beginning of the slot.
174  # - enable_backup_ref_ptr_slow_checks: enable additional safety checks that
175  #   are too expensive to have on by default.
176  # - enable_dangling_raw_ptr_checks: enable checking raw_ptr do not become
177  #   dangling during their lifetime.
178  # - backup_ref_ptr_poison_oob_ptr: poison out-of-bounds (OOB) pointers to
179  #   generate an exception in the event that an OOB pointer is dereferenced.
180  put_ref_count_in_previous_slot =
181      put_ref_count_in_previous_slot_default && enable_backup_ref_ptr_support
182
183  enable_backup_ref_ptr_slow_checks =
184      enable_backup_ref_ptr_slow_checks_default && enable_backup_ref_ptr_support
185
186  # Enable the feature flag required to activate backup ref pointers. That is to
187  # say `PartitionAllocBackupRefPtr`.
188  #
189  # This is meant to be used primarily on bots. It is much easier to override
190  # the feature flags using a binary flag instead of updating multiple bots's
191  # scripts to pass command line arguments.
192  enable_backup_ref_ptr_feature_flag = false
193
194  # Build support for Dangling Ptr Detection (DPD) via BackupRefPtr (BRP),
195  # making the raw_ptr<T> implementation to RawPtrBackupRefImpl if active.
196  enable_dangling_raw_ptr_checks =
197      enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support
198
199  # Enable the feature flag required to check for dangling pointers. That is to
200  # say `PartitionAllocDanglingPtr`.
201  #
202  # This is meant to be used primarily on bots. It is much easier to override
203  # the feature flags using a binary flag instead of updating multiple bots's
204  # scripts to pass command line arguments.
205  enable_dangling_raw_ptr_feature_flag = false
206
207  # Enables the dangling raw_ptr checks feature for the performance experiment.
208  # Not every dangling pointers have been fixed or annotated yet. To avoid
209  # accounting for the cost of calling the PA's embedder's callbacks when a
210  # dangling pointer has been detected, this simulates the raw_ptr to be
211  # allowed to dangle.
212  #
213  # This flag is temporary, and isn't used by PA embedders, so it doesn't need
214  # to go through build_overrides
215  enable_dangling_raw_ptr_perf_experiment = false
216
217  # Set to `enable_backup_ref_ptr_support && has_64_bit_pointers` when enabling.
218  backup_ref_ptr_poison_oob_ptr = false
219}
220
221declare_args() {
222  # Shadow metadata is still under development and only supports Linux
223  # for now.
224  enable_shadow_metadata = false
225}
226
227# *Scan is currently only used by Chromium, and supports only 64-bit.
228use_starscan = build_with_chromium && has_64_bit_pointers
229
230pcscan_stack_supported =
231    use_starscan &&
232    (current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" ||
233     current_cpu == "arm64" || current_cpu == "riscv64")
234
235# We want to provide assertions that guard against inconsistent build
236# args, but there is no point in having them fire if we're not building
237# PartitionAlloc at all. If `use_partition_alloc` is false, we jam all
238# related args to `false`.
239if (!use_partition_alloc) {
240  use_partition_alloc_as_malloc = false
241  enable_backup_ref_ptr_support = false
242  use_asan_backup_ref_ptr = false
243  use_asan_unowned_ptr = false
244  use_hookable_raw_ptr = false
245  put_ref_count_in_previous_slot = false
246  enable_backup_ref_ptr_slow_checks = false
247  enable_dangling_raw_ptr_checks = false
248  enable_dangling_raw_ptr_perf_experiment = false
249  enable_pointer_subtraction_check = false
250  backup_ref_ptr_poison_oob_ptr = false
251  use_starscan = false
252}
253
254# put_ref_count_in_previous_slot can only be used if
255# enable_backup_ref_ptr_support is true.
256assert(
257    enable_backup_ref_ptr_support || !put_ref_count_in_previous_slot,
258    "Can't put ref count in the previous slot if BackupRefPtr isn't enabled " +
259        "at all")
260
261# enable_backup_ref_ptr_slow_checks can only be used if
262# enable_backup_ref_ptr_support is true.
263assert(enable_backup_ref_ptr_support || !enable_backup_ref_ptr_slow_checks,
264       "Can't enable additional BackupRefPtr checks if it isn't enabled at all")
265
266# enable_dangling_raw_ptr_checks can only be used if
267# enable_backup_ref_ptr_support is true.
268assert(
269    enable_backup_ref_ptr_support || !enable_dangling_raw_ptr_checks,
270    "Can't enable dangling raw_ptr checks if BackupRefPtr isn't enabled at all")
271
272# To run the dangling raw_ptr detector experiment, the underlying feature must
273# be enabled too.
274assert(
275    enable_dangling_raw_ptr_checks || !enable_dangling_raw_ptr_perf_experiment,
276    "Missing dangling pointer checks feature for its performance experiment")
277
278# To poison OOB pointers for BackupRefPtr, the underlying feature must be
279# enabled, too.
280assert(
281    enable_backup_ref_ptr_support || !backup_ref_ptr_poison_oob_ptr,
282    "Can't enable poisoning for OOB pointers if BackupRefPtr isn't enabled " +
283        "at all")
284assert(has_64_bit_pointers || !backup_ref_ptr_poison_oob_ptr,
285       "Can't enable poisoning for OOB pointers if pointers are only 32-bit")
286
287# AsanBackupRefPtr and AsanUnownedPtr are mutually exclusive variants of
288# raw_ptr.
289assert(
290    !use_asan_unowned_ptr || !use_asan_backup_ref_ptr,
291    "Both AsanUnownedPtr and AsanBackupRefPtr can't be enabled at the same " +
292        "time")
293
294# BackupRefPtr and AsanBackupRefPtr are mutually exclusive variants of raw_ptr.
295assert(
296    !enable_backup_ref_ptr_support || !use_asan_backup_ref_ptr,
297    "Both BackupRefPtr and AsanBackupRefPtr can't be enabled at the same time")
298
299# BackupRefPtr and AsanUnownedPtr are mutually exclusive variants of raw_ptr.
300assert(!enable_backup_ref_ptr_support || !use_asan_unowned_ptr,
301       "Both BackupRefPtr and AsanUnownedPtr can't be enabled at the same time")
302
303# RawPtrHookableImpl and BackupRefPtr are mutually exclusive variants of
304# raw_ptr.
305assert(
306    !use_hookable_raw_ptr || !enable_backup_ref_ptr_support,
307    "Both RawPtrHookableImpl and BackupRefPtr can't be enabled at the same " +
308        "time")
309
310# RawPtrHookableImpl and AsanUnownedPtr are mutually exclusive variants of
311# raw_ptr.
312assert(
313    !use_hookable_raw_ptr || !use_asan_unowned_ptr,
314    "Both RawPtrHookableImpl and AsanUnownedPtr can't be enabled at the same " +
315        "time")
316
317assert(!use_asan_backup_ref_ptr || is_asan,
318       "AsanBackupRefPtr requires AddressSanitizer")
319
320assert(!use_asan_unowned_ptr || is_asan,
321       "AsanUnownedPtr requires AddressSanitizer")
322
323# AsanBackupRefPtr is not supported outside Chromium. The implementation is
324# entangled with `//base`. The code is only physically located with the rest of
325# `raw_ptr` to keep it together.
326assert(build_with_chromium || !use_asan_backup_ref_ptr,
327       "AsanBackupRefPtr is not supported outside Chromium")
328
329assert(!use_asan_backup_ref_ptr || use_hookable_raw_ptr,
330       "AsanBackupRefPtr requires RawPtrHookableImpl")
331
332declare_args() {
333  # pkeys support is explicitly disabled in all Cronet builds, as some test
334  # dependencies that use partition_allocator are compiled in AOSP against a
335  # version of glibc that does not include pkeys syscall numbers.
336  enable_pkeys = is_linux && target_cpu == "x64" && !is_cronet_build
337}
338assert(!enable_pkeys || (is_linux && target_cpu == "x64"),
339       "Pkeys are only supported on x64 linux")
340
341# Some implementations of raw_ptr<>, like BackupRefPtr, require zeroing when
342# constructing, destructing or moving out of a pointer. When using these
343# implementations, raw_ptrs<> will be always be zeroed, no matter what
344# GN args or flags are present.
345#
346# Other implementations of raw_ptr<>, like NoOpImpl, don't require zeroing
347# and do not do so by default. This can lead to subtle bugs when testing
348# against one of the zeroing impls and then deploying on a platform that is
349# using a non-zeroing implementation. Setting the following GN args to
350# true triggers zeroing even for implementations that don't require it.
351# This provides consistency with the other impls. This is the recommended
352# setting.
353#
354# Setting these to false will make raw_ptr<> behave more like raw C++ pointer
355# `T*`, making NoOpImpl act like an actual no-op, so use it if you're worried
356# about performance of your project. Use at your own risk, as it's unsupported
357# and untested within Chromium.
358#
359# Even when these are set to true, the raw_ptr trait AllowUninitialized
360# provides a finer-grained mechanism for opting out of initialization on a
361# pointer by pointer basis when using a non-zeroing implementation.
362#
363# Caveat: _zero_on_move and _on_destruct will prevent the type from being
364# trivially copyable, _zero_on_construct and _on_destruct will prevent the
365# type from being trivially default constructible.
366declare_args() {
367  raw_ptr_zero_on_construct = raw_ptr_zero_on_construct_default
368  raw_ptr_zero_on_move = raw_ptr_zero_on_move_default
369  raw_ptr_zero_on_destruct = raw_ptr_zero_on_destruct_default
370}
371