Reland "partition_alloc: Move pa tests into pa."
This reverts commit5d5831911b
. The diff is fixing an issue on Android. On Android the 'open' function has two versions: - int open(const char *pathname, int flags); - int open(const char *pathname, int flags, mode_t mode); This doesn't play well with WrapEINTR template. So an alias was created Original change's description: > Revert "partition_alloc: Move pa tests into pa." > > This reverts commit17884376ce
. > > Reason for revert: Fails to compile on `android-archive-rel` > https://ci.chromium.org/ui/p/chromium/builders/ci/android-archive-rel/42067/overview > > NOTRY=true > NOTREECHECKS=true > > Original change's description: > > partition_alloc: Move pa tests into pa. > > > > This addresses a TODO about moving partition_alloc's tests into > > partition_alloc. > > > > Bug: 40158212 > > Change-Id: Ia4b2017e2da38bd3fed904558126076b2deafc51 > > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5659601 > > Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org> > > Reviewed-by: Kentaro Hara <haraken@chromium.org> > > Reviewed-by: danakj <danakj@chromium.org> > > Reviewed-by: Colin Blundell <blundell@chromium.org> > > Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org> > > Cr-Commit-Position: refs/heads/main@{#1323243} > > Bug: 40158212 > Change-Id: I8831dbcffd8c328a0722fe1f53e382c68a6056a9 > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5676232 > Commit-Queue: Titouan Rigoudy <titouan@chromium.org> > Auto-Submit: Titouan Rigoudy <titouan@chromium.org> > Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org> > Owners-Override: Titouan Rigoudy <titouan@chromium.org> > Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org> > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > Cr-Commit-Position: refs/heads/main@{#1323249} Bug: 40158212 Change-Id: Ie60a85c296224ef3cfdcc17371db100cf2ce0db1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5675456 Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org> Reviewed-by: Kentaro Hara <haraken@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Cr-Commit-Position: refs/heads/main@{#1323319}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
8e776b2fa5
commit
2ecbb28535
base
BUILD.gn
allocator
partition_allocator
DEPSPRESUBMIT.py
build_overrides
gn
src
partition_alloc
components/heap_profiling/multi_process
gin
166
base/BUILD.gn
166
base/BUILD.gn
@ -2830,12 +2830,13 @@ test("base_perftests") {
|
||||
"//third_party/google_benchmark",
|
||||
]
|
||||
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
if (use_partition_alloc) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_lock_perftest.cc",
|
||||
]
|
||||
deps += [ ":partition_alloc_test_support" ]
|
||||
deps += [ "allocator/partition_allocator/src/partition_alloc:test_support" ]
|
||||
}
|
||||
|
||||
data_deps = [
|
||||
@ -3146,19 +3147,6 @@ if (is_fuchsia) {
|
||||
}
|
||||
}
|
||||
|
||||
source_set("arm_bti_testfunctions") {
|
||||
testonly = true
|
||||
|
||||
sources = []
|
||||
|
||||
if (target_cpu == "arm64" && (is_linux || is_android)) {
|
||||
sources = [
|
||||
"allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.S",
|
||||
"allocator/partition_allocator/src/partition_alloc/arm_bti_test_functions.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("path_service_unittest") {
|
||||
testonly = true
|
||||
|
||||
@ -3187,9 +3175,6 @@ test("base_unittests") {
|
||||
"allocator/dispatcher/testing/observer_mock.h",
|
||||
"allocator/dispatcher/testing/tools.h",
|
||||
"allocator/dispatcher/tls_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc",
|
||||
"at_exit_unittest.cc",
|
||||
"atomicops_unittest.cc",
|
||||
"auto_reset_unittest.cc",
|
||||
@ -3557,6 +3542,11 @@ test("base_unittests") {
|
||||
"values_unittest.cc",
|
||||
"version_unittest.cc",
|
||||
"vlog_unittest.cc",
|
||||
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_test_support.h",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc",
|
||||
]
|
||||
|
||||
if (!is_cronet_build) {
|
||||
@ -3580,13 +3570,11 @@ test("base_unittests") {
|
||||
defines = []
|
||||
|
||||
deps = [
|
||||
":arm_bti_testfunctions",
|
||||
":base",
|
||||
":base_stack_sampling_profiler_test_util",
|
||||
":check_version_internal",
|
||||
":feature_list_buildflags",
|
||||
":i18n",
|
||||
":partition_alloc_test_support",
|
||||
":path_service_unittest",
|
||||
":sanitizer_buildflags",
|
||||
"//base/allocator:buildflags",
|
||||
@ -3597,6 +3585,7 @@ test("base_unittests") {
|
||||
"//base/test:test_proto",
|
||||
"//base/test:test_support",
|
||||
"//build:blink_buildflags",
|
||||
"//build:branding_buildflags",
|
||||
"//build:chromecast_buildflags",
|
||||
"//build:chromeos_buildflags",
|
||||
"//testing/gmock",
|
||||
@ -3604,6 +3593,9 @@ test("base_unittests") {
|
||||
"//third_party/abseil-cpp:absl",
|
||||
"//third_party/icu",
|
||||
"//third_party/modp_b64",
|
||||
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
"allocator/partition_allocator/src/partition_alloc:test_support",
|
||||
]
|
||||
|
||||
data_deps = [
|
||||
@ -3636,8 +3628,10 @@ test("base_unittests") {
|
||||
|
||||
if (use_blink) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/tagging_unittest.cc",
|
||||
"metrics/histogram_shared_memory_unittest.cc",
|
||||
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
"allocator/partition_allocator/src/partition_alloc/tagging_unittest.cc",
|
||||
]
|
||||
|
||||
if (!is_ios) {
|
||||
@ -3929,57 +3923,9 @@ test("base_unittests") {
|
||||
"immediate_crash_unittest.cc",
|
||||
]
|
||||
|
||||
if (use_allocator_shim) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple_unittest.mm",
|
||||
"allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple_unittest.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if (use_blink) {
|
||||
sources += [ "files/file_path_watcher_unittest.cc" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (use_partition_alloc) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/address_pool_manager_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/compressed_pointer_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/no_destructor_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/scoped_clear_last_error_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_lock_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/reverse_bytes_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/slot_start_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/use_death_tests.h",
|
||||
]
|
||||
|
||||
if (use_starscan) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/stack/stack_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/starscan/scan_loop_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap_unittest.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if ((is_android || is_linux) && target_cpu == "arm64") {
|
||||
cflags = [
|
||||
@ -3990,19 +3936,11 @@ test("base_unittests") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/files/file_path_pa_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/native_library_pa_unittest.cc",
|
||||
]
|
||||
} else if (is_fuchsia) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging_pa_unittest.cc" ]
|
||||
}
|
||||
|
||||
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).
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc" ]
|
||||
|
||||
# We want to test the pkey code without access to memory that is not
|
||||
@ -4013,7 +3951,7 @@ test("base_unittests") {
|
||||
configs += [ ":no_stack_protector" ]
|
||||
}
|
||||
|
||||
deps += [ ":partition_alloc_test_support" ]
|
||||
deps += [ "allocator/partition_allocator/src/partition_alloc:test_support" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
@ -4021,7 +3959,6 @@ test("base_unittests") {
|
||||
frameworks = [
|
||||
"CoreFoundation.framework",
|
||||
"Foundation.framework",
|
||||
"OpenCL.framework",
|
||||
]
|
||||
if (current_cpu == "x64") {
|
||||
deps += [ ":base_profiler_test_support_library" ]
|
||||
@ -4159,18 +4096,12 @@ test("base_unittests") {
|
||||
|
||||
if (use_allocator_shim) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_unittest.cc",
|
||||
"sampling_heap_profiler/poisson_allocation_sampler_unittest.cc",
|
||||
"sampling_heap_profiler/sampling_heap_profiler_unittest.cc",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win_unittest.cc" ]
|
||||
}
|
||||
|
||||
sources += [
|
||||
# TODO(crbug.com/40158212): Move partition_alloc tests into its repository.
|
||||
"allocator/partition_alloc_support_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc_unittest.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_unittest.cc",
|
||||
]
|
||||
}
|
||||
|
||||
@ -5544,67 +5475,6 @@ fuzzer_test("pickle_fuzzer") {
|
||||
]
|
||||
}
|
||||
|
||||
# TODO(crbug.com/40158212): Temporarily move test_support from
|
||||
# //base/allocator/partition_allocator/src/partition_alloc/BUILD.gn to //base/BUILD.gn. After
|
||||
# fixing partition_allocator tests issue, we will move test_support to
|
||||
# //base/allocator/partition_allocator/src/partition_alloc/BUILD.gn again.
|
||||
source_set("partition_alloc_test_support") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"allocator/partition_allocator/src/partition_alloc/extended_api.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/extended_api.h",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_for_testing.h",
|
||||
"allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_counting_impl_for_test.h",
|
||||
]
|
||||
if (is_posix) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc" ]
|
||||
}
|
||||
if (is_fuchsia) {
|
||||
sources += [
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc",
|
||||
"allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc",
|
||||
]
|
||||
}
|
||||
if (is_win) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc" ]
|
||||
}
|
||||
if (is_apple) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_apple_for_testing.mm" ]
|
||||
}
|
||||
if (is_linux || is_chromeos) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_linux_for_testing.cc" ]
|
||||
}
|
||||
if (is_android) {
|
||||
sources += [ "allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_android_for_testing.cc" ]
|
||||
}
|
||||
public_deps = [
|
||||
"allocator/partition_allocator:buildflags",
|
||||
"//build:branding_buildflags",
|
||||
"//build/config/compiler:compiler_buildflags",
|
||||
]
|
||||
public_configs = []
|
||||
if (is_fuchsia) {
|
||||
public_deps += [
|
||||
"//third_party/fuchsia-sdk/sdk/pkg/fit",
|
||||
"//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" ]
|
||||
}
|
||||
deps = [ ":base" ]
|
||||
|
||||
if (!is_debug) {
|
||||
configs -= [ "//build/config/compiler:default_optimization" ]
|
||||
configs += [ "//build/config/compiler:optimize_speed" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_base_tracing) {
|
||||
# This group makes visible those targets in subdirectories that are not
|
||||
# explicitly depended on.
|
||||
|
@ -18,24 +18,20 @@ specific_include_rules = {
|
||||
"+testing/gtest/include/gtest/gtest.h",
|
||||
"+testing/perf/perf_result_reporter.h",
|
||||
],
|
||||
"gtest_util.h": [
|
||||
"+testing/gtest/include/gtest/gtest.h",
|
||||
],
|
||||
|
||||
# Dependencies on //base:
|
||||
"extended_api\.cc": [
|
||||
"+base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h",
|
||||
],
|
||||
"page_allocator_unittest\.cc": [
|
||||
"+base/debug/proc_maps_linux.h",
|
||||
],
|
||||
"partition_alloc_perftest\.cc": [
|
||||
"+base/allocator/dispatcher/dispatcher.h",
|
||||
"+base/debug/allocation_trace.h",
|
||||
"+base/debug/debugging_buildflags.h",
|
||||
"+base/timer/lap_timer.h",
|
||||
],
|
||||
"partition_alloc_unittest\.cc": [
|
||||
"+base/system/sys_info.h",
|
||||
"+base/test/gtest_util.h",
|
||||
],
|
||||
"partition_lock_perftest\.cc": [
|
||||
"+base/timer/lap_timer.h",
|
||||
],
|
||||
|
@ -117,6 +117,9 @@ def CheckNoExternalImportInGn(input_api, output_api):
|
||||
continue;
|
||||
if not import_path.startswith('//'):
|
||||
continue;
|
||||
# Allow //testing, but only within `build_with_chromium`.
|
||||
if import_path.startswith('//testing'):
|
||||
continue;
|
||||
errors.append(output_api.PresubmitError(
|
||||
'%s:%d\nPartitionAlloc disallow external import: %s' %
|
||||
(f.LocalPath(), line_number + 1, import_path)))
|
||||
|
@ -1,9 +0,0 @@
|
||||
# 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.
|
||||
|
||||
# This file will be used to check out PartitionAlloc and to build it as
|
||||
# standalone library. In this case, PartitionAlloc needs to define
|
||||
# build_with_chromium. If building PartitionAlloc as a part of chromium,
|
||||
# chromium will provide build_with_chromium=true.
|
||||
build_with_chromium = false
|
@ -2,7 +2,8 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build_overrides/build.gni")
|
||||
# By definition, PartitionAlloc standalone builds outside of chromium.
|
||||
build_with_chromium = false
|
||||
|
||||
# This is the default build configuration when building PartitionAlloc
|
||||
# as a standalone library.
|
||||
|
@ -8,7 +8,6 @@
|
||||
# - skia: //gn/BUILDCONFIG.gn
|
||||
# - chromium: //build/config/BUILDCONFIG.gn
|
||||
|
||||
is_partition_alloc_standalone = true
|
||||
build_with_chromium = false
|
||||
is_asan = false
|
||||
|
||||
|
@ -634,7 +634,9 @@ if (is_clang_or_gcc) {
|
||||
"partition_alloc_base/threading/platform_thread_win.cc",
|
||||
"partition_alloc_base/time/time_win.cc",
|
||||
]
|
||||
} else if (is_posix) {
|
||||
}
|
||||
|
||||
if (is_posix) {
|
||||
sources += [
|
||||
"partition_alloc_base/debug/stack_trace_posix.cc",
|
||||
"partition_alloc_base/files/file_util.h",
|
||||
@ -665,7 +667,9 @@ if (is_clang_or_gcc) {
|
||||
} else {
|
||||
sources += [ "partition_alloc_base/time/time_now_posix.cc" ]
|
||||
}
|
||||
} else if (is_fuchsia) {
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
sources += [
|
||||
"partition_alloc_base/fuchsia/fuchsia_logging.cc",
|
||||
"partition_alloc_base/fuchsia/fuchsia_logging.h",
|
||||
@ -679,6 +683,7 @@ if (is_clang_or_gcc) {
|
||||
"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.
|
||||
@ -691,6 +696,7 @@ if (is_clang_or_gcc) {
|
||||
"partition_alloc_base/native_library_posix.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_apple) {
|
||||
# Apple-specific utilities
|
||||
sources += [
|
||||
@ -888,6 +894,204 @@ if (is_clang_or_gcc) {
|
||||
]
|
||||
}
|
||||
} # if (is_clang_or_gcc)
|
||||
# TODO(crbug.com/40158212): After making partition_alloc a standalone library,
|
||||
# move test code here. i.e. test("partition_alloc_tests") { ... } and
|
||||
# test("partition_alloc_perftests").
|
||||
|
||||
# TODO(crbug.com/40158212): Consider supporting building tests outside of
|
||||
# chromium.
|
||||
if (build_with_chromium) {
|
||||
import("//testing/test.gni")
|
||||
|
||||
test("partition_alloc_tests") {
|
||||
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 (use_starscan) {
|
||||
sources += [
|
||||
"stack/stack_unittest.cc",
|
||||
"starscan/pcscan_scheduling_unittest.cc",
|
||||
"starscan/pcscan_unittest.cc",
|
||||
"starscan/scan_loop_unittest.cc",
|
||||
"starscan/state_bitmap_unittest.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
]
|
||||
}
|
||||
|
||||
frameworks = []
|
||||
if (is_mac) {
|
||||
frameworks += [
|
||||
"Foundation.framework",
|
||||
"OpenCL.framework",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
# GTest
|
||||
"//testing/gtest:gtest",
|
||||
"//testing/gtest:gtest_main",
|
||||
|
||||
# GMock
|
||||
"//testing/gmock:gmock",
|
||||
|
||||
# PartitionAlloc
|
||||
":partition_alloc",
|
||||
":test_support",
|
||||
]
|
||||
|
||||
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",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "partition_alloc/tagging.h"
|
||||
|
||||
#if defined(LINUX_NAME_REGION)
|
||||
#include "base/debug/proc_maps_linux.h"
|
||||
#include "partition_alloc/partition_alloc_base/debug/proc_maps_linux.h"
|
||||
#endif
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -499,9 +499,9 @@ TEST(PartitionAllocPageAllocatorTest, PageTagging) {
|
||||
|
||||
auto is_region_named = [](uintptr_t start_address) {
|
||||
std::string proc_maps;
|
||||
EXPECT_TRUE(::base::debug::ReadProcMaps(&proc_maps));
|
||||
std::vector<::base::debug::MappedMemoryRegion> regions;
|
||||
EXPECT_TRUE(::base::debug::ParseProcMaps(proc_maps, ®ions));
|
||||
EXPECT_TRUE(base::debug::ReadProcMaps(&proc_maps));
|
||||
std::vector<base::debug::MappedMemoryRegion> regions;
|
||||
EXPECT_TRUE(base::debug::ParseProcMaps(proc_maps, ®ions));
|
||||
|
||||
bool found = false;
|
||||
for (const auto& region : regions) {
|
||||
|
193
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.cc
Normal file
193
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.cc
Normal file
@ -0,0 +1,193 @@
|
||||
// Copyright 2013 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifdef UNSAFE_BUFFERS_BUILD
|
||||
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
|
||||
#pragma allow_unsafe_buffers
|
||||
#endif
|
||||
|
||||
#include "partition_alloc/partition_alloc_base/debug/proc_maps_linux.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "partition_alloc/build_config.h"
|
||||
#include "partition_alloc/partition_alloc_base/files/file_util.h"
|
||||
#include "partition_alloc/partition_alloc_base/logging.h"
|
||||
#include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h"
|
||||
#include "partition_alloc/partition_alloc_check.h"
|
||||
|
||||
#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) || \
|
||||
PA_BUILDFLAG(IS_ANDROID)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
namespace partition_alloc::internal::base::debug {
|
||||
|
||||
namespace {
|
||||
// On Android the 'open' function may have two versions:
|
||||
// int open(const char *pathname, int flags);
|
||||
// int open(const char *pathname, int flags, mode_t mode);
|
||||
//
|
||||
// This doesn't play well with WrapEINTR template. This alias helps the compiler
|
||||
// to make a decision.
|
||||
int OpenFile(const char* pathname, int flags) {
|
||||
return open(pathname, flags);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Scans |proc_maps| starting from |pos| returning true if the gate VMA was
|
||||
// found, otherwise returns false.
|
||||
static bool ContainsGateVMA(std::string* proc_maps, size_t pos) {
|
||||
#if PA_BUILDFLAG(PA_ARCH_CPU_ARM_FAMILY)
|
||||
// The gate VMA on ARM kernels is the interrupt vectors page.
|
||||
return proc_maps->find(" [vectors]\n", pos) != std::string::npos;
|
||||
#elif PA_BUILDFLAG(PA_ARCH_CPU_X86_64)
|
||||
// The gate VMA on x86 64-bit kernels is the virtual system call page.
|
||||
return proc_maps->find(" [vsyscall]\n", pos) != std::string::npos;
|
||||
#else
|
||||
// Otherwise assume there is no gate VMA in which case we shouldn't
|
||||
// get duplicate entries.
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ReadProcMaps(std::string* proc_maps) {
|
||||
// seq_file only writes out a page-sized amount on each call. Refer to header
|
||||
// file for details.
|
||||
const size_t read_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
|
||||
int fd = WrapEINTR(OpenFile)("/proc/self/maps", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
PA_LOG(ERROR) << "Couldn't open /proc/self/maps";
|
||||
WrapEINTR(close)(fd);
|
||||
return false;
|
||||
}
|
||||
proc_maps->clear();
|
||||
|
||||
while (true) {
|
||||
// To avoid a copy, resize |proc_maps| so read() can write directly into it.
|
||||
// Compute |buffer| afterwards since resize() may reallocate.
|
||||
size_t pos = proc_maps->size();
|
||||
proc_maps->resize(pos + read_size);
|
||||
void* buffer = &(*proc_maps)[pos];
|
||||
|
||||
ssize_t bytes_read = WrapEINTR(read)(fd, buffer, read_size);
|
||||
if (bytes_read < 0) {
|
||||
PA_DPLOG(ERROR) << "Couldn't read /proc/self/maps";
|
||||
proc_maps->clear();
|
||||
WrapEINTR(close)(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... and don't forget to trim off excess bytes.
|
||||
proc_maps->resize(pos + static_cast<size_t>(bytes_read));
|
||||
|
||||
if (bytes_read == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// The gate VMA is handled as a special case after seq_file has finished
|
||||
// iterating through all entries in the virtual memory table.
|
||||
//
|
||||
// Unfortunately, if additional entries are added at this point in time
|
||||
// seq_file gets confused and the next call to read() will return duplicate
|
||||
// entries including the gate VMA again.
|
||||
//
|
||||
// Avoid this by searching for the gate VMA and breaking early.
|
||||
if (ContainsGateVMA(proc_maps, pos)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WrapEINTR(close)(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseProcMaps(const std::string& input,
|
||||
std::vector<MappedMemoryRegion>* regions_out) {
|
||||
PA_CHECK(regions_out);
|
||||
std::vector<MappedMemoryRegion> regions;
|
||||
|
||||
// This isn't async safe nor terribly efficient, but it doesn't need to be at
|
||||
// this point in time.
|
||||
std::vector<std::string> lines;
|
||||
int start = 0;
|
||||
for (size_t i = 0; i < input.size(); ++i) {
|
||||
if (input[i] == '\n') {
|
||||
lines.push_back(input.substr(start, i - start));
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
// Due to splitting on '\n' the last line should be empty.
|
||||
if (i == lines.size() - 1) {
|
||||
if (!lines[i].empty()) {
|
||||
PA_DLOG(WARNING) << "Last line not empty";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
MappedMemoryRegion region;
|
||||
const char* line = lines[i].c_str();
|
||||
char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
|
||||
uint8_t dev_major = 0;
|
||||
uint8_t dev_minor = 0;
|
||||
long inode = 0;
|
||||
int path_index = 0;
|
||||
|
||||
// Sample format from man 5 proc:
|
||||
//
|
||||
// address perms offset dev inode pathname
|
||||
// 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
|
||||
//
|
||||
// The final %n term captures the offset in the input string, which is used
|
||||
// to determine the path name. It *does not* increment the return value.
|
||||
// Refer to man 3 sscanf for details.
|
||||
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %llx %hhx:%hhx %ld %n",
|
||||
®ion.start, ®ion.end, permissions, ®ion.offset,
|
||||
&dev_major, &dev_minor, &inode, &path_index) < 7) {
|
||||
PA_LOG(WARNING) << "sscanf failed for line: " << line;
|
||||
return false;
|
||||
}
|
||||
|
||||
region.permissions = 0;
|
||||
|
||||
if (permissions[0] == 'r') {
|
||||
region.permissions |= MappedMemoryRegion::READ;
|
||||
} else if (permissions[0] != '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (permissions[1] == 'w') {
|
||||
region.permissions |= MappedMemoryRegion::WRITE;
|
||||
} else if (permissions[1] != '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (permissions[2] == 'x') {
|
||||
region.permissions |= MappedMemoryRegion::EXECUTE;
|
||||
} else if (permissions[2] != '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (permissions[3] == 'p') {
|
||||
region.permissions |= MappedMemoryRegion::PRIVATE;
|
||||
} else if (permissions[3] != 's' &&
|
||||
permissions[3] != 'S') { // Shared memory.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pushing then assigning saves us a string copy.
|
||||
regions.push_back(region);
|
||||
regions.back().path.assign(line + path_index);
|
||||
}
|
||||
|
||||
regions_out->swap(regions);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace partition_alloc::internal::base::debug
|
93
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.h
Normal file
93
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright 2013 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_
|
||||
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "partition_alloc/partition_alloc_base/component_export.h"
|
||||
|
||||
namespace partition_alloc::internal::base::debug {
|
||||
|
||||
// Describes a region of mapped memory and the path of the file mapped.
|
||||
struct MappedMemoryRegion {
|
||||
enum Permission {
|
||||
READ = 1 << 0,
|
||||
WRITE = 1 << 1,
|
||||
EXECUTE = 1 << 2,
|
||||
PRIVATE = 1 << 3, // If set, region is private, otherwise it is shared.
|
||||
};
|
||||
|
||||
// The address range [start,end) of mapped memory.
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
|
||||
// Byte offset into |path| of the range mapped into memory.
|
||||
unsigned long long offset;
|
||||
|
||||
// Image base, if this mapping corresponds to an ELF image.
|
||||
uintptr_t base;
|
||||
|
||||
// Bitmask of read/write/execute/private/shared permissions.
|
||||
uint8_t permissions;
|
||||
|
||||
// Name of the file mapped into memory.
|
||||
//
|
||||
// NOTE: path names aren't guaranteed to point at valid files. For example,
|
||||
// "[heap]" and "[stack]" are used to represent the location of the process'
|
||||
// heap and stack, respectively.
|
||||
std::string path;
|
||||
};
|
||||
|
||||
// Reads the data from /proc/self/maps and stores the result in |proc_maps|.
|
||||
// Returns true if successful, false otherwise.
|
||||
//
|
||||
// There is *NO* guarantee that the resulting contents will be free of
|
||||
// duplicates or even contain valid entries by time the method returns.
|
||||
//
|
||||
//
|
||||
// THE GORY DETAILS
|
||||
//
|
||||
// Did you know it's next-to-impossible to atomically read the whole contents
|
||||
// of /proc/<pid>/maps? You would think that if we passed in a large-enough
|
||||
// buffer to read() that It Should Just Work(tm), but sadly that's not the case.
|
||||
//
|
||||
// Linux's procfs uses seq_file [1] for handling iteration, text formatting,
|
||||
// and dealing with resulting data that is larger than the size of a page. That
|
||||
// last bit is especially important because it means that seq_file will never
|
||||
// return more than the size of a page in a single call to read().
|
||||
//
|
||||
// Unfortunately for a program like Chrome the size of /proc/self/maps is
|
||||
// larger than the size of page so we're forced to call read() multiple times.
|
||||
// If the virtual memory table changed in any way between calls to read() (e.g.,
|
||||
// a different thread calling mprotect()), it can make seq_file generate
|
||||
// duplicate entries or skip entries.
|
||||
//
|
||||
// Even if seq_file was changed to keep flushing the contents of its page-sized
|
||||
// buffer to the usermode buffer inside a single call to read(), it has to
|
||||
// release its lock on the virtual memory table to handle page faults while
|
||||
// copying data to usermode. This puts us in the same situation where the table
|
||||
// can change while we're copying data.
|
||||
//
|
||||
// Alternatives such as fork()-and-suspend-the-parent-while-child-reads were
|
||||
// attempted, but they present more subtle problems than it's worth. Depending
|
||||
// on your use case your best bet may be to read /proc/<pid>/maps prior to
|
||||
// starting other threads.
|
||||
//
|
||||
// [1] http://kernelnewbies.org/Documents/SeqFileHowTo
|
||||
PA_COMPONENT_EXPORT(PARTITION_ALLOC) bool ReadProcMaps(std::string* proc_maps);
|
||||
|
||||
// Parses /proc/<pid>/maps input data and stores in |regions|. Returns true
|
||||
// and updates |regions| if and only if all of |input| was successfully parsed.
|
||||
PA_COMPONENT_EXPORT(PARTITION_ALLOC)
|
||||
bool ParseProcMaps(const std::string& input,
|
||||
std::vector<MappedMemoryRegion>* regions);
|
||||
|
||||
} // namespace partition_alloc::internal::base::debug
|
||||
|
||||
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_
|
87
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/gtest_util.h
Normal file
87
base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/gtest_util.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_
|
||||
#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_
|
||||
|
||||
#include "partition_alloc/build_config.h"
|
||||
#include "partition_alloc/buildflags.h"
|
||||
#include "partition_alloc/partition_alloc_base/check.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
// EXPECT/ASSERT_DCHECK_DEATH is intended to replace EXPECT/ASSERT_DEBUG_DEATH
|
||||
// when the death is expected to be caused by a DCHECK. Contrary to
|
||||
// EXPECT/ASSERT_DEBUG_DEATH however, it doesn't execute the statement in non-
|
||||
// dcheck builds as DCHECKs are intended to catch things that should never
|
||||
// happen and as such executing the statement results in undefined behavior
|
||||
// (|statement| is compiled in unsupported configurations nonetheless).
|
||||
// DCHECK_IS_CONFIGURABLE is excluded from DCHECK_DEATH because it's non-FATAL
|
||||
// by default and there are no known tests that configure a FATAL level. If this
|
||||
// gets used from FATAL contexts under DCHECK_IS_CONFIGURABLE this may need to
|
||||
// be updated to look at LOGGING_DCHECK's current severity level.
|
||||
// Death tests misbehave on Android.
|
||||
#if PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) && \
|
||||
!PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID)
|
||||
|
||||
// EXPECT/ASSERT_DCHECK_DEATH tests verify that a DCHECK is hit ("Check failed"
|
||||
// is part of the error message). Optionally you may specify part of the message
|
||||
// to verify which DCHECK (or LOG(DFATAL)) is being hit.
|
||||
#define PA_EXPECT_DCHECK_DEATH(statement) \
|
||||
EXPECT_DEATH(statement, "Check failed")
|
||||
#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg)
|
||||
#define PA_ASSERT_DCHECK_DEATH(statement) \
|
||||
ASSERT_DEATH(statement, "Check failed")
|
||||
#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) ASSERT_DEATH(statement, msg)
|
||||
|
||||
#else
|
||||
|
||||
#define PA_EXPECT_DCHECK_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", )
|
||||
#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, )
|
||||
#define PA_ASSERT_DCHECK_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", return)
|
||||
#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, return)
|
||||
|
||||
#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) &&
|
||||
// !PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID)
|
||||
|
||||
// As above, but for CHECK().
|
||||
#if defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
|
||||
|
||||
#if PA_BASE_CHECK_WILL_STREAM()
|
||||
#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "Check failed")
|
||||
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg)
|
||||
#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "Check failed")
|
||||
#define PA_EXPECT_NOTREACHED_DEATH(statement) \
|
||||
EXPECT_DEATH(statement, "NOTREACHED hit")
|
||||
#define PA_ASSERT_NOTREACHED_DEATH(statement) \
|
||||
ASSERT_DEATH(statement, "NOTREACHED hit")
|
||||
#else
|
||||
#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "")
|
||||
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, "")
|
||||
#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "")
|
||||
#define PA_EXPECT_NOTREACHED_DEATH(statement) EXPECT_DEATH(statement, "")
|
||||
#define PA_ASSERT_NOTREACHED_DEATH(statement) ASSERT_DEATH(statement, "")
|
||||
#endif // PA_BASE_CHECK_WILL_STREAM()
|
||||
|
||||
#else // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
|
||||
|
||||
// Note GTEST_UNSUPPORTED_DEATH_TEST takes a |regex| only to see whether it is a
|
||||
// valid regex. It is never evaluated.
|
||||
#define PA_EXPECT_CHECK_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
|
||||
#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
|
||||
#define PA_ASSERT_CHECK_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return)
|
||||
#define PA_EXPECT_NOTREACHED_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", )
|
||||
#define PA_ASSERT_NOTREACHED_DEATH(statement) \
|
||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return)
|
||||
|
||||
#endif // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID)
|
||||
|
||||
#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
@ -16,8 +18,6 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "base/system/sys_info.h"
|
||||
#include "base/test/gtest_util.h"
|
||||
#include "partition_alloc/address_space_randomization.h"
|
||||
#include "partition_alloc/build_config.h"
|
||||
#include "partition_alloc/buildflags.h"
|
||||
@ -34,6 +34,8 @@
|
||||
#include "partition_alloc/partition_alloc_base/logging.h"
|
||||
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
|
||||
#include "partition_alloc/partition_alloc_base/rand_util.h"
|
||||
#include "partition_alloc/partition_alloc_base/system/sys_info.h"
|
||||
#include "partition_alloc/partition_alloc_base/test/gtest_util.h"
|
||||
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
|
||||
#include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h"
|
||||
#include "partition_alloc/partition_alloc_config.h"
|
||||
@ -80,6 +82,18 @@
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
// Headers for the AmountOfPhysicalMemory() function.
|
||||
#if PA_BUILDFLAG(IS_FUCHSIA)
|
||||
#include <zircon/syscalls.h>
|
||||
#elif PA_BUILDFLAG(IS_WIN)
|
||||
#include <windows.h>
|
||||
#elif PA_BUILDFLAG(IS_APPLE)
|
||||
#include <mach/host_info.h>
|
||||
#include <mach/mach.h>
|
||||
#elif PA_BUILDFLAG(IS_POSIX)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// In the MTE world, the upper bits of a pointer can be decorated with a tag,
|
||||
// thus allowing many versions of the same pointer to exist. These macros take
|
||||
// that into account when comparing.
|
||||
@ -88,10 +102,40 @@
|
||||
#define PA_EXPECT_PTR_NE(ptr1, ptr2) \
|
||||
{ EXPECT_NE(UntagPtr(ptr1), UntagPtr(ptr2)); }
|
||||
|
||||
#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
|
||||
|
||||
namespace {
|
||||
|
||||
// Best effort to get the amount of physical memory available to the system.
|
||||
// Returns 0 on failure.
|
||||
uint64_t AmountOfPhysicalMemory() {
|
||||
#if PA_BUILDFLAG(IS_FUCHSIA)
|
||||
return zx_system_get_physmem();
|
||||
#elif PA_BUILDFLAG(IS_WIN)
|
||||
MEMORYSTATUSEX mem_status = {.dwLength = sizeof(mem_status)};
|
||||
if (GlobalMemoryStatusEx(&mem_status)) {
|
||||
return mem_status.ullTotalPhys;
|
||||
}
|
||||
return 0;
|
||||
#elif PA_BUILDFLAG(IS_APPLE)
|
||||
struct host_basic_info host_basic_info;
|
||||
mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
|
||||
if (host_info(mach_host_self(), HOST_BASIC_INFO,
|
||||
reinterpret_cast<host_info_t>(&host_basic_info),
|
||||
&count) == KERN_SUCCESS) {
|
||||
return host_basic_info.max_mem;
|
||||
}
|
||||
return 0;
|
||||
#elif PA_BUILDFLAG(IS_POSIX)
|
||||
long pages = sysconf(_SC_PHYS_PAGES);
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if (pages >= 0 && page_size >= 0) {
|
||||
return static_cast<uint64_t>(pages) * static_cast<uint64_t>(page_size);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsLargeMemoryDevice() {
|
||||
// Treat any device with 4GiB or more of physical memory as a "large memory
|
||||
// device". We check for slightly less than GiB so that devices with a small
|
||||
@ -99,7 +143,7 @@ bool IsLargeMemoryDevice() {
|
||||
//
|
||||
// Set to 4GiB, since we have 2GiB Android devices where tests flakily fail
|
||||
// (e.g. Nexus 5X, crbug.com/1191195).
|
||||
return base::SysInfo::AmountOfPhysicalMemory() >= 4000ULL * 1024 * 1024;
|
||||
return AmountOfPhysicalMemory() >= 4000ULL * 1024 * 1024;
|
||||
}
|
||||
|
||||
bool SetAddressSpaceLimit() {
|
||||
@ -4805,7 +4849,7 @@ TEST_P(PartitionAllocDeathTest, ReleaseUnderflowRawPtr) {
|
||||
allocator.root()->InSlotMetadataPointerFromObjectForTesting(ptr);
|
||||
in_slot_metadata->Acquire();
|
||||
EXPECT_FALSE(in_slot_metadata->Release());
|
||||
EXPECT_DCHECK_DEATH(in_slot_metadata->Release());
|
||||
PA_EXPECT_DCHECK_DEATH(in_slot_metadata->Release());
|
||||
allocator.root()->Free(ptr);
|
||||
}
|
||||
|
||||
@ -4821,7 +4865,7 @@ TEST_P(PartitionAllocDeathTest, ReleaseUnderflowDanglingPtr) {
|
||||
allocator.root()->InSlotMetadataPointerFromObjectForTesting(ptr);
|
||||
in_slot_metadata->AcquireFromUnprotectedPtr();
|
||||
EXPECT_FALSE(in_slot_metadata->ReleaseFromUnprotectedPtr());
|
||||
EXPECT_DCHECK_DEATH(in_slot_metadata->ReleaseFromUnprotectedPtr());
|
||||
PA_EXPECT_DCHECK_DEATH(in_slot_metadata->ReleaseFromUnprotectedPtr());
|
||||
allocator.root()->Free(ptr);
|
||||
}
|
||||
|
||||
@ -5038,7 +5082,7 @@ TEST_P(PartitionAllocTest, FastPathOrReturnNull) {
|
||||
#if !defined(OFFICIAL_BUILD) || !defined(NDEBUG)
|
||||
|
||||
TEST_P(PartitionAllocDeathTest, CheckTriggered) {
|
||||
EXPECT_DCHECK_DEATH_WITH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
|
||||
PA_EXPECT_DCHECK_DEATH_WITH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
|
||||
EXPECT_DEATH(PA_CHECK(5 == 7), "Check failed.*5 == 7");
|
||||
}
|
||||
|
||||
@ -5689,28 +5733,30 @@ TEST_P(PartitionAllocTest, FastReclaim) {
|
||||
PurgeFlags::kDiscardUnusedSystemPages;
|
||||
allocator.root()->PurgeMemory(kFlags);
|
||||
ASSERT_GT(now, base::TimeTicks());
|
||||
// Here and below, using TS_UNCHECKED_READ since the root is not used
|
||||
// Here and below, using PA_TS_UNCHECKED_READ since the root is not used
|
||||
// conccurently.
|
||||
//
|
||||
// Went around all buckets.
|
||||
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
|
||||
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
0u);
|
||||
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Ran out of time.
|
||||
unsigned int next_bucket =
|
||||
TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
|
||||
PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
|
||||
EXPECT_NE(next_bucket, 0u);
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Make some progress, but not through all buckets yet.
|
||||
EXPECT_GT(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
EXPECT_GT(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
next_bucket);
|
||||
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Ran out of time.
|
||||
EXPECT_NE(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
|
||||
EXPECT_NE(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
0u);
|
||||
|
||||
// But eventually we make it through all buckets.
|
||||
while (TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index) != 0) {
|
||||
while (PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index) != 0) {
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
}
|
||||
// No expectation, test will time out if it's incorrect.
|
||||
@ -5730,33 +5776,36 @@ TEST_P(PartitionAllocTest, FastReclaimEventuallyLooksAtAllBuckets) {
|
||||
PurgeFlags::kDiscardUnusedSystemPages;
|
||||
allocator.root()->PurgeMemory(kFlags);
|
||||
ASSERT_GT(now, base::TimeTicks());
|
||||
// Here and below, using TS_UNCHECKED_READ since the root is not used
|
||||
// Here and below, using PA_TS_UNCHECKED_READ since the root is not used
|
||||
// conccurently.
|
||||
//
|
||||
// Went around all buckets, generation is incremented.
|
||||
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
|
||||
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
|
||||
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
0u);
|
||||
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
|
||||
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Ran out of time.
|
||||
unsigned int next_bucket =
|
||||
TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
|
||||
PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index);
|
||||
EXPECT_NE(next_bucket, 0u);
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Make some progress, but not through all buckets yet.
|
||||
EXPECT_GT(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
EXPECT_GT(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
next_bucket);
|
||||
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
|
||||
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_generation), 1u);
|
||||
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
// Ran out of time.
|
||||
EXPECT_NE(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
|
||||
EXPECT_NE(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
0u);
|
||||
|
||||
// But eventually we make it through all generations.
|
||||
while (TS_UNCHECKED_READ(allocator.root()->purge_generation) != 0) {
|
||||
while (PA_TS_UNCHECKED_READ(allocator.root()->purge_generation) != 0) {
|
||||
allocator.root()->PurgeMemory(kFlags | PurgeFlags::kLimitDuration);
|
||||
}
|
||||
EXPECT_EQ(TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index), 0u);
|
||||
EXPECT_EQ(PA_TS_UNCHECKED_READ(allocator.root()->purge_next_bucket_index),
|
||||
0u);
|
||||
|
||||
allocator.root()->now_maybe_overridden_for_testing = base::TimeTicks::Now;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ source_set("test_support") {
|
||||
deps = [
|
||||
":multi_process",
|
||||
"//base",
|
||||
"//base:partition_alloc_test_support",
|
||||
"//base/allocator/partition_allocator/src/partition_alloc:test_support",
|
||||
"//base/test:test_support",
|
||||
"//components/services/heap_profiling/public/cpp",
|
||||
"//content/public/browser",
|
||||
|
@ -233,7 +233,7 @@ test("gin_unittests") {
|
||||
if (use_partition_alloc) {
|
||||
sources += [ "v8_platform_page_allocator_unittest.cc" ]
|
||||
if (target_cpu == "arm64" && (is_linux || is_android)) {
|
||||
deps += [ "//base:arm_bti_testfunctions" ]
|
||||
deps += [ "//base/allocator/partition_allocator/src/partition_alloc:arm_bti_testfunctions" ]
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user