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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Display group information and walk all elements of a group 31 */ 32 33 #include "group.h" 34 35 #include <mdb/mdb_modapi.h> 36 #include <sys/group.h> 37 38 /* 39 * Display group information 40 */ 41 42 /* ARGSUSED */ 43 int 44 group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 45 { 46 group_t group; 47 int opt_q = 0; /* display only address. */ 48 49 /* Should provide an address */ 50 if (!(flags & DCMD_ADDRSPEC)) 51 return (DCMD_USAGE); 52 53 if (mdb_getopts(argc, argv, 54 'q', MDB_OPT_SETBITS, TRUE, &opt_q, 55 NULL) != argc) 56 return (DCMD_USAGE); 57 58 if (flags & DCMD_PIPE_OUT) 59 opt_q = B_TRUE; 60 61 if (DCMD_HDRSPEC(flags) && !opt_q) { 62 mdb_printf("%?s %6s %9s %?s\n", 63 "ADDR", 64 "SIZE", 65 "CAPACITY", 66 "SET"); 67 } 68 69 if (mdb_vread(&group, sizeof (struct group), addr) == -1) { 70 mdb_warn("unable to read 'group' at %p", addr); 71 return (DCMD_ERR); 72 } 73 74 if (opt_q) { 75 mdb_printf("%0?p\n", addr); 76 return (DCMD_OK); 77 } 78 79 mdb_printf("%?p %6d %9d %?p\n", 80 addr, group.grp_size, group.grp_capacity, group.grp_set); 81 82 return (DCMD_OK); 83 } 84 85 /* 86 * Walk all elements in the group set. 87 */ 88 89 typedef struct group_walk { 90 uintptr_t *gw_set; 91 int gw_size; 92 int gw_pos; 93 int gw_initialized; 94 } group_walk_t; 95 96 97 /* 98 * Initialize the walk structure with the copy of a group set, its size and the 99 * initial pointer position. 100 */ 101 int 102 group_walk_init(mdb_walk_state_t *wsp) 103 { 104 group_walk_t *gw; 105 group_t group; 106 107 gw = mdb_alloc(sizeof (group_walk_t), UM_SLEEP | UM_GC); 108 109 if (mdb_vread(&group, sizeof (struct group), wsp->walk_addr) == -1) { 110 mdb_warn("couldn't read 'group' at %p", wsp->walk_addr); 111 return (WALK_ERR); 112 } 113 114 gw->gw_size = group.grp_size; 115 gw->gw_initialized = 0; 116 gw->gw_pos = 0; 117 118 if (gw->gw_size < 0) { 119 mdb_warn("invalid group at %p", wsp->walk_addr); 120 return (WALK_ERR); 121 } 122 123 if (gw->gw_size == 0) 124 return (WALK_DONE); 125 126 /* 127 * Allocate space for the set and copy all set entries. 128 */ 129 gw->gw_set = mdb_alloc(group.grp_size * sizeof (uintptr_t), 130 UM_SLEEP | UM_GC); 131 132 if (mdb_vread(gw->gw_set, group.grp_size * sizeof (uintptr_t), 133 (uintptr_t)group.grp_set) == -1) { 134 mdb_warn("couldn't read 'group set' at %p", group.grp_set); 135 return (WALK_ERR); 136 } 137 138 wsp->walk_data = gw; 139 wsp->walk_addr = gw->gw_set[0]; 140 gw->gw_pos = 0; 141 142 return (WALK_NEXT); 143 } 144 145 /* 146 * Print element of the set and advance the pointer. 147 */ 148 int 149 group_walk_step(mdb_walk_state_t *wsp) 150 { 151 group_walk_t *gw = (group_walk_t *)wsp->walk_data; 152 int status; 153 154 /* 155 * Already visited all valid elements, nothing else to do. 156 */ 157 if (gw->gw_size < 0) 158 return (WALK_DONE); 159 160 /* 161 * Print non-NULL elements 162 */ 163 status = wsp->walk_addr == NULL ? 164 WALK_NEXT : 165 wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 166 wsp->walk_cbdata); 167 168 /* 169 * Adjust walk_addr to point to the next element 170 */ 171 gw->gw_size--; 172 173 if (gw->gw_size > 0) 174 wsp->walk_addr = gw->gw_set[++gw->gw_pos]; 175 else 176 status = WALK_DONE; 177 178 return (status); 179 } 180