xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/group.c (revision c97ad5cdc75eb73e3cc38542ca3ba783574b0a7a)
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