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 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #define LK_NUM_TYPES 8 /* arbitrary */ 35 36 #ifdef _KERNEL 37 typedef pc_t leak_pc_t; 38 #else 39 typedef uintptr_t leak_pc_t; 40 #endif 41 42 typedef struct leak_mtab { 43 uintptr_t lkm_base; 44 uintptr_t lkm_limit; 45 uintptr_t lkm_bufctl; /* target-defined */ 46 } leak_mtab_t; 47 48 typedef struct leak_bufctl { 49 struct leak_bufctl *lkb_hash_next; /* internal use only */ 50 struct leak_bufctl *lkb_next; 51 uintptr_t lkb_addr; /* should be unique */ 52 uintptr_t lkb_bufaddr; 53 uintptr_t lkb_data; 54 uintptr_t lkb_cid; 55 hrtime_t lkb_timestamp; 56 int lkb_dups; 57 uint8_t lkb_type; 58 uint8_t lkb_depth; 59 leak_pc_t lkb_stack[1]; /* actually lkb_depth */ 60 } leak_bufctl_t; 61 #define LEAK_BUFCTL_SIZE(d) (OFFSETOF(leak_bufctl_t, lkb_stack[(d)])) 62 63 /* 64 * callbacks for target to use 65 */ 66 extern void leaky_grep(uintptr_t, size_t); /* grep a vaddr range */ 67 extern void leaky_grep_ptr(uintptr_t); /* grep a pointer */ 68 extern void leaky_mark_ptr(uintptr_t); /* mark a pointer */ 69 extern int leaky_lookup_marked(uintptr_t, uintptr_t *, size_t *); 70 71 extern void leaky_add_leak(int, uintptr_t, uintptr_t, hrtime_t, 72 leak_pc_t *, uint_t, uintptr_t, uintptr_t); 73 74 /* 75 * ::findleaks target interface 76 * 77 * int leaky_subr_estimate(estp) 78 * Validate that any debugging options ::findleaks needs are active, 79 * and store an upper bound on the number of buffers in the system into 80 * estp. 81 * 82 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 83 * 84 * int leaky_subr_fill(mtpp) 85 * Passes a pointer to an mtab pointer, which points to the beginning 86 * of the mtab array. Target should add an entry for each buffer in 87 * the system to the array, and update the pointer to point at the end 88 * of the table (i.e. one mtab beyond the last valid entry). 89 * 90 * The lkm_bufctl entry in each mtab is target-defined. 91 * 92 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 93 * 94 * int leaky_subr_run(void) 95 * Target should invoke leaky_grep() or one of its variants on the 96 * root portions of the virtual address space. Any pointers which 97 * are not reachable from those roots will be reported as leaks. 98 * 99 * Returns DCMD_OK to proceed, DCMD_ERR to abort ::findleaks. 100 * 101 * void leaky_subr_add_leak(mtp) 102 * Invoked once for each leak. Target should call leaky_add_leak() 103 * with the full details of the leak, which will be copied into a 104 * leak_bufctl_t. That will be used in subsequent target invocations 105 * to identify the buffer. 106 * 107 * leaky_add_leak() takes the following arguments: 108 * type target-defined, 0 <= type < LK_NUM_TYPES. Leaks are 109 * grouped by type. 110 * 111 * addr Address of the control structure for this leak. 112 * Should be unique across all types -- ::walk leak and 113 * ::walk leakbuf use this field to identify leaks. 114 * 115 * bufaddr Address of the beginning of the buffer -- reported by 116 * ::walk leakbuf. 117 * 118 * timestamp 119 * High-resolution timestamp, usually of the time of 120 * allocation. Coalesced leaks are represented by 121 * the leak with the earliest timestamp. 122 * 123 * stack, depth 124 * The stack trace for this leak. Leaks with 125 * identical stack traces will be coalesced. 126 * 127 * cid coalesce identifier -- leaks with differing 128 * cids will not be coalesced. 129 * 130 * data target-defined data 131 * 132 * int leaky_subr_bufctl_cmp(lhs, rhs) 133 * Target-defined display order for two leaks. Both leaks will have 134 * the same lkb_type -- full display order is type (lowest-to-highest), 135 * then whatever order this function defines. 136 * 137 * void leaky_subr_dump_start(type) 138 * void leaky_subr_dump(lkb, verbose) 139 * void leaky_subr_dump_end(type) 140 * Used to dump the table of discovered leaks. invoked as: 141 * 142 * for i in 0 .. LK_NUM_TYPES 143 * leaky_subr_dump_start(i) 144 * for lkb in (possibly a subset of) the type i leaks 145 * leaky_subr_dump(lkb, 0) 146 * leaky_subr_dump_end(i) 147 * 148 * if (-d was passed to ::findleaks) 149 * for i in 0 .. LK_NUM_TYPES 150 * for lkb of type i, same subset/order as above 151 * leaky_subr_dump(lkb, 1) 152 * 153 * leaky_subr_dump_start()/end() are always invoked for each type, even 154 * if there are no leaks of that type. leaky_subr_dump() can use the 155 * leaks chained off of lkb_next to access coalesced leaks. lkb_dups 156 * is the length of the dup list. 157 * 158 * int leaky_subr_invoke_callback(lkb, cb, cbarg) 159 * Underlying implementation of '::walk leak' walker -- target should 160 * invoke cb for the passed in leak_bufctl_t. 161 */ 162 extern int leaky_subr_estimate(size_t *); 163 extern int leaky_subr_fill(leak_mtab_t **); 164 165 extern int leaky_subr_run(void); 166 167 extern void leaky_subr_add_leak(leak_mtab_t *); 168 169 extern int leaky_subr_bufctl_cmp(const leak_bufctl_t *, const leak_bufctl_t *); 170 171 extern void leaky_subr_dump_start(int); 172 extern void leaky_subr_dump(const leak_bufctl_t *, int verbose); 173 extern void leaky_subr_dump_end(int); 174 175 extern int leaky_subr_invoke_callback(const leak_bufctl_t *, mdb_walk_cb_t, 176 void *); 177 178 #ifdef __cplusplus 179 } 180 #endif 181 182 #endif /* _LEAKY_IMPL_H */ 183