| 1 | /* |
| 2 | * Copyright (c) 2000-2012 Apple Inc. All rights reserved. |
| 3 | * |
| 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
| 5 | * |
| 6 | * This file contains Original Code and/or Modifications of Original Code |
| 7 | * as defined in and that are subject to the Apple Public Source License |
| 8 | * Version 2.0 (the 'License'). You may not use this file except in |
| 9 | * compliance with the License. The rights granted to you under the License |
| 10 | * may not be used to create, or enable the creation or redistribution of, |
| 11 | * unlawful or unlicensed copies of an Apple operating system, or to |
| 12 | * circumvent, violate, or enable the circumvention or violation of, any |
| 13 | * terms of an Apple operating system software license agreement. |
| 14 | * |
| 15 | * Please obtain a copy of the License at |
| 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
| 17 | * |
| 18 | * The Original Code and all software distributed under the License are |
| 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
| 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
| 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
| 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
| 23 | * Please see the License for the specific language governing rights and |
| 24 | * limitations under the License. |
| 25 | * |
| 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
| 27 | */ |
| 28 | /* |
| 29 | * @OSF_COPYRIGHT@ |
| 30 | */ |
| 31 | /* |
| 32 | * HISTORY |
| 33 | * |
| 34 | * Revision 1.1.1.1 1998/09/22 21:05:49 wsanchez |
| 35 | * Import of Mac OS X kernel (~semeria) |
| 36 | * |
| 37 | * Revision 1.1.1.1 1998/03/07 02:26:08 wsanchez |
| 38 | * Import of OSF Mach kernel (~mburg) |
| 39 | * |
| 40 | * Revision 1.1.5.2 1996/07/31 09:57:36 paire |
| 41 | * Added some more constraints to __asm__ functions for compilation |
| 42 | * under gcc2.7.1 for PROF_CNT_[L]{ADD|SUB} macros |
| 43 | * [96/06/14 paire] |
| 44 | * |
| 45 | * Revision 1.1.5.1 1995/01/06 19:53:52 devrcs |
| 46 | * mk6 CR668 - 1.3b26 merge |
| 47 | * new file for mk6 |
| 48 | * [1994/10/12 22:25:27 dwm] |
| 49 | * |
| 50 | * Revision 1.1.2.2 1994/05/16 19:19:26 meissner |
| 51 | * Add {,L}PROF_CNT_{SUB,LSUB,OVERFLOW} macros for gprof command. |
| 52 | * [1994/05/10 10:36:06 meissner] |
| 53 | * |
| 54 | * Correct 64-bit integer asms to specify result values as inputs, and use =g instead of =m. |
| 55 | * Cast the integer argument to PROF_CNT_ADD to unsigned long, so a short register is widened. |
| 56 | * Add more support for writing the gprof command. |
| 57 | * PROF_CNT_{EQ,NE} should not use ^=, it just uses ^. |
| 58 | * Round PROF_CNT_DIGITS up to 24 bytes so it is word aligned. |
| 59 | * _profile_cnt_to_decimal now takes the low/high values as separate arguments. |
| 60 | * Delete _profile_cnt_to_hex. |
| 61 | * [1994/04/28 21:45:07 meissner] |
| 62 | * |
| 63 | * Add more 64 bit arithmetic macros to support writing gprof. |
| 64 | * [1994/04/20 15:47:05 meissner] |
| 65 | * |
| 66 | * Revision 1.1.2.1 1994/04/08 17:51:56 meissner |
| 67 | * Correct spelling on LPROF_CNT_TO_LDOUBLE macro. |
| 68 | * [1994/04/08 16:18:06 meissner] |
| 69 | * |
| 70 | * Make LHISTCOUNTER be 64 bits. |
| 71 | * Define LPROF_CNT_INC to increment LHISTCOUNTER. |
| 72 | * [1994/04/08 12:40:32 meissner] |
| 73 | * |
| 74 | * Make most stats 64 bits, except for things like memory allocation. |
| 75 | * [1994/04/02 14:58:34 meissner] |
| 76 | * |
| 77 | * Add overflow support for {gprof,prof,old,dummy}_mcount counters. |
| 78 | * [1994/03/17 20:13:37 meissner] |
| 79 | * |
| 80 | * Add gprof/prof overflow support |
| 81 | * [1994/03/17 14:56:56 meissner] |
| 82 | * |
| 83 | * Define LHISTCOUNTER. |
| 84 | * [1994/02/28 12:05:16 meissner] |
| 85 | * |
| 86 | * Set HISTFRACTION to 4, so new lprofil call takes the same space. |
| 87 | * [1994/02/24 16:15:34 meissner] |
| 88 | * |
| 89 | * Add too_low/too_high to profile_stats. |
| 90 | * [1994/02/16 22:38:23 meissner] |
| 91 | * |
| 92 | * Make prof_cnt_t unsigned long. |
| 93 | * [1994/02/11 16:52:09 meissner] |
| 94 | * |
| 95 | * Remember function unique ptr in gfuncs structure to reset profiling. |
| 96 | * Add support for range checking gprof arc {from,self}pc addresses. |
| 97 | * Add counter for # times acontext was locked. |
| 98 | * Expand copyright. |
| 99 | * [1994/02/07 12:41:08 meissner] |
| 100 | * |
| 101 | * Keep track of the number of times the kernel overflows the HISTCOUNTER counter. |
| 102 | * [1994/02/03 20:13:31 meissner] |
| 103 | * |
| 104 | * Add stats for {user,kernel,idle} mode in the kernel. |
| 105 | * [1994/02/03 15:17:36 meissner] |
| 106 | * |
| 107 | * No change. |
| 108 | * [1994/02/03 00:58:59 meissner] |
| 109 | * |
| 110 | * Combine _profile_{vars,stats,md}; Allow more than one _profile_vars. |
| 111 | * [1994/02/01 12:04:04 meissner] |
| 112 | * |
| 113 | * Split # records to # gprof and # prof records. |
| 114 | * Add my_cpu/max_cpu fields. |
| 115 | * [1994/01/28 23:33:30 meissner] |
| 116 | * |
| 117 | * Eliminate hash_{size,mask} from gfuncs structure. |
| 118 | * [1994/01/26 20:23:41 meissner] |
| 119 | * |
| 120 | * Add structure size fields to _profile_{vars,stats,md}. |
| 121 | * Add major/minor version number to _profile_md. |
| 122 | * Move allocation context block pointer to main structure. |
| 123 | * Delete shift count for allocation contexts. |
| 124 | * [1994/01/25 01:46:08 meissner] |
| 125 | * |
| 126 | * Add HASHFRACTION |
| 127 | * [1994/01/22 01:14:02 meissner] |
| 128 | * |
| 129 | * Split profile-md.h into profile-internal.h and profile-md. |
| 130 | * [1994/01/20 20:57:18 meissner] |
| 131 | * |
| 132 | * Fixup copyright. |
| 133 | * [1994/01/18 23:08:14 meissner] |
| 134 | * |
| 135 | * Make flags byte-sized. |
| 136 | * Add have_bb flag. |
| 137 | * Add init_format flag. |
| 138 | * [1994/01/18 21:57:18 meissner] |
| 139 | * |
| 140 | * CR 10198 - Initial version. |
| 141 | * [1994/01/18 19:44:59 meissner] |
| 142 | * |
| 143 | * $EndLog$ |
| 144 | */ |
| 145 | |
| 146 | #ifndef _PROFILE_MD_H |
| 147 | #define _PROFILE_MD_H |
| 148 | |
| 149 | #include <types.h> |
| 150 | |
| 151 | /* |
| 152 | * Define the interfaces between the assembly language profiling support |
| 153 | * that is common between the kernel, mach servers, and user space library. |
| 154 | */ |
| 155 | |
| 156 | /* |
| 157 | * Integer types used. |
| 158 | */ |
| 159 | |
| 160 | /* |
| 161 | * These hold either a pointer or a signed/unsigned int. |
| 162 | * They are 32 bit on i386 and 64 bit on x86_64. |
| 163 | */ |
| 164 | typedef long prof_ptrint_t; |
| 165 | typedef unsigned long prof_uptrint_t; |
| 166 | |
| 167 | typedef long prof_lock_t; /* lock word type */ |
| 168 | typedef unsigned char prof_flag_t; /* type for boolean flags */ |
| 169 | |
| 170 | /* |
| 171 | * Double precision counter. |
| 172 | */ |
| 173 | |
| 174 | /* These are 64 bit on both i386 and x86_64 */ |
| 175 | typedef unsigned long prof_cnt_t; |
| 176 | |
| 177 | /* x86_64 */ |
| 178 | #define PROF_CNT_INC(cnt) (cnt++) |
| 179 | #define PROF_CNT_ADD(cnt,val) (cnt+=val) |
| 180 | #define PROF_CNT_LADD(cnt,val) (cnt+=val) |
| 181 | #define PROF_CNT_SUB(cnt,val) (cnt-=val) |
| 182 | #define PROF_CNT_LSUB(cnt,val) (cnt-=val) |
| 183 | |
| 184 | #define PROF_ULONG_TO_CNT(cnt,val) (((cnt).high = 0), ((cnt).low = val)) |
| 185 | #define PROF_CNT_OVERFLOW(cnt,high,low) (((high) = (cnt).high), ((low) = (cnt).low)) |
| 186 | #define PROF_CNT_TO_ULONG(cnt) (((cnt).high == 0) ? (cnt).low : 0xffffffffu) |
| 187 | #define PROF_CNT_TO_LDOUBLE(cnt) ((((long double)(cnt).high) * 4294967296.0L) + (long double)(cnt).low) |
| 188 | #define PROF_CNT_TO_DECIMAL(buf,cnt) _profile_cnt_to_decimal(buf, (cnt).low, (cnt).high) |
| 189 | #define PROF_CNT_EQ_0(cnt) (((cnt).high | (cnt).low) == 0) |
| 190 | #define PROF_CNT_NE_0(cnt) (((cnt).high | (cnt).low) != 0) |
| 191 | #define PROF_CNT_EQ(cnt1,cnt2) ((((cnt1).high ^ (cnt2).high) | ((cnt1).low ^ (cnt2).low)) == 0) |
| 192 | #define PROF_CNT_NE(cnt1,cnt2) ((((cnt1).high ^ (cnt2).high) | ((cnt1).low ^ (cnt2).low)) != 0) |
| 193 | #define PROF_CNT_GT(cnt1,cnt2) (((cnt1).high > (cnt2).high) || ((cnt1).low > (cnt2).low)) |
| 194 | #define PROF_CNT_LT(cnt1,cnt2) (((cnt1).high < (cnt2).high) || ((cnt1).low < (cnt2).low)) |
| 195 | |
| 196 | /* max # digits + null to hold prof_cnt_t values (round up to multiple of 4) */ |
| 197 | #define PROF_CNT_DIGITS 24 |
| 198 | |
| 199 | /* |
| 200 | * Types of the profil counter. |
| 201 | */ |
| 202 | |
| 203 | typedef unsigned short HISTCOUNTER; /* profil */ |
| 204 | typedef prof_cnt_t LHISTCOUNTER; /* lprofil */ |
| 205 | |
| 206 | #define LPROF_ULONG_TO_CNT(cnt,val) PROF_ULONG_TO_CNT(cnt,val) |
| 207 | #define LPROF_CNT_INC(lp) PROF_CNT_INC(lp) |
| 208 | #define LPROF_CNT_ADD(lp,val) PROF_CNT_ADD(lp,val) |
| 209 | #define LPROF_CNT_LADD(lp,val) PROF_CNT_LADD(lp,val) |
| 210 | #define LPROF_CNT_SUB(lp,val) PROF_CNT_SUB(lp,val) |
| 211 | #define LPROF_CNT_LSUB(lp,val) PROF_CNT_LSUB(lp,val) |
| 212 | #define LPROF_CNT_OVERFLOW(lp,high,low) PROF_CNT_OVERFLOW(lp,high,low) |
| 213 | #define LPROF_CNT_TO_ULONG(lp) PROF_CNT_TO_ULONG(lp) |
| 214 | #define LPROF_CNT_TO_LDOUBLE(lp) PROF_CNT_TO_LDOUBLE(lp) |
| 215 | #define LPROF_CNT_TO_DECIMAL(buf,cnt) PROF_CNT_TO_DECIMAL(buf,cnt) |
| 216 | #define LPROF_CNT_EQ_0(cnt) PROF_CNT_EQ_0(cnt) |
| 217 | #define LPROF_CNT_NE_0(cnt) PROF_CNT_NE_0(cnt) |
| 218 | #define LPROF_CNT_EQ(cnt1,cnt2) PROF_CNT_EQ(cnt1,cnt2) |
| 219 | #define LPROF_CNT_NE(cnt1,cnt2) PROF_CNT_NE(cnt1,cnt2) |
| 220 | #define LPROF_CNT_GT(cnt1,cnt2) PROF_CNT_GT(cnt1,cnt2) |
| 221 | #define LPROF_CNT_LT(cnt1,cnt2) PROF_CNT_LT(cnt1,cnt2) |
| 222 | #define LPROF_CNT_DIGITS PROF_CNT_DIGITS |
| 223 | |
| 224 | /* |
| 225 | * fraction of text space to allocate for histogram counters |
| 226 | */ |
| 227 | |
| 228 | #define HISTFRACTION 4 |
| 229 | |
| 230 | /* |
| 231 | * Fraction of text space to allocate for from hash buckets. |
| 232 | */ |
| 233 | |
| 234 | #define HASHFRACTION HISTFRACTION |
| 235 | |
| 236 | /* |
| 237 | * Prof call count, external format. |
| 238 | */ |
| 239 | |
| 240 | struct prof_ext { |
| 241 | prof_uptrint_t cvalue; /* caller address */ |
| 242 | prof_uptrint_t cncall; /* # of calls */ |
| 243 | }; |
| 244 | |
| 245 | /* |
| 246 | * Prof call count, internal format. |
| 247 | */ |
| 248 | |
| 249 | struct prof_int { |
| 250 | struct prof_ext prof; /* external prof struct */ |
| 251 | prof_uptrint_t overflow; /* # times prof counter overflowed */ |
| 252 | }; |
| 253 | |
| 254 | /* |
| 255 | * Gprof arc, external format. |
| 256 | */ |
| 257 | |
| 258 | struct gprof_arc { |
| 259 | prof_uptrint_t frompc; /* caller's caller */ |
| 260 | prof_uptrint_t selfpc; /* caller's address */ |
| 261 | prof_uptrint_t count; /* # times arc traversed */ |
| 262 | }; |
| 263 | |
| 264 | /* |
| 265 | * Gprof arc, internal format. |
| 266 | */ |
| 267 | |
| 268 | struct hasharc { |
| 269 | struct hasharc *next; /* next gprof record */ |
| 270 | struct gprof_arc arc; /* gprof record */ |
| 271 | prof_uptrint_t overflow; /* # times counter overflowed */ |
| 272 | }; |
| 273 | |
| 274 | /* |
| 275 | * Linked list of all function profile blocks. |
| 276 | */ |
| 277 | |
| 278 | #define MAX_CACHE 3 /* # cache table entries */ |
| 279 | |
| 280 | struct gfuncs { |
| 281 | struct hasharc **hash_ptr; /* gprof hash table */ |
| 282 | struct hasharc **unique_ptr; /* function unique pointer */ |
| 283 | struct prof_int prof; /* -p stats for elf */ |
| 284 | struct hasharc *cache_ptr[MAX_CACHE]; /* cache element pointers */ |
| 285 | }; |
| 286 | |
| 287 | /* |
| 288 | * Profile information which might be written out in ELF {,g}mon.out files. |
| 289 | */ |
| 290 | |
| 291 | #define MAX_BUCKETS 9 /* max bucket chain to print out */ |
| 292 | |
| 293 | struct profile_stats { /* Debugging counters */ |
| 294 | prof_uptrint_t major_version; /* major version number */ |
| 295 | prof_uptrint_t minor_version; /* minor version number */ |
| 296 | prof_uptrint_t stats_size; /* size of profile_vars structure */ |
| 297 | prof_uptrint_t profil_buckets; /* # profil buckets */ |
| 298 | prof_uptrint_t my_cpu; /* identify current cpu/thread */ |
| 299 | prof_uptrint_t max_cpu; /* identify max cpu/thread */ |
| 300 | prof_uptrint_t prof_records; /* # of functions profiled */ |
| 301 | prof_uptrint_t gprof_records; /* # of gprof arcs */ |
| 302 | prof_uptrint_t hash_buckets; /* # gprof hash buckets */ |
| 303 | prof_uptrint_t bogus_count; /* # of bogus functions found in gprof */ |
| 304 | |
| 305 | prof_cnt_t cnt; /* # of calls to _{,g}prof_mcount */ |
| 306 | prof_cnt_t dummy; /* # of calls to _dummy_mcount */ |
| 307 | prof_cnt_t old_mcount; /* # of calls to old mcount */ |
| 308 | prof_cnt_t hash_search; /* # hash buckets searched */ |
| 309 | prof_cnt_t hash_num; /* # times hash table searched */ |
| 310 | prof_cnt_t user_ticks; /* # ticks in user space */ |
| 311 | prof_cnt_t kernel_ticks; /* # ticks in kernel space */ |
| 312 | prof_cnt_t idle_ticks; /* # ticks in idle mode */ |
| 313 | prof_cnt_t overflow_ticks; /* # ticks where HISTCOUNTER overflowed */ |
| 314 | prof_cnt_t acontext_locked; /* # times an acontext was locked */ |
| 315 | prof_cnt_t too_low; /* # times a histogram tick was too low */ |
| 316 | prof_cnt_t too_high; /* # times a histogram tick was too high */ |
| 317 | prof_cnt_t prof_overflow; /* # times a prof count field overflowed */ |
| 318 | prof_cnt_t gprof_overflow; /* # times a gprof count field overflowed */ |
| 319 | |
| 320 | /* allocation statistics */ |
| 321 | prof_uptrint_t num_alloc [(int)ACONTEXT_MAX]; /* # allocations */ |
| 322 | prof_uptrint_t bytes_alloc[(int)ACONTEXT_MAX]; /* bytes allocated */ |
| 323 | prof_uptrint_t num_context[(int)ACONTEXT_MAX]; /* # contexts */ |
| 324 | prof_uptrint_t wasted [(int)ACONTEXT_MAX]; /* wasted bytes */ |
| 325 | prof_uptrint_t overhead [(int)ACONTEXT_MAX]; /* overhead bytes */ |
| 326 | |
| 327 | prof_uptrint_t buckets[MAX_BUCKETS+1]; /* # hash indexes that have n buckets */ |
| 328 | prof_cnt_t cache_hits[MAX_CACHE]; /* # times nth cache entry matched */ |
| 329 | |
| 330 | prof_cnt_t stats_unused[64]; /* reserved for future use */ |
| 331 | }; |
| 332 | |
| 333 | #define PROFILE_MAJOR_VERSION 1 |
| 334 | #define PROFILE_MINOR_VERSION 1 |
| 335 | |
| 336 | /* |
| 337 | * Machine dependent fields. |
| 338 | */ |
| 339 | |
| 340 | struct profile_md { |
| 341 | int major_version; /* major version number */ |
| 342 | int minor_version; /* minor version number */ |
| 343 | size_t md_size; /* size of profile_md structure */ |
| 344 | struct hasharc **hash_ptr; /* gprof hash table */ |
| 345 | size_t hash_size; /* size of hash table */ |
| 346 | prof_uptrint_t num_cache; /* # of cache entries */ |
| 347 | void (*save_mcount_ptr)(void); /* save for _mcount_ptr */ |
| 348 | void (**mcount_ptr_ptr)(void); /* pointer to _mcount_ptr */ |
| 349 | struct hasharc *dummy_ptr; /* pointer to dummy gprof record */ |
| 350 | void *(*alloc_pages)(size_t); /* pointer to _profile_alloc_pages */ |
| 351 | char num_buffer[PROF_CNT_DIGITS]; /* convert 64 bit ints to string */ |
| 352 | long md_unused[58]; /* add unused fields */ |
| 353 | }; |
| 354 | |
| 355 | /* |
| 356 | * Record information about each function call. Specify |
| 357 | * caller, caller's caller, and a unique label for use by |
| 358 | * the profiling routines. |
| 359 | */ |
| 360 | extern void _prof_mcount(void); |
| 361 | extern void _gprof_mcount(void); |
| 362 | extern void _dummy_mcount(void); |
| 363 | extern void (*_mcount_ptr)(void); |
| 364 | |
| 365 | /* |
| 366 | * Function in profile-md.c to convert prof_cnt_t to string format (decimal & hex). |
| 367 | */ |
| 368 | extern char *_profile_cnt_to_decimal(char *, prof_uptrint_t, prof_uptrint_t); |
| 369 | |
| 370 | #endif /* _PROFILE_MD_H */ |
| 371 | |