Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(956)

Side by Side Diff: third_party/tcmalloc/chromium/src/malloc_hook.cc

Issue 7430007: Merge tcmalloc r111 (perftools v. 1.8) with the chromium/ branch. Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2005, Google Inc. 1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 void InitialPreMMapHook(const void* start, 121 void InitialPreMMapHook(const void* start,
122 size_t size, 122 size_t size,
123 int protection, 123 int protection,
124 int flags, 124 int flags,
125 int fd, 125 int fd,
126 off_t offset) { 126 off_t offset) {
127 perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers); 127 perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers);
128 MallocHook::InvokePreMmapHook(start, size, protection, flags, fd, offset); 128 MallocHook::InvokePreMmapHook(start, size, protection, flags, fd, offset);
129 } 129 }
130 130
131 void InitialPreSbrkHook(std::ptrdiff_t increment) { 131 void InitialPreSbrkHook(ptrdiff_t increment) {
132 perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers); 132 perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers);
133 MallocHook::InvokePreSbrkHook(increment); 133 MallocHook::InvokePreSbrkHook(increment);
134 } 134 }
135 135
136 // This function is called at most once by one of the above initial malloc 136 // This function is called at most once by one of the above initial malloc
137 // hooks. It removes all initial hooks and initializes all other clients that 137 // hooks. It removes all initial hooks and initializes all other clients that
138 // want to get control at the very first memory allocation. The initializers 138 // want to get control at the very first memory allocation. The initializers
139 // may assume that the initial malloc hooks have been removed. The initializers 139 // may assume that the initial malloc hooks have been removed. The initializers
140 // may set up malloc hooks and allocate memory. 140 // may set up malloc hooks and allocate memory.
141 void RemoveInitialHooksAndCallInitializers() { 141 void RemoveInitialHooksAndCallInitializers() {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return actual_hooks_end; 276 return actual_hooks_end;
277 } 277 }
278 278
279 // Initialize a HookList (optionally with the given initial_value in index 0). 279 // Initialize a HookList (optionally with the given initial_value in index 0).
280 #define INIT_HOOK_LIST { 0 } 280 #define INIT_HOOK_LIST { 0 }
281 #define INIT_HOOK_LIST_WITH_VALUE(initial_value) \ 281 #define INIT_HOOK_LIST_WITH_VALUE(initial_value) \
282 { 1, { reinterpret_cast<AtomicWord>(initial_value) } } 282 { 1, { reinterpret_cast<AtomicWord>(initial_value) } }
283 283
284 // Explicit instantiation for malloc_hook_test.cc. This ensures all the methods 284 // Explicit instantiation for malloc_hook_test.cc. This ensures all the methods
285 // are instantiated. 285 // are instantiated.
286 template class HookList<MallocHook::NewHook>; 286 template struct HookList<MallocHook::NewHook>;
287 287
288 HookList<MallocHook::NewHook> new_hooks_ = 288 HookList<MallocHook::NewHook> new_hooks_ =
289 INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook); 289 INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook);
290 HookList<MallocHook::DeleteHook> delete_hooks_ = INIT_HOOK_LIST; 290 HookList<MallocHook::DeleteHook> delete_hooks_ = INIT_HOOK_LIST;
291 HookList<MallocHook::PreMmapHook> premmap_hooks_ = 291 HookList<MallocHook::PreMmapHook> premmap_hooks_ =
292 INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook); 292 INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook);
293 HookList<MallocHook::MmapHook> mmap_hooks_ = INIT_HOOK_LIST; 293 HookList<MallocHook::MmapHook> mmap_hooks_ = INIT_HOOK_LIST;
294 HookList<MallocHook::MunmapHook> munmap_hooks_ = INIT_HOOK_LIST; 294 HookList<MallocHook::MunmapHook> munmap_hooks_ = INIT_HOOK_LIST;
295 HookList<MallocHook::MremapHook> mremap_hooks_ = INIT_HOOK_LIST; 295 HookList<MallocHook::MremapHook> mremap_hooks_ = INIT_HOOK_LIST;
296 HookList<MallocHook::PreSbrkHook> presbrk_hooks_ = 296 HookList<MallocHook::PreSbrkHook> presbrk_hooks_ =
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 void MallocHook::InvokeMremapHookSlow(const void* result, 582 void MallocHook::InvokeMremapHookSlow(const void* result,
583 const void* old_addr, 583 const void* old_addr,
584 size_t old_size, 584 size_t old_size,
585 size_t new_size, 585 size_t new_size,
586 int flags, 586 int flags,
587 const void* new_addr) { 587 const void* new_addr) {
588 INVOKE_HOOKS(MremapHook, mremap_hooks_, (result, old_addr, old_size, new_size, 588 INVOKE_HOOKS(MremapHook, mremap_hooks_, (result, old_addr, old_size, new_size,
589 flags, new_addr)); 589 flags, new_addr));
590 } 590 }
591 591
592 void MallocHook::InvokePreSbrkHookSlow(std::ptrdiff_t increment) { 592 void MallocHook::InvokePreSbrkHookSlow(ptrdiff_t increment) {
593 INVOKE_HOOKS(PreSbrkHook, presbrk_hooks_, (increment)); 593 INVOKE_HOOKS(PreSbrkHook, presbrk_hooks_, (increment));
594 } 594 }
595 595
596 void MallocHook::InvokeSbrkHookSlow(const void* result, std::ptrdiff_t increment ) { 596 void MallocHook::InvokeSbrkHookSlow(const void* result, ptrdiff_t increment) {
597 INVOKE_HOOKS(SbrkHook, sbrk_hooks_, (result, increment)); 597 INVOKE_HOOKS(SbrkHook, sbrk_hooks_, (result, increment));
598 } 598 }
599 599
600 #undef INVOKE_HOOKS 600 #undef INVOKE_HOOKS
601 601
602 DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc); 602 DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc);
603 DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc); 603 DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc);
604 // actual functions are in debugallocation.cc or tcmalloc.cc 604 // actual functions are in debugallocation.cc or tcmalloc.cc
605 DEFINE_ATTRIBUTE_SECTION_VARS(malloc_hook); 605 DEFINE_ATTRIBUTE_SECTION_VARS(malloc_hook);
606 DECLARE_ATTRIBUTE_SECTION_VARS(malloc_hook); 606 DECLARE_ATTRIBUTE_SECTION_VARS(malloc_hook);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 } 691 }
692 RAW_LOG(WARNING, "Hooked allocator frame not found, returning empty trace"); 692 RAW_LOG(WARNING, "Hooked allocator frame not found, returning empty trace");
693 // If this happens try increasing kMaxSkip 693 // If this happens try increasing kMaxSkip
694 // or else something must be wrong with InHookCaller, 694 // or else something must be wrong with InHookCaller,
695 // e.g. for every section used in InHookCaller 695 // e.g. for every section used in InHookCaller
696 // all functions in that section must be inside the same library. 696 // all functions in that section must be inside the same library.
697 return 0; 697 return 0;
698 #endif 698 #endif
699 } 699 }
700 700
701 // On Linux/x86, we override mmap/munmap/mremap/sbrk 701 // On systems where we know how, we override mmap/munmap/mremap/sbrk
702 // and provide support for calling the related hooks. 702 // to provide support for calling the related hooks (in addition,
703 // 703 // of course, to doing what these functions normally do).
704 // We define mmap() and mmap64(), which somewhat reimplements libc's mmap
705 // syscall stubs. Unfortunately libc only exports the stubs via weak symbols
706 // (which we're overriding with our mmap64() and mmap() wrappers) so we can't
707 // just call through to them.
708 704
705 #if defined(__linux)
706 # include "malloc_hook_mmap_linux.h"
709 707
710 #if defined(__linux) && \ 708 // This code doesn't even compile on my freebsd 8.1 (x86_64) system,
711 (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) 709 // so comment it out for now. TODO(csilvers): fix this!
712 #include <unistd.h> 710 #elif 0 && defined(__FreeBSD__)
713 #include <syscall.h> 711 # include "malloc_hook_mmap_freebsd.h"
714 #include <sys/mman.h>
715 #include <errno.h>
716 #include "base/linux_syscall_support.h"
717 712
718 // The x86-32 case and the x86-64 case differ: 713 #else
719 // 32b has a mmap2() syscall, 64b does not.
720 // 64b and 32b have different calling conventions for mmap().
721 #if defined(__x86_64__) || defined(__PPC64__)
722
723 static inline void* do_mmap64(void *start, size_t length,
724 int prot, int flags,
725 int fd, __off64_t offset) __THROW {
726 return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset);
727 }
728
729 #elif defined(__i386__) || defined(__PPC__)
730
731 static inline void* do_mmap64(void *start, size_t length,
732 int prot, int flags,
733 int fd, __off64_t offset) __THROW {
734 void *result;
735
736 // Try mmap2() unless it's not supported
737 static bool have_mmap2 = true;
738 if (have_mmap2) {
739 static int pagesize = 0;
740 if (!pagesize) pagesize = getpagesize();
741
742 // Check that the offset is page aligned
743 if (offset & (pagesize - 1)) {
744 result = MAP_FAILED;
745 errno = EINVAL;
746 goto out;
747 }
748
749 result = (void *)syscall(SYS_mmap2,
750 start, length, prot, flags, fd,
751 (off_t) (offset / pagesize));
752 if (result != MAP_FAILED || errno != ENOSYS) goto out;
753
754 // We don't have mmap2() after all - don't bother trying it in future
755 have_mmap2 = false;
756 }
757
758 if (((off_t)offset) != offset) {
759 // If we're trying to map a 64-bit offset, fail now since we don't
760 // have 64-bit mmap() support.
761 result = MAP_FAILED;
762 errno = EINVAL;
763 goto out;
764 }
765
766 {
767 // Fall back to old 32-bit offset mmap() call
768 // Old syscall interface cannot handle six args, so pass in an array
769 int32 args[6] = { (int32) start, length, prot, flags, fd, (off_t) offset };
770 result = (void *)syscall(SYS_mmap, args);
771 }
772 out:
773 return result;
774 }
775
776 # endif // defined(__x86_64__)
777
778 // We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook
779 // calls right into mmap and mmap64, so that the stack frames in the caller's
780 // stack are at the same offsets for all the calls of memory allocating
781 // functions.
782
783 // Put all callers of MallocHook::Invoke* in this module into
784 // malloc_hook section,
785 // so that MallocHook::GetCallerStackTrace can function accurately:
786
787 // Make sure mmap doesn't get #define'd away by <sys/mman.h>
788 #undef mmap
789
790 extern "C" {
791 void* mmap64(void *start, size_t length, int prot, int flags,
792 int fd, __off64_t offset ) __THROW
793 ATTRIBUTE_SECTION(malloc_hook);
794 void* mmap(void *start, size_t length,int prot, int flags,
795 int fd, off_t offset) __THROW
796 ATTRIBUTE_SECTION(malloc_hook);
797 int munmap(void* start, size_t length) __THROW
798 ATTRIBUTE_SECTION(malloc_hook);
799 void* mremap(void* old_addr, size_t old_size, size_t new_size,
800 int flags, ...) __THROW
801 ATTRIBUTE_SECTION(malloc_hook);
802 void* sbrk(std::ptrdiff_t increment) __THROW
803 ATTRIBUTE_SECTION(malloc_hook);
804 }
805
806 extern "C" void* mmap64(void *start, size_t length, int prot, int flags,
807 int fd, __off64_t offset) __THROW {
808 MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
809 void *result;
810 if (!MallocHook::InvokeMmapReplacement(
811 start, length, prot, flags, fd, offset, &result)) {
812 result = do_mmap64(start, length, prot, flags, fd, offset);
813 }
814 MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
815 return result;
816 }
817
818 #if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)
819
820 extern "C" void* mmap(void *start, size_t length, int prot, int flags,
821 int fd, off_t offset) __THROW {
822 MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
823 void *result;
824 if (!MallocHook::InvokeMmapReplacement(
825 start, length, prot, flags, fd, offset, &result)) {
826 result = do_mmap64(start, length, prot, flags, fd,
827 static_cast<size_t>(offset)); // avoid sign extension
828 }
829 MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
830 return result;
831 }
832
833 #endif // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)
834
835 extern "C" int munmap(void* start, size_t length) __THROW {
836 MallocHook::InvokeMunmapHook(start, length);
837 int result;
838 if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
839 result = syscall(SYS_munmap, start, length);
840 }
841 return result;
842 }
843
844 extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size,
845 int flags, ...) __THROW {
846 va_list ap;
847 va_start(ap, flags);
848 void *new_address = va_arg(ap, void *);
849 va_end(ap);
850 void* result = sys_mremap(old_addr, old_size, new_size, flags, new_address);
851 MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags,
852 new_address);
853 return result;
854 }
855
856 // libc's version:
857 extern "C" void* __sbrk(std::ptrdiff_t increment);
858
859 extern "C" void* sbrk(std::ptrdiff_t increment) __THROW {
860 MallocHook::InvokePreSbrkHook(increment);
861 void *result = __sbrk(increment);
862 MallocHook::InvokeSbrkHook(result, increment);
863 return result;
864 }
865
866 /*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot,
867 int flags, int fd, off_t offset) {
868 void* result;
869 if (!MallocHook::InvokeMmapReplacement(
870 start, length, prot, flags, fd, offset, &result)) {
871 result = do_mmap64(start, length, prot, flags, fd, offset);
872 }
873 return result;
874 }
875
876 /*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) {
877 int result;
878 if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
879 result = sys_munmap(start, length);
880 }
881 return result;
882 }
883
884 #else // defined(__linux) &&
885 // (defined(__i386__) || defined(__x86_64__) || defined(__PPC__))
886 714
887 /*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, 715 /*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot,
888 int flags, int fd, off_t offset) { 716 int flags, int fd, off_t offset) {
889 void* result; 717 void* result;
890 if (!MallocHook::InvokeMmapReplacement( 718 if (!MallocHook::InvokeMmapReplacement(
891 start, length, prot, flags, fd, offset, &result)) { 719 start, length, prot, flags, fd, offset, &result)) {
892 result = mmap(start, length, prot, flags, fd, offset); 720 result = mmap(start, length, prot, flags, fd, offset);
893 } 721 }
894 return result; 722 return result;
895 } 723 }
896 724
897 /*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { 725 /*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) {
898 int result; 726 int result;
899 if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { 727 if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
900 result = munmap(start, length); 728 result = munmap(start, length);
901 } 729 }
902 return result; 730 return result;
903 } 731 }
904 732
905 #endif // defined(__linux) && 733 #endif
906 // (defined(__i386__) || defined(__x86_64__) || defined(__PPC__))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698