# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build_overrides/partition_alloc.gni")
# PartitionAlloc have limited support for MSVC's cl.exe compiler. It can only
# access the generate "buildflags" and the "raw_ptr" definitions implemented
# with RawPtrNoOpImpl. Everything else is considered not supported.
#
# Since there are no other good ways to detect MSVC's cl.exe, we are reusing the
# same definition used by Chrome in //base/BUILD.gn. See
# https://crbug.com/988071.
is_clang_or_gcc = is_clang || !is_win
# Whether 64-bit pointers are used.
# A static_assert in partition_alloc_config.h verifies that.
if (is_nacl) {
# NaCl targets don't use 64-bit pointers.
has_64_bit_pointers = false
} else if (current_cpu == "x64" || current_cpu == "arm64" ||
current_cpu == "loong64" || current_cpu == "riscv64") {
has_64_bit_pointers = true
} else if (current_cpu == "x86" || current_cpu == "arm") {
has_64_bit_pointers = false
} else {
assert(false, "Unknown CPU: $current_cpu")
}
# Increases the size of the empty slot span ring.
use_large_empty_slot_span_ring = is_mac
has_memory_tagging =
current_cpu == "arm64" && is_clang && !is_asan && (is_linux || is_android)
declare_args() {
# Causes all the allocations to be routed via allocator_shim.cc. Usually,
# the allocator shim will, in turn, route them to PartitionAlloc, but
# other allocators are also supported by the allocator shim.
use_allocator_shim = use_allocator_shim_default && is_clang_or_gcc
# Whether PartitionAlloc should be available for use or not.
# true makes PartitionAlloc linked to the executable or shared library and
# makes it available for use. It doesn't mean that the default allocator
# is PartitionAlloc, which is governed by |use_partition_alloc_as_malloc|.
#
# N.B. generally, embedders should look at this GN arg and at the
# corresponding buildflag to determine whether to interact with PA
# source at all (pulling the component in via GN, including headers,
# etc.). There is nothing stopping a lazy embedder from ignoring this
# and unconditionally using PA, but such a setup is inadvisable.
#
# In Chromium, this is set true, except:
#
# 1. On Cronet bots, because Cronet doesn't use PartitionAlloc at all,
# and doesn't wish to incur the library size increase (crbug.com/674570).
# 2. On NaCl (through this declaration), where PartitionAlloc doesn't
# build at all.
use_partition_alloc = !is_nacl && is_clang_or_gcc
}
if (!is_clang_or_gcc) {
assert(!use_partition_alloc,
"PartitionAlloc's allocator does not support this compiler")
assert(!use_allocator_shim,
"PartitionAlloc's allocator shim does not support this compiler")
}
if (is_nacl) {
assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl")
}
declare_args() {
# PartitionAlloc-Everywhere (PA-E). Causes allocator_shim.cc to route
# calls to PartitionAlloc, rather than some other platform allocator.
use_partition_alloc_as_malloc = use_partition_alloc && use_allocator_shim &&
use_partition_alloc_as_malloc_default
}
declare_args() {
# Whether PartitionAlloc dispatch can be replaced with another dispatch with
# some more safety checks at runtime or not. When true, the allocator shim
# provides an extended API to swap PartitionAlloc.
# TODO(https://crbug.com/351974425): Enable this when `use_partition_alloc_as_malloc` is true.
enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support =
false
}
assert(
!enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support || use_partition_alloc_as_malloc,
"PartitionAlloc with advanced checks requires PartitionAlloc itself.")
assert(!use_allocator_shim || (is_android || is_apple || is_chromeos ||
is_fuchsia || is_linux || is_win),
"The allocator shim does not (yet) support the platform.")
if (use_allocator_shim && is_win) {
# It's hard to override CRT's malloc family in every case in the component
# build, and it's very easy to override it partially and to be inconsistent
# among allocations and deallocations. Then, we'll crash when PA deallocates
# a memory region allocated by the CRT's malloc or vice versa.
# Since PartitionAlloc depends on libc++, it is difficult to link libc++.dll
# with PartitionAlloc to replace its allocator with PartitionAlloc.
# If using libcxx_is_shared=true,
# a. since inline methods or inline functions defined in some libc++ headers,
# e.g. vector, use new, malloc(), and so on, the memory allocation will
# be done inside a client code.
# b. on the other hand, libc++.dll deallocates the memory allocated by the
# inline methods or inline functions. It will not be run inside the client
# code.
# So a.'s allocation is done by PartitionAlloc, but b.'s deallocation is
# done by system allocator. This will cause heap check failure (WinHeap
# doesn't know PartitionAlloc) and crash.
# If libcxx_is_shared=false, libc++ is a static library. All libc++ code
# will be run inside the client. The above issue will disappear.
assert(
!is_component_build || (!libcxx_is_shared && !is_debug),
"The allocator shim for the Windows component build needs !libcxx_is_shared && !is_debug.")
}
declare_args() {
use_freeslot_bitmap = false
# Puts the regular and BRP pools right next to each other, so that we can
# check "belongs to one of the two pools" with a single bitmask operation.
# TODO(crbug.com/350104111): Fix ios-simulator failures to remove `!is_ios`.
glue_core_pools = use_partition_alloc_as_malloc && !is_ios
# Introduces pointer compression support in PA. These are 4-byte
# pointers that can point within the core pools (regular and BRP).
#
# This is effective only for memory allocated from PartitionAlloc, so it is
# recommended to enable PA-E above, but isn't strictly necessary. Embedders
# can create and use PA partitions explicitly.
enable_pointer_compression_support = false
# Enables a bounds check when two pointers (at least one being raw_ptr) are
# subtracted (if supported by the underlying implementation).
enable_pointer_subtraction_check = false
# Enables a compile-time check that all raw_ptrs to which arithmetic
# operations are to be applied are annotated with the AllowPtrArithmetic
# trait,
enable_pointer_arithmetic_trait_check = true
# Forwards all the allocation/freeing calls in shim (e.g. operator new)
# through malloc. Useful for using with tools that intercept malloc, e.g.
# heaptrack.
forward_through_malloc = false
}
declare_args() {
# Build support for Use-after-Free protection via BackupRefPtr (BRP),
# making the raw_ptr<T> implementation to RawPtrBackupRefImpl if active.
#
# These are effective only for memory allocated from PartitionAlloc, so it is
# recommended to enable PA-E above, but isn't strictly necessary. Embedders
# can create and use PA partitions explicitly.
#
# Note that |enable_backup_ref_ptr_support = true| doesn't necessarily enable
# BRP protection. It'll be enabled only for partition created with
# partition_alloc::PartitionOptions::kEnabled.
enable_backup_ref_ptr_support =
use_partition_alloc && enable_backup_ref_ptr_support_default
# RAW_PTR_EXCLUSION macro is disabled on official builds because it increased
# binary size. This flag can be used to enable it for official builds too.
force_enable_raw_ptr_exclusion = false
}
assert(!enable_pointer_compression_support || glue_core_pools,
"Pointer compression relies on core pools being contiguous.")
declare_args() {
# We want to use RawPtrBackupRefImpl as the raw_ptr<> implementation
# iff BRP support is enabled. However, for purpose of performance
# investigations we want to be able to control each separately.
#
# TEST ONLY! Don't touch unless you think you know what you're doing. Play
# with enable_backup_ref_ptr_support instead.
use_raw_ptr_backup_ref_impl = enable_backup_ref_ptr_support
# Make explicit calls to ASAN at runtime, e.g. to mark quarrantined memory
# as poisoned. Allows ASAN to tell if a particular memory error is protected
# by BRP in its reports.
#
# The implementation of ASan BRP is purpose-built to inspect Chromium
# internals and is entangled with `//base` s.t. it cannot be used
# outside of Chromium.
use_asan_backup_ref_ptr =
build_with_chromium && is_asan &&
(is_win || is_android || is_linux || is_mac || is_chromeos)
# Use probe-on-destruct unowned ptr detection with ASAN.
use_raw_ptr_asan_unowned_impl = false
}
# Use the version of raw_ptr<T> that allows the embedder to implement custom
# logic.
use_raw_ptr_hookable_impl = use_asan_backup_ref_ptr
declare_args() {
# - enable_backup_ref_ptr_slow_checks: enable additional safety checks that
# are too expensive to have on by default.
# - enable_dangling_raw_ptr_checks: enable checking raw_ptr do not become
# dangling during their lifetime.
# - backup_ref_ptr_poison_oob_ptr: poison out-of-bounds (OOB) pointers to
# generate an exception in the event that an OOB pointer is dereferenced.
# - enable_backup_ref_ptr_instance_tracer: use a global table to track all
# live raw_ptr/raw_ref instances to help debug dangling pointers at test
# end.
enable_backup_ref_ptr_slow_checks =
enable_backup_ref_ptr_slow_checks_default && enable_backup_ref_ptr_support
# Enable the feature flag required to activate backup ref pointers. That is to
# say `PartitionAllocBackupRefPtr`.
#
# This is meant to be used primarily on bots. It is much easier to override
# the feature flags using a binary flag instead of updating multiple bots's
# scripts to pass command line arguments.
#
# TODO(328104161): Remove this flag.
enable_backup_ref_ptr_feature_flag = false
# Build support for Dangling Ptr Detection (DPD) via BackupRefPtr (BRP),
# making the raw_ptr<T> implementation to RawPtrBackupRefImpl if active.
enable_dangling_raw_ptr_checks =
enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support &&
use_raw_ptr_backup_ref_impl
enable_backup_ref_ptr_instance_tracer = false
backup_ref_ptr_extra_oob_checks =
enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl
}
declare_args() {
# Enable the feature flag required to check for dangling pointers. That is to
# say `PartitionAllocDanglingPtr`.
#
# This is meant to be used primarily on bots. It is much easier to override
# the feature flags using a binary flag instead of updating multiple bots's
# scripts to pass command line arguments.
#
# TODO(328104161): Remove this flag.
enable_dangling_raw_ptr_feature_flag = enable_dangling_raw_ptr_checks
}
declare_args() {
backup_ref_ptr_poison_oob_ptr =
false && backup_ref_ptr_extra_oob_checks && has_64_bit_pointers
}
declare_args() {
# Shadow metadata is still under development and only supports Linux
# for now.
enable_shadow_metadata = false
}
declare_args() {
# Use full MTE protection available by changing the feature flag default
# values. So sync mode on all processes. Also disables permissive MTE.
#
# This is meant to be used primarily on bots. It is much easier to override
# the feature flags using a binary flag instead of updating multiple bots's
# scripts to pass command line arguments.
use_full_mte = false
}
stack_scan_supported =
current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" ||
current_cpu == "arm64" || current_cpu == "riscv64"
# We want to provide assertions that guard against inconsistent build
# args, but there is no point in having them fire if we're not building
# PartitionAlloc at all. If `use_partition_alloc` is false, we jam all
# related args to `false`.
#
# Do not clear the following, as they can function outside of PartitionAlloc
# - has_64_bit_pointers
# - has_memory_tagging
if (!use_partition_alloc ||
(defined(toolchain_allows_use_partition_alloc_as_malloc) &&
!toolchain_allows_use_partition_alloc_as_malloc)) {
use_partition_alloc_as_malloc = false
glue_core_pools = false
enable_backup_ref_ptr_support = false
use_raw_ptr_backup_ref_impl = false
use_asan_backup_ref_ptr = false
use_raw_ptr_asan_unowned_impl = false
use_raw_ptr_hookable_impl = false
enable_backup_ref_ptr_slow_checks = false
enable_dangling_raw_ptr_checks = false
enable_dangling_raw_ptr_feature_flag = false
enable_pointer_subtraction_check = false
backup_ref_ptr_poison_oob_ptr = false
backup_ref_ptr_extra_oob_checks = false
enable_backup_ref_ptr_instance_tracer = false
use_full_mte = false
}
# Disable |use_full_mte| if memory tagging is not available. This is for targets that run as part the build process.
if (!has_memory_tagging) {
use_full_mte = false
}
# use_raw_ptr_backup_ref_impl can only be used if
# enable_backup_ref_ptr_support is true.
assert(enable_backup_ref_ptr_support || !use_raw_ptr_backup_ref_impl,
"Can't use RawPtrBackupRefImpl if BRP isn't enabled at all")
# enable_backup_ref_ptr_slow_checks can only be used if
# enable_backup_ref_ptr_support is true.
assert(enable_backup_ref_ptr_support || !enable_backup_ref_ptr_slow_checks,
"Can't enable additional BRP checks if it isn't enabled at all")
# enable_dangling_raw_ptr_checks can only be used if
# enable_backup_ref_ptr_support & use_raw_ptr_backup_ref_impl are true.
assert((enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl) ||
!enable_dangling_raw_ptr_checks,
"Can't enable dangling raw_ptr checks if BRP isn't enabled and used")
# It's meaningless to force on DPD (e.g. on bots) if the support isn't compiled
# in.
assert(enable_dangling_raw_ptr_checks || !enable_dangling_raw_ptr_feature_flag,
"Meaningless to enable DPD without it compiled.")
# To enable extra OOB checks for BRP, the underlying feature must be
# enabled, too.
assert((enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl) ||
!backup_ref_ptr_extra_oob_checks,
"Can't enable extra OOB checks if BRP isn't enabled and used")
# To poison OOB pointers for BRP, the underlying feature must be
# enabled, too.
assert(backup_ref_ptr_extra_oob_checks || !backup_ref_ptr_poison_oob_ptr,
"Can't enable poisoning for OOB pointers if OOB checks aren't enabled " +
"at all")
assert(has_64_bit_pointers || !backup_ref_ptr_poison_oob_ptr,
"Can't enable poisoning for OOB pointers if pointers are only 32-bit")
# AsanBackupRefPtr and AsanUnownedPtr are mutually exclusive variants of
# raw_ptr.
assert(
!use_raw_ptr_asan_unowned_impl || !use_asan_backup_ref_ptr,
"Both AsanUnownedPtr and AsanBackupRefPtr can't be enabled at the same " +
"time")
# BackupRefPtr and AsanBackupRefPtr are mutually exclusive variants of raw_ptr.
assert(
!enable_backup_ref_ptr_support || !use_asan_backup_ref_ptr,
"Both BackupRefPtr and AsanBackupRefPtr can't be enabled at the same time")
# BackupRefPtr and AsanUnownedPtr are mutually exclusive variants of raw_ptr.
assert(!enable_backup_ref_ptr_support || !use_raw_ptr_asan_unowned_impl,
"Both BackupRefPtr and AsanUnownedPtr can't be enabled at the same time")
# RawPtrHookableImpl and BackupRefPtr are mutually exclusive variants of
# raw_ptr.
assert(
!use_raw_ptr_hookable_impl || !enable_backup_ref_ptr_support,
"Both RawPtrHookableImpl and BackupRefPtr can't be enabled at the same " +
"time")
# RawPtrHookableImpl and AsanUnownedPtr are mutually exclusive variants of
# raw_ptr.
assert(
!use_raw_ptr_hookable_impl || !use_raw_ptr_asan_unowned_impl,
"Both RawPtrHookableImpl and AsanUnownedPtr can't be enabled at the same " +
"time")
assert(!use_asan_backup_ref_ptr || is_asan,
"AsanBackupRefPtr requires AddressSanitizer")
assert(!use_raw_ptr_asan_unowned_impl || is_asan,
"AsanUnownedPtr requires AddressSanitizer")
# AsanBackupRefPtr is not supported outside Chromium. The implementation is
# entangled with `//base`. The code is only physically located with the rest of
# `raw_ptr` to keep it together.
assert(build_with_chromium || !use_asan_backup_ref_ptr,
"AsanBackupRefPtr is not supported outside Chromium")
assert(!use_asan_backup_ref_ptr || use_raw_ptr_hookable_impl,
"AsanBackupRefPtr requires RawPtrHookableImpl")
# pkeys support is explicitly disabled in all Cronet builds, as some test
# dependencies that use partition_allocator are compiled in AOSP against a
# version of glibc that does not include pkeys syscall numbers.
is_pkeys_available =
(is_linux || is_chromeos) && current_cpu == "x64" && !is_cronet_build
declare_args() {
enable_pkeys = is_pkeys_available
}
assert(!enable_pkeys || is_pkeys_available,
"Pkeys are only supported on x64 linux and ChromeOS")
# Some implementations of raw_ptr<>, like BackupRefPtr, require zeroing when
# constructing, destructing or moving out of a pointer. When using these
# implementations, raw_ptrs<> will be always be zeroed, no matter what
# GN args or flags are present.
#
# Other implementations of raw_ptr<>, like NoOpImpl, don't require zeroing
# and do not do so by default. This can lead to subtle bugs when testing
# against one of the zeroing impls and then deploying on a platform that is
# using a non-zeroing implementation. Setting the following GN args to
# true triggers zeroing even for implementations that don't require it.
# This provides consistency with the other impls. This is the recommended
# setting.
#
# Setting these to false will make raw_ptr<> behave more like raw C++ pointer
# `T*`, making NoOpImpl act like an actual no-op, so use it if you're worried
# about performance of your project. Use at your own risk, as it's unsupported
# and untested within Chromium.
#
# Even when these are set to true, the raw_ptr trait AllowUninitialized
# provides a finer-grained mechanism for opting out of initialization on a
# pointer by pointer basis when using a non-zeroing implementation.
#
# Caveat: _zero_on_move and _on_destruct will prevent the type from being
# trivially copyable, _zero_on_construct and _on_destruct will prevent the
# type from being trivially default constructible.
declare_args() {
raw_ptr_zero_on_construct = raw_ptr_zero_on_construct_default
raw_ptr_zero_on_move = raw_ptr_zero_on_move_default
raw_ptr_zero_on_destruct = raw_ptr_zero_on_destruct_default
}
declare_args() {
# Assert that PartitionAlloc and MiraclePtr run on C++20 when set to true.
# Embedders may opt-out of using C++ 20 build.
assert_cpp20 = assert_cpp20_default
}