1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _LEAKY_IMPL_H 28 #define _LEAKY_IMPL_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #define LK_NUM_TYPES 8 /* arbitrary */ 37 38 #ifdef _KERNEL 39 typedef pc_t leak_pc_t; 40 #else 41 typedef uintptr_t leak_pc_t; 42 #endif 43 44 typedef struct leak_mtab { 45 uintptr_t lkm_base; 46 uintptr_t lkm_limit; 47 uintptr_t lkm_bufctl; /* target-defined */ 48 } leak_mtab_t; 49 50 typedef struct leak_bufctl { 51 struct leak_bufctl *lkb_hash_next; /* internal use only */ 52 struct leak_bufctl *lkb_next; 53 uintptr_t lkb_addr; /* should be unique */ 54 uintptr_t lkb_bufaddr; 55 uintptr_t lkb_data; 56 uintptr_t lkb_cid; 57 hrtime_t lkb_timestamp; 58 int lkb_dups; 59 uint8_t lkb_type; 60 uint8_t lkb_depth; 61 leak_pc_t lkb_stack[1]; /* actually lkb_depth */ 62 } leak_bufctl_t; 63 #define LEAK_BUFCTL_SIZE(d) (OFFSETOF(leak_bufctl_t, lkb_stack[(d)])) 64 65 /* 66 * callbacks for target to use 67 */ 68 extern void leaky_grep(uintptr_t, size_t); /* grep a vaddr range */ 69 extern void leaky_grep_ptr(uintptr_t); /* grep a pointer */ 70 extern void leaky_mark_ptr(uintptr_t); /* mark a pointer */ 71 extern int leaky_lookup_marked(uintptr_t, uintptr_t *, size_t *); 72 73 extern void leaky_add_leak(int, uintptr_t, uintptr_t, hrtime_t, 74 leak_pc_t *, uint_t, uintptr_t, uintptr_t); 75 76 /* 77 * ::findleaks target interface 78 * 79 * int leaky_subr_estimate(estp) 80 * Validate that any debugging options ::findleaks needs are active, 81 * and store an upper bound on the number of buffers in the system into 82 * estp. 83 * 84 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 85 * 86 * int leaky_subr_fill(mtpp) 87 * Passes a pointer to an mtab pointer, which points to the beginning 88 * of the mtab array. Target should add an entry for each buffer in 89 * the system to the array, and update the pointer to point at the end 90 * of the table (i.e. one mtab beyond the last valid entry). 91 * 92 * The lkm_bufctl entry in each mtab is target-defined. 93 * 94 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 95 * 96 * int leaky_subr_run(void) 97 * Target should invoke leaky_grep() or one of its variants on the 98 * root portions of the virtual address space. Any pointers which 99 * are not reachable from those roots will be reported as leaks. 100 * 101 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 102 * 103 * void leaky_subr_add_leak(mtp) 104 * Invoked once for each leak. Target should call leaky_add_leak() 105 * with the full details of the leak, which will be copied into a 106 * leak_bufctl_t. That will be used in subsequent target invocations 107 * to identify the buffer. 108 * 109 * leaky_add_leak() takes the following arguments: 110 * type target-defined, 0 <= type < LK_NUM_TYPES. Leaks are 111 * grouped by type. 112 * 113 * addr Address of the control structure for this leak. 114 * Should be unique across all types -- ::walk leak and 115 * ::walk leakbuf use this field to identify leaks. 116 * 117 * bufaddr Address of the beginning of the buffer -- reported by 118 * ::walk leakbuf. 119 * 120 * timestamp 121 * High-resolution timestamp, usually of the time of 122 * allocation. Coalesced leaks are represented by 123 * the leak with the earliest timestamp. 124 * 125 * stack, depth 126 * The stack trace for this leak. Leaks with 127 * identical stack traces will be coalesced. 128 * 129 * cid coalesce identifier -- leaks with differing 130 * cids will not be coalesced. 131 * 132 * data target-defined data 133 * 134 * int leaky_subr_bufctl_cmp(lhs, rhs) 135 * Target-defined display order for two leaks. Both leaks will have 136 * the same lkb_type -- full display order is type (lowest-to-highest), 137 * then whatever order this function defines. 138 * 139 * void leaky_subr_dump_start(type) 140 * void leaky_subr_dump(lkb, verbose) 141 * void leaky_subr_dump_end(type) 142 * Used to dump the table of discovered leaks. invoked as: 143 * 144 * for i in 0 .. LK_NUM_TYPES 145 * leaky_subr_dump_start(i) 146 * for lkb in (possibly a subset of) the type i leaks 147 * leaky_subr_dump(lkb, 0) 148 * leaky_subr_dump_end(i) 149 * 150 * if (-d was passed to ::findleaks) 151 * for i in 0 .. LK_NUM_TYPES 152 * for lkb of type i, same subset/order as above 153 * leaky_subr_dump(lkb, 1) 154 * 155 * leaky_subr_dump_start()/end() are always invoked for each type, even 156 * if there are no leaks of that type. leaky_subr_dump() can use the 157 * leaks chained off of lkb_next to access coalesced leaks. lkb_dups 158 * is the length of the dup list. 159 * 160 * int leaky_subr_invoke_callback(lkb, cb, cbarg) 161 * Underlying implementation of '::walk leak' walker -- target should 162 * invoke cb for the passed in leak_bufctl_t. 163 */ 164 extern int leaky_subr_estimate(size_t *); 165 extern int leaky_subr_fill(leak_mtab_t **); 166 167 extern int leaky_subr_run(void); 168 169 extern void leaky_subr_add_leak(leak_mtab_t *); 170 171 extern int leaky_subr_bufctl_cmp(const leak_bufctl_t *, const leak_bufctl_t *); 172 173 extern void leaky_subr_dump_start(int); 174 extern void leaky_subr_dump(const leak_bufctl_t *, int verbose); 175 extern void leaky_subr_dump_end(int); 176 177 extern int leaky_subr_invoke_callback(const leak_bufctl_t *, mdb_walk_cb_t, 178 void *); 179 180 #ifdef __cplusplus 181 } 182 #endif 183 184 #endif /* _LEAKY_IMPL_H */ 185