bool MachTask::HasMallocLoggingEnabled () { bool found = false; __mach_stack_logging_enumerate_records(m_task, 0x0, foundStackLog, &found); return found; }
malloc_stack_entry * get_stack_history_for_address (const void * addr, int history) { std::vector<malloc_stack_entry> empty; g_malloc_stack_history.swap(empty); if (!stack_logging_enable_logging || (history && !stack_logging_dontcompact)) { if (history) strncpy(g_error_string, "error: stack history logging is not enabled, set MallocStackLoggingNoCompact=1 in the environment when launching to enable stack history logging.", sizeof(g_error_string)); else strncpy(g_error_string, "error: stack logging is not enabled, set MallocStackLogging=1 in the environment when launching to enable stack logging.", sizeof(g_error_string)); return NULL; } kern_return_t err; task_t task = mach_task_self(); if (history) { err = __mach_stack_logging_enumerate_records (task, (mach_vm_address_t)addr, get_stack_for_address_enumerator, &task); } else { uint32_t num_frames = 0; err = __mach_stack_logging_get_frames(task, (mach_vm_address_t)addr, g_stack_frames, MAX_FRAMES, &num_frames); if (err == 0 && num_frames > 0) { g_malloc_stack_history.resize(1); g_malloc_stack_history.back().address = addr; g_malloc_stack_history.back().type_flags = stack_logging_type_alloc; g_malloc_stack_history.back().argument = 0; if (num_frames > 0) g_malloc_stack_history.back().frames.assign(g_stack_frames, g_stack_frames + num_frames); g_malloc_stack_history.back().frames.push_back(0); // Terminate the frames with zero } } // Append an empty entry if (g_malloc_stack_history.empty()) return NULL; g_malloc_stack_history.resize(g_malloc_stack_history.size() + 1); g_malloc_stack_history.back().address = 0; g_malloc_stack_history.back().type_flags = 0; g_malloc_stack_history.back().argument = 0; return g_malloc_stack_history.data(); }
bool MachTask::EnumerateMallocRecords (mach_vm_address_t address, MachMallocEvent *event_buffer, uint32_t buffer_size, uint32_t *count) { if (!event_buffer || !count) return false; if (buffer_size == 0) return false; *count = 0; history_enumerator_impl_data data = { event_buffer, count, buffer_size }; __mach_stack_logging_enumerate_records(m_task, address, history_enumerator_impl, &data); return (*count > 0); }
malloc_stack_entry * get_stack_history_for_address (const void * addr, int history) { if (!stack_logging_enable_logging) return NULL; g_malloc_stack_history.clear(); kern_return_t err; task_t task = mach_task_self(); if (history) { err = __mach_stack_logging_enumerate_records (task, (mach_vm_address_t)addr, get_stack_for_address_enumerator, &task); } else { malloc_stack_entry *stack_entry = g_malloc_stack_history.next(); if (stack_entry) { stack_entry->address = addr; stack_entry->type_flags = stack_logging_type_alloc; stack_entry->argument = 0; stack_entry->num_frames = 0; stack_entry->frames[0] = 0; err = __mach_stack_logging_get_frames(task, (mach_vm_address_t)addr, stack_entry->frames, MAX_FRAMES, &stack_entry->num_frames); if (err == 0 && stack_entry->num_frames > 0) { // Terminate the frames with zero if there is room if (stack_entry->num_frames < MAX_FRAMES) stack_entry->frames[stack_entry->num_frames] = 0; } else { g_malloc_stack_history.clear(); } } } // Return data if there is any return g_malloc_stack_history.data(); }