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 /* 28 * Display group information and walk all elements of a group 29 */ 30 31 #include "group.h" 32 33 #include <mdb/mdb_modapi.h> 34 #include <sys/group.h> 35 36 /* 37 * Display group information 38 */ 39 40 /* ARGSUSED */ 41 int 42 group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 43 { 44 group_t group; 45 int opt_q = 0; /* display only address. */ 46 47 /* Should provide an address */ 48 if (!(flags & DCMD_ADDRSPEC)) 49 return (DCMD_USAGE); 50 51 if (mdb_getopts(argc, argv, 52 'q', MDB_OPT_SETBITS, TRUE, &opt_q, 53 NULL) != argc) 54 return (DCMD_USAGE); 55 56 if (flags & DCMD_PIPE_OUT) 57 opt_q = B_TRUE; 58 59 if (DCMD_HDRSPEC(flags) && !opt_q) { 60 mdb_printf("%?s %6s %9s %?s\n", 61 "ADDR", 62 "SIZE", 63 "CAPACITY", 64 "SET"); 65 } 66 67 if (mdb_vread(&group, sizeof (struct group), addr) == -1) { 68 mdb_warn("unable to read 'group' at %p", addr); 69 return (DCMD_ERR); 70 } 71 72 if (opt_q) { 73 mdb_printf("%0?p\n", addr); 74 return (DCMD_OK); 75 } 76 77 mdb_printf("%?p %6d %9d %?p\n", 78 addr, group.grp_size, group.grp_capacity, group.grp_set); 79 80 return (DCMD_OK); 81 } 82 83 /* 84 * Walk all elements in the group set. 85 */ 86 87 typedef struct group_walk { 88 uintptr_t *gw_set; 89 int gw_size; 90 int gw_pos; 91 int gw_initialized; 92 } group_walk_t; 93 94 95 /* 96 * Initialize the walk structure with the copy of a group set, its size and the 97 * initial pointer position. 98 */ 99 int 100 group_walk_init(mdb_walk_state_t *wsp) 101 { 102 group_walk_t *gw; 103 group_t group; 104 105 gw = mdb_alloc(sizeof (group_walk_t), UM_SLEEP | UM_GC); 106 107 if (mdb_vread(&group, sizeof (struct group), wsp->walk_addr) == -1) { 108 mdb_warn("couldn't read 'group' at %p", wsp->walk_addr); 109 return (WALK_ERR); 110 } 111 112 gw->gw_size = group.grp_size; 113 gw->gw_initialized = 0; 114 gw->gw_pos = 0; 115 116 if (gw->gw_size < 0) { 117 mdb_warn("invalid group at %p", wsp->walk_addr); 118 return (WALK_ERR); 119 } 120 121 if (gw->gw_size == 0) 122 return (WALK_DONE); 123 124 /* 125 * Allocate space for the set and copy all set entries. 126 */ 127 gw->gw_set = mdb_alloc(group.grp_size * sizeof (uintptr_t), 128 UM_SLEEP | UM_GC); 129 130 if (mdb_vread(gw->gw_set, group.grp_size * sizeof (uintptr_t), 131 (uintptr_t)group.grp_set) == -1) { 132 mdb_warn("couldn't read 'group set' at %p", group.grp_set); 133 return (WALK_ERR); 134 } 135 136 wsp->walk_data = gw; 137 wsp->walk_addr = gw->gw_set[0]; 138 gw->gw_pos = 0; 139 140 return (WALK_NEXT); 141 } 142 143 /* 144 * Print element of the set and advance the pointer. 145 */ 146 int 147 group_walk_step(mdb_walk_state_t *wsp) 148 { 149 group_walk_t *gw = (group_walk_t *)wsp->walk_data; 150 int status; 151 152 /* 153 * Already visited all valid elements, nothing else to do. 154 */ 155 if (gw->gw_size < 0) 156 return (WALK_DONE); 157 158 /* 159 * Print non-NULL elements 160 */ 161 status = wsp->walk_addr == 0 ? 162 WALK_NEXT : 163 wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 164 wsp->walk_cbdata); 165 166 /* 167 * Adjust walk_addr to point to the next element 168 */ 169 gw->gw_size--; 170 171 if (gw->gw_size > 0) 172 wsp->walk_addr = gw->gw_set[++gw->gw_pos]; 173 else 174 status = WALK_DONE; 175 176 return (status); 177 } 178