OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains all the logic necessary to intercept allocations on | 5 // This file contains all the logic necessary to intercept allocations on |
6 // macOS. "malloc zones" are an abstraction that allows the process to intercept | 6 // macOS. "malloc zones" are an abstraction that allows the process to intercept |
7 // all malloc-related functions. There is no good mechanism [short of | 7 // all malloc-related functions. There is no good mechanism [short of |
8 // interposition] to determine new malloc zones are added, so there's no clean | 8 // interposition] to determine new malloc zones are added, so there's no clean |
9 // mechanism to intercept all malloc zones. This file contains logic to | 9 // mechanism to intercept all malloc zones. This file contains logic to |
10 // intercept the default and purgeable zones, which always exist. A cursory | 10 // intercept the default and purgeable zones, which always exist. A cursory |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 | 345 |
346 vm_address_t* zones; | 346 vm_address_t* zones; |
347 unsigned int count; | 347 unsigned int count; |
348 kern_return_t kr = malloc_get_all_zones(mach_task_self(), 0, &zones, &count); | 348 kern_return_t kr = malloc_get_all_zones(mach_task_self(), 0, &zones, &count); |
349 if (kr != KERN_SUCCESS) | 349 if (kr != KERN_SUCCESS) |
350 return; | 350 return; |
351 for (unsigned int i = 0; i < count; ++i) { | 351 for (unsigned int i = 0; i < count; ++i) { |
352 ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); | 352 ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); |
353 StoreMallocZone(zone); | 353 StoreMallocZone(zone); |
354 } | 354 } |
| 355 |
| 356 // This ensures that the purgeable zone is at the back of the array. |
| 357 ChromeMallocZone* purgeable_zone = |
| 358 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
| 359 StoreMallocZone(purgeable_zone); |
355 } | 360 } |
356 | 361 |
357 void ReplaceFunctionsForStoredZones(const MallocZoneFunctions* functions) { | 362 void ReplaceFunctionsForStoredZones(const MallocZoneFunctions* functions) { |
| 363 ChromeMallocZone* default_zone = |
| 364 reinterpret_cast<ChromeMallocZone*>(malloc_default_zone()); |
| 365 if (IsMallocZoneAlreadyStored(default_zone) && |
| 366 default_zone->malloc != functions->malloc) { |
| 367 ReplaceZoneFunctions(default_zone, functions); |
| 368 } |
| 369 |
358 vm_address_t* zones; | 370 vm_address_t* zones; |
359 unsigned int count; | 371 unsigned int count; |
360 kern_return_t kr = | 372 kern_return_t kr = |
361 malloc_get_all_zones(mach_task_self(), nullptr, &zones, &count); | 373 malloc_get_all_zones(mach_task_self(), nullptr, &zones, &count); |
362 if (kr != KERN_SUCCESS) | 374 if (kr != KERN_SUCCESS) |
363 return; | 375 return; |
364 for (unsigned int i = 0; i < count; ++i) { | 376 for (unsigned int i = 0; i < count; ++i) { |
365 ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); | 377 ChromeMallocZone* zone = reinterpret_cast<ChromeMallocZone*>(zones[i]); |
366 if (IsMallocZoneAlreadyStored(zone) && zone->malloc != functions->malloc) { | 378 if (IsMallocZoneAlreadyStored(zone) && zone->malloc != functions->malloc) { |
367 ReplaceZoneFunctions(zone, functions); | 379 ReplaceZoneFunctions(zone, functions); |
368 } | 380 } |
369 } | 381 } |
| 382 |
| 383 ChromeMallocZone* purgeable_zone = |
| 384 reinterpret_cast<ChromeMallocZone*>(malloc_default_purgeable_zone()); |
| 385 if (IsMallocZoneAlreadyStored(purgeable_zone) && |
| 386 purgeable_zone->malloc != functions->malloc) { |
| 387 ReplaceZoneFunctions(purgeable_zone, functions); |
| 388 } |
| 389 |
370 g_replaced_default_zone = true; | 390 g_replaced_default_zone = true; |
371 } | 391 } |
372 | 392 |
373 void InterceptAllocationsMac() { | 393 void InterceptAllocationsMac() { |
374 if (g_oom_killer_enabled) | 394 if (g_oom_killer_enabled) |
375 return; | 395 return; |
376 | 396 |
377 g_oom_killer_enabled = true; | 397 g_oom_killer_enabled = true; |
378 | 398 |
379 // === C malloc/calloc/valloc/realloc/posix_memalign === | 399 // === C malloc/calloc/valloc/realloc/posix_memalign === |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 g_old_allocWithZone = | 511 g_old_allocWithZone = |
492 reinterpret_cast<allocWithZone_t>(method_getImplementation(orig_method)); | 512 reinterpret_cast<allocWithZone_t>(method_getImplementation(orig_method)); |
493 CHECK(g_old_allocWithZone) | 513 CHECK(g_old_allocWithZone) |
494 << "Failed to get allocWithZone allocation function."; | 514 << "Failed to get allocWithZone allocation function."; |
495 method_setImplementation(orig_method, | 515 method_setImplementation(orig_method, |
496 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 516 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
497 } | 517 } |
498 | 518 |
499 } // namespace allocator | 519 } // namespace allocator |
500 } // namespace base | 520 } // namespace base |
OLD | NEW |