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