stack_logging.h
6.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* Copyright (c) 1999-2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef malloc_history_test_stack_logging_h
#define malloc_history_test_stack_logging_h
#import <malloc/malloc.h>
#define stack_logging_type_free 0
#define stack_logging_type_generic \
1 /* anything that is not allocation/deallocation */
#define stack_logging_type_alloc 2 /* malloc, realloc, etc... */
#define stack_logging_type_dealloc 4 /* free, realloc, etc... */
// Following flags are absorbed by stack_logging_log_stack()
#define stack_logging_flag_zone 8 /* NSZoneMalloc, etc... */
#define stack_logging_flag_calloc 16 /* multiply arguments to get the size */
#define stack_logging_flag_object \
32 /* NSAllocateObject(Class, extraBytes, zone) */
#define stack_logging_flag_cleared 64 /* for NewEmptyHandle */
#define stack_logging_flag_handle 128 /* for Handle (de-)allocation routines \
*/
#define stack_logging_flag_set_handle_size \
256 /* (Handle, newSize) treated specially */
/* Macro used to disguise addresses so that leak finding can work */
#define STACK_LOGGING_DISGUISE(address) \
((address) ^ 0x00005555) /* nicely idempotent */
extern "C" int
stack_logging_enable_logging; /* when clear, no logging takes place */
extern "C" int stack_logging_dontcompact; /* default is to compact; when set
does not compact alloc/free logs;
useful for tracing history */
extern "C" void stack_logging_log_stack(unsigned type, unsigned arg1,
unsigned arg2, unsigned arg3,
unsigned result,
unsigned num_hot_to_skip);
/* This is the old log-to-memory logger, which is now deprecated. It remains
* for compatibility with performance tools that haven't been updated to
* disk_stack_logging_log_stack() yet. */
extern "C" void
__disk_stack_logging_log_stack(uint32_t type_flags, uintptr_t zone_ptr,
uintptr_t size, uintptr_t ptr_arg,
uintptr_t return_val, uint32_t num_hot_to_skip);
/* Fits as the malloc_logger; logs malloc/free/realloc events and can log custom
* events if called directly */
/* 64-bit-aware stack log access. */
typedef struct {
uint32_t type_flags;
uint64_t stack_identifier;
uint64_t argument;
mach_vm_address_t address;
} mach_stack_logging_record_t;
extern "C" kern_return_t
__mach_stack_logging_get_frames(task_t task, mach_vm_address_t address,
mach_vm_address_t *stack_frames_buffer,
uint32_t max_stack_frames, uint32_t *count);
/* Gets the last allocation record (malloc, realloc, or free) about address */
extern "C" kern_return_t __mach_stack_logging_enumerate_records(
task_t task, mach_vm_address_t address,
void enumerator(mach_stack_logging_record_t, void *), void *context);
/* Applies enumerator to all records involving address sending context as
* enumerator's second parameter; if !address, applies enumerator to all records
*/
extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack(
task_t task, uint64_t stack_identifier,
mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames,
uint32_t *count);
/* Given a uniqued_stack fills stack_frames_buffer */
#pragma mark -
#pragma mark Legacy
/* The following is the old 32-bit-only, in-process-memory stack logging. This
* is deprecated and clients should move to the above 64-bit-aware disk stack
* logging SPI. */
typedef struct {
unsigned type;
unsigned uniqued_stack;
unsigned argument;
unsigned address; /* disguised, to avoid confusing leaks */
} stack_logging_record_t;
typedef struct {
unsigned overall_num_bytes;
unsigned num_records;
unsigned lock; /* 0 means OK to lock; used for inter-process locking */
unsigned *uniquing_table; /* allocated using vm_allocate() */
/* hashtable organized as (PC, uniqued parent)
Only the second half of the table is active
To enable us to grow dynamically */
unsigned uniquing_table_num_pages; /* number of pages of the table */
unsigned extra_retain_count; /* not used by stack_logging_log_stack */
unsigned filler[2]; /* align to cache lines for better performance */
stack_logging_record_t records[0]; /* records follow here */
} stack_logging_record_list_t;
extern "C" stack_logging_record_list_t *stack_logging_the_record_list;
/* This is the global variable containing all logs */
extern "C" kern_return_t
stack_logging_get_frames(task_t task, memory_reader_t reader,
vm_address_t address,
vm_address_t *stack_frames_buffer,
unsigned max_stack_frames, unsigned *num_frames);
/* Gets the last record in stack_logging_the_record_list about address */
#define STACK_LOGGING_ENUMERATION_PROVIDED \
1 // temporary to avoid dependencies between projects
extern "C" kern_return_t stack_logging_enumerate_records(
task_t task, memory_reader_t reader, vm_address_t address,
void enumerator(stack_logging_record_t, void *), void *context);
/* Gets all the records about address;
If !address, gets all records */
extern "C" kern_return_t stack_logging_frames_for_uniqued_stack(
task_t task, memory_reader_t reader, unsigned uniqued_stack,
vm_address_t *stack_frames_buffer, unsigned max_stack_frames,
unsigned *num_frames);
/* Given a uniqued_stack fills stack_frames_buffer */
extern "C" void thread_stack_pcs(vm_address_t *buffer, unsigned max,
unsigned *num);
/* Convenience to fill buffer with the PCs of the frames, starting with the hot
frames;
num: returned number of frames
*/
#endif