chromium/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn

# 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("../../partition_alloc.gni")
import("buildflag_header.gni")

# //build_overrides/partition_alloc.gni should define partition_alloc_{
# add,remove}_configs. But if not defined (e.g. the embedder misses the config),
# define them here.
if (!defined(partition_alloc_add_configs)) {
  partition_alloc_add_configs = []
}
if (!defined(partition_alloc_remove_configs)) {
  partition_alloc_remove_configs = []
}

# Enables compilation of the freelist dispatcher, which we'll use to
# carry out runtime evaluation of PartitionAlloc's two freelist
# implementations: the existing encoded-next freelist and the new
# pool offset freelist. When false, the latter is not built.
use_freelist_dispatcher = has_64_bit_pointers

assert(has_64_bit_pointers || !use_freelist_dispatcher,
       "freelist dispatcher can't be used without 64-bit pointers")

record_alloc_info = false

# GWP-ASan is tied to BRP's enablement.
enable_gwp_asan_support = enable_backup_ref_ptr_support

# Pools are a logical concept when address space is 32-bit.
glue_core_pools = glue_core_pools && has_64_bit_pointers

# Pointer compression requires 64-bit pointers.
enable_pointer_compression =
    enable_pointer_compression_support && has_64_bit_pointers

# Duplicates the setup Chromium uses to define `DCHECK_IS_ON()`, but avails it
# as a buildflag.
dchecks_are_on = is_debug || dcheck_always_on

# Building PartitionAlloc for Windows component build.
# Currently use build_with_chromium not to affect any third_party code,
# but if any third_party code wants to use, remove build_with_chromium.
use_partition_alloc_as_malloc_on_win_component_build =
    build_with_chromium && is_win && is_component_build

# TODO(crbug.com/40276913): Split PartitionAlloc into a public and
# private parts. The public config would include add the "./include" dir and
# the private config would add the "./src" dir.
# TODO(crbug.com/40276913): Move this config and several target into
# "../..".
config("public_includes") {
  include_dirs = [
    "..",
    "$root_gen_dir/" + rebase_path("..", "//"),
  ]
}

# Enable more warnings that were found when using PartitionAlloc in other
# projects.
#
# This list was initially copied from Dawn, who gathered this list from its own
# dependants.
config("dependants_extra_warnings") {
  # Add them only when building PartitionAlloc as part of Chrome, because we
  # control which clang version we use. Otherwise we risk breaking dependants
  # when they use a different clang version.
  #
  # Fuchsia has been excluded from the extra warnings: Dependency over
  # fuchsia.kernel involves too many warning. This is not a real issue, because
  # the header is only used by PartitionAlloc internally. The dependants do not
  # include it transitively.
  if (build_with_chromium && is_clang && !is_fuchsia) {
    cflags = [
      "-Wc++11-narrowing",
      "-Wconditional-uninitialized",
      "-Wcstring-format-directive",
      "-Wctad-maybe-unsupported",
      "-Wdeprecated-copy",
      "-Wdeprecated-copy-dtor",
      "-Wduplicate-enum",
      "-Wextra-semi",
      "-Wextra-semi-stmt",
      "-Widiomatic-parentheses",
      "-Wimplicit-fallthrough",
      "-Winconsistent-missing-destructor-override",
      "-Winvalid-offsetof",
      "-Wmissing-field-initializers",
      "-Wnon-c-typedef-for-linkage",
      "-Wpessimizing-move",
      "-Wrange-loop-analysis",
      "-Wredundant-move",
      "-Wshadow-field",
      "-Wstrict-prototypes",
      "-Wsuggest-destructor-override",
      "-Wsuggest-override",
      "-Wtautological-unsigned-zero-compare",
      "-Wunreachable-code-aggressive",
      "-Wunused-but-set-variable",
      "-Wunused-macros",
    ]

    # clang-cl doesn't know -pedantic, pass it explicitly to the clang driver
    if (is_win) {
      cflags += [ "/clang:-pedantic" ]
    } else {
      cflags += [ "-pedantic" ]
    }
  }
}

# This will generate warnings when using Clang if code generates exit-time
# destructors, which will slow down closing the program.
# TODO(thakis): Make this a blocklist instead, http://crbug.com/101600
config("wexit_time_destructors") {
  if (is_clang) {
    cflags = [ "-Wexit-time-destructors" ]
  }
}

source_set("buildflag_macro") {
  sources = [ "buildflag.h" ]
  public_configs = [ ":public_includes" ]
}

pa_buildflag_header("buildflags") {
  header = "buildflags.h"
  flags = [
    "ASSERT_CPP_20=$assert_cpp20",
    "BACKUP_REF_PTR_EXTRA_OOB_CHECKS=$backup_ref_ptr_extra_oob_checks",
    "BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr",
    "ENABLE_BACKUP_REF_PTR_FEATURE_FLAG=$enable_backup_ref_ptr_feature_flag",
    "ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER=$enable_backup_ref_ptr_instance_tracer",
    "ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$enable_backup_ref_ptr_slow_checks",
    "ENABLE_BACKUP_REF_PTR_SUPPORT=$enable_backup_ref_ptr_support",
    "ENABLE_DANGLING_RAW_PTR_CHECKS=$enable_dangling_raw_ptr_checks",
    "ENABLE_DANGLING_RAW_PTR_FEATURE_FLAG=$enable_dangling_raw_ptr_feature_flag",
    "ENABLE_GWP_ASAN_SUPPORT=$enable_gwp_asan_support",
    "ENABLE_PKEYS=$enable_pkeys",
    "ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK=$enable_pointer_arithmetic_trait_check",
    "ENABLE_POINTER_COMPRESSION=$enable_pointer_compression",
    "ENABLE_POINTER_SUBTRACTION_CHECK=$enable_pointer_subtraction_check",
    "ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=$enable_shadow_metadata",
    "ENABLE_THREAD_ISOLATION=$enable_pkeys",
    "FORCE_ENABLE_RAW_PTR_EXCLUSION=$force_enable_raw_ptr_exclusion",
    "FORWARD_THROUGH_MALLOC=$forward_through_malloc",
    "GLUE_CORE_POOLS=$glue_core_pools",
    "HAS_64_BIT_POINTERS=$has_64_bit_pointers",
    "HAS_MEMORY_TAGGING=$has_memory_tagging",
    "IS_CASTOS=$is_castos",
    "IS_CAST_ANDROID=$is_cast_android",
    "IS_CHROMEOS=$is_chromeos",
    "IS_DEBUG=$is_debug",
    "RAW_PTR_ZERO_ON_CONSTRUCT=$raw_ptr_zero_on_construct",
    "RAW_PTR_ZERO_ON_DESTRUCT=$raw_ptr_zero_on_destruct",
    "RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move",
    "RECORD_ALLOC_INFO=$record_alloc_info",
    "STACK_SCAN_SUPPORTED=$stack_scan_supported",
    "USE_ALLOCATOR_SHIM=$use_allocator_shim",
    "USE_ASAN_BACKUP_REF_PTR=$use_asan_backup_ref_ptr",
    "USE_FREELIST_DISPATCHER=$use_freelist_dispatcher",
    "USE_FREESLOT_BITMAP=$use_freeslot_bitmap",
    "USE_FULL_MTE=$use_full_mte",
    "USE_LARGE_EMPTY_SLOT_SPAN_RING=$use_large_empty_slot_span_ring",
    "USE_PARTITION_ALLOC=$use_partition_alloc",
    "USE_PARTITION_ALLOC_AS_MALLOC=$use_partition_alloc_as_malloc",
    "USE_RAW_PTR_ASAN_UNOWNED_IMPL=$use_raw_ptr_asan_unowned_impl",
    "USE_RAW_PTR_BACKUP_REF_IMPL=$use_raw_ptr_backup_ref_impl",
    "USE_RAW_PTR_HOOKABLE_IMPL=$use_raw_ptr_hookable_impl",
    "ENABLE_ALLOCATOR_SHIM_PARTITION_ALLOC_DISPATCH_WITH_ADVANCED_CHECKS_SUPPORT=$enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support",
    "DCHECKS_ARE_ON=$dchecks_are_on",
    "EXPENSIVE_DCHECKS_ARE_ON=$enable_expensive_dchecks",
    "DCHECK_IS_CONFIGURABLE=$dcheck_is_configurable",
    "CAN_UNWIND_WITH_FRAME_POINTERS=$can_unwind_with_frame_pointers",
  ]
}

# TODO(crbug.com/41481467): Remove this alias.
# Temporary alias, the time to update partition_alloc dependants.
# Currently needed by pdfium and dawn.
source_set("partition_alloc_buildflags") {
  public = [ "partition_alloc_buildflags.h" ]
  public_deps = [ ":buildflags" ]
}

# Provides platform and architecture detections from the compiler defines.
source_set("build_config") {
  sources = [
    "build_config.h",
    "buildflag.h",
  ]
  public_deps = [
    ":buildflag_macro",  # Provides 'PA_BUILDFLAG()' macro.
    ":buildflags",  # Provides `IS_CHROMEOS` definition.
  ]
  public_configs = [ ":public_includes" ]
}

component("raw_ptr") {
  # `gn check` is unhappy with most `#includes` when PA isn't
  # actually built.
  check_includes = use_partition_alloc
  public = [
    "pointers/instance_tracer.h",
    "pointers/raw_ptr.h",
    "pointers/raw_ptr_cast.h",
    "pointers/raw_ptr_exclusion.h",
    "pointers/raw_ptr_noop_impl.h",
    "pointers/raw_ref.h",
  ]
  sources = [ "pointers/instance_tracer.cc" ]
  public_configs = [ ":public_includes" ]
  configs += [ ":wexit_time_destructors" ]

  if (use_raw_ptr_backup_ref_impl) {
    sources += [
      "pointers/raw_ptr_backup_ref_impl.cc",
      "pointers/raw_ptr_backup_ref_impl.h",
    ]
  } else if (use_raw_ptr_hookable_impl) {
    sources += [
      "pointers/raw_ptr_hookable_impl.cc",
      "pointers/raw_ptr_hookable_impl.h",
    ]
  } else if (use_raw_ptr_asan_unowned_impl) {
    sources += [
      "pointers/raw_ptr_asan_unowned_impl.cc",
      "pointers/raw_ptr_asan_unowned_impl.h",
    ]
  } else {
    sources += [ "pointers/raw_ptr_noop_impl.h" ]
    sources += [ "pointers/empty.cc" ]
  }
  public_deps = [
    ":build_config",
    ":buildflags",
  ]
  if (use_partition_alloc) {
    public_deps += [ ":partition_alloc" ]
  }

  # See also: `partition_alloc_base/component_export.h`
  defines = [ "IS_RAW_PTR_IMPL" ]

  configs -= partition_alloc_remove_configs
  configs += partition_alloc_add_configs
  configs += [ ":dependants_extra_warnings" ]
}

if (is_clang_or_gcc) {
  config("partition_alloc_implementation") {
    # See also: `partition_alloc_base/component_export.h`
    defines = [ "IS_PARTITION_ALLOC_IMPL" ]
  }

  config("partition_alloc_base_implementation") {
    # See also: `partition_alloc_base/component_export.h`
    defines = [ "IS_PARTITION_ALLOC_BASE_IMPL" ]
  }

  config("allocator_shim_implementation") {
    # See also: `partition_alloc_base/component_export.h`
    defines = [ "IS_ALLOCATOR_SHIM_IMPL" ]
  }

  config("memory_tagging") {
    if (current_cpu == "arm64" &&
        (is_linux || is_chromeos || is_android || is_fuchsia)) {
      # base/ has access to the MTE intrinsics because it needs to use them,
      # but they're not backwards compatible. Use base::CPU::has_mte()
      # beforehand to confirm or use indirect functions (ifuncs) to select
      # an MTE-specific implementation at dynamic link-time.
      cflags = [
        "-Xclang",
        "-target-feature",
        "-Xclang",
        "+mte",
      ]
    }
  }

  # Used to shim malloc symbols on Android. see //base/allocator/README.md.
  config("wrap_malloc_symbols") {
    ldflags = [
      "-Wl,-wrap,calloc",
      "-Wl,-wrap,free",
      "-Wl,-wrap,malloc",
      "-Wl,-wrap,memalign",
      "-Wl,-wrap,posix_memalign",
      "-Wl,-wrap,pvalloc",
      "-Wl,-wrap,realloc",
      "-Wl,-wrap,valloc",

      # Not allocating memory, but part of the API
      "-Wl,-wrap,malloc_usable_size",

      # <cstdlib> functions
      "-Wl,-wrap,realpath",

      # <string.h> functions
      "-Wl,-wrap,strdup",
      "-Wl,-wrap,strndup",

      # <unistd.h> functions
      "-Wl,-wrap,getcwd",

      # <cstdio> functions
      "-Wl,-wrap,asprintf",
      "-Wl,-wrap,vasprintf",
    ]
  }

  config("mac_no_default_new_delete_symbols") {
    if (!is_component_build) {
      # This is already set when we compile libc++, see
      # buildtools/third_party/libc++/BUILD.gn. But it needs to be set here as
      # well, since the shim defines the symbols, to prevent them being exported.
      cflags = [ "-fvisibility-global-new-delete=force-hidden" ]
    }
  }

  if (is_fuchsia) {
    config("fuchsia_sync_lib") {
      libs = [
        "sync",  # Used by spinning_mutex.h.
      ]
    }
  }

  if (enable_pkeys && is_debug) {
    config("no_stack_protector") {
      cflags = [ "-fno-stack-protector" ]
    }
  }

  group("partition_alloc") {
    public_deps = [
      ":allocator_base",
      ":allocator_core",
      ":allocator_shim",
      ":buildflags",
    ]
  }

  if (is_win && is_component_build) {
    group("win_component_build_adapter") {
      # Currently guard this target by using build_with_chromium to avoid
      # any issues on third_party build. But if any third_party code wants to
      # use allocator_shim for its own component build, we will remove this
      # guard.
      if (build_with_chromium) {
        if (use_allocator_shim) {
          public_deps = [
            ":allocator_base",
            ":allocator_shim",
          ]
        }
      }
      # If not with chromium, currently do nothing.
    }
  }

  component("allocator_core") {
    visibility = [ ":*" ]

    if (use_partition_alloc_as_malloc_on_win_component_build) {
      # Since common_deps defined in //build/config/BUILD.gn depends on
      # PartitionAlloc for PartitionAlloc-Everywhere, we need no_default_deps
      # here, because default deps includes common_deps dependency.
      # Without no_defaults_deps=true, we will see cyclic deps:
      # common_deps=>PartitionAlloc=>common_deps
      no_default_deps = true
    }

    sources = [
      "aarch64_support.h",
      "address_pool_manager.cc",
      "address_pool_manager.h",
      "address_pool_manager_bitmap.cc",
      "address_pool_manager_bitmap.h",
      "address_pool_manager_types.h",
      "address_space_randomization.cc",
      "address_space_randomization.h",
      "address_space_stats.h",
      "allocation_guard.cc",
      "allocation_guard.h",
      "compressed_pointer.cc",
      "compressed_pointer.h",
      "dangling_raw_ptr_checks.cc",
      "dangling_raw_ptr_checks.h",
      "flags.h",
      "freeslot_bitmap.h",
      "freeslot_bitmap_constants.h",
      "gwp_asan_support.cc",
      "gwp_asan_support.h",
      "in_slot_metadata.h",
      "internal_allocator.cc",
      "internal_allocator.h",
      "internal_allocator_forward.h",
      "lightweight_quarantine.cc",
      "lightweight_quarantine.h",
      "memory_reclaimer.cc",
      "memory_reclaimer.h",
      "oom.cc",
      "oom.h",
      "oom_callback.cc",
      "oom_callback.h",
      "page_allocator.cc",
      "page_allocator.h",
      "page_allocator_constants.h",
      "page_allocator_internal.h",
      "partition_address_space.cc",
      "partition_address_space.h",
      "partition_alloc-inl.h",
      "partition_alloc.cc",
      "partition_alloc.h",
      "partition_alloc_allocation_data.h",
      "partition_alloc_check.h",
      "partition_alloc_config.h",
      "partition_alloc_constants.h",
      "partition_alloc_forward.h",
      "partition_alloc_hooks.cc",
      "partition_alloc_hooks.h",
      "partition_bucket.cc",
      "partition_bucket.h",
      "partition_bucket_lookup.h",
      "partition_cookie.h",
      "partition_dcheck_helper.cc",
      "partition_dcheck_helper.h",
      "partition_direct_map_extent.h",
      "partition_freelist_entry.cc",
      "partition_freelist_entry.h",
      "partition_lock.h",
      "partition_oom.cc",
      "partition_oom.h",
      "partition_page.cc",
      "partition_page.h",
      "partition_page_constants.h",
      "partition_root.cc",
      "partition_root.h",
      "partition_stats.cc",
      "partition_stats.h",
      "partition_superpage_extent_entry.h",
      "partition_tls.h",
      "random.cc",
      "random.h",
      "reservation_offset_table.cc",
      "reservation_offset_table.h",
      "reverse_bytes.h",
      "spinning_mutex.cc",
      "spinning_mutex.h",
      "stack/stack.cc",
      "stack/stack.h",
      "tagging.cc",
      "tagging.h",
      "thread_cache.cc",
      "thread_cache.h",
      "thread_isolation/alignment.h",
      "thread_isolation/pkey.cc",
      "thread_isolation/pkey.h",
      "thread_isolation/thread_isolation.cc",
      "thread_isolation/thread_isolation.h",
      "yield_processor.h",
    ]

    defines = []
    if (is_win) {
      sources += [
        "page_allocator_internals_win.h",
        "partition_tls_win.cc",
      ]
    } else if (is_posix) {
      sources += [
        "page_allocator_internals_posix.cc",
        "page_allocator_internals_posix.h",
      ]
    } else if (is_fuchsia) {
      sources += [ "page_allocator_internals_fuchsia.h" ]
    }
    if (is_android) {
      # The Android NDK supports PR_MTE_* macros as of NDK r23.
      defines += [ "HAS_PR_MTE_MACROS" ]
    }
    if (current_cpu == "x64") {
      assert(stack_scan_supported)
      sources += [ "stack/asm/x64/push_registers_asm.cc" ]
    } else if (current_cpu == "x86") {
      assert(stack_scan_supported)
      sources += [ "stack/asm/x86/push_registers_asm.cc" ]
    } else if (current_cpu == "arm") {
      assert(stack_scan_supported)
      sources += [ "stack/asm/arm/push_registers_asm.cc" ]
    } else if (current_cpu == "arm64") {
      assert(stack_scan_supported)
      sources += [ "stack/asm/arm64/push_registers_asm.cc" ]
    } else if (current_cpu == "riscv64") {
      assert(stack_scan_supported)
      sources += [ "stack/asm/riscv64/push_registers_asm.cc" ]
    } else {
      # To support a trampoline for another arch, please refer to v8/src/heap/base.
      assert(!stack_scan_supported)
    }

    # TODO(crbug.com/40274683): once we evaluate pool offset freelists,
    # we should erase the dispatcher and compile (& use) exactly one
    # freelist implementation.
    if (use_freelist_dispatcher) {
      sources += [ "pool_offset_freelist.h" ]
    }
    sources += [ "encoded_next_freelist.h" ]

    public_deps = [
      ":build_config",
      ":buildflags",
    ]

    configs += [
      ":partition_alloc_implementation",
      ":memory_tagging",
      ":wexit_time_destructors",
    ]
    deps = [ ":allocator_base" ]
    if (use_partition_alloc_as_malloc_on_win_component_build) {
      # We need to add explicit libc++ dependency here because of
      # no_default_deps=true.
      deps += [ "//buildtools/third_party/libc++:libc++" ]
    }

    public_configs = []
    if (is_fuchsia) {
      deps += [
        "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.kernel:fuchsia.kernel_cpp",
        "//third_party/fuchsia-sdk/sdk/pkg/component_incoming_cpp",
      ]
      public_deps += [
        "//third_party/fuchsia-sdk/sdk/pkg/sync",
        "//third_party/fuchsia-sdk/sdk/pkg/zx",
      ]

      # Needed for users of spinning_mutex.h, which for performance reasons,
      # contains inlined calls to `libsync` inside the header file.
      # It appends an entry to the "libs" section of the dependent target.
      public_configs += [ ":fuchsia_sync_lib" ]
    }

    frameworks = []
    if (is_mac) {
      # SecTaskGetCodeSignStatus needs:
      frameworks += [ "Security.framework" ]
    }

    if (is_apple) {
      frameworks += [
        "CoreFoundation.framework",
        "Foundation.framework",
      ]
    }

    configs -= partition_alloc_remove_configs
    configs += partition_alloc_add_configs
    configs += [ ":dependants_extra_warnings" ]

    # We want to be able to test pkey mode without access to the default pkey.
    # This is incompatible with stack protectors since the TLS won't be pkey-tagged.
    if (enable_pkeys && is_debug) {
      configs += [ ":no_stack_protector" ]
    }
  }

  component("allocator_base") {
    visibility = [ ":*" ]
    if (use_partition_alloc_as_malloc_on_win_component_build) {
      # Since common_deps defined in //build/config/BUILD.gn depends on
      # PartitionAlloc for PartitionAlloc-Everywhere, we need no_default_deps
      # here, because default deps includes common_deps dependency.
      # Without no_defaults_deps=true, we will see cyclic deps:
      # common_deps=>PartitionAlloc=>common_deps
      no_default_deps = true
    }

    sources = [
      "partition_alloc_base/atomic_ref_count.h",
      "partition_alloc_base/augmentations/compiler_specific.h",
      "partition_alloc_base/bit_cast.h",
      "partition_alloc_base/bits.h",
      "partition_alloc_base/check.cc",
      "partition_alloc_base/check.h",
      "partition_alloc_base/compiler_specific.h",
      "partition_alloc_base/component_export.h",
      "partition_alloc_base/cpu.cc",
      "partition_alloc_base/cpu.h",
      "partition_alloc_base/cxx20_is_constant_evaluated.h",
      "partition_alloc_base/debug/alias.cc",
      "partition_alloc_base/debug/alias.h",
      "partition_alloc_base/debug/stack_trace.cc",
      "partition_alloc_base/debug/stack_trace.h",
      "partition_alloc_base/export_template.h",
      "partition_alloc_base/immediate_crash.h",
      "partition_alloc_base/log_message.cc",
      "partition_alloc_base/log_message.h",
      "partition_alloc_base/logging.cc",
      "partition_alloc_base/logging.h",
      "partition_alloc_base/memory/page_size.h",
      "partition_alloc_base/memory/ref_counted.cc",
      "partition_alloc_base/memory/ref_counted.h",
      "partition_alloc_base/memory/scoped_policy.h",
      "partition_alloc_base/memory/scoped_refptr.h",
      "partition_alloc_base/no_destructor.h",
      "partition_alloc_base/notreached.h",
      "partition_alloc_base/numerics/checked_math.h",
      "partition_alloc_base/numerics/checked_math_impl.h",
      "partition_alloc_base/numerics/clamped_math.h",
      "partition_alloc_base/numerics/clamped_math_impl.h",
      "partition_alloc_base/numerics/safe_conversions.h",
      "partition_alloc_base/numerics/safe_conversions_arm_impl.h",
      "partition_alloc_base/numerics/safe_conversions_impl.h",
      "partition_alloc_base/numerics/safe_math.h",
      "partition_alloc_base/numerics/safe_math_arm_impl.h",
      "partition_alloc_base/numerics/safe_math_clang_gcc_impl.h",
      "partition_alloc_base/numerics/safe_math_shared_impl.h",
      "partition_alloc_base/posix/eintr_wrapper.h",
      "partition_alloc_base/process/process_handle.h",
      "partition_alloc_base/rand_util.cc",
      "partition_alloc_base/rand_util.h",
      "partition_alloc_base/scoped_clear_last_error.h",
      "partition_alloc_base/strings/cstring_builder.cc",
      "partition_alloc_base/strings/cstring_builder.h",
      "partition_alloc_base/strings/safe_sprintf.cc",
      "partition_alloc_base/strings/safe_sprintf.h",
      "partition_alloc_base/strings/string_util.cc",
      "partition_alloc_base/strings/string_util.h",
      "partition_alloc_base/strings/stringprintf.cc",
      "partition_alloc_base/strings/stringprintf.h",
      "partition_alloc_base/system/sys_info.h",
      "partition_alloc_base/thread_annotations.h",
      "partition_alloc_base/threading/platform_thread.cc",
      "partition_alloc_base/threading/platform_thread.h",
      "partition_alloc_base/threading/platform_thread_ref.h",
      "partition_alloc_base/time/time.cc",
      "partition_alloc_base/time/time.h",
      "partition_alloc_base/time/time_override.cc",
      "partition_alloc_base/time/time_override.h",
      "partition_alloc_base/types/strong_alias.h",
      "partition_alloc_base/win/win_handle_types.h",
      "partition_alloc_base/win/win_handle_types_list.inc",
      "partition_alloc_base/win/windows_types.h",
    ]

    if (is_win) {
      sources += [
        "partition_alloc_base/debug/stack_trace_win.cc",
        "partition_alloc_base/memory/page_size_win.cc",
        "partition_alloc_base/process/process_handle_win.cc",
        "partition_alloc_base/rand_util_win.cc",
        "partition_alloc_base/scoped_clear_last_error_win.cc",
        "partition_alloc_base/threading/platform_thread_win.cc",
        "partition_alloc_base/time/time_win.cc",
      ]
    }

    if (is_posix) {
      sources += [
        "partition_alloc_base/debug/stack_trace_posix.cc",
        "partition_alloc_base/files/file_util.h",
        "partition_alloc_base/files/file_util_posix.cc",
        "partition_alloc_base/memory/page_size_posix.cc",
        "partition_alloc_base/posix/safe_strerror.cc",
        "partition_alloc_base/posix/safe_strerror.h",
        "partition_alloc_base/process/process_handle_posix.cc",
        "partition_alloc_base/rand_util_posix.cc",
        "partition_alloc_base/threading/platform_thread_internal_posix.h",
        "partition_alloc_base/threading/platform_thread_posix.cc",
        "partition_alloc_base/time/time_conversion_posix.cc",
      ]

      if (is_linux || is_chromeos) {
        sources += [ "partition_alloc_base/debug/stack_trace_linux.cc" ]
      }

      if (is_apple) {
        # Request <dlfcn.h> to provide the `dladdr()` function. This is used to
        # translate address to symbolic information.
        defines = [ "HAVE_DLADDR" ]

        sources += [
          "partition_alloc_base/debug/stack_trace_mac.cc",
          "partition_alloc_base/time/time_apple.mm",
        ]
      } else {
        sources += [ "partition_alloc_base/time/time_now_posix.cc" ]
      }
    }

    if (is_fuchsia) {
      sources += [
        "partition_alloc_base/fuchsia/fuchsia_logging.cc",
        "partition_alloc_base/fuchsia/fuchsia_logging.h",
        "partition_alloc_base/memory/page_size_posix.cc",
        "partition_alloc_base/posix/safe_strerror.cc",
        "partition_alloc_base/posix/safe_strerror.h",
        "partition_alloc_base/rand_util_fuchsia.cc",
        "partition_alloc_base/threading/platform_thread_internal_posix.h",
        "partition_alloc_base/threading/platform_thread_posix.cc",
        "partition_alloc_base/time/time_conversion_posix.cc",
        "partition_alloc_base/time/time_fuchsia.cc",
      ]
    }

    if (is_android) {
      # Only android build requires native_library, and native_library depends
      # on file_path. So file_path is added if is_android = true.
      sources += [
        "partition_alloc_base/debug/stack_trace_android.cc",
        "partition_alloc_base/files/file_path.cc",
        "partition_alloc_base/files/file_path.h",
        "partition_alloc_base/native_library.cc",
        "partition_alloc_base/native_library.h",
        "partition_alloc_base/native_library_posix.cc",
      ]
    }

    if (is_apple) {
      # Apple-specific utilities
      sources += [
        "partition_alloc_base/apple/foundation_util.h",
        "partition_alloc_base/apple/foundation_util.mm",
        "partition_alloc_base/apple/mach_logging.cc",
        "partition_alloc_base/apple/mach_logging.h",
        "partition_alloc_base/apple/scoped_cftyperef.h",
        "partition_alloc_base/apple/scoped_typeref.h",
      ]
      if (is_ios) {
        sources += [
          "partition_alloc_base/ios/ios_util.h",
          "partition_alloc_base/ios/ios_util.mm",
          "partition_alloc_base/system/sys_info_ios.mm",
        ]
      }
      if (is_mac) {
        sources += [
          "partition_alloc_base/mac/mac_util.h",
          "partition_alloc_base/mac/mac_util.mm",
          "partition_alloc_base/system/sys_info_mac.mm",
        ]
      }
    }

    public_deps = [
      ":build_config",
      ":buildflags",
    ]
    public_configs = [ ":public_includes" ]
    configs += [
      ":partition_alloc_base_implementation",
      ":wexit_time_destructors",
    ]

    deps = []
    if (use_partition_alloc_as_malloc_on_win_component_build) {
      # We need to add explicit libc++ dependency here because of
      # no_default_deps=true.
      deps += [ "//buildtools/third_party/libc++:libc++" ]
    }
    if (is_fuchsia) {
      public_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/fit" ]
    }

    frameworks = []
    if (is_apple) {
      frameworks += [
        "CoreFoundation.framework",
        "Foundation.framework",
      ]
    }

    configs -= partition_alloc_remove_configs
    configs += partition_alloc_add_configs
    configs += [ ":dependants_extra_warnings" ]
  }

  component("allocator_shim") {
    visibility = [ ":*" ]

    sources = []
    deps = []
    all_dependent_configs = []
    public_configs = [ ":public_includes" ]
    configs += [
      ":allocator_shim_implementation",
      ":wexit_time_destructors",
    ]
    frameworks = []

    configs -= partition_alloc_remove_configs
    configs += partition_alloc_add_configs
    configs += [ ":dependants_extra_warnings" ]

    shim_headers = []
    shim_sources = []

    shim_sources += [
      "shim/allocator_shim.cc",
      "shim/allocator_shim_dispatch_to_noop_on_free.cc",
    ]
    shim_headers += [
      "shim/allocator_shim.h",
      "shim/allocator_shim_internals.h",
      "shim/shim_alloc_functions.h",
      "shim/allocator_shim_functions.h",
      "shim/allocator_dispatch.h",
      "shim/allocator_shim_dispatch_to_noop_on_free.h",
    ]
    if (use_partition_alloc) {
      shim_sources +=
          [ "shim/allocator_shim_default_dispatch_to_partition_alloc.cc" ]
      shim_headers +=
          [ "shim/allocator_shim_default_dispatch_to_partition_alloc.h" ]
    }
    if (enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support) {
      shim_sources += [ "shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.cc" ]
      shim_headers += [ "shim/allocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.h" ]
    }
    if (is_android) {
      shim_headers += [
        "shim/allocator_shim_override_cpp_symbols.h",
        "shim/allocator_shim_override_linker_wrapped_symbols.h",
      ]
      shim_sources -= [ "shim/allocator_shim.cc" ]
      shim_sources += [ "shim/allocator_shim_android.cc" ]
      if (use_allocator_shim) {
        all_dependent_configs += [ ":wrap_malloc_symbols" ]
      }
    }
    if (is_apple) {
      shim_headers += [
        "shim/allocator_shim_override_apple_default_zone.h",
        "shim/allocator_shim_override_apple_symbols.h",
        "shim/early_zone_registration_constants.h",
        "shim/allocator_interception_apple.h",
        "shim/malloc_zone_functions_apple.h",
      ]
      shim_sources -= [ "shim/allocator_shim.cc" ]
      shim_sources += [
        "shim/allocator_interception_apple.mm",
        "shim/allocator_shim_apple.cc",
        "shim/malloc_zone_functions_apple.cc",
      ]
      frameworks += [ "CoreFoundation.framework" ]

      if (use_allocator_shim) {
        configs += [ ":mac_no_default_new_delete_symbols" ]

        # Do not compile with ARC because this target has to interface with
        # low-level Objective-C and having ARC would interfere.
        configs -= [ partition_alloc_enable_arc_config ]
      }
    }
    if (is_chromeos || is_linux) {
      shim_headers += [
        "shim/allocator_shim_override_cpp_symbols.h",
        "shim/allocator_shim_override_glibc_weak_symbols.h",
        "shim/allocator_shim_override_libc_symbols.h",
      ]
    }
    if (is_win) {
      shim_headers += [
        "shim/allocator_shim_override_ucrt_symbols_win.h",
        "shim/winheap_stubs_win.h",
      ]
      shim_sources -= [ "shim/allocator_shim.cc" ]
      shim_sources += [ "shim/winheap_stubs_win.cc" ]

      if (!is_component_build) {
        shim_sources += [
          "shim/allocator_shim_win_static.cc",
          "shim/checked_multiply_win.h",
        ]
      } else {
        shim_sources += [
          "shim/allocator_shim_functions_win_component.cc",
          "shim/allocator_shim_win_component.cc",
        ]

        # allocator_shim cannot depend on libc++ objects because they use malloc()
        # internally.
        no_default_deps = true
      }
    }

    if (!use_partition_alloc_as_malloc) {
      if (is_android) {
        shim_sources += [
          "shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
        ]
      }
      if (is_apple) {
        shim_sources +=
            [ "shim/allocator_shim_default_dispatch_to_apple_zoned_malloc.cc" ]
      }
      if (is_chromeos || is_linux) {
        shim_sources += [ "shim/allocator_shim_default_dispatch_to_glibc.cc" ]
      }
      if (is_win) {
        shim_sources += [ "shim/allocator_shim_default_dispatch_to_winheap.cc" ]
      }
    }

    sources = shim_headers
    if (use_allocator_shim) {
      sources += shim_sources
    } else {
      # To avoid "lld-link: error: <root>: undefined symbol: _DllMainCRTStartup",
      # at least one object file is required when linking allocator_shim.dll.
      sources += [ "shim/empty.cc" ]
    }

    deps += [
      ":allocator_base",
      ":allocator_core",
      ":buildflags",
    ]
  }
}  # if (is_clang_or_gcc)

# TODO(crbug.com/40158212): Consider supporting building tests outside of
# chromium and having a dedicated 'partition_alloc_unittests' target.
if (build_with_chromium) {
  source_set("unittests") {
    testonly = true

    sources = [ "partition_alloc_base/test/gtest_util.h" ]

    if (is_linux || is_chromeos || is_android) {
      sources += [
        "partition_alloc_base/debug/proc_maps_linux.cc",
        "partition_alloc_base/debug/proc_maps_linux.h",
      ]
    }

    if (is_android) {
      sources += [
        "partition_alloc_base/files/file_path_pa_unittest.cc",
        "partition_alloc_base/native_library_pa_unittest.cc",
      ]
    }

    if (use_partition_alloc) {
      sources += [
        "address_pool_manager_unittest.cc",
        "address_space_randomization_unittest.cc",
        "compressed_pointer_unittest.cc",
        "freeslot_bitmap_unittest.cc",
        "hardening_unittest.cc",
        "lightweight_quarantine_unittest.cc",
        "memory_reclaimer_unittest.cc",
        "page_allocator_unittest.cc",
        "partition_alloc_base/bits_pa_unittest.cc",
        "partition_alloc_base/component_export_pa_unittest.cc",
        "partition_alloc_base/cpu_pa_unittest.cc",
        "partition_alloc_base/logging_pa_unittest.cc",
        "partition_alloc_base/no_destructor_pa_unittest.cc",
        "partition_alloc_base/rand_util_pa_unittest.cc",
        "partition_alloc_base/scoped_clear_last_error_pa_unittest.cc",
        "partition_alloc_base/strings/cstring_builder_pa_unittest.cc",
        "partition_alloc_base/strings/safe_sprintf_pa_unittest.cc",
        "partition_alloc_base/strings/string_util_pa_unittest.cc",
        "partition_alloc_base/strings/stringprintf_pa_unittest.cc",
        "partition_alloc_base/thread_annotations_pa_unittest.cc",
        "partition_alloc_unittest.cc",
        "partition_lock_unittest.cc",
        "reverse_bytes_unittest.cc",
        "slot_start_unittest.cc",
        "thread_cache_unittest.cc",
        "use_death_tests.h",
      ]
    }

    if (is_fuchsia) {
      sources +=
          [ "partition_alloc_base/fuchsia/fuchsia_logging_pa_unittest.cc" ]
    }

    if (use_allocator_shim) {
      sources += [
        "shim/allocator_shim_default_dispatch_to_partition_alloc_unittest.cc",
      ]

      if (is_win) {
        sources += [ "shim/winheap_stubs_win_unittest.cc" ]
      }

      if (is_ios) {
        sources += [
          "shim/allocator_interception_apple_unittest.mm",
          "shim/malloc_zone_functions_apple_unittest.cc",
        ]
      }
    }

    if ((is_android || is_linux) && target_cpu == "arm64") {
      cflags = [
        "-Xclang",
        "-target-feature",
        "-Xclang",
        "+mte",
      ]
    }

    if (enable_pkeys && is_debug && !is_component_build) {
      # This test requires RELRO, which is not enabled in component builds.
      # Also, require a debug build, since we only disable stack protectors in
      # debug builds in PartitionAlloc (see below why it's needed).
      sources += [ "thread_isolation/pkey_unittest.cc" ]

      # We want to test the pkey code without access to memory that is not
      # pkey-tagged. This will allow us to catch unintended memory accesses
      # that could break our security assumptions. The stack protector reads a
      # value from the TLS which won't be pkey-tagged, hence disabling it for
      # the test.
      configs += [ ":no_stack_protector" ]
    }

    frameworks = []
    if (is_mac) {
      frameworks += [
        "Foundation.framework",
        "OpenCL.framework",
      ]
    }

    deps = [
      ":partition_alloc",
      ":test_support",
      "//testing/gmock",
      "//testing/gtest",
    ]

    configs -= partition_alloc_remove_configs
    configs += partition_alloc_add_configs
  }
}

source_set("test_support") {
  testonly = true

  sources = [
    "extended_api.cc",
    "extended_api.h",
    "partition_alloc_base/threading/platform_thread_for_testing.h",
    "partition_alloc_for_testing.h",
    "pointers/raw_ptr_counting_impl_for_test.h",
  ]
  if (is_posix) {
    sources += [
      "partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
    ]
  }
  if (is_fuchsia) {
    sources += [
      "partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc",
      "partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
    ]
  }
  if (is_win) {
    sources +=
        [ "partition_alloc_base/threading/platform_thread_win_for_testing.cc" ]
  }
  if (is_apple) {
    sources += [
      "partition_alloc_base/threading/platform_thread_apple_for_testing.mm",
    ]
  }
  if (is_linux || is_chromeos) {
    sources += [
      "partition_alloc_base/threading/platform_thread_linux_for_testing.cc",
    ]
  }
  if (is_android) {
    sources += [
      "partition_alloc_base/threading/platform_thread_android_for_testing.cc",
    ]
  }
  public_deps = [
    ":arm_bti_testfunctions",
    ":buildflags",
    ":partition_alloc",
    ":raw_ptr",
  ]
  public_configs = []

  if (is_fuchsia) {
    public_deps += [
      "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger:fuchsia.logger_hlcpp",
      "//third_party/fuchsia-sdk/sdk/pkg/fit",
      "//third_party/fuchsia-sdk/sdk/pkg/sync",
      "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
      "//third_party/fuchsia-sdk/sdk/pkg/zx",
    ]

    # Needed for users of spinning_mutex.h, which for performance reasons,
    # contains inlined calls to `libsync` inside the header file.
    # It appends an entry to the "libs" section of the dependent target.
    public_configs += [ ":fuchsia_sync_lib" ]
  }

  configs -= partition_alloc_remove_configs
  configs += partition_alloc_add_configs
}

source_set("arm_bti_testfunctions") {
  testonly = true
  sources = []
  if (target_cpu == "arm64" && (is_linux || is_android)) {
    sources = [
      "arm_bti_test_functions.S",
      "arm_bti_test_functions.h",
    ]
  }
}