xref: /onnv-gate/usr/src/cmd/mdb/common/modules/genunix/list.c (revision 6712:79afecec3f3c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6712Stomee  * Common Development and Distribution License (the "License").
6*6712Stomee  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*6712Stomee  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
290Sstevel@tonic-gate #include <sys/list.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate typedef struct list_walk_data {
32*6712Stomee 	uintptr_t lw_head;	/* address of list head */
33*6712Stomee 	size_t	lw_size;	/* size of list element */
34*6712Stomee 	size_t	lw_offset;	/* list element linkage offset */
35*6712Stomee 	void	*lw_obj;	/* buffer of lw_size to hold list element */
36*6712Stomee 	uintptr_t lw_end;	/* last node in specified range */
37*6712Stomee 	const char *lw_elem_name;
38*6712Stomee 	int	(*lw_elem_check)(void *, uintptr_t, void *);
39*6712Stomee 	void	*lw_elem_check_arg;
400Sstevel@tonic-gate } list_walk_data_t;
410Sstevel@tonic-gate 
42*6712Stomee /*
43*6712Stomee  * Initialize a forward walk through a list.
44*6712Stomee  *
45*6712Stomee  * begin and end optionally specify objects other than the first and last
46*6712Stomee  * objects in the list; either or both may be NULL (defaulting to first and
47*6712Stomee  * last).
48*6712Stomee  *
49*6712Stomee  * list_name and element_name specify command-specific labels other than
50*6712Stomee  * "list_t" and "list element" for use in error messages.
51*6712Stomee  *
52*6712Stomee  * element_check() returns -1, 1, or 0: abort the walk with an error, stop
53*6712Stomee  * without an error, or allow the normal callback; arg is an optional user
54*6712Stomee  * argument to element_check().
55*6712Stomee  */
560Sstevel@tonic-gate int
list_walk_init_range(mdb_walk_state_t * wsp,uintptr_t begin,uintptr_t end,const char * list_name,const char * element_name,int (* element_check)(void *,uintptr_t,void *),void * arg)57*6712Stomee list_walk_init_range(mdb_walk_state_t *wsp, uintptr_t begin, uintptr_t end,
58*6712Stomee     const char *list_name, const char *element_name,
59*6712Stomee     int (*element_check)(void *, uintptr_t, void *), void *arg)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	list_walk_data_t *lwd;
620Sstevel@tonic-gate 	list_t list;
630Sstevel@tonic-gate 
64*6712Stomee 	if (list_name == NULL)
65*6712Stomee 		list_name = "list_t";
66*6712Stomee 	if (element_name == NULL)
67*6712Stomee 		element_name = "list element";
68*6712Stomee 
690Sstevel@tonic-gate 	lwd = mdb_alloc(sizeof (list_walk_data_t), UM_SLEEP);
700Sstevel@tonic-gate 	if (mdb_vread(&list, sizeof (list_t), wsp->walk_addr) == -1) {
71*6712Stomee 		mdb_warn("failed to read %s at %#lx", list_name,
72*6712Stomee 		    wsp->walk_addr);
730Sstevel@tonic-gate 		mdb_free(lwd, sizeof (list_walk_data_t));
740Sstevel@tonic-gate 		return (WALK_ERR);
750Sstevel@tonic-gate 	}
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	lwd->lw_size = list.list_size;
780Sstevel@tonic-gate 	lwd->lw_offset = list.list_offset;
790Sstevel@tonic-gate 	lwd->lw_obj = mdb_alloc(list.list_size, UM_SLEEP);
80*6712Stomee 	lwd->lw_head = (uintptr_t)&((list_t *)wsp->walk_addr)->list_head;
81*6712Stomee 	lwd->lw_end = (end == NULL ? NULL : end + lwd->lw_offset);
82*6712Stomee 	lwd->lw_elem_name = element_name;
83*6712Stomee 	lwd->lw_elem_check = element_check;
84*6712Stomee 	lwd->lw_elem_check_arg = arg;
850Sstevel@tonic-gate 
86*6712Stomee 	wsp->walk_addr = (begin == NULL
87*6712Stomee 	    ? (uintptr_t)list.list_head.list_next
88*6712Stomee 	    : begin + lwd->lw_offset);
890Sstevel@tonic-gate 	wsp->walk_data = lwd;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	return (WALK_NEXT);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate int
list_walk_init(mdb_walk_state_t * wsp)95*6712Stomee list_walk_init(mdb_walk_state_t *wsp)
96*6712Stomee {
97*6712Stomee 	return (list_walk_init_range(wsp, NULL, NULL, NULL, NULL, NULL, NULL));
98*6712Stomee }
99*6712Stomee 
100*6712Stomee int
list_walk_init_named(mdb_walk_state_t * wsp,const char * list_name,const char * element_name)101*6712Stomee list_walk_init_named(mdb_walk_state_t *wsp,
102*6712Stomee     const char *list_name, const char *element_name)
103*6712Stomee {
104*6712Stomee 	return (list_walk_init_range(wsp, NULL, NULL, list_name, element_name,
105*6712Stomee 	    NULL, NULL));
106*6712Stomee }
107*6712Stomee 
108*6712Stomee int
list_walk_init_checked(mdb_walk_state_t * wsp,const char * list_name,const char * element_name,int (* element_check)(void *,uintptr_t,void *),void * arg)109*6712Stomee list_walk_init_checked(mdb_walk_state_t *wsp,
110*6712Stomee     const char *list_name, const char *element_name,
111*6712Stomee     int (*element_check)(void *, uintptr_t, void *), void *arg)
112*6712Stomee {
113*6712Stomee 	return (list_walk_init_range(wsp, NULL, NULL, list_name, element_name,
114*6712Stomee 	    element_check, arg));
115*6712Stomee }
116*6712Stomee 
117*6712Stomee int
list_walk_step(mdb_walk_state_t * wsp)1180Sstevel@tonic-gate list_walk_step(mdb_walk_state_t *wsp)
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate 	list_walk_data_t *lwd = wsp->walk_data;
1210Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr - lwd->lw_offset;
1220Sstevel@tonic-gate 	list_node_t *node;
1230Sstevel@tonic-gate 	int status;
1240Sstevel@tonic-gate 
125*6712Stomee 	if (wsp->walk_addr == lwd->lw_head)
126*6712Stomee 		return (WALK_DONE);
127*6712Stomee 
128*6712Stomee 	if (lwd->lw_end != NULL && wsp->walk_addr == lwd->lw_end)
1290Sstevel@tonic-gate 		return (WALK_DONE);
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	if (mdb_vread(lwd->lw_obj, lwd->lw_size, addr) == -1) {
132*6712Stomee 		mdb_warn("failed to read %s at %#lx", lwd->lw_elem_name, addr);
1330Sstevel@tonic-gate 		return (WALK_ERR);
1340Sstevel@tonic-gate 	}
1350Sstevel@tonic-gate 
136*6712Stomee 	if (lwd->lw_elem_check != NULL) {
137*6712Stomee 		int rc = lwd->lw_elem_check(lwd->lw_obj, addr,
138*6712Stomee 		    lwd->lw_elem_check_arg);
139*6712Stomee 		if (rc == -1)
140*6712Stomee 			return (WALK_ERR);
141*6712Stomee 		else if (rc == 1)
142*6712Stomee 			return (WALK_DONE);
143*6712Stomee 	}
144*6712Stomee 
1450Sstevel@tonic-gate 	status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata);
1460Sstevel@tonic-gate 	node = (list_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset);
1470Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)node->list_next;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	return (status);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate void
list_walk_fini(mdb_walk_state_t * wsp)1530Sstevel@tonic-gate list_walk_fini(mdb_walk_state_t *wsp)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	list_walk_data_t *lwd = wsp->walk_data;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	mdb_free(lwd->lw_obj, lwd->lw_size);
1580Sstevel@tonic-gate 	mdb_free(lwd, sizeof (list_walk_data_t));
1590Sstevel@tonic-gate }
160