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