OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 | 5 |
6 #include "base/process_util.h" | 6 #include "base/process_util.h" |
7 | 7 |
8 #import <Cocoa/Cocoa.h> | 8 #import <Cocoa/Cocoa.h> |
9 #include <crt_externs.h> | 9 #include <crt_externs.h> |
10 #include <dlfcn.h> | 10 #include <dlfcn.h> |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include <new> | 23 #include <new> |
24 #include <string> | 24 #include <string> |
25 | 25 |
26 #include "base/debug_util.h" | 26 #include "base/debug_util.h" |
27 #include "base/eintr_wrapper.h" | 27 #include "base/eintr_wrapper.h" |
28 #include "base/logging.h" | 28 #include "base/logging.h" |
29 #include "base/string_util.h" | 29 #include "base/string_util.h" |
30 #include "base/sys_info.h" | 30 #include "base/sys_info.h" |
31 #include "base/sys_string_conversions.h" | 31 #include "base/sys_string_conversions.h" |
32 #include "base/time.h" | 32 #include "base/time.h" |
| 33 #include "third_party/apple_apsl/CFBase.h" |
| 34 #include "third_party/apple_apsl/malloc.h" |
33 | 35 |
34 namespace base { | 36 namespace base { |
35 | 37 |
36 void RestoreDefaultExceptionHandler() { | 38 void RestoreDefaultExceptionHandler() { |
37 // This function is tailored to remove the Breakpad exception handler. | 39 // This function is tailored to remove the Breakpad exception handler. |
38 // exception_mask matches s_exception_mask in | 40 // exception_mask matches s_exception_mask in |
39 // breakpad/src/client/mac/handler/exception_handler.cc | 41 // breakpad/src/client/mac/handler/exception_handler.cc |
40 const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | | 42 const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | |
41 EXC_MASK_BAD_INSTRUCTION | | 43 EXC_MASK_BAD_INSTRUCTION | |
42 EXC_MASK_ARITHMETIC | | 44 EXC_MASK_ARITHMETIC | |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 } | 365 } |
364 | 366 |
365 // ------------------------------------------------------------------------ | 367 // ------------------------------------------------------------------------ |
366 | 368 |
367 namespace { | 369 namespace { |
368 | 370 |
369 bool g_oom_killer_enabled; | 371 bool g_oom_killer_enabled; |
370 | 372 |
371 // === C malloc/calloc/valloc/realloc/posix_memalign === | 373 // === C malloc/calloc/valloc/realloc/posix_memalign === |
372 | 374 |
373 // The extended version of malloc_zone_t from the 10.6 SDK's <malloc/malloc.h>, | |
374 // included here to allow for compilation in 10.5. (10.5 has version 3 zone | |
375 // allocators, while 10.6 has version 6 allocators.) | |
376 struct ChromeMallocZone { | |
377 void* reserved1; | |
378 void* reserved2; | |
379 size_t (*size)(struct _malloc_zone_t* zone, const void* ptr); | |
380 void* (*malloc)(struct _malloc_zone_t* zone, size_t size); | |
381 void* (*calloc)(struct _malloc_zone_t* zone, size_t num_items, size_t size); | |
382 void* (*valloc)(struct _malloc_zone_t* zone, size_t size); | |
383 void (*free)(struct _malloc_zone_t* zone, void* ptr); | |
384 void* (*realloc)(struct _malloc_zone_t* zone, void* ptr, size_t size); | |
385 void (*destroy)(struct _malloc_zone_t* zone); | |
386 const char* zone_name; | |
387 unsigned (*batch_malloc)(struct _malloc_zone_t* zone, size_t size, | |
388 void** results, unsigned num_requested); | |
389 void (*batch_free)(struct _malloc_zone_t* zone, void** to_be_freed, | |
390 unsigned num_to_be_freed); | |
391 struct malloc_introspection_t* introspect; | |
392 unsigned version; | |
393 void* (*memalign)(struct _malloc_zone_t* zone, size_t alignment, | |
394 size_t size); // version >= 5 | |
395 void (*free_definite_size)(struct _malloc_zone_t* zone, void* ptr, | |
396 size_t size); // version >= 6 | |
397 }; | |
398 | |
399 typedef void* (*malloc_type)(struct _malloc_zone_t* zone, | 375 typedef void* (*malloc_type)(struct _malloc_zone_t* zone, |
400 size_t size); | 376 size_t size); |
401 typedef void* (*calloc_type)(struct _malloc_zone_t* zone, | 377 typedef void* (*calloc_type)(struct _malloc_zone_t* zone, |
402 size_t num_items, | 378 size_t num_items, |
403 size_t size); | 379 size_t size); |
404 typedef void* (*valloc_type)(struct _malloc_zone_t* zone, | 380 typedef void* (*valloc_type)(struct _malloc_zone_t* zone, |
405 size_t size); | 381 size_t size); |
406 typedef void* (*realloc_type)(struct _malloc_zone_t* zone, | 382 typedef void* (*realloc_type)(struct _malloc_zone_t* zone, |
407 void* ptr, | 383 void* ptr, |
408 size_t size); | 384 size_t size); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 } | 495 } |
520 | 496 |
521 // === C++ operator new === | 497 // === C++ operator new === |
522 | 498 |
523 void oom_killer_new() { | 499 void oom_killer_new() { |
524 DebugUtil::BreakDebugger(); | 500 DebugUtil::BreakDebugger(); |
525 } | 501 } |
526 | 502 |
527 // === Core Foundation CFAllocators === | 503 // === Core Foundation CFAllocators === |
528 | 504 |
529 // This is the real structure of a CFAllocatorRef behind the scenes. See | |
530 // http://opensource.apple.com/source/CF/CF-476.19/CFBase.c (10.5.8) and | |
531 // http://opensource.apple.com/source/CF/CF-550/CFBase.c (10.6) for details. | |
532 struct ChromeCFRuntimeBase { | |
533 uintptr_t _cfisa; | |
534 uint8_t _cfinfo[4]; | |
535 #if __LP64__ | |
536 uint32_t _rc; | |
537 #endif | |
538 }; | |
539 | |
540 struct ChromeCFAllocator { | |
541 ChromeCFRuntimeBase cf_runtime_base; | |
542 size_t (*size)(struct _malloc_zone_t* zone, const void* ptr); | |
543 void* (*malloc)(struct _malloc_zone_t* zone, size_t size); | |
544 void* (*calloc)(struct _malloc_zone_t* zone, size_t num_items, size_t size); | |
545 void* (*valloc)(struct _malloc_zone_t* zone, size_t size); | |
546 void (*free)(struct _malloc_zone_t* zone, void* ptr); | |
547 void* (*realloc)(struct _malloc_zone_t* zone, void* ptr, size_t size); | |
548 void (*destroy)(struct _malloc_zone_t* zone); | |
549 const char* zone_name; | |
550 unsigned (*batch_malloc)(struct _malloc_zone_t* zone, size_t size, | |
551 void** results, unsigned num_requested); | |
552 void (*batch_free)(struct _malloc_zone_t* zone, void** to_be_freed, | |
553 unsigned num_to_be_freed); | |
554 struct malloc_introspection_t* introspect; | |
555 void* reserved5; | |
556 | |
557 void* allocator; | |
558 CFAllocatorContext context; | |
559 }; | |
560 typedef ChromeCFAllocator* ChromeCFAllocatorRef; | 505 typedef ChromeCFAllocator* ChromeCFAllocatorRef; |
561 | 506 |
562 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; | 507 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; |
563 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; | 508 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; |
564 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; | 509 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; |
565 | 510 |
566 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, | 511 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, |
567 CFOptionFlags hint, | 512 CFOptionFlags hint, |
568 void* info) { | 513 void* info) { |
569 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); | 514 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && | 711 CHECK(!g_old_cfallocator_system_default && !g_old_cfallocator_malloc && |
767 !g_old_cfallocator_malloc_zone) | 712 !g_old_cfallocator_malloc_zone) |
768 << "Old allocators unexpectedly non-null"; | 713 << "Old allocators unexpectedly non-null"; |
769 | 714 |
770 bool cf_allocator_internals_known = | 715 bool cf_allocator_internals_known = |
771 darwin_version == 9 || darwin_version == 10; | 716 darwin_version == 9 || darwin_version == 10; |
772 | 717 |
773 if (cf_allocator_internals_known) { | 718 if (cf_allocator_internals_known) { |
774 ChromeCFAllocatorRef allocator = const_cast<ChromeCFAllocatorRef>( | 719 ChromeCFAllocatorRef allocator = const_cast<ChromeCFAllocatorRef>( |
775 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorSystemDefault)); | 720 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorSystemDefault)); |
776 g_old_cfallocator_system_default = allocator->context.allocate; | 721 g_old_cfallocator_system_default = allocator->_context.allocate; |
777 CHECK(g_old_cfallocator_system_default) | 722 CHECK(g_old_cfallocator_system_default) |
778 << "Failed to get kCFAllocatorSystemDefault allocation function."; | 723 << "Failed to get kCFAllocatorSystemDefault allocation function."; |
779 allocator->context.allocate = oom_killer_cfallocator_system_default; | 724 allocator->_context.allocate = oom_killer_cfallocator_system_default; |
780 | 725 |
781 allocator = const_cast<ChromeCFAllocatorRef>( | 726 allocator = const_cast<ChromeCFAllocatorRef>( |
782 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMalloc)); | 727 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMalloc)); |
783 g_old_cfallocator_malloc = allocator->context.allocate; | 728 g_old_cfallocator_malloc = allocator->_context.allocate; |
784 CHECK(g_old_cfallocator_malloc) | 729 CHECK(g_old_cfallocator_malloc) |
785 << "Failed to get kCFAllocatorMalloc allocation function."; | 730 << "Failed to get kCFAllocatorMalloc allocation function."; |
786 allocator->context.allocate = oom_killer_cfallocator_malloc; | 731 allocator->_context.allocate = oom_killer_cfallocator_malloc; |
787 | 732 |
788 allocator = const_cast<ChromeCFAllocatorRef>( | 733 allocator = const_cast<ChromeCFAllocatorRef>( |
789 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMallocZone)); | 734 reinterpret_cast<const ChromeCFAllocator*>(kCFAllocatorMallocZone)); |
790 g_old_cfallocator_malloc_zone = allocator->context.allocate; | 735 g_old_cfallocator_malloc_zone = allocator->_context.allocate; |
791 CHECK(g_old_cfallocator_malloc_zone) | 736 CHECK(g_old_cfallocator_malloc_zone) |
792 << "Failed to get kCFAllocatorMallocZone allocation function."; | 737 << "Failed to get kCFAllocatorMallocZone allocation function."; |
793 allocator->context.allocate = oom_killer_cfallocator_malloc_zone; | 738 allocator->_context.allocate = oom_killer_cfallocator_malloc_zone; |
794 } else { | 739 } else { |
795 NSLog(@"Internals of CFAllocator not known; out-of-memory failures via " | 740 NSLog(@"Internals of CFAllocator not known; out-of-memory failures via " |
796 "CFAllocator will not result in termination. http://crbug.com/45650"); | 741 "CFAllocator will not result in termination. http://crbug.com/45650"); |
797 } | 742 } |
798 | 743 |
799 // === Cocoa NSObject allocation === | 744 // === Cocoa NSObject allocation === |
800 | 745 |
801 // Note that both +[NSObject new] and +[NSObject alloc] call through to | 746 // Note that both +[NSObject new] and +[NSObject alloc] call through to |
802 // +[NSObject allocWithZone:]. | 747 // +[NSObject allocWithZone:]. |
803 | 748 |
804 CHECK(!g_old_allocWithZone) | 749 CHECK(!g_old_allocWithZone) |
805 << "Old allocator unexpectedly non-null"; | 750 << "Old allocator unexpectedly non-null"; |
806 | 751 |
807 Class nsobject_class = [NSObject class]; | 752 Class nsobject_class = [NSObject class]; |
808 Method orig_method = class_getClassMethod(nsobject_class, | 753 Method orig_method = class_getClassMethod(nsobject_class, |
809 @selector(allocWithZone:)); | 754 @selector(allocWithZone:)); |
810 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 755 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
811 method_getImplementation(orig_method)); | 756 method_getImplementation(orig_method)); |
812 CHECK(g_old_allocWithZone) | 757 CHECK(g_old_allocWithZone) |
813 << "Failed to get allocWithZone allocation function."; | 758 << "Failed to get allocWithZone allocation function."; |
814 method_setImplementation(orig_method, | 759 method_setImplementation(orig_method, |
815 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 760 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
816 } | 761 } |
817 | 762 |
818 } // namespace base | 763 } // namespace base |
OLD | NEW |