Index: base/allocator/allocator_interception_mac.mm |
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm |
index e945a293beb58fbe36e9e4f2c17f1525293b28cc..c484830da5e2538904cd1b8218ca8fb97e354536 100644 |
--- a/base/allocator/allocator_interception_mac.mm |
+++ b/base/allocator/allocator_interception_mac.mm |
@@ -29,6 +29,7 @@ |
#include "base/allocator/allocator_shim.h" |
#include "base/allocator/features.h" |
+#include "base/allocator/malloc_zone_functions_mac.h" |
#include "base/logging.h" |
#include "base/mac/mac_util.h" |
#include "base/mac/mach_logging.h" |
@@ -42,8 +43,6 @@ namespace allocator { |
bool g_replaced_default_zone = false; |
-MallocZoneFunctions::MallocZoneFunctions() {} |
- |
namespace { |
bool g_oom_killer_enabled; |
@@ -295,31 +294,6 @@ bool UncheckedCallocMac(size_t num_items, size_t size, void** result) { |
return *result != NULL; |
} |
-void StoreZoneFunctions(ChromeMallocZone* zone, |
- MallocZoneFunctions* functions) { |
- functions->malloc = zone->malloc; |
- functions->calloc = zone->calloc; |
- functions->valloc = zone->valloc; |
- functions->free = zone->free; |
- functions->realloc = zone->realloc; |
- functions->size = zone->size; |
- CHECK(functions->malloc && functions->calloc && functions->valloc && |
- functions->free && functions->realloc && functions->size); |
- |
- // These functions might be nullptr. |
- functions->batch_malloc = zone->batch_malloc; |
- functions->batch_free = zone->batch_free; |
- |
- if (zone->version >= 5) { |
- functions->memalign = zone->memalign; |
- CHECK(functions->memalign); |
- } |
- if (zone->version >= 6) { |
- // This may be nullptr. |
- functions->free_definite_size = zone->free_definite_size; |
- } |
-} |
- |
void ReplaceZoneFunctions(ChromeMallocZone* zone, |
const MallocZoneFunctions* functions) { |
// Remove protection. |
@@ -358,21 +332,42 @@ void ReplaceZoneFunctions(ChromeMallocZone* zone, |
} |
} |
-void StoreFunctionsForDefaultZone(MallocZoneFunctions* functions) { |
+void StoreFunctionsForDefaultZone() { |
ChromeMallocZone* default_zone = reinterpret_cast<ChromeMallocZone*>( |
malloc_default_zone()); |
- StoreZoneFunctions(default_zone, functions); |
+ StoreMallocZone(default_zone); |
+} |
+ |
+void StoreFunctionsForAllZones() { |
+ // This ensures that the default zone is always at the front of the array, |
+ // which is important for performance. |
+ StoreFunctionsForDefaultZone(); |
+ |
+ vm_address_t* zones; |
+ unsigned int count; |
+ kern_return_t kr = malloc_get_all_zones(mach_task_self(), 0, &zones, &count); |
+ if (kr != KERN_SUCCESS) |
+ return; |
+ for (unsigned int i = 0; i < count; ++i) { |
+ ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); |
+ StoreMallocZone(zone); |
+ } |
} |
-void ReplaceFunctionsForDefaultZone(const MallocZoneFunctions* functions) { |
- CHECK(!g_replaced_default_zone); |
+void ReplaceFunctionsForStoredZones(const MallocZoneFunctions* functions) { |
+ vm_address_t* zones; |
+ unsigned int count; |
+ kern_return_t kr = |
+ malloc_get_all_zones(mach_task_self(), nullptr, &zones, &count); |
+ if (kr != KERN_SUCCESS) |
+ return; |
+ for (unsigned int i = 0; i < count; ++i) { |
+ ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); |
+ if (IsMallocZoneAlreadyStored(zone) && zone->malloc != functions->malloc) { |
+ ReplaceZoneFunctions(zone, functions); |
+ } |
+ } |
g_replaced_default_zone = true; |
-#if !defined(ADDRESS_SANITIZER) |
- StoreFunctionsForDefaultZone(&g_old_zone); |
-#endif |
- ChromeMallocZone* default_zone = reinterpret_cast<ChromeMallocZone*>( |
- malloc_default_zone()); |
- ReplaceZoneFunctions(default_zone, functions); |
} |
void InterceptAllocationsMac() { |
@@ -393,8 +388,10 @@ void InterceptAllocationsMac() { |
#if !defined(ADDRESS_SANITIZER) |
// Don't do anything special on OOM for the malloc zones replaced by |
// AddressSanitizer, as modifying or protecting them may not work correctly. |
- if (!g_replaced_default_zone) { |
- StoreFunctionsForDefaultZone(&g_old_zone); |
+ ChromeMallocZone* default_zone = |
+ reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
+ if (!IsMallocZoneAlreadyStored(default_zone)) { |
+ StoreZoneFunctions(default_zone, &g_old_zone); |
MallocZoneFunctions new_functions; |
new_functions.malloc = oom_killer_malloc; |
new_functions.calloc = oom_killer_calloc; |
@@ -402,12 +399,14 @@ void InterceptAllocationsMac() { |
new_functions.free = oom_killer_free; |
new_functions.realloc = oom_killer_realloc; |
new_functions.memalign = oom_killer_memalign; |
- ReplaceFunctionsForDefaultZone(&new_functions); |
+ |
+ ReplaceZoneFunctions(default_zone, &new_functions); |
+ g_replaced_default_zone = true; |
} |
ChromeMallocZone* purgeable_zone = |
reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
- if (purgeable_zone) { |
+ if (purgeable_zone && !IsMallocZoneAlreadyStored(purgeable_zone)) { |
StoreZoneFunctions(purgeable_zone, &g_old_purgeable_zone); |
MallocZoneFunctions new_functions; |
new_functions.malloc = oom_killer_malloc_purgeable; |