mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:26:06 +00:00
ios: More deflaking handler forbidden allocators.
- Stop overloading introspect (or implement this in the future) - Store each overridden allocation zone and correctly direct calls to the requested zone. Change-Id: I7294e476bb683149acc61419b095ec0e1098781b Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/4574037 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
402d43192a
commit
1fdbd3736c
@ -30,7 +30,25 @@ namespace {
|
||||
|
||||
uint64_t g_main_thread = 0;
|
||||
uint64_t g_mach_exception_thread = 0;
|
||||
malloc_zone_t g_old_zone;
|
||||
|
||||
// Somewhat simplified logic copied from Chromium's
|
||||
// base/allocator/partition_allocator/shim/malloc_zone_functions_mac.h. The
|
||||
// arrays g_original_zones and g_original_zones_ptr stores all information about
|
||||
// malloc zones before they are shimmed. This information needs to be accessed
|
||||
// during dispatch back into the zone.
|
||||
constexpr int kMaxZoneCount = 30;
|
||||
malloc_zone_t g_original_zones[kMaxZoneCount];
|
||||
malloc_zone_t* g_original_zones_ptr[kMaxZoneCount];
|
||||
unsigned int g_zone_count = 0;
|
||||
|
||||
struct _malloc_zone_t original_zone_for_zone(struct _malloc_zone_t* zone) {
|
||||
for (unsigned int i = 0; i < g_zone_count; ++i) {
|
||||
if (g_original_zones_ptr[i] == zone) {
|
||||
return g_original_zones[i];
|
||||
}
|
||||
}
|
||||
return g_original_zones[0];
|
||||
}
|
||||
|
||||
bool is_handler_thread() {
|
||||
uint64_t thread_self;
|
||||
@ -44,7 +62,7 @@ void* handler_forbidden_malloc(struct _malloc_zone_t* zone, size_t size) {
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_malloc allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.malloc(zone, size);
|
||||
return original_zone_for_zone(zone).malloc(zone, size);
|
||||
}
|
||||
|
||||
void* handler_forbidden_calloc(struct _malloc_zone_t* zone,
|
||||
@ -54,7 +72,7 @@ void* handler_forbidden_calloc(struct _malloc_zone_t* zone,
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_calloc allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.calloc(zone, num_items, size);
|
||||
return original_zone_for_zone(zone).calloc(zone, num_items, size);
|
||||
}
|
||||
|
||||
void* handler_forbidden_valloc(struct _malloc_zone_t* zone, size_t size) {
|
||||
@ -62,7 +80,7 @@ void* handler_forbidden_valloc(struct _malloc_zone_t* zone, size_t size) {
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_valloc allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.valloc(zone, size);
|
||||
return original_zone_for_zone(zone).valloc(zone, size);
|
||||
}
|
||||
|
||||
void handler_forbidden_free(struct _malloc_zone_t* zone, void* ptr) {
|
||||
@ -70,7 +88,7 @@ void handler_forbidden_free(struct _malloc_zone_t* zone, void* ptr) {
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_free allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_old_zone.free(zone, ptr);
|
||||
original_zone_for_zone(zone).free(zone, ptr);
|
||||
}
|
||||
|
||||
void* handler_forbidden_realloc(struct _malloc_zone_t* zone,
|
||||
@ -80,7 +98,7 @@ void* handler_forbidden_realloc(struct _malloc_zone_t* zone,
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_realloc allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.realloc(zone, ptr, size);
|
||||
return original_zone_for_zone(zone).realloc(zone, ptr, size);
|
||||
}
|
||||
|
||||
void handler_forbidden_destroy(struct _malloc_zone_t* zone) {
|
||||
@ -88,7 +106,7 @@ void handler_forbidden_destroy(struct _malloc_zone_t* zone) {
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_destroy allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_old_zone.destroy(zone);
|
||||
original_zone_for_zone(zone).destroy(zone);
|
||||
}
|
||||
|
||||
void* handler_forbidden_memalign(struct _malloc_zone_t* zone,
|
||||
@ -98,7 +116,7 @@ void* handler_forbidden_memalign(struct _malloc_zone_t* zone,
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_memalign allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.memalign(zone, alignment, size);
|
||||
return original_zone_for_zone(zone).memalign(zone, alignment, size);
|
||||
}
|
||||
|
||||
unsigned handler_forbidden_batch_malloc(struct _malloc_zone_t* zone,
|
||||
@ -110,7 +128,8 @@ unsigned handler_forbidden_batch_malloc(struct _malloc_zone_t* zone,
|
||||
"handler_forbidden_batch_malloc allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.batch_malloc(zone, size, results, num_requested);
|
||||
return original_zone_for_zone(zone).batch_malloc(
|
||||
zone, size, results, num_requested);
|
||||
}
|
||||
|
||||
void handler_forbidden_batch_free(struct _malloc_zone_t* zone,
|
||||
@ -120,7 +139,7 @@ void handler_forbidden_batch_free(struct _malloc_zone_t* zone,
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_batch_free allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_old_zone.batch_free(zone, to_be_freed, num_to_be_freed);
|
||||
original_zone_for_zone(zone).batch_free(zone, to_be_freed, num_to_be_freed);
|
||||
}
|
||||
|
||||
void handler_forbidden_free_definite_size(struct _malloc_zone_t* zone,
|
||||
@ -131,7 +150,7 @@ void handler_forbidden_free_definite_size(struct _malloc_zone_t* zone,
|
||||
"handler_forbidden_free_definite_size allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_old_zone.free_definite_size(zone, ptr, size);
|
||||
original_zone_for_zone(zone).free_definite_size(zone, ptr, size);
|
||||
}
|
||||
|
||||
size_t handler_forbidden_pressure_relief(struct _malloc_zone_t* zone,
|
||||
@ -141,7 +160,7 @@ size_t handler_forbidden_pressure_relief(struct _malloc_zone_t* zone,
|
||||
"handler_forbidden_pressure_relief allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.pressure_relief(zone, goal);
|
||||
return original_zone_for_zone(zone).pressure_relief(zone, goal);
|
||||
}
|
||||
|
||||
boolean_t handler_forbidden_claimed_address(struct _malloc_zone_t* zone,
|
||||
@ -152,14 +171,14 @@ boolean_t handler_forbidden_claimed_address(struct _malloc_zone_t* zone,
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (g_old_zone.claimed_address) {
|
||||
return g_old_zone.claimed_address(zone, ptr);
|
||||
if (original_zone_for_zone(zone).claimed_address) {
|
||||
return original_zone_for_zone(zone).claimed_address(zone, ptr);
|
||||
}
|
||||
|
||||
// If the fast API 'claimed_address' is not implemented in the specified zone,
|
||||
// fall back to 'size' function, which also tells whether the given address
|
||||
// belongs to the zone or not although it'd be slow.
|
||||
return g_old_zone.size(zone, ptr);
|
||||
return original_zone_for_zone(zone).size(zone, ptr);
|
||||
}
|
||||
|
||||
#if defined(__IPHONE_16_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_1
|
||||
@ -199,8 +218,8 @@ void handler_forbidden_try_free_default(struct _malloc_zone_t* zone,
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (g_old_zone.try_free_default) {
|
||||
return g_old_zone.try_free_default(zone, ptr);
|
||||
if (original_zone_for_zone(zone).try_free_default) {
|
||||
return original_zone_for_zone(zone).try_free_default(zone, ptr);
|
||||
}
|
||||
TryFreeDefaultFallbackToFindZoneAndFree(ptr);
|
||||
}
|
||||
@ -211,7 +230,7 @@ size_t handler_forbidden_size(struct _malloc_zone_t* zone, const void* ptr) {
|
||||
CRASHPAD_RAW_LOG("handler_forbidden_size allocator used in handler.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return g_old_zone.size(zone, ptr);
|
||||
return original_zone_for_zone(zone).size(zone, ptr);
|
||||
}
|
||||
|
||||
bool DeprotectMallocZone(malloc_zone_t* default_zone,
|
||||
@ -293,7 +312,6 @@ void ReplaceZoneFunctions(malloc_zone_t* zone, const malloc_zone_t* functions) {
|
||||
zone->destroy = functions->destroy;
|
||||
zone->batch_malloc = functions->batch_malloc;
|
||||
zone->batch_free = functions->batch_free;
|
||||
zone->introspect = functions->introspect;
|
||||
zone->memalign = functions->memalign;
|
||||
zone->free_definite_size = functions->free_definite_size;
|
||||
zone->pressure_relief = functions->pressure_relief;
|
||||
@ -326,8 +344,6 @@ void ReplaceAllocatorsWithHandlerForbidden() {
|
||||
CrashpadClient crashpad_client;
|
||||
g_mach_exception_thread = crashpad_client.GetThreadIdForTesting();
|
||||
|
||||
malloc_zone_t* default_zone = malloc_default_zone();
|
||||
memcpy(&g_old_zone, default_zone, sizeof(g_old_zone));
|
||||
malloc_zone_t new_functions = {};
|
||||
new_functions.size = handler_forbidden_size;
|
||||
new_functions.malloc = handler_forbidden_malloc;
|
||||
@ -345,8 +361,16 @@ void ReplaceAllocatorsWithHandlerForbidden() {
|
||||
#if defined(__IPHONE_16_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_1
|
||||
new_functions.try_free_default = handler_forbidden_try_free_default;
|
||||
#endif
|
||||
malloc_zone_t* default_zone = malloc_default_zone();
|
||||
g_original_zones_ptr[g_zone_count] = default_zone;
|
||||
ReplaceZoneFunctions(&g_original_zones[g_zone_count++], default_zone);
|
||||
ReplaceZoneFunctions(default_zone, &new_functions);
|
||||
|
||||
malloc_zone_t* purgeable_zone = malloc_default_purgeable_zone();
|
||||
g_original_zones_ptr[g_zone_count] = purgeable_zone;
|
||||
ReplaceZoneFunctions(&g_original_zones[g_zone_count++], purgeable_zone);
|
||||
ReplaceZoneFunctions(purgeable_zone, &new_functions);
|
||||
|
||||
vm_address_t* zones;
|
||||
unsigned int count;
|
||||
kern_return_t kr =
|
||||
@ -355,11 +379,13 @@ void ReplaceAllocatorsWithHandlerForbidden() {
|
||||
return;
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
malloc_zone_t* zone = reinterpret_cast<malloc_zone_t*>(zones[i]);
|
||||
g_original_zones_ptr[g_zone_count] = zone;
|
||||
ReplaceZoneFunctions(&g_original_zones[g_zone_count++], zone);
|
||||
ReplaceZoneFunctions(zone, &new_functions);
|
||||
}
|
||||
|
||||
malloc_zone_t* purgeable_zone = malloc_default_purgeable_zone();
|
||||
ReplaceZoneFunctions(purgeable_zone, &new_functions);
|
||||
if (g_zone_count >= kMaxZoneCount)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
Loading…
x
Reference in New Issue
Block a user