Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "base/process_util.h" | 5 #include "base/process_util.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #include <crt_externs.h> | 8 #include <crt_externs.h> |
| 9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
| 10 #include <mach/mach.h> | 10 #include <mach/mach.h> |
| 11 #include <mach/mach_init.h> | 11 #include <mach/mach_init.h> |
| 12 #include <mach/mach_vm.h> | 12 #include <mach/mach_vm.h> |
| 13 #include <mach/shared_region.h> | 13 #include <mach/shared_region.h> |
| 14 #include <mach/task.h> | 14 #include <mach/task.h> |
| 15 #include <mach-o/dyld.h> | |
| 16 #include <mach-o/nlist.h> | |
| 15 #include <malloc/malloc.h> | 17 #include <malloc/malloc.h> |
| 16 #import <objc/runtime.h> | 18 #import <objc/runtime.h> |
| 17 #include <spawn.h> | 19 #include <spawn.h> |
| 18 #include <sys/mman.h> | 20 #include <sys/mman.h> |
| 19 #include <sys/sysctl.h> | 21 #include <sys/sysctl.h> |
| 20 #include <sys/types.h> | 22 #include <sys/types.h> |
| 21 #include <sys/wait.h> | 23 #include <sys/wait.h> |
| 22 | 24 |
| 23 #include <new> | 25 #include <new> |
| 24 #include <string> | 26 #include <string> |
| 25 | 27 |
| 26 #include "base/debug/debugger.h" | 28 #include "base/debug/debugger.h" |
| 27 #include "base/eintr_wrapper.h" | 29 #include "base/eintr_wrapper.h" |
| 28 #include "base/hash_tables.h" | 30 #include "base/hash_tables.h" |
| 29 #include "base/logging.h" | 31 #include "base/logging.h" |
| 30 #include "base/mac/mac_util.h" | 32 #include "base/mac/mac_util.h" |
| 31 #include "base/string_util.h" | 33 #include "base/string_util.h" |
| 32 #include "base/sys_info.h" | 34 #include "base/sys_info.h" |
| 33 #include "base/sys_string_conversions.h" | 35 #include "base/sys_string_conversions.h" |
| 34 #include "base/time.h" | 36 #include "base/time.h" |
| 35 #include "third_party/apple_apsl/CFBase.h" | 37 #include "third_party/apple_apsl/CFBase.h" |
| 36 #include "third_party/apple_apsl/malloc.h" | 38 #include "third_party/apple_apsl/malloc.h" |
| 39 #include "third_party/mach_override/mach_override.h" | |
| 37 | 40 |
| 38 namespace base { | 41 namespace base { |
| 39 | 42 |
| 40 void RestoreDefaultExceptionHandler() { | 43 void RestoreDefaultExceptionHandler() { |
| 41 // This function is tailored to remove the Breakpad exception handler. | 44 // This function is tailored to remove the Breakpad exception handler. |
| 42 // exception_mask matches s_exception_mask in | 45 // exception_mask matches s_exception_mask in |
| 43 // breakpad/src/client/mac/handler/exception_handler.cc | 46 // breakpad/src/client/mac/handler/exception_handler.cc |
| 44 const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | | 47 const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | |
| 45 EXC_MASK_BAD_INSTRUCTION | | 48 EXC_MASK_BAD_INSTRUCTION | |
| 46 EXC_MASK_ARITHMETIC | | 49 EXC_MASK_ARITHMETIC | |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 vm_size_t page_size; | 479 vm_size_t page_size; |
| 477 kr = host_page_size(host, &page_size); | 480 kr = host_page_size(host, &page_size); |
| 478 if (kr) { | 481 if (kr) { |
| 479 LOG(ERROR) << "Failed to fetch host page size."; | 482 LOG(ERROR) << "Failed to fetch host page size."; |
| 480 return 0; | 483 return 0; |
| 481 } | 484 } |
| 482 | 485 |
| 483 return (data.active_count * page_size) / 1024; | 486 return (data.active_count * page_size) / 1024; |
| 484 } | 487 } |
| 485 | 488 |
| 489 namespace { | |
| 490 | |
| 491 // Finds the library path for malloc() and thus the libC part of libSystem, | |
| 492 // which in Lion is in a separate image. | |
| 493 const char* LookUpLibCPath() { | |
| 494 const void* addr = reinterpret_cast<void*>(&malloc); | |
| 495 | |
| 496 Dl_info info; | |
| 497 if (dladdr(addr, &info)) | |
| 498 return info.dli_fname; | |
| 499 | |
| 500 LOG(WARNING) << "Could not find image path for malloc()"; | |
| 501 return NULL; | |
| 502 } | |
| 503 | |
| 504 typedef void(*malloc_error_break_t)(void); | |
| 505 malloc_error_break_t g_original_malloc_error_break = NULL; | |
| 506 | |
| 507 // Returns the function pointer for malloc_error_break. This symbol is declared | |
| 508 // as __private_extern__ and cannot be dlsym()ed. Instead, use nlist() to | |
| 509 // get it. | |
| 510 malloc_error_break_t LookUpMallocErrorBreak() { | |
|
Scott Hess - ex-Googler
2011/08/22 19:50:35
Would it be worthwhile to unify this with the comp
Robert Sesek
2011/08/22 19:52:14
We want to explicitly discourage this kind of very
Mark Mentovai
2011/08/22 20:07:23
shess wrote:
| |
| 511 #if ARCH_CPU_32_BITS | |
| 512 const char* lib_c_path = LookUpLibCPath(); | |
| 513 if (!lib_c_path) | |
| 514 return NULL; | |
| 515 | |
| 516 // Only need to look up two symbols, but nlist() requires a NULL-terminated | |
| 517 // array and takes no count. | |
| 518 struct nlist nl[3]; | |
| 519 bzero(&nl, sizeof(nl)); | |
| 520 | |
| 521 // The symbol to find. | |
| 522 nl[0].n_un.n_name = const_cast<char*>("_malloc_error_break"); | |
| 523 | |
| 524 // A reference symbol by which the address of the desired symbol will be | |
| 525 // calculated. | |
| 526 nl[1].n_un.n_name = const_cast<char*>("_malloc"); | |
| 527 | |
| 528 int rv = nlist(lib_c_path, nl); | |
| 529 if (rv != 0 || nl[0].n_type == N_UNDF || nl[1].n_type == N_UNDF) { | |
| 530 return NULL; | |
| 531 } | |
| 532 | |
| 533 // nlist() returns addresses as offsets in the image, not the instruction | |
| 534 // pointer in memory. Use the known in-memory address of malloc() | |
| 535 // to compute the offset for malloc_error_break(). | |
| 536 uintptr_t reference_addr = reinterpret_cast<uintptr_t>(&malloc); | |
| 537 reference_addr -= nl[1].n_value; | |
| 538 reference_addr += nl[0].n_value; | |
| 539 | |
| 540 return reinterpret_cast<malloc_error_break_t>(reference_addr); | |
| 541 #endif // ARCH_CPU_32_BITS | |
| 542 | |
| 543 return NULL; | |
| 544 } | |
| 545 | |
| 546 void CrMallocErrorBreak() { | |
| 547 g_original_malloc_error_break(); | |
| 548 LOG(ERROR) << | |
| 549 "Terminating process due to a potential for future heap corruption"; | |
| 550 base::debug::BreakDebugger(); | |
| 551 } | |
| 552 | |
| 553 } // namespace | |
| 554 | |
| 555 void EnableTerminationOnHeapCorruption() { | |
| 556 malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak(); | |
| 557 if (!malloc_error_break) { | |
| 558 LOG(WARNING) << "Could not find malloc_error_break"; | |
| 559 return; | |
| 560 } | |
| 561 | |
| 562 mach_error_t err = mach_override_ptr( | |
| 563 (void*)malloc_error_break, | |
| 564 (void*)&CrMallocErrorBreak, | |
| 565 (void**)&g_original_malloc_error_break); | |
| 566 | |
| 567 if (err != err_none) | |
| 568 LOG(WARNING) << "Could not override malloc_error_break; error = " << err; | |
| 569 } | |
| 570 | |
| 486 // ------------------------------------------------------------------------ | 571 // ------------------------------------------------------------------------ |
| 487 | 572 |
| 488 namespace { | 573 namespace { |
| 489 | 574 |
| 490 bool g_oom_killer_enabled; | 575 bool g_oom_killer_enabled; |
| 491 | 576 |
| 492 // === C malloc/calloc/valloc/realloc/posix_memalign === | 577 // === C malloc/calloc/valloc/realloc/posix_memalign === |
| 493 | 578 |
| 494 typedef void* (*malloc_type)(struct _malloc_zone_t* zone, | 579 typedef void* (*malloc_type)(struct _malloc_zone_t* zone, |
| 495 size_t size); | 580 size_t size); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 892 if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) { | 977 if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) { |
| 893 PLOG(ERROR) << "sysctl"; | 978 PLOG(ERROR) << "sysctl"; |
| 894 return -1; | 979 return -1; |
| 895 } | 980 } |
| 896 if (length == 0) | 981 if (length == 0) |
| 897 return -1; | 982 return -1; |
| 898 return info.kp_eproc.e_ppid; | 983 return info.kp_eproc.e_ppid; |
| 899 } | 984 } |
| 900 | 985 |
| 901 } // namespace base | 986 } // namespace base |
| OLD | NEW |