[PA/shim] Support sized-delete
This is a change to add support to C++'s sized deallocation inside Allocator Shim at Chrome. There is a planned change, https://crrev.com/c/6445033, to enable sized deallocation support on the compiler side. As current Shim does not export symbol with the extra size parameter, the information is just ignored. Such information can be useful in some scenarios and it would be great if Shim users can choose to utilize the size info. Therefore, this patch makes following changes: 1. Adds new dispatcher functions: - `free_with_size_function`: `free()` but with known size; this was existing on `IS_APPLE` platforms as `free_definite_size_function` but added to other platforms. - `free_with_alignment_function`: `free()` but with known alignment. - `free_with_size_and_alignment_function`: `free()` but with known size and alignment. 2. Adds implementations of the functions above to the existing shim dispatchers. 3. Exported C++ symbols for sized deallocation now routes free requests through the new dispatcher functions. See `allocator_shim_override_cpp_symbols.h` for details. 4. Expanded an unit-test for C++ operators. See `allocator_shim_unittest.cc` for details. 5. Adds `shim_supports_sized_dealloc` gn arg, which is disabled by default. 3 are gated behind this flag and this patch is no-op unless this flag is explicitly flipped. 1-2 are intentionally not gated so that dispatcher users does not need to pay attention to build configuration in use. The new dispatcher functions are just not called when disabled. Bug: 410190984, 410192659 Change-Id: I350fe94ce84a100ead22cb6eb9a557031fd57b29 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6442080 Reviewed-by: Francois Pierre Doray <fdoray@chromium.org> Reviewed-by: Takashi Sakamoto <tasak@google.com> Mega-CQ: Mikihito Matsuura <mikt@google.com> Commit-Queue: Mikihito Matsuura <mikt@google.com> Reviewed-by: Yuki Shiino <yukishiino@chromium.org> Reviewed-by: Paul Semel <paulsemel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1450497}
This commit is contained in:
base
allocator
dispatcher
partition_allocator
build_overrides
partition_alloc.gnisrc
partition_alloc
BUILD.gn
shim
allocator_dispatch.hallocator_shim_default_dispatch_to_apple_zoned_malloc.ccallocator_shim_default_dispatch_to_glibc.ccallocator_shim_default_dispatch_to_linker_wrapped_symbols.ccallocator_shim_default_dispatch_to_partition_alloc.ccallocator_shim_default_dispatch_to_partition_alloc.hallocator_shim_default_dispatch_to_partition_alloc_with_advanced_checks.ccallocator_shim_default_dispatch_to_winheap.ccallocator_shim_dispatch_to_noop_on_free.ccallocator_shim_override_apple_default_zone.hallocator_shim_override_apple_symbols.hallocator_shim_override_cpp_symbols.hallocator_shim_unittest.ccshim_alloc_functions.h
debug
build_overrides
components/gwp_asan/client
@ -195,6 +195,30 @@ struct DispatcherImpl {
|
|||||||
MUSTTAIL return allocator_dispatch_.next->free_function(address, context);
|
MUSTTAIL return allocator_dispatch_.next->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FreeWithSizeFn(void* address, size_t size, void* context) {
|
||||||
|
DoNotifyFreeForShim(address);
|
||||||
|
MUSTTAIL return allocator_dispatch_.next->free_with_size_function(
|
||||||
|
address, size, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeWithAlignmentFn(void* address,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
DoNotifyFreeForShim(address);
|
||||||
|
MUSTTAIL return allocator_dispatch_.next->free_with_alignment_function(
|
||||||
|
address, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
DoNotifyFreeForShim(address);
|
||||||
|
MUSTTAIL return allocator_dispatch_.next
|
||||||
|
->free_with_size_and_alignment_function(address, size, alignment,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned BatchMallocFn(size_t size,
|
static unsigned BatchMallocFn(size_t size,
|
||||||
void** results,
|
void** results,
|
||||||
unsigned num_requested,
|
unsigned num_requested,
|
||||||
@ -219,12 +243,6 @@ struct DispatcherImpl {
|
|||||||
to_be_freed, num_to_be_freed, context);
|
to_be_freed, num_to_be_freed, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FreeDefiniteSizeFn(void* address, size_t size, void* context) {
|
|
||||||
DoNotifyFreeForShim(address);
|
|
||||||
MUSTTAIL return allocator_dispatch_.next->free_definite_size_function(
|
|
||||||
address, size, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TryFreeDefaultFn(void* address, void* context) {
|
static void TryFreeDefaultFn(void* address, void* context) {
|
||||||
DoNotifyFreeForShim(address);
|
DoNotifyFreeForShim(address);
|
||||||
MUSTTAIL return allocator_dispatch_.next->try_free_default_function(
|
MUSTTAIL return allocator_dispatch_.next->try_free_default_function(
|
||||||
@ -324,26 +342,28 @@ std::tuple<ObserverTypes*...> DispatcherImpl<ObserverTypes...>::s_observers;
|
|||||||
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
|
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
|
||||||
template <typename... ObserverTypes>
|
template <typename... ObserverTypes>
|
||||||
AllocatorDispatch DispatcherImpl<ObserverTypes...>::allocator_dispatch_ = {
|
AllocatorDispatch DispatcherImpl<ObserverTypes...>::allocator_dispatch_ = {
|
||||||
AllocFn, // alloc_function
|
AllocFn, // alloc_function
|
||||||
AllocUncheckedFn, // alloc_unchecked_function
|
AllocUncheckedFn, // alloc_unchecked_function
|
||||||
AllocZeroInitializedFn, // alloc_zero_initialized_function
|
AllocZeroInitializedFn, // alloc_zero_initialized_function
|
||||||
AllocAlignedFn, // alloc_aligned_function
|
AllocAlignedFn, // alloc_aligned_function
|
||||||
ReallocFn, // realloc_function
|
ReallocFn, // realloc_function
|
||||||
ReallocUncheckedFn, // realloc_unchecked_function
|
ReallocUncheckedFn, // realloc_unchecked_function
|
||||||
FreeFn, // free_function
|
FreeFn, // free_function
|
||||||
nullptr, // get_size_estimate_function
|
FreeWithSizeFn, // free_with_size_function
|
||||||
nullptr, // good_size_function
|
FreeWithAlignmentFn, // free_with_alignment_function
|
||||||
nullptr, // claimed_address_function
|
FreeWithSizeAndAlignmentFn, // free_with_size_and_alignment_function
|
||||||
BatchMallocFn, // batch_malloc_function
|
nullptr, // get_size_estimate_function
|
||||||
BatchFreeFn, // batch_free_function
|
nullptr, // good_size_function
|
||||||
FreeDefiniteSizeFn, // free_definite_size_function
|
nullptr, // claimed_address_function
|
||||||
TryFreeDefaultFn, // try_free_default_function
|
BatchMallocFn, // batch_malloc_function
|
||||||
AlignedMallocFn, // aligned_malloc_function
|
BatchFreeFn, // batch_free_function
|
||||||
AlignedMallocUncheckedFn, // aligned_malloc_unchecked_function
|
TryFreeDefaultFn, // try_free_default_function
|
||||||
AlignedReallocFn, // aligned_realloc_function
|
AlignedMallocFn, // aligned_malloc_function
|
||||||
AlignedReallocUncheckedFn, // aligned_realloc_unchecked_function
|
AlignedMallocUncheckedFn, // aligned_malloc_unchecked_function
|
||||||
AlignedFreeFn, // aligned_free_function
|
AlignedReallocFn, // aligned_realloc_function
|
||||||
nullptr // next
|
AlignedReallocUncheckedFn, // aligned_realloc_unchecked_function
|
||||||
|
AlignedFreeFn, // aligned_free_function
|
||||||
|
nullptr // next
|
||||||
};
|
};
|
||||||
#endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
|
#endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
|
||||||
|
|
||||||
|
@ -146,12 +146,14 @@ struct AllocationEventDispatcherInternalTest : public DispatcherTest {
|
|||||||
&realloc_function,
|
&realloc_function,
|
||||||
&realloc_unchecked_function,
|
&realloc_unchecked_function,
|
||||||
[](void*, void*) {},
|
[](void*, void*) {},
|
||||||
|
[](void*, size_t, void*) {},
|
||||||
|
[](void*, size_t, void*) {},
|
||||||
|
[](void*, size_t, size_t, void*) {},
|
||||||
&get_size_estimate_function,
|
&get_size_estimate_function,
|
||||||
&good_size_function,
|
&good_size_function,
|
||||||
&claimed_address_function,
|
&claimed_address_function,
|
||||||
&batch_malloc_function,
|
&batch_malloc_function,
|
||||||
[](void**, unsigned, void*) {},
|
[](void**, unsigned, void*) {},
|
||||||
[](void*, size_t, void*) {},
|
|
||||||
[](void*, void*) {},
|
[](void*, void*) {},
|
||||||
&aligned_malloc_function,
|
&aligned_malloc_function,
|
||||||
&aligned_malloc_unchecked_function,
|
&aligned_malloc_unchecked_function,
|
||||||
@ -259,7 +261,7 @@ TEST_F(AllocationEventDispatcherInternalTest, VerifyAllocatorShimDataIsSet) {
|
|||||||
EXPECT_NE(nullptr, allocator_dispatch->free_function);
|
EXPECT_NE(nullptr, allocator_dispatch->free_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->batch_malloc_function);
|
EXPECT_NE(nullptr, allocator_dispatch->batch_malloc_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->batch_free_function);
|
EXPECT_NE(nullptr, allocator_dispatch->batch_free_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->free_definite_size_function);
|
EXPECT_NE(nullptr, allocator_dispatch->free_with_size_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->try_free_default_function);
|
EXPECT_NE(nullptr, allocator_dispatch->try_free_default_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_function);
|
EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_function);
|
||||||
EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_unchecked_function);
|
EXPECT_NE(nullptr, allocator_dispatch->aligned_malloc_unchecked_function);
|
||||||
@ -515,7 +517,7 @@ TEST_F(AllocationEventDispatcherInternalTest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AllocationEventDispatcherInternalTest,
|
TEST_F(AllocationEventDispatcherInternalTest,
|
||||||
VerifyAllocatorShimHooksTriggerCorrectly_free_definite_size_function) {
|
VerifyAllocatorShimHooksTriggerCorrectly_free_with_size_function) {
|
||||||
std::array<ObserverMock, kMaximumNumberOfObservers> observers;
|
std::array<ObserverMock, kMaximumNumberOfObservers> observers;
|
||||||
|
|
||||||
for (auto& mock : observers) {
|
for (auto& mock : observers) {
|
||||||
@ -530,12 +532,12 @@ TEST_F(AllocationEventDispatcherInternalTest,
|
|||||||
GetNotificationHooks(CreateTupleOfPointers(observers));
|
GetNotificationHooks(CreateTupleOfPointers(observers));
|
||||||
|
|
||||||
auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
|
auto* const allocator_dispatch = dispatch_data.GetAllocatorDispatch();
|
||||||
EXPECT_NE(allocator_dispatch->free_definite_size_function, nullptr);
|
EXPECT_NE(allocator_dispatch->free_with_size_function, nullptr);
|
||||||
|
|
||||||
allocator_dispatch->next = GetNextAllocatorDispatch();
|
allocator_dispatch->next = GetNextAllocatorDispatch();
|
||||||
|
|
||||||
allocator_dispatch->free_definite_size_function(GetAllocatedAddress(),
|
allocator_dispatch->free_with_size_function(GetAllocatedAddress(),
|
||||||
GetAllocatedSize(), nullptr);
|
GetAllocatedSize(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AllocationEventDispatcherInternalTest,
|
TEST_F(AllocationEventDispatcherInternalTest,
|
||||||
|
@ -12,6 +12,7 @@ build_with_chromium = false
|
|||||||
# configuration.
|
# configuration.
|
||||||
use_partition_alloc_as_malloc_default = false
|
use_partition_alloc_as_malloc_default = false
|
||||||
use_allocator_shim_default = false
|
use_allocator_shim_default = false
|
||||||
|
shim_supports_sized_dealloc_default = false
|
||||||
enable_backup_ref_ptr_support_default = false
|
enable_backup_ref_ptr_support_default = false
|
||||||
enable_backup_ref_ptr_slow_checks_default = false
|
enable_backup_ref_ptr_slow_checks_default = false
|
||||||
enable_dangling_raw_ptr_checks_default = false
|
enable_dangling_raw_ptr_checks_default = false
|
||||||
|
@ -142,6 +142,9 @@ declare_args() {
|
|||||||
# calls to PartitionAlloc, rather than some other platform allocator.
|
# 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 = use_partition_alloc && use_allocator_shim &&
|
||||||
use_partition_alloc_as_malloc_default
|
use_partition_alloc_as_malloc_default
|
||||||
|
|
||||||
|
shim_supports_sized_dealloc =
|
||||||
|
use_allocator_shim && shim_supports_sized_dealloc_default
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_args() {
|
declare_args() {
|
||||||
|
@ -183,6 +183,7 @@ pa_buildflag_header("buildflags") {
|
|||||||
"RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move",
|
"RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move",
|
||||||
"REALLOC_GROWTH_FACTOR_MITIGATION=$partition_alloc_realloc_growth_factor_mitigation",
|
"REALLOC_GROWTH_FACTOR_MITIGATION=$partition_alloc_realloc_growth_factor_mitigation",
|
||||||
"RECORD_ALLOC_INFO=$record_alloc_info",
|
"RECORD_ALLOC_INFO=$record_alloc_info",
|
||||||
|
"SHIM_SUPPORTS_SIZED_DEALLOC=$shim_supports_sized_dealloc",
|
||||||
"SMALLER_PARTITION_COOKIE=$smaller_partition_cookie",
|
"SMALLER_PARTITION_COOKIE=$smaller_partition_cookie",
|
||||||
"STACK_SCAN_SUPPORTED=$stack_scan_supported",
|
"STACK_SCAN_SUPPORTED=$stack_scan_supported",
|
||||||
"USE_ALLOCATOR_SHIM=$use_allocator_shim",
|
"USE_ALLOCATOR_SHIM=$use_allocator_shim",
|
||||||
|
@ -31,7 +31,12 @@ struct AllocatorDispatch {
|
|||||||
using BatchFreeFn = void(void** to_be_freed,
|
using BatchFreeFn = void(void** to_be_freed,
|
||||||
unsigned num_to_be_freed,
|
unsigned num_to_be_freed,
|
||||||
void* context);
|
void* context);
|
||||||
using FreeDefiniteSizeFn = void(void* ptr, size_t size, void* context);
|
using FreeWithSizeFn = void(void* ptr, size_t size, void* context);
|
||||||
|
using FreeWithAlignmentFn = void(void* ptr, size_t alignment, void* context);
|
||||||
|
using FreeWithSizeAndAlignmentFn = void(void* ptr,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context);
|
||||||
using TryFreeDefaultFn = void(void* ptr, void* context);
|
using TryFreeDefaultFn = void(void* ptr, void* context);
|
||||||
using AlignedMallocFn = void*(size_t size, size_t alignment, void* context);
|
using AlignedMallocFn = void*(size_t size, size_t alignment, void* context);
|
||||||
using AlignedMallocUncheckedFn = void*(size_t size,
|
using AlignedMallocUncheckedFn = void*(size_t size,
|
||||||
@ -54,14 +59,16 @@ struct AllocatorDispatch {
|
|||||||
ReallocFn* realloc_function;
|
ReallocFn* realloc_function;
|
||||||
ReallocUncheckedFn* realloc_unchecked_function;
|
ReallocUncheckedFn* realloc_unchecked_function;
|
||||||
FreeFn* free_function;
|
FreeFn* free_function;
|
||||||
|
FreeWithSizeFn* free_with_size_function;
|
||||||
|
FreeWithAlignmentFn* free_with_alignment_function;
|
||||||
|
FreeWithSizeAndAlignmentFn* free_with_size_and_alignment_function;
|
||||||
GetSizeEstimateFn* get_size_estimate_function;
|
GetSizeEstimateFn* get_size_estimate_function;
|
||||||
GoodSizeFn* good_size_function;
|
GoodSizeFn* good_size_function;
|
||||||
// claimed_address, batch_malloc, batch_free, free_definite_size and
|
// claimed_address, batch_malloc, batch_free and
|
||||||
// try_free_default are specific to the OSX and iOS allocators.
|
// try_free_default are specific to the OSX and iOS allocators.
|
||||||
ClaimedAddressFn* claimed_address_function;
|
ClaimedAddressFn* claimed_address_function;
|
||||||
BatchMallocFn* batch_malloc_function;
|
BatchMallocFn* batch_malloc_function;
|
||||||
BatchFreeFn* batch_free_function;
|
BatchFreeFn* batch_free_function;
|
||||||
FreeDefiniteSizeFn* free_definite_size_function;
|
|
||||||
TryFreeDefaultFn* try_free_default_function;
|
TryFreeDefaultFn* try_free_default_function;
|
||||||
// _aligned_malloc, _aligned_realloc, and _aligned_free are specific to the
|
// _aligned_malloc, _aligned_realloc, and _aligned_free are specific to the
|
||||||
// Windows allocator.
|
// Windows allocator.
|
||||||
@ -125,12 +132,14 @@ struct AllocatorDispatch {
|
|||||||
COPY_IF_NULLPTR(realloc_function);
|
COPY_IF_NULLPTR(realloc_function);
|
||||||
COPY_IF_NULLPTR(realloc_unchecked_function);
|
COPY_IF_NULLPTR(realloc_unchecked_function);
|
||||||
COPY_IF_NULLPTR(free_function);
|
COPY_IF_NULLPTR(free_function);
|
||||||
|
COPY_IF_NULLPTR(free_with_size_function);
|
||||||
|
COPY_IF_NULLPTR(free_with_alignment_function);
|
||||||
|
COPY_IF_NULLPTR(free_with_size_and_alignment_function);
|
||||||
COPY_IF_NULLPTR(get_size_estimate_function);
|
COPY_IF_NULLPTR(get_size_estimate_function);
|
||||||
COPY_IF_NULLPTR(good_size_function);
|
COPY_IF_NULLPTR(good_size_function);
|
||||||
COPY_IF_NULLPTR(claimed_address_function);
|
COPY_IF_NULLPTR(claimed_address_function);
|
||||||
COPY_IF_NULLPTR(batch_malloc_function);
|
COPY_IF_NULLPTR(batch_malloc_function);
|
||||||
COPY_IF_NULLPTR(batch_free_function);
|
COPY_IF_NULLPTR(batch_free_function);
|
||||||
COPY_IF_NULLPTR(free_definite_size_function);
|
|
||||||
COPY_IF_NULLPTR(try_free_default_function);
|
COPY_IF_NULLPTR(try_free_default_function);
|
||||||
COPY_IF_NULLPTR(aligned_malloc_function);
|
COPY_IF_NULLPTR(aligned_malloc_function);
|
||||||
COPY_IF_NULLPTR(aligned_malloc_unchecked_function);
|
COPY_IF_NULLPTR(aligned_malloc_unchecked_function);
|
||||||
|
@ -40,6 +40,26 @@ void FreeImpl(void* ptr, void* context) {
|
|||||||
functions.free(reinterpret_cast<struct _malloc_zone_t*>(context), ptr);
|
functions.free(reinterpret_cast<struct _malloc_zone_t*>(context), ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeImpl(void* ptr, size_t size, void* context) {
|
||||||
|
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
||||||
|
functions.free_definite_size(
|
||||||
|
reinterpret_cast<struct _malloc_zone_t*>(context), ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithAlignmentImpl(void* ptr, size_t, void* context) {
|
||||||
|
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
||||||
|
functions.free(reinterpret_cast<struct _malloc_zone_t*>(context), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeAndAlignmentImpl(void* ptr,
|
||||||
|
size_t size,
|
||||||
|
size_t,
|
||||||
|
void* context) {
|
||||||
|
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
||||||
|
functions.free_definite_size(
|
||||||
|
reinterpret_cast<struct _malloc_zone_t*>(context), ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetSizeEstimateImpl(void* ptr, void* context) {
|
size_t GetSizeEstimateImpl(void* ptr, void* context) {
|
||||||
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
||||||
return functions.size(reinterpret_cast<struct _malloc_zone_t*>(context), ptr);
|
return functions.size(reinterpret_cast<struct _malloc_zone_t*>(context), ptr);
|
||||||
@ -84,12 +104,6 @@ void BatchFreeImpl(void** to_be_freed,
|
|||||||
to_be_freed, num_to_be_freed);
|
to_be_freed, num_to_be_freed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeDefiniteSizeImpl(void* ptr, size_t size, void* context) {
|
|
||||||
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
|
||||||
functions.free_definite_size(
|
|
||||||
reinterpret_cast<struct _malloc_zone_t*>(context), ptr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TryFreeDefaultImpl(void* ptr, void* context) {
|
void TryFreeDefaultImpl(void* ptr, void* context) {
|
||||||
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
MallocZoneFunctions& functions = GetFunctionsForZone(context);
|
||||||
if (functions.try_free_default) {
|
if (functions.try_free_default) {
|
||||||
@ -102,26 +116,28 @@ void TryFreeDefaultImpl(void* ptr, void* context) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
||||||
&MallocImpl, /* alloc_function */
|
&MallocImpl, /* alloc_function */
|
||||||
&MallocImpl, /* alloc_unchecked_function */
|
&MallocImpl, /* alloc_unchecked_function */
|
||||||
&CallocImpl, /* alloc_zero_initialized_function */
|
&CallocImpl, /* alloc_zero_initialized_function */
|
||||||
&MemalignImpl, /* alloc_aligned_function */
|
&MemalignImpl, /* alloc_aligned_function */
|
||||||
&ReallocImpl, /* realloc_function */
|
&ReallocImpl, /* realloc_function */
|
||||||
&ReallocImpl, /* realloc_unchecked_function */
|
&ReallocImpl, /* realloc_unchecked_function */
|
||||||
&FreeImpl, /* free_function */
|
&FreeImpl, /* free_function */
|
||||||
&GetSizeEstimateImpl, /* get_size_estimate_function */
|
&FreeWithSizeImpl, /* free_with_size_function */
|
||||||
&GoodSizeImpl, /* good_size_function */
|
&FreeWithAlignmentImpl, /* free_with_size_function */
|
||||||
&ClaimedAddressImpl, /* claimed_address_function */
|
&FreeWithSizeAndAlignmentImpl, /* free_with_size_function */
|
||||||
&BatchMallocImpl, /* batch_malloc_function */
|
&GetSizeEstimateImpl, /* get_size_estimate_function */
|
||||||
&BatchFreeImpl, /* batch_free_function */
|
&GoodSizeImpl, /* good_size_function */
|
||||||
&FreeDefiniteSizeImpl, /* free_definite_size_function */
|
&ClaimedAddressImpl, /* claimed_address_function */
|
||||||
&TryFreeDefaultImpl, /* try_free_default_function */
|
&BatchMallocImpl, /* batch_malloc_function */
|
||||||
nullptr, /* aligned_malloc_function */
|
&BatchFreeImpl, /* batch_free_function */
|
||||||
nullptr, /* aligned_malloc_unchecked_function */
|
&TryFreeDefaultImpl, /* try_free_default_function */
|
||||||
nullptr, /* aligned_realloc_function */
|
nullptr, /* aligned_malloc_function */
|
||||||
nullptr, /* aligned_realloc_unchecked_function */
|
nullptr, /* aligned_malloc_unchecked_function */
|
||||||
nullptr, /* aligned_free_function */
|
nullptr, /* aligned_realloc_function */
|
||||||
nullptr, /* next */
|
nullptr, /* aligned_realloc_unchecked_function */
|
||||||
|
nullptr, /* aligned_free_function */
|
||||||
|
nullptr, /* next */
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace allocator_shim
|
} // namespace allocator_shim
|
||||||
|
@ -88,6 +88,21 @@ void GlibcFree(void* address, void* context) {
|
|||||||
__libc_free(address);
|
__libc_free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlibcFreeWithSize(void* address, size_t, void* context) {
|
||||||
|
__libc_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlibcFreeWithAlignment(void* address, size_t, void* context) {
|
||||||
|
__libc_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlibcFreeWithSizeAndAlignment(void* address,
|
||||||
|
size_t,
|
||||||
|
size_t,
|
||||||
|
void* context) {
|
||||||
|
__libc_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
PA_NO_SANITIZE("cfi-icall")
|
PA_NO_SANITIZE("cfi-icall")
|
||||||
size_t GlibcGetSizeEstimate(void* address, void* context) {
|
size_t GlibcGetSizeEstimate(void* address, void* context) {
|
||||||
// glibc does not expose an alias to resolve malloc_usable_size. Dynamically
|
// glibc does not expose an alias to resolve malloc_usable_size. Dynamically
|
||||||
@ -112,17 +127,21 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
|||||||
&GlibcRealloc, /* realloc_function */
|
&GlibcRealloc, /* realloc_function */
|
||||||
&GlibcUncheckedRealloc, /* realloc_unchecked_function */
|
&GlibcUncheckedRealloc, /* realloc_unchecked_function */
|
||||||
&GlibcFree, /* free_function */
|
&GlibcFree, /* free_function */
|
||||||
&GlibcGetSizeEstimate, /* get_size_estimate_function */
|
GlibcFreeWithSize, /* free_with_size_function */
|
||||||
nullptr, /* good_size_function */
|
GlibcFreeWithAlignment,
|
||||||
nullptr, /* claimed_address */
|
/* free_with_alignment_function */
|
||||||
nullptr, /* batch_malloc_function */
|
GlibcFreeWithSizeAndAlignment,
|
||||||
nullptr, /* batch_free_function */
|
/* free_with_size_and_alignment_function */
|
||||||
nullptr, /* free_definite_size_function */
|
&GlibcGetSizeEstimate, /* get_size_estimate_function */
|
||||||
nullptr, /* try_free_default_function */
|
nullptr, /* good_size_function */
|
||||||
nullptr, /* aligned_malloc_function */
|
nullptr, /* claimed_address */
|
||||||
nullptr, /* aligned_malloc_unchecked_function */
|
nullptr, /* batch_malloc_function */
|
||||||
nullptr, /* aligned_realloc_function */
|
nullptr, /* batch_free_function */
|
||||||
nullptr, /* aligned_realloc_unchecked_function */
|
nullptr, /* try_free_default_function */
|
||||||
nullptr, /* aligned_free_function */
|
nullptr, /* aligned_malloc_function */
|
||||||
nullptr, /* next */
|
nullptr, /* aligned_malloc_unchecked_function */
|
||||||
|
nullptr, /* aligned_realloc_function */
|
||||||
|
nullptr, /* aligned_realloc_unchecked_function */
|
||||||
|
nullptr, /* aligned_free_function */
|
||||||
|
nullptr, /* next */
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,21 @@ void RealFree(void* address, void* context) {
|
|||||||
__real_free(address);
|
__real_free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealFreeWithSize(void* address, size_t, void* context) {
|
||||||
|
__real_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RealFreeWithAlignment(void* address, size_t, void* context) {
|
||||||
|
__real_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RealFreeWithSizeAndAlignment(void* address,
|
||||||
|
size_t,
|
||||||
|
size_t,
|
||||||
|
void* context) {
|
||||||
|
__real_free(address);
|
||||||
|
}
|
||||||
|
|
||||||
size_t RealSizeEstimate(void* address, void* context) {
|
size_t RealSizeEstimate(void* address, void* context) {
|
||||||
return __real_malloc_usable_size(address);
|
return __real_malloc_usable_size(address);
|
||||||
}
|
}
|
||||||
@ -56,24 +71,26 @@ size_t RealSizeEstimate(void* address, void* context) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
||||||
&RealMalloc, /* alloc_function */
|
&RealMalloc, /* alloc_function */
|
||||||
&RealMalloc, /* alloc_unchecked_function */
|
&RealMalloc, /* alloc_unchecked_function */
|
||||||
&RealCalloc, /* alloc_zero_initialized_function */
|
&RealCalloc, /* alloc_zero_initialized_function */
|
||||||
&RealMemalign, /* alloc_aligned_function */
|
&RealMemalign, /* alloc_aligned_function */
|
||||||
&RealRealloc, /* realloc_function */
|
&RealRealloc, /* realloc_function */
|
||||||
&RealRealloc, /* realloc_unchecked_function */
|
&RealRealloc, /* realloc_unchecked_function */
|
||||||
&RealFree, /* free_function */
|
&RealFree, /* free_function */
|
||||||
&RealSizeEstimate, /* get_size_estimate_function */
|
&RealFreeWithSize, /* free_with_size_function */
|
||||||
nullptr, /* good_size_function */
|
&RealFreeWithAlignment, /* free_with_alignment_function */
|
||||||
nullptr, /* claimed_address */
|
&RealFreeWithSizeAndAlignment, /* free_with_size_and_alignment_function */
|
||||||
nullptr, /* batch_malloc_function */
|
&RealSizeEstimate, /* get_size_estimate_function */
|
||||||
nullptr, /* batch_free_function */
|
nullptr, /* good_size_function */
|
||||||
nullptr, /* free_definite_size_function */
|
nullptr, /* claimed_address */
|
||||||
nullptr, /* try_free_default_function */
|
nullptr, /* batch_malloc_function */
|
||||||
nullptr, /* aligned_malloc_function */
|
nullptr, /* batch_free_function */
|
||||||
nullptr, /* aligned_malloc_unchecked_function */
|
nullptr, /* try_free_default_function */
|
||||||
nullptr, /* aligned_realloc_function */
|
nullptr, /* aligned_malloc_function */
|
||||||
nullptr, /* aligned_realloc_unchecked_function */
|
nullptr, /* aligned_malloc_unchecked_function */
|
||||||
nullptr, /* aligned_free_function */
|
nullptr, /* aligned_realloc_function */
|
||||||
nullptr, /* next */
|
nullptr, /* aligned_realloc_unchecked_function */
|
||||||
|
nullptr, /* aligned_free_function */
|
||||||
|
nullptr, /* next */
|
||||||
};
|
};
|
||||||
|
@ -435,25 +435,46 @@ PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::Free(
|
|||||||
object);
|
object);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_BUILDFLAG(IS_APPLE)
|
|
||||||
// Normal free() path on Apple OSes:
|
|
||||||
// 1. size = GetSizeEstimate(ptr);
|
|
||||||
// 2. if (size) FreeDefiniteSize(ptr, size)
|
|
||||||
//
|
|
||||||
// So we don't need to re-check that the pointer is owned in Free(), and we
|
|
||||||
// can use the size.
|
|
||||||
// static
|
// static
|
||||||
template <partition_alloc::AllocFlags base_alloc_flags,
|
template <partition_alloc::AllocFlags base_alloc_flags,
|
||||||
partition_alloc::FreeFlags base_free_flags>
|
partition_alloc::FreeFlags base_free_flags>
|
||||||
void PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::
|
PA_ALWAYS_INLINE void
|
||||||
FreeDefiniteSize(void* address, size_t size, void* context) {
|
PartitionAllocFunctionsInternal<base_alloc_flags,
|
||||||
partition_alloc::ScopedDisallowAllocations guard{};
|
base_free_flags>::FreeWithSize(void* object,
|
||||||
|
size_t size,
|
||||||
|
void* context) {
|
||||||
// TODO(lizeb): Optimize PartitionAlloc to use the size information. This is
|
// TODO(lizeb): Optimize PartitionAlloc to use the size information. This is
|
||||||
// still useful though, as we avoid double-checking that the address is owned.
|
// still useful though, as we avoid double-checking that the address is owned.
|
||||||
partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<base_free_flags>(
|
PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::Free(
|
||||||
address);
|
object, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
template <partition_alloc::AllocFlags base_alloc_flags,
|
||||||
|
partition_alloc::FreeFlags base_free_flags>
|
||||||
|
PA_ALWAYS_INLINE void
|
||||||
|
PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::
|
||||||
|
FreeWithAlignment(void* object, size_t alignment, void* context) {
|
||||||
|
// TODO(lizeb): Optimize PartitionAlloc to use the size information. This is
|
||||||
|
// still useful though, as we avoid double-checking that the address is owned.
|
||||||
|
PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::Free(
|
||||||
|
object, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
template <partition_alloc::AllocFlags base_alloc_flags,
|
||||||
|
partition_alloc::FreeFlags base_free_flags>
|
||||||
|
PA_ALWAYS_INLINE void PartitionAllocFunctionsInternal<
|
||||||
|
base_alloc_flags,
|
||||||
|
base_free_flags>::FreeWithSizeAndAlignment(void* object,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
// TODO(lizeb): Optimize PartitionAlloc to use the size information. This is
|
||||||
|
// still useful though, as we avoid double-checking that the address is owned.
|
||||||
|
PartitionAllocFunctionsInternal<base_alloc_flags, base_free_flags>::Free(
|
||||||
|
object, context);
|
||||||
}
|
}
|
||||||
#endif // PA_BUILDFLAG(IS_APPLE)
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
template <partition_alloc::AllocFlags base_alloc_flags,
|
template <partition_alloc::AllocFlags base_alloc_flags,
|
||||||
|
@ -62,9 +62,14 @@ class PartitionAllocFunctionsInternal {
|
|||||||
|
|
||||||
static void Free(void* object, void* context);
|
static void Free(void* object, void* context);
|
||||||
|
|
||||||
#if PA_BUILDFLAG(IS_APPLE)
|
static void FreeWithSize(void* object, size_t size, void* context);
|
||||||
static void FreeDefiniteSize(void* address, size_t size, void* context);
|
|
||||||
#endif // PA_BUILDFLAG(IS_APPLE)
|
static void FreeWithAlignment(void* object, size_t alignment, void* context);
|
||||||
|
|
||||||
|
static void FreeWithSizeAndAlignment(void* object,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context);
|
||||||
|
|
||||||
static size_t GetSizeEstimate(void* address, void* context);
|
static size_t GetSizeEstimate(void* address, void* context);
|
||||||
|
|
||||||
@ -89,14 +94,17 @@ class PartitionAllocFunctionsInternal {
|
|||||||
|
|
||||||
static constexpr AllocatorDispatch MakeDispatch() {
|
static constexpr AllocatorDispatch MakeDispatch() {
|
||||||
return {
|
return {
|
||||||
&Malloc, // alloc_function
|
&Malloc, // alloc_function
|
||||||
&MallocUnchecked, // alloc_unchecked_function
|
&MallocUnchecked, // alloc_unchecked_function
|
||||||
&Calloc, // alloc_zero_initialized_function
|
&Calloc, // alloc_zero_initialized_function
|
||||||
&Memalign, // alloc_aligned_function
|
&Memalign, // alloc_aligned_function
|
||||||
&Realloc, // realloc_function
|
&Realloc, // realloc_function
|
||||||
&ReallocUnchecked, // realloc_unchecked_function
|
&ReallocUnchecked, // realloc_unchecked_function
|
||||||
&Free, // free_function
|
&Free, // free_function
|
||||||
&GetSizeEstimate, // get_size_estimate_function
|
&FreeWithSize, // free_with_size_function
|
||||||
|
&FreeWithAlignment, // free_with_alignment_function
|
||||||
|
&FreeWithSizeAndAlignment, // free_with_size_and_alignment_function
|
||||||
|
&GetSizeEstimate, // get_size_estimate_function
|
||||||
#if PA_BUILDFLAG(IS_APPLE)
|
#if PA_BUILDFLAG(IS_APPLE)
|
||||||
&GoodSize, // good_size
|
&GoodSize, // good_size
|
||||||
&ClaimedAddress, // claimed_address
|
&ClaimedAddress, // claimed_address
|
||||||
@ -107,15 +115,10 @@ class PartitionAllocFunctionsInternal {
|
|||||||
&BatchMalloc, // batch_malloc_function
|
&BatchMalloc, // batch_malloc_function
|
||||||
&BatchFree, // batch_free_function
|
&BatchFree, // batch_free_function
|
||||||
#if PA_BUILDFLAG(IS_APPLE)
|
#if PA_BUILDFLAG(IS_APPLE)
|
||||||
// On Apple OSes, free_definite_size() is always called from free(),
|
|
||||||
// since get_size_estimate() is used to determine whether an allocation
|
|
||||||
// belongs to the current zone. It makes sense to optimize for it.
|
|
||||||
&FreeDefiniteSize,
|
|
||||||
// On Apple OSes, try_free_default() is sometimes called as an
|
// On Apple OSes, try_free_default() is sometimes called as an
|
||||||
// optimization of free().
|
// optimization of free().
|
||||||
&TryFreeDefault,
|
&TryFreeDefault,
|
||||||
#else
|
#else
|
||||||
nullptr, // free_definite_size_function
|
|
||||||
nullptr, // try_free_default_function
|
nullptr, // try_free_default_function
|
||||||
#endif
|
#endif
|
||||||
&AlignedAlloc, // aligned_malloc_function
|
&AlignedAlloc, // aligned_malloc_function
|
||||||
|
@ -58,6 +58,28 @@ void DelegatedFreeFn(void* address, void* context) {
|
|||||||
PA_MUSTTAIL return delegate->free_function(address, context);
|
PA_MUSTTAIL return delegate->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DelegatedFreeWithSizeFn(void* address, size_t size, void* context) {
|
||||||
|
const AllocatorDispatch* delegate = GetDelegate();
|
||||||
|
PA_MUSTTAIL return delegate->free_with_size_function(address, size, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelegatedFreeWithAlignmentFn(void* address,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
const AllocatorDispatch* delegate = GetDelegate();
|
||||||
|
PA_MUSTTAIL return delegate->free_with_alignment_function(address, alignment,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelegatedFreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
const AllocatorDispatch* delegate = GetDelegate();
|
||||||
|
PA_MUSTTAIL return delegate->free_with_size_and_alignment_function(
|
||||||
|
address, size, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
size_t DelegatedGetSizeEstimateFn(void* address, void* context) {
|
size_t DelegatedGetSizeEstimateFn(void* address, void* context) {
|
||||||
const AllocatorDispatch* delegate = GetDelegate();
|
const AllocatorDispatch* delegate = GetDelegate();
|
||||||
PA_MUSTTAIL return delegate->get_size_estimate_function(address, context);
|
PA_MUSTTAIL return delegate->get_size_estimate_function(address, context);
|
||||||
@ -90,12 +112,6 @@ void DelegatedBatchFreeFn(void** to_be_freed,
|
|||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelegatedFreeDefiniteSizeFn(void* address, size_t size, void* context) {
|
|
||||||
const AllocatorDispatch* delegate = GetDelegate();
|
|
||||||
PA_MUSTTAIL return delegate->free_definite_size_function(address, size,
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DelegatedTryFreeDefaultFn(void* address, void* context) {
|
void DelegatedTryFreeDefaultFn(void* address, void* context) {
|
||||||
const AllocatorDispatch* delegate = GetDelegate();
|
const AllocatorDispatch* delegate = GetDelegate();
|
||||||
PA_MUSTTAIL return delegate->try_free_default_function(address, context);
|
PA_MUSTTAIL return delegate->try_free_default_function(address, context);
|
||||||
@ -158,7 +174,7 @@ void InstallCustomDispatch(AllocatorDispatch* dispatch) {
|
|||||||
PA_DCHECK(dispatch->batch_malloc_function != nullptr);
|
PA_DCHECK(dispatch->batch_malloc_function != nullptr);
|
||||||
PA_DCHECK(dispatch->batch_free_function != nullptr);
|
PA_DCHECK(dispatch->batch_free_function != nullptr);
|
||||||
#if PA_BUILDFLAG(IS_APPLE)
|
#if PA_BUILDFLAG(IS_APPLE)
|
||||||
PA_DCHECK(dispatch->free_definite_size_function != nullptr);
|
PA_DCHECK(dispatch->free_with_size_function != nullptr);
|
||||||
PA_DCHECK(dispatch->try_free_default_function != nullptr);
|
PA_DCHECK(dispatch->try_free_default_function != nullptr);
|
||||||
#endif // PA_BUILDFLAG(IS_APPLE)
|
#endif // PA_BUILDFLAG(IS_APPLE)
|
||||||
PA_DCHECK(dispatch->aligned_malloc_function != nullptr);
|
PA_DCHECK(dispatch->aligned_malloc_function != nullptr);
|
||||||
@ -210,12 +226,15 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
|||||||
.realloc_function = &DelegatedReallocFn,
|
.realloc_function = &DelegatedReallocFn,
|
||||||
.realloc_unchecked_function = &DelegatedReallocUncheckedFn,
|
.realloc_unchecked_function = &DelegatedReallocUncheckedFn,
|
||||||
.free_function = &DelegatedFreeFn,
|
.free_function = &DelegatedFreeFn,
|
||||||
|
.free_with_size_function = &DelegatedFreeWithSizeFn,
|
||||||
|
.free_with_alignment_function = &DelegatedFreeWithAlignmentFn,
|
||||||
|
.free_with_size_and_alignment_function =
|
||||||
|
&DelegatedFreeWithSizeAndAlignmentFn,
|
||||||
.get_size_estimate_function = &DelegatedGetSizeEstimateFn,
|
.get_size_estimate_function = &DelegatedGetSizeEstimateFn,
|
||||||
.good_size_function = &DelegatedGoodSizeFn,
|
.good_size_function = &DelegatedGoodSizeFn,
|
||||||
.claimed_address_function = &DelegatedClaimedAddressFn,
|
.claimed_address_function = &DelegatedClaimedAddressFn,
|
||||||
.batch_malloc_function = &DelegatedBatchMallocFn,
|
.batch_malloc_function = &DelegatedBatchMallocFn,
|
||||||
.batch_free_function = &DelegatedBatchFreeFn,
|
.batch_free_function = &DelegatedBatchFreeFn,
|
||||||
.free_definite_size_function = &DelegatedFreeDefiniteSizeFn,
|
|
||||||
.try_free_default_function = &DelegatedTryFreeDefaultFn,
|
.try_free_default_function = &DelegatedTryFreeDefaultFn,
|
||||||
.aligned_malloc_function = &DelegatedAlignedMallocFn,
|
.aligned_malloc_function = &DelegatedAlignedMallocFn,
|
||||||
.aligned_malloc_unchecked_function = &DelegatedAlignedMallocUncheckedFn,
|
.aligned_malloc_unchecked_function = &DelegatedAlignedMallocUncheckedFn,
|
||||||
|
@ -43,6 +43,23 @@ void DefaultWinHeapFreeImpl(void* address, void* context) {
|
|||||||
allocator_shim::WinHeapFree(address);
|
allocator_shim::WinHeapFree(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DefaultWinHeapFreeWithSizeImpl(void* address, size_t size, void* context) {
|
||||||
|
allocator_shim::WinHeapFree(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultWinHeapFreeWithAlignmentImpl(void* address,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
allocator_shim::WinHeapFree(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultWinHeapFreeWithSizeAndAlignmentImpl(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
allocator_shim::WinHeapFree(address);
|
||||||
|
}
|
||||||
|
|
||||||
size_t DefaultWinHeapGetSizeEstimateImpl(void* address, void* context) {
|
size_t DefaultWinHeapGetSizeEstimateImpl(void* address, void* context) {
|
||||||
return allocator_shim::WinHeapGetSizeEstimate(address);
|
return allocator_shim::WinHeapGetSizeEstimate(address);
|
||||||
}
|
}
|
||||||
@ -77,12 +94,14 @@ constexpr AllocatorDispatch AllocatorDispatch::default_dispatch = {
|
|||||||
&DefaultWinHeapReallocImpl,
|
&DefaultWinHeapReallocImpl,
|
||||||
&DefaultWinHeapReallocImpl, /* realloc_unchecked_function */
|
&DefaultWinHeapReallocImpl, /* realloc_unchecked_function */
|
||||||
&DefaultWinHeapFreeImpl,
|
&DefaultWinHeapFreeImpl,
|
||||||
|
&DefaultWinHeapFreeWithSizeImpl,
|
||||||
|
&DefaultWinHeapFreeWithAlignmentImpl,
|
||||||
|
&DefaultWinHeapFreeWithSizeAndAlignmentImpl,
|
||||||
&DefaultWinHeapGetSizeEstimateImpl,
|
&DefaultWinHeapGetSizeEstimateImpl,
|
||||||
nullptr, /* good_size */
|
nullptr, /* good_size */
|
||||||
nullptr, /* claimed_address */
|
nullptr, /* claimed_address */
|
||||||
nullptr, /* batch_malloc_function */
|
nullptr, /* batch_malloc_function */
|
||||||
nullptr, /* batch_free_function */
|
nullptr, /* batch_free_function */
|
||||||
nullptr, /* free_definite_size_function */
|
|
||||||
nullptr, /* try_free_default_function */
|
nullptr, /* try_free_default_function */
|
||||||
&DefaultWinHeapAlignedMallocImpl,
|
&DefaultWinHeapAlignedMallocImpl,
|
||||||
&DefaultWinHeapAlignedMallocImpl, /* aligned_malloc_unchecked_function */
|
&DefaultWinHeapAlignedMallocImpl, /* aligned_malloc_unchecked_function */
|
||||||
|
@ -15,35 +15,44 @@ namespace {
|
|||||||
|
|
||||||
void FreeFn(void* address, void* context) {}
|
void FreeFn(void* address, void* context) {}
|
||||||
|
|
||||||
void BatchFreeFn(void** to_be_freed, unsigned num_to_be_freed, void* context) {}
|
void FreeWithSizeFn(void* address, size_t size, void* context) {}
|
||||||
|
|
||||||
void FreeDefiniteSizeFn(void* address, size_t size, void* context) {}
|
void FreeWithAlignmentFn(void* address, size_t alignment, void* context) {}
|
||||||
|
|
||||||
|
void FreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {}
|
||||||
|
|
||||||
|
void BatchFreeFn(void** to_be_freed, unsigned num_to_be_freed, void* context) {}
|
||||||
|
|
||||||
void TryFreeDefaultFn(void* address, void* context) {}
|
void TryFreeDefaultFn(void* address, void* context) {}
|
||||||
|
|
||||||
static void AlignedFreeFn(void* address, void* context) {}
|
static void AlignedFreeFn(void* address, void* context) {}
|
||||||
|
|
||||||
AllocatorDispatch allocator_dispatch = {
|
AllocatorDispatch allocator_dispatch = {
|
||||||
nullptr, // alloc_function
|
nullptr, // alloc_function
|
||||||
nullptr, // alloc_unchecked_function
|
nullptr, // alloc_unchecked_function
|
||||||
nullptr, // alloc_zero_initialized_function
|
nullptr, // alloc_zero_initialized_function
|
||||||
nullptr, // alloc_aligned_function
|
nullptr, // alloc_aligned_function
|
||||||
nullptr, // realloc_function
|
nullptr, // realloc_function
|
||||||
nullptr, // realloc_unchecked_function
|
nullptr, // realloc_unchecked_function
|
||||||
FreeFn, // free_function
|
FreeFn, // free_function
|
||||||
nullptr, // get_size_estimate_function
|
FreeWithSizeFn, // free_definite_size_function
|
||||||
nullptr, // good_size_function
|
FreeWithAlignmentFn, // free_with_alignment_function
|
||||||
nullptr, // claimed_address_function
|
FreeWithSizeAndAlignmentFn, // free_with_size_and_alignment_function
|
||||||
nullptr, // batch_malloc_function
|
nullptr, // get_size_estimate_function
|
||||||
BatchFreeFn, // batch_free_function
|
nullptr, // good_size_function
|
||||||
FreeDefiniteSizeFn, // free_definite_size_function
|
nullptr, // claimed_address_function
|
||||||
TryFreeDefaultFn, // try_free_default_function
|
nullptr, // batch_malloc_function
|
||||||
nullptr, // aligned_malloc_function
|
BatchFreeFn, // batch_free_function
|
||||||
nullptr, // aligned_malloc_unchecked_function
|
TryFreeDefaultFn, // try_free_default_function
|
||||||
nullptr, // aligned_realloc_function
|
nullptr, // aligned_malloc_function
|
||||||
nullptr, // aligned_realloc_unchecked_function
|
nullptr, // aligned_malloc_unchecked_function
|
||||||
AlignedFreeFn, // aligned_free_function
|
nullptr, // aligned_realloc_function
|
||||||
nullptr // next
|
nullptr, // aligned_realloc_unchecked_function
|
||||||
|
AlignedFreeFn, // aligned_free_function
|
||||||
|
nullptr // next
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -177,7 +177,7 @@ void* MallocZoneMemalign(malloc_zone_t* zone, size_t alignment, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MallocZoneFreeDefiniteSize(malloc_zone_t* zone, void* ptr, size_t size) {
|
void MallocZoneFreeDefiniteSize(malloc_zone_t* zone, void* ptr, size_t size) {
|
||||||
return ShimFreeDefiniteSize(ptr, size, nullptr);
|
return ShimFreeWithSize(ptr, size, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned MallocZoneBatchMalloc(malloc_zone_t* zone,
|
unsigned MallocZoneBatchMalloc(malloc_zone_t* zone,
|
||||||
|
2
base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h
2
base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h
@ -62,7 +62,7 @@ MallocZoneFunctions MallocZoneFunctionsToReplaceDefault() {
|
|||||||
};
|
};
|
||||||
new_functions.free_definite_size = [](malloc_zone_t* zone, void* ptr,
|
new_functions.free_definite_size = [](malloc_zone_t* zone, void* ptr,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
ShimFreeDefiniteSize(ptr, size, zone);
|
ShimFreeWithSize(ptr, size, zone);
|
||||||
};
|
};
|
||||||
new_functions.try_free_default = [](malloc_zone_t* zone, void* ptr) {
|
new_functions.try_free_default = [](malloc_zone_t* zone, void* ptr) {
|
||||||
ShimTryFreeDefault(ptr, zone);
|
ShimTryFreeDefault(ptr, zone);
|
||||||
|
74
base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h
74
base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h
@ -102,17 +102,21 @@ SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p, size_t) __THROW {
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p, size_t size) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithSize(p, size);
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p, size_t) __THROW {
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p, size_t size) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithSize(p, size);
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
@ -137,30 +141,36 @@ SHIM_CPP_SYMBOLS_EXPORT void* operator new(std::size_t size,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p,
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete(
|
||||||
std::align_val_t) __THROW {
|
void* p,
|
||||||
|
std::align_val_t alignment) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithAlignment(p, static_cast<size_t>(alignment));
|
||||||
|
#else
|
||||||
|
ShimCppDelete(p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SHIM_CPP_SYMBOLS_EXPORT void
|
||||||
|
operator delete(void* p, std::size_t size, std::align_val_t alignment) __THROW {
|
||||||
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithSizeAndAlignment(p, size, static_cast<size_t>(alignment));
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p,
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p,
|
||||||
std::size_t size,
|
std::align_val_t alignment,
|
||||||
std::align_val_t) __THROW {
|
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
|
||||||
free(p);
|
|
||||||
#else
|
|
||||||
ShimCppDelete(p);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete(void* p,
|
|
||||||
std::align_val_t,
|
|
||||||
const std::nothrow_t&) __THROW {
|
const std::nothrow_t&) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithAlignment(p, static_cast<size_t>(alignment));
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
@ -185,30 +195,38 @@ SHIM_CPP_SYMBOLS_EXPORT void* operator new[](std::size_t size,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](
|
||||||
std::align_val_t) __THROW {
|
void* p,
|
||||||
|
std::align_val_t alignment) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithAlignment(p, static_cast<size_t>(alignment));
|
||||||
|
#else
|
||||||
|
ShimCppDelete(p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](
|
||||||
|
void* p,
|
||||||
|
std::size_t size,
|
||||||
|
std::align_val_t alignment) __THROW {
|
||||||
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithSizeAndAlignment(p, size, static_cast<size_t>(alignment));
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
|
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
|
||||||
std::size_t size,
|
std::align_val_t alignment,
|
||||||
std::align_val_t) __THROW {
|
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
|
||||||
free(p);
|
|
||||||
#else
|
|
||||||
ShimCppDelete(p);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
|
|
||||||
std::align_val_t,
|
|
||||||
const std::nothrow_t&) __THROW {
|
const std::nothrow_t&) __THROW {
|
||||||
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
#if PA_BUILDFLAG(FORWARD_THROUGH_MALLOC)
|
||||||
free(p);
|
free(p);
|
||||||
|
#elif PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
ShimCppDeleteWithAlignment(p, static_cast<size_t>(alignment));
|
||||||
#else
|
#else
|
||||||
ShimCppDelete(p);
|
ShimCppDelete(p);
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -112,6 +112,42 @@ PA_ALWAYS_INLINE void ShimCppDelete(void* address) {
|
|||||||
return chain_head->free_function(address, context);
|
return chain_head->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
PA_ALWAYS_INLINE void ShimCppDeleteWithSize(void* address, size_t size) {
|
||||||
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
|
allocator_shim::internal::GetChainHead();
|
||||||
|
void* context = nullptr;
|
||||||
|
#if PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
|
context = malloc_default_zone();
|
||||||
|
#endif
|
||||||
|
return chain_head->free_with_size_function(address, size, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
PA_ALWAYS_INLINE void ShimCppDeleteWithAlignment(void* address,
|
||||||
|
size_t alignment) {
|
||||||
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
|
allocator_shim::internal::GetChainHead();
|
||||||
|
void* context = nullptr;
|
||||||
|
#if PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
|
context = malloc_default_zone();
|
||||||
|
#endif
|
||||||
|
return chain_head->free_with_alignment_function(address, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
PA_ALWAYS_INLINE void ShimCppDeleteWithSizeAndAlignment(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment) {
|
||||||
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
|
allocator_shim::internal::GetChainHead();
|
||||||
|
void* context = nullptr;
|
||||||
|
#if PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
|
context = malloc_default_zone();
|
||||||
|
#endif
|
||||||
|
return chain_head->free_with_size_and_alignment_function(address, size,
|
||||||
|
alignment, context);
|
||||||
|
}
|
||||||
|
#endif // PA_BUILDFLAG(SHIM_SUPPORTS_SIZED_DEALLOC)
|
||||||
|
|
||||||
PA_ALWAYS_INLINE void* ShimMalloc(size_t size, void* context) {
|
PA_ALWAYS_INLINE void* ShimMalloc(size_t size, void* context) {
|
||||||
const allocator_shim::AllocatorDispatch* const chain_head =
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
allocator_shim::internal::GetChainHead();
|
allocator_shim::internal::GetChainHead();
|
||||||
@ -213,6 +249,12 @@ PA_ALWAYS_INLINE void ShimFree(void* address, void* context) {
|
|||||||
return chain_head->free_function(address, context);
|
return chain_head->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PA_ALWAYS_INLINE void ShimFreeWithSize(void* ptr, size_t size, void* context) {
|
||||||
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
|
allocator_shim::internal::GetChainHead();
|
||||||
|
return chain_head->free_with_size_function(ptr, size, context);
|
||||||
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE size_t ShimGetSizeEstimate(const void* address,
|
PA_ALWAYS_INLINE size_t ShimGetSizeEstimate(const void* address,
|
||||||
void* context) {
|
void* context) {
|
||||||
const allocator_shim::AllocatorDispatch* const chain_head =
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
@ -251,14 +293,6 @@ PA_ALWAYS_INLINE void ShimBatchFree(void** to_be_freed,
|
|||||||
return chain_head->batch_free_function(to_be_freed, num_to_be_freed, context);
|
return chain_head->batch_free_function(to_be_freed, num_to_be_freed, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE void ShimFreeDefiniteSize(void* ptr,
|
|
||||||
size_t size,
|
|
||||||
void* context) {
|
|
||||||
const allocator_shim::AllocatorDispatch* const chain_head =
|
|
||||||
allocator_shim::internal::GetChainHead();
|
|
||||||
return chain_head->free_definite_size_function(ptr, size, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_ALWAYS_INLINE void ShimTryFreeDefault(void* ptr, void* context) {
|
PA_ALWAYS_INLINE void ShimTryFreeDefault(void* ptr, void* context) {
|
||||||
const allocator_shim::AllocatorDispatch* const chain_head =
|
const allocator_shim::AllocatorDispatch* const chain_head =
|
||||||
allocator_shim::internal::GetChainHead();
|
allocator_shim::internal::GetChainHead();
|
||||||
|
@ -205,12 +205,14 @@ allocator_shim::AllocatorDispatch g_bad_malloc_dispatch = {
|
|||||||
&BadRealloc, /* realloc_function */
|
&BadRealloc, /* realloc_function */
|
||||||
&BadRealloc, /* realloc_unchecked_function */
|
&BadRealloc, /* realloc_unchecked_function */
|
||||||
&BadFree, /* free_function */
|
&BadFree, /* free_function */
|
||||||
|
nullptr, /* free_with_size_function */
|
||||||
|
nullptr, /* free_with_alignment_function */
|
||||||
|
nullptr, /* free_with_size_and_alignment_function */
|
||||||
nullptr, /* get_size_estimate_function */
|
nullptr, /* get_size_estimate_function */
|
||||||
nullptr, /* good_size_function */
|
nullptr, /* good_size_function */
|
||||||
nullptr, /* claimed_address_function */
|
nullptr, /* claimed_address_function */
|
||||||
nullptr, /* batch_malloc_function */
|
nullptr, /* batch_malloc_function */
|
||||||
nullptr, /* batch_free_function */
|
nullptr, /* batch_free_function */
|
||||||
nullptr, /* free_definite_size_function */
|
|
||||||
nullptr, /* try_free_default_function */
|
nullptr, /* try_free_default_function */
|
||||||
&BadAlignedAlloc, /* aligned_malloc_function */
|
&BadAlignedAlloc, /* aligned_malloc_function */
|
||||||
&BadAlignedAlloc, /* aligned_malloc_unchecked_function */
|
&BadAlignedAlloc, /* aligned_malloc_unchecked_function */
|
||||||
|
@ -111,6 +111,8 @@ if (is_win && is_component_build && (!use_custom_libcxx || libcxx_is_shared)) {
|
|||||||
use_allocator_shim_default = false
|
use_allocator_shim_default = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shim_supports_sized_dealloc_default = use_sized_deallocation
|
||||||
|
|
||||||
use_partition_alloc_as_malloc_default =
|
use_partition_alloc_as_malloc_default =
|
||||||
use_allocator_shim_default && _is_partition_alloc_everywhere_platform &&
|
use_allocator_shim_default && _is_partition_alloc_everywhere_platform &&
|
||||||
!_disable_partition_alloc_everywhere
|
!_disable_partition_alloc_everywhere
|
||||||
|
@ -96,7 +96,7 @@ bool TryInitSlow() {
|
|||||||
//
|
//
|
||||||
// This code runs only on the codepaths of deallocations (`free`, `delete`,
|
// This code runs only on the codepaths of deallocations (`free`, `delete`,
|
||||||
// etc.) and _never_ runs on the codepaths of allocations (`malloc`, `new`,
|
// etc.) and _never_ runs on the codepaths of allocations (`malloc`, `new`,
|
||||||
// etc.) because this allocator shim hooks only FreeFn, FreeDefiniteSizeFn,
|
// etc.) because this allocator shim hooks only FreeFn, FreeWithSizeFn,
|
||||||
// etc. So, it's safe to allocate memory here as it doesn't recurse, however,
|
// etc. So, it's safe to allocate memory here as it doesn't recurse, however,
|
||||||
// it's _NOT_ allowed to deallocate memory here as it _does_ recurse.
|
// it's _NOT_ allowed to deallocate memory here as it _does_ recurse.
|
||||||
//
|
//
|
||||||
@ -218,16 +218,40 @@ void FreeFn(void* address, void* context) {
|
|||||||
MUSTTAIL return allocator_dispatch.next->free_function(address, context);
|
MUSTTAIL return allocator_dispatch.next->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeDefiniteSizeFn(void* address, size_t size, void* context) {
|
void FreeWithSizeFn(void* address, size_t size, void* context) {
|
||||||
if (sampling_state.Sample()) [[unlikely]] {
|
if (sampling_state.Sample()) [[unlikely]] {
|
||||||
if (Quarantine(address)) [[likely]] {
|
if (Quarantine(address)) [[likely]] {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MUSTTAIL return allocator_dispatch.next->free_definite_size_function(
|
MUSTTAIL return allocator_dispatch.next->free_with_size_function(
|
||||||
address, size, context);
|
address, size, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FreeWithAlignmentFn(void* address, size_t alignment, void* context) {
|
||||||
|
if (sampling_state.Sample()) [[unlikely]] {
|
||||||
|
if (Quarantine(address)) [[likely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MUSTTAIL return allocator_dispatch.next->free_with_alignment_function(
|
||||||
|
address, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
if (sampling_state.Sample()) [[unlikely]] {
|
||||||
|
if (Quarantine(address)) [[likely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MUSTTAIL return allocator_dispatch.next
|
||||||
|
->free_with_size_and_alignment_function(address, size, alignment,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
AllocatorDispatch allocator_dispatch = {
|
AllocatorDispatch allocator_dispatch = {
|
||||||
nullptr, // alloc_function
|
nullptr, // alloc_function
|
||||||
nullptr, // alloc_unchecked_function
|
nullptr, // alloc_unchecked_function
|
||||||
@ -235,17 +259,19 @@ AllocatorDispatch allocator_dispatch = {
|
|||||||
nullptr, // alloc_aligned_function
|
nullptr, // alloc_aligned_function
|
||||||
// realloc doesn't always deallocate memory, so the Extreme LUD doesn't
|
// realloc doesn't always deallocate memory, so the Extreme LUD doesn't
|
||||||
// support realloc.
|
// support realloc.
|
||||||
nullptr, // realloc_function
|
nullptr, // realloc_function
|
||||||
nullptr, // realloc_unchecked_function
|
nullptr, // realloc_unchecked_function
|
||||||
FreeFn, // free_function
|
FreeFn, // free_function
|
||||||
nullptr, // get_size_estimate_function
|
FreeWithSizeFn, // free_with_size_function
|
||||||
nullptr, // good_size_function
|
FreeWithAlignmentFn, // free_with_alignment_function
|
||||||
nullptr, // claimed_address_function
|
FreeWithSizeAndAlignmentFn, // free_with_size_and_alignment_function
|
||||||
nullptr, // batch_malloc_function
|
nullptr, // get_size_estimate_function
|
||||||
|
nullptr, // good_size_function
|
||||||
|
nullptr, // claimed_address_function
|
||||||
|
nullptr, // batch_malloc_function
|
||||||
// batch_free is rarely used, so the Extreme LUD doesn't support batch_free
|
// batch_free is rarely used, so the Extreme LUD doesn't support batch_free
|
||||||
// (at least for now).
|
// (at least for now).
|
||||||
nullptr, // batch_free_function
|
nullptr, // batch_free_function
|
||||||
FreeDefiniteSizeFn, // free_definite_size_function
|
|
||||||
// try_free_default is rarely used, so the Extreme LUD doesn't support
|
// try_free_default is rarely used, so the Extreme LUD doesn't support
|
||||||
// try_free_default (at least for now).
|
// try_free_default (at least for now).
|
||||||
nullptr, // try_free_default_function
|
nullptr, // try_free_default_function
|
||||||
|
@ -62,16 +62,40 @@ void FreeFn(void* address, void* context) {
|
|||||||
MUSTTAIL return g_allocator_dispatch.next->free_function(address, context);
|
MUSTTAIL return g_allocator_dispatch.next->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeDefiniteSizeFn(void* address, size_t size, void* context) {
|
void FreeWithSizeFn(void* address, size_t size, void* context) {
|
||||||
if (MaybeQuarantine(address, size, context,
|
if (MaybeQuarantine(address, size, context,
|
||||||
FreeFunctionKind::kFreeDefiniteSize)) {
|
FreeFunctionKind::kFreeWithSize)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUSTTAIL return g_allocator_dispatch.next->free_definite_size_function(
|
MUSTTAIL return g_allocator_dispatch.next->free_with_size_function(
|
||||||
address, size, context);
|
address, size, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FreeWithAlignmentFn(void* address, size_t alignment, void* context) {
|
||||||
|
if (MaybeQuarantine(address, std::nullopt, context,
|
||||||
|
FreeFunctionKind::kFreeWithAlignment)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MUSTTAIL return g_allocator_dispatch.next->free_with_alignment_function(
|
||||||
|
address, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
if (MaybeQuarantine(address, size, context,
|
||||||
|
FreeFunctionKind::kFreeWithSizeAndAlignment)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MUSTTAIL return g_allocator_dispatch.next
|
||||||
|
->free_with_size_and_alignment_function(address, size, alignment,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
void TryFreeDefaultFn(void* address, void* context) {
|
void TryFreeDefaultFn(void* address, void* context) {
|
||||||
if (MaybeQuarantine(address, std::nullopt, context,
|
if (MaybeQuarantine(address, std::nullopt, context,
|
||||||
FreeFunctionKind::kTryFreeDefault)) {
|
FreeFunctionKind::kTryFreeDefault)) {
|
||||||
@ -93,26 +117,28 @@ static void AlignedFreeFn(void* address, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AllocatorDispatch g_allocator_dispatch = {
|
AllocatorDispatch g_allocator_dispatch = {
|
||||||
nullptr, // alloc_function
|
nullptr, // alloc_function
|
||||||
nullptr, // alloc_unchecked_function
|
nullptr, // alloc_unchecked_function
|
||||||
nullptr, // alloc_zero_initialized_function
|
nullptr, // alloc_zero_initialized_function
|
||||||
nullptr, // alloc_aligned_function
|
nullptr, // alloc_aligned_function
|
||||||
nullptr, // realloc_function
|
nullptr, // realloc_function
|
||||||
nullptr, // realloc_unchecked_function
|
nullptr, // realloc_unchecked_function
|
||||||
FreeFn, // free_function
|
FreeFn, // free_function
|
||||||
nullptr, // get_size_estimate_function
|
FreeWithSizeFn, // free_with_size_function
|
||||||
nullptr, // good_size_function
|
FreeWithAlignmentFn, // free_with_alignment_function
|
||||||
nullptr, // claimed_address_function
|
FreeWithSizeAndAlignmentFn, // free_with_size_and_alignment_function
|
||||||
nullptr, // batch_malloc_function
|
nullptr, // get_size_estimate_function
|
||||||
nullptr, // batch_free_function
|
nullptr, // good_size_function
|
||||||
FreeDefiniteSizeFn, // free_definite_size_function
|
nullptr, // claimed_address_function
|
||||||
TryFreeDefaultFn, // try_free_default_function
|
nullptr, // batch_malloc_function
|
||||||
nullptr, // aligned_malloc_function
|
nullptr, // batch_free_function
|
||||||
nullptr, // aligned_malloc_unchecked_function
|
TryFreeDefaultFn, // try_free_default_function
|
||||||
nullptr, // aligned_realloc_function
|
nullptr, // aligned_malloc_function
|
||||||
nullptr, // aligned_realloc_unchecked_function
|
nullptr, // aligned_malloc_unchecked_function
|
||||||
AlignedFreeFn, // aligned_free_function
|
nullptr, // aligned_realloc_function
|
||||||
nullptr // next
|
nullptr, // aligned_realloc_unchecked_function
|
||||||
|
AlignedFreeFn, // aligned_free_function
|
||||||
|
nullptr // next
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -145,9 +171,19 @@ void FinishFree(const AllocationInfo& allocation) {
|
|||||||
case FreeFunctionKind::kFree:
|
case FreeFunctionKind::kFree:
|
||||||
next->free_function(allocation.address, context);
|
next->free_function(allocation.address, context);
|
||||||
break;
|
break;
|
||||||
case FreeFunctionKind::kFreeDefiniteSize:
|
case FreeFunctionKind::kFreeWithSize:
|
||||||
next->free_definite_size_function(allocation.address, allocation.size,
|
next->free_with_size_function(allocation.address, allocation.size,
|
||||||
context);
|
context);
|
||||||
|
break;
|
||||||
|
case FreeFunctionKind::kFreeWithAlignment:
|
||||||
|
// TODO(crbug.com/412358843): Memory and forward alignment information.
|
||||||
|
next->free_function(allocation.address, context);
|
||||||
|
break;
|
||||||
|
case FreeFunctionKind::kFreeWithSizeAndAlignment:
|
||||||
|
// TODO(crbug.com/412358843): Similar to above, forward alignment
|
||||||
|
// information. We shall not forward size information here because it can
|
||||||
|
// confuse an allocator by alignment mismatch.
|
||||||
|
next->free_function(allocation.address, context);
|
||||||
break;
|
break;
|
||||||
case FreeFunctionKind::kTryFreeDefault:
|
case FreeFunctionKind::kTryFreeDefault:
|
||||||
next->try_free_default_function(allocation.address, context);
|
next->try_free_default_function(allocation.address, context);
|
||||||
|
@ -19,7 +19,9 @@ namespace gwp_asan::internal::lud {
|
|||||||
enum class FreeFunctionKind : uint8_t {
|
enum class FreeFunctionKind : uint8_t {
|
||||||
kUnknown,
|
kUnknown,
|
||||||
kFree,
|
kFree,
|
||||||
kFreeDefiniteSize,
|
kFreeWithSize,
|
||||||
|
kFreeWithAlignment,
|
||||||
|
kFreeWithSizeAndAlignment,
|
||||||
kTryFreeDefault,
|
kTryFreeDefault,
|
||||||
kAlignedFree,
|
kAlignedFree,
|
||||||
};
|
};
|
||||||
|
@ -160,6 +160,44 @@ void FreeFn(void* address, void* context) {
|
|||||||
g_allocator_dispatch.next->free_function(address, context);
|
g_allocator_dispatch.next->free_function(address, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeFn(void* address, size_t size, void* context) {
|
||||||
|
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
||||||
|
// TODO(vtsyrklevich): Perform this check in GuardedPageAllocator and report
|
||||||
|
// failed checks using the same pipeline.
|
||||||
|
CHECK_EQ(size, gpa->GetRequestedSize(address));
|
||||||
|
gpa->Deallocate(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_allocator_dispatch.next->free_with_size_function(address, size, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithAlignmentFn(void* address, size_t alignment, void* context) {
|
||||||
|
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
||||||
|
gpa->Deallocate(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_allocator_dispatch.next->free_with_alignment_function(address, alignment,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeWithSizeAndAlignmentFn(void* address,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
void* context) {
|
||||||
|
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
||||||
|
// TODO(vtsyrklevich): Perform this check in GuardedPageAllocator and report
|
||||||
|
// failed checks using the same pipeline.
|
||||||
|
CHECK_EQ(size, gpa->GetRequestedSize(address));
|
||||||
|
gpa->Deallocate(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_allocator_dispatch.next->free_with_size_and_alignment_function(
|
||||||
|
address, size, alignment, context);
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetSizeEstimateFn(void* address, void* context) {
|
size_t GetSizeEstimateFn(void* address, void* context) {
|
||||||
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
||||||
return gpa->GetRequestedSize(address);
|
return gpa->GetRequestedSize(address);
|
||||||
@ -212,19 +250,6 @@ void BatchFreeFn(void** to_be_freed, unsigned num_to_be_freed, void* context) {
|
|||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeDefiniteSizeFn(void* address, size_t size, void* context) {
|
|
||||||
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
|
||||||
// TODO(vtsyrklevich): Perform this check in GuardedPageAllocator and report
|
|
||||||
// failed checks using the same pipeline.
|
|
||||||
CHECK_EQ(size, gpa->GetRequestedSize(address));
|
|
||||||
gpa->Deallocate(address);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_allocator_dispatch.next->free_definite_size_function(address, size,
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TryFreeDefaultFn(void* address, void* context) {
|
void TryFreeDefaultFn(void* address, void* context) {
|
||||||
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
if (gpa->PointerIsMine(address)) [[unlikely]] {
|
||||||
gpa->Deallocate(address);
|
gpa->Deallocate(address);
|
||||||
@ -335,12 +360,14 @@ AllocatorDispatch g_allocator_dispatch = {
|
|||||||
&ReallocFn,
|
&ReallocFn,
|
||||||
&ReallocUncheckedFn,
|
&ReallocUncheckedFn,
|
||||||
&FreeFn,
|
&FreeFn,
|
||||||
|
&FreeWithSizeFn,
|
||||||
|
&FreeWithAlignmentFn,
|
||||||
|
&FreeWithSizeAndAlignmentFn,
|
||||||
&GetSizeEstimateFn,
|
&GetSizeEstimateFn,
|
||||||
&GoodSizeFn,
|
&GoodSizeFn,
|
||||||
&ClaimedAddressFn,
|
&ClaimedAddressFn,
|
||||||
&BatchMallocFn,
|
&BatchMallocFn,
|
||||||
&BatchFreeFn,
|
&BatchFreeFn,
|
||||||
&FreeDefiniteSizeFn,
|
|
||||||
&TryFreeDefaultFn,
|
&TryFreeDefaultFn,
|
||||||
&AlignedMallocFn,
|
&AlignedMallocFn,
|
||||||
&AlignedMallocUncheckedFn,
|
&AlignedMallocUncheckedFn,
|
||||||
|
Reference in New Issue
Block a user