Index: lib/asan/asan_mac.cc =================================================================== --- lib/asan/asan_mac.cc +++ lib/asan/asan_mac.cc @@ -21,6 +21,7 @@ #include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_atomic.h" +#include "sanitizer_common/sanitizer_file.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mac.h" @@ -78,6 +79,45 @@ return shadow_start; } +void WriteMemoryProfile(char *buf, uptr buf_size) { + uptr pos = 0; +#define SNPRINTF_CONCAT(...) \ + if (pos < buf_size) { \ + pos += internal_snprintf(buf + pos, buf_size - pos, __VA_ARGS__); \ + } +#define PRINT_STAT_FOR_REGION(name, beg, end) \ + { \ + uptr res, dirty; \ + RegionMemUsage(beg, end, &res, &dirty); \ + SNPRINTF_CONCAT("%s (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n", \ + name, (uptr)beg, (uptr)end, res / 1024, dirty / 1024); \ + } + + PRINT_STAT_FOR_REGION("HighMem ", kHighMemBeg, kHighMemEnd); + PRINT_STAT_FOR_REGION("HighShadow", kHighShadowBeg, kHighShadowEnd); + if (kMidMemBeg) { + PRINT_STAT_FOR_REGION("ShadowGap3", kShadowGap3Beg, kShadowGap3End); + PRINT_STAT_FOR_REGION("MidMem ", kMidMemBeg, kMidMemEnd); + PRINT_STAT_FOR_REGION("ShadowGap2", kShadowGap2Beg, kShadowGap2End); + PRINT_STAT_FOR_REGION("MidShadow ", kMidShadowBeg, kMidShadowEnd); + } + PRINT_STAT_FOR_REGION("ShadowGap ", kShadowGapBeg, kShadowGapEnd); + if (kLowShadowBeg) { + PRINT_STAT_FOR_REGION("LowShadow ", kLowShadowBeg, kLowShadowEnd); + PRINT_STAT_FOR_REGION("LowMem ", kLowMemBeg, kLowMemEnd); + } + SNPRINTF_CONCAT("------------------------------\n"); + +#undef SNPRINTF_CONCAT +#undef PRINT_STAT_FOR_REGION +} + +void MemoryProfiler() { + InternalScopedBuffer buf(4096); + WriteMemoryProfile(buf.data(), buf.size()); + WriteToFile(STDERR_FILENO, buf.data(), internal_strlen(buf.data())); +} + // No-op. Mac does not support static linkage anyway. void AsanCheckDynamicRTPrereqs() {} Index: lib/sanitizer_common/sanitizer_mac.h =================================================================== --- lib/sanitizer_common/sanitizer_mac.h +++ lib/sanitizer_common/sanitizer_mac.h @@ -36,6 +36,7 @@ char **GetEnviron(); +void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty); void RestrictMemoryToMaxAddress(uptr max_address); } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -506,6 +506,30 @@ return info.resident_size; } +void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) { + vm_address_t address = start; + vm_address_t end_address = end; + uptr resident_pages = 0; + uptr dirty_pages = 0; + while (address < end_address) { + vm_size_t vm_region_size; + mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT; + vm_region_extended_info_data_t vm_region_info; + mach_port_t object_name; + kern_return_t ret = vm_region_64( + mach_task_self(), &address, &vm_region_size, VM_REGION_EXTENDED_INFO, + (vm_region_info_t)&vm_region_info, &count, &object_name); + if (ret != KERN_SUCCESS) break; + + resident_pages += vm_region_info.pages_resident; + dirty_pages += vm_region_info.pages_dirtied; + + address += vm_region_size; + } + *res = resident_pages * GetPageSizeCached(); + *dirty = dirty_pages * GetPageSizeCached(); +} + void *internal_start_thread(void(*func)(void *arg), void *arg) { // Start the thread with signals blocked, otherwise it can steal user signals. __sanitizer_sigset_t set, old; Index: lib/tsan/rtl/tsan_platform_mac.cc =================================================================== --- lib/tsan/rtl/tsan_platform_mac.cc +++ lib/tsan/rtl/tsan_platform_mac.cc @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_mac.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" @@ -111,30 +112,6 @@ void FlushShadowMemory() { } -static void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) { - vm_address_t address = start; - vm_address_t end_address = end; - uptr resident_pages = 0; - uptr dirty_pages = 0; - while (address < end_address) { - vm_size_t vm_region_size; - mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT; - vm_region_extended_info_data_t vm_region_info; - mach_port_t object_name; - kern_return_t ret = vm_region_64( - mach_task_self(), &address, &vm_region_size, VM_REGION_EXTENDED_INFO, - (vm_region_info_t)&vm_region_info, &count, &object_name); - if (ret != KERN_SUCCESS) break; - - resident_pages += vm_region_info.pages_resident; - dirty_pages += vm_region_info.pages_dirtied; - - address += vm_region_size; - } - *res = resident_pages * GetPageSizeCached(); - *dirty = dirty_pages * GetPageSizeCached(); -} - void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { uptr shadow_res, shadow_dirty; uptr meta_res, meta_dirty;