113f1d561SEnrico Granata /* 213f1d561SEnrico Granata * Copyright (c) 1999-2007 Apple Inc. All rights reserved. 313f1d561SEnrico Granata * 413f1d561SEnrico Granata * @APPLE_LICENSE_HEADER_START@ 513f1d561SEnrico Granata * 613f1d561SEnrico Granata * This file contains Original Code and/or Modifications of Original Code 713f1d561SEnrico Granata * as defined in and that are subject to the Apple Public Source License 813f1d561SEnrico Granata * Version 2.0 (the 'License'). You may not use this file except in 913f1d561SEnrico Granata * compliance with the License. Please obtain a copy of the License at 1013f1d561SEnrico Granata * http://www.opensource.apple.com/apsl/ and read it before using this 1113f1d561SEnrico Granata * file. 1213f1d561SEnrico Granata * 1313f1d561SEnrico Granata * The Original Code and all software distributed under the License are 1413f1d561SEnrico Granata * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 1513f1d561SEnrico Granata * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 1613f1d561SEnrico Granata * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 1713f1d561SEnrico Granata * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 1813f1d561SEnrico Granata * Please see the License for the specific language governing rights and 1913f1d561SEnrico Granata * limitations under the License. 2013f1d561SEnrico Granata * 2113f1d561SEnrico Granata * @APPLE_LICENSE_HEADER_END@ 2213f1d561SEnrico Granata */ 2313f1d561SEnrico Granata 2413f1d561SEnrico Granata #ifndef malloc_history_test_stack_logging_h 2513f1d561SEnrico Granata #define malloc_history_test_stack_logging_h 2613f1d561SEnrico Granata 2713f1d561SEnrico Granata #import <malloc/malloc.h> 2813f1d561SEnrico Granata 2913f1d561SEnrico Granata #define stack_logging_type_free 0 30*b9c1b51eSKate Stone #define stack_logging_type_generic \ 31*b9c1b51eSKate Stone 1 /* anything that is not allocation/deallocation */ 3213f1d561SEnrico Granata #define stack_logging_type_alloc 2 /* malloc, realloc, etc... */ 3313f1d561SEnrico Granata #define stack_logging_type_dealloc 4 /* free, realloc, etc... */ 3413f1d561SEnrico Granata 3513f1d561SEnrico Granata // Following flags are absorbed by stack_logging_log_stack() 3613f1d561SEnrico Granata #define stack_logging_flag_zone 8 /* NSZoneMalloc, etc... */ 3713f1d561SEnrico Granata #define stack_logging_flag_calloc 16 /* multiply arguments to get the size */ 38*b9c1b51eSKate Stone #define stack_logging_flag_object \ 39*b9c1b51eSKate Stone 32 /* NSAllocateObject(Class, extraBytes, zone) */ 4013f1d561SEnrico Granata #define stack_logging_flag_cleared 64 /* for NewEmptyHandle */ 41*b9c1b51eSKate Stone #define stack_logging_flag_handle 128 /* for Handle (de-)allocation routines \ 42*b9c1b51eSKate Stone */ 43*b9c1b51eSKate Stone #define stack_logging_flag_set_handle_size \ 44*b9c1b51eSKate Stone 256 /* (Handle, newSize) treated specially */ 4513f1d561SEnrico Granata 4613f1d561SEnrico Granata /* Macro used to disguise addresses so that leak finding can work */ 47*b9c1b51eSKate Stone #define STACK_LOGGING_DISGUISE(address) \ 48*b9c1b51eSKate Stone ((address) ^ 0x00005555) /* nicely idempotent */ 4913f1d561SEnrico Granata 50*b9c1b51eSKate Stone extern "C" int 51*b9c1b51eSKate Stone stack_logging_enable_logging; /* when clear, no logging takes place */ 52*b9c1b51eSKate Stone extern "C" int stack_logging_dontcompact; /* default is to compact; when set 53*b9c1b51eSKate Stone does not compact alloc/free logs; 54*b9c1b51eSKate Stone useful for tracing history */ 5513f1d561SEnrico Granata 56*b9c1b51eSKate Stone extern "C" void stack_logging_log_stack(unsigned type, unsigned arg1, 57*b9c1b51eSKate Stone unsigned arg2, unsigned arg3, 58*b9c1b51eSKate Stone unsigned result, 59*b9c1b51eSKate Stone unsigned num_hot_to_skip); 60*b9c1b51eSKate Stone /* This is the old log-to-memory logger, which is now deprecated. It remains 61*b9c1b51eSKate Stone * for compatibility with performance tools that haven't been updated to 62*b9c1b51eSKate Stone * disk_stack_logging_log_stack() yet. */ 6313f1d561SEnrico Granata 64*b9c1b51eSKate Stone extern "C" void 65*b9c1b51eSKate Stone __disk_stack_logging_log_stack(uint32_t type_flags, uintptr_t zone_ptr, 66*b9c1b51eSKate Stone uintptr_t size, uintptr_t ptr_arg, 67*b9c1b51eSKate Stone uintptr_t return_val, uint32_t num_hot_to_skip); 68*b9c1b51eSKate Stone /* Fits as the malloc_logger; logs malloc/free/realloc events and can log custom 69*b9c1b51eSKate Stone * events if called directly */ 7013f1d561SEnrico Granata 7113f1d561SEnrico Granata /* 64-bit-aware stack log access. */ 7213f1d561SEnrico Granata typedef struct { 7313f1d561SEnrico Granata uint32_t type_flags; 7413f1d561SEnrico Granata uint64_t stack_identifier; 7513f1d561SEnrico Granata uint64_t argument; 7613f1d561SEnrico Granata mach_vm_address_t address; 7713f1d561SEnrico Granata } mach_stack_logging_record_t; 7813f1d561SEnrico Granata 79*b9c1b51eSKate Stone extern "C" kern_return_t 80*b9c1b51eSKate Stone __mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, 81*b9c1b51eSKate Stone mach_vm_address_t *stack_frames_buffer, 82*b9c1b51eSKate Stone uint32_t max_stack_frames, uint32_t *count); 8313f1d561SEnrico Granata /* Gets the last allocation record (malloc, realloc, or free) about address */ 8413f1d561SEnrico Granata 85*b9c1b51eSKate Stone extern "C" kern_return_t __mach_stack_logging_enumerate_records( 86*b9c1b51eSKate Stone task_t task, mach_vm_address_t address, 87*b9c1b51eSKate Stone void enumerator(mach_stack_logging_record_t, void *), void *context); 88*b9c1b51eSKate Stone /* Applies enumerator to all records involving address sending context as 89*b9c1b51eSKate Stone * enumerator's second parameter; if !address, applies enumerator to all records 90*b9c1b51eSKate Stone */ 9113f1d561SEnrico Granata 92*b9c1b51eSKate Stone extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack( 93*b9c1b51eSKate Stone task_t task, uint64_t stack_identifier, 94*b9c1b51eSKate Stone mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, 95*b9c1b51eSKate Stone uint32_t *count); 9613f1d561SEnrico Granata /* Given a uniqued_stack fills stack_frames_buffer */ 9713f1d561SEnrico Granata 9813f1d561SEnrico Granata #pragma mark - 9913f1d561SEnrico Granata #pragma mark Legacy 10013f1d561SEnrico Granata 101*b9c1b51eSKate Stone /* The following is the old 32-bit-only, in-process-memory stack logging. This 102*b9c1b51eSKate Stone * is deprecated and clients should move to the above 64-bit-aware disk stack 103*b9c1b51eSKate Stone * logging SPI. */ 10413f1d561SEnrico Granata 10513f1d561SEnrico Granata typedef struct { 10613f1d561SEnrico Granata unsigned type; 10713f1d561SEnrico Granata unsigned uniqued_stack; 10813f1d561SEnrico Granata unsigned argument; 10913f1d561SEnrico Granata unsigned address; /* disguised, to avoid confusing leaks */ 11013f1d561SEnrico Granata } stack_logging_record_t; 11113f1d561SEnrico Granata 11213f1d561SEnrico Granata typedef struct { 11313f1d561SEnrico Granata unsigned overall_num_bytes; 11413f1d561SEnrico Granata unsigned num_records; 11513f1d561SEnrico Granata unsigned lock; /* 0 means OK to lock; used for inter-process locking */ 11613f1d561SEnrico Granata unsigned *uniquing_table; /* allocated using vm_allocate() */ 11713f1d561SEnrico Granata /* hashtable organized as (PC, uniqued parent) 11813f1d561SEnrico Granata Only the second half of the table is active 11913f1d561SEnrico Granata To enable us to grow dynamically */ 12013f1d561SEnrico Granata unsigned uniquing_table_num_pages; /* number of pages of the table */ 12113f1d561SEnrico Granata unsigned extra_retain_count; /* not used by stack_logging_log_stack */ 12213f1d561SEnrico Granata unsigned filler[2]; /* align to cache lines for better performance */ 12313f1d561SEnrico Granata stack_logging_record_t records[0]; /* records follow here */ 12413f1d561SEnrico Granata } stack_logging_record_list_t; 12513f1d561SEnrico Granata 12613f1d561SEnrico Granata extern "C" stack_logging_record_list_t *stack_logging_the_record_list; 12713f1d561SEnrico Granata /* This is the global variable containing all logs */ 12813f1d561SEnrico Granata 129*b9c1b51eSKate Stone extern "C" kern_return_t 130*b9c1b51eSKate Stone stack_logging_get_frames(task_t task, memory_reader_t reader, 131*b9c1b51eSKate Stone vm_address_t address, 132*b9c1b51eSKate Stone vm_address_t *stack_frames_buffer, 133*b9c1b51eSKate Stone unsigned max_stack_frames, unsigned *num_frames); 13413f1d561SEnrico Granata /* Gets the last record in stack_logging_the_record_list about address */ 13513f1d561SEnrico Granata 136*b9c1b51eSKate Stone #define STACK_LOGGING_ENUMERATION_PROVIDED \ 137*b9c1b51eSKate Stone 1 // temporary to avoid dependencies between projects 13813f1d561SEnrico Granata 139*b9c1b51eSKate Stone extern "C" kern_return_t stack_logging_enumerate_records( 140*b9c1b51eSKate Stone task_t task, memory_reader_t reader, vm_address_t address, 141*b9c1b51eSKate Stone void enumerator(stack_logging_record_t, void *), void *context); 14213f1d561SEnrico Granata /* Gets all the records about address; 14313f1d561SEnrico Granata If !address, gets all records */ 14413f1d561SEnrico Granata 145*b9c1b51eSKate Stone extern "C" kern_return_t stack_logging_frames_for_uniqued_stack( 146*b9c1b51eSKate Stone task_t task, memory_reader_t reader, unsigned uniqued_stack, 147*b9c1b51eSKate Stone vm_address_t *stack_frames_buffer, unsigned max_stack_frames, 148*b9c1b51eSKate Stone unsigned *num_frames); 14913f1d561SEnrico Granata /* Given a uniqued_stack fills stack_frames_buffer */ 15013f1d561SEnrico Granata 151*b9c1b51eSKate Stone extern "C" void thread_stack_pcs(vm_address_t *buffer, unsigned max, 152*b9c1b51eSKate Stone unsigned *num); 153*b9c1b51eSKate Stone /* Convenience to fill buffer with the PCs of the frames, starting with the hot 154*b9c1b51eSKate Stone frames; 15513f1d561SEnrico Granata num: returned number of frames 15613f1d561SEnrico Granata */ 15713f1d561SEnrico Granata 15813f1d561SEnrico Granata #endif 159