xref: /illumos-gate/usr/src/cmd/mdb/common/modules/ipp/ipp.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2001-2002 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 #include <sys/time.h>
30 #include <ipp/ipp.h>
31 #include <ipp/ipp_impl.h>
32 #include <mdb/mdb_modapi.h>
33 
34 static uintptr_t	ipp_mod_byid;
35 static uintptr_t	ipp_action_byid;
36 
37 static int	byid_walk_init(mdb_walk_state_t *);
38 static int	byid_walk_step(mdb_walk_state_t *);
39 static void	byid_walk_fini(mdb_walk_state_t *);
40 
41 static int	action(uintptr_t, uint_t, int, const mdb_arg_t *);
42 static int	action_format(uintptr_t, const void *, void *);
43 static int	action_dump(uintptr_t, ipp_action_t *, boolean_t);
44 static int	action_summary(uintptr_t, ipp_action_t *, boolean_t);
45 
46 static int	cfglock(uintptr_t, uint_t, int, const mdb_arg_t *);
47 
48 static int	mod(uintptr_t, uint_t, int, const mdb_arg_t *);
49 static int	mod_format(uintptr_t, const void *, void *);
50 static int	mod_dump(uintptr_t, ipp_mod_t *, boolean_t);
51 static int	mod_summary(uintptr_t, ipp_mod_t *, boolean_t);
52 static int	cfglock(uintptr_t, uint_t, int, const mdb_arg_t *);
53 
54 static int	ippops(uintptr_t, uint_t, int, const mdb_arg_t *);
55 
56 static int	packet(uintptr_t, uint_t, int, const mdb_arg_t *);
57 static void	dump_classes(uintptr_t, uint_t);
58 static void	dump_log(uintptr_t, uint_t);
59 static void	aid2aname(ipp_action_id_t, char *);
60 
61 static int	ref_walk_init(mdb_walk_state_t *);
62 static int	ref_walk_step(mdb_walk_state_t *);
63 static void	ref_walk_fini(mdb_walk_state_t *);
64 
65 typedef	struct afdata {
66 	boolean_t	af_banner;
67 	uint_t		af_flags;
68 } afdata_t;
69 
70 #define	AF_VERBOSE	1
71 
72 typedef	struct mfdata {
73 	boolean_t	mf_banner;
74 	uint_t		mf_flags;
75 } mfdata_t;
76 
77 #define	MF_VERBOSE	1
78 
79 /*
80  * walker. Skips entries that are NULL.
81  */
82 
83 static int
84 byid_walk_init(
85 	mdb_walk_state_t *wsp)
86 {
87 	uintptr_t	start;
88 
89 	if (mdb_vread(&start, sizeof (uintptr_t), wsp->walk_addr) == -1) {
90 		mdb_warn("failed to read from address %p", wsp->walk_addr);
91 		return (WALK_ERR);
92 	}
93 
94 	wsp->walk_addr = start;
95 
96 	return (WALK_NEXT);
97 }
98 
99 static int
100 byid_walk_step(
101 	mdb_walk_state_t *wsp)
102 {
103 	int		status;
104 	void 		*ptr;
105 
106 	if (mdb_vread(&ptr, sizeof (void *), wsp->walk_addr) == -1) {
107 		mdb_warn("failed to read from address %p", wsp->walk_addr);
108 		return (WALK_ERR);
109 	}
110 
111 	if (ptr == (void *)-1) {
112 		status = WALK_DONE;
113 	} else if (ptr == NULL) {
114 		status = WALK_NEXT;
115 	} else {
116 		status = wsp->walk_callback((uintptr_t)ptr, NULL,
117 		    wsp->walk_cbdata);
118 	}
119 
120 	wsp->walk_addr += sizeof (void *);
121 
122 	return (status);
123 }
124 
125 /*ARGSUSED*/
126 static void
127 byid_walk_fini(
128 	mdb_walk_state_t *wsp)
129 {
130 }
131 
132 
133 /*ARGSUSED*/
134 static int
135 action(
136 	uintptr_t	addr,
137 	uint_t		flags,
138 	int		argc,
139 	const mdb_arg_t	*argv)
140 {
141 	int		status;
142 	int		rc = DCMD_OK;
143 	afdata_t	*afp;
144 
145 	afp = mdb_zalloc(sizeof (afdata_t), UM_SLEEP);
146 
147 	if (mdb_getopts(argc, argv,
148 	    'v', MDB_OPT_SETBITS, AF_VERBOSE, &afp->af_flags,
149 	    NULL) != argc)
150 		return (DCMD_USAGE);
151 
152 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP))
153 		afp->af_banner = B_TRUE;
154 
155 	if (flags & DCMD_ADDRSPEC) {
156 		status = action_format(addr, NULL, afp);
157 		rc = (status == WALK_NEXT) ? DCMD_OK : DCMD_ERR;
158 		goto cleanup;
159 	}
160 
161 	if (mdb_pwalk("ipp_byid", action_format, afp,
162 	    ipp_action_byid) == -1) {
163 		mdb_warn("failed to execute ipp_byid walk");
164 		rc = DCMD_ERR;
165 	}
166 
167 cleanup:
168 	mdb_free(afp, sizeof (afdata_t));
169 
170 	return (rc);
171 }
172 
173 /*ARGSUSED*/
174 static int
175 action_format(
176 	uintptr_t	addr,
177 	const void	*data,
178 	void		*arg)
179 {
180 	afdata_t	*afp = (afdata_t *)arg;
181 	ipp_action_t	*ap;
182 	int		rc;
183 
184 	ap = mdb_alloc(sizeof (ipp_action_t), UM_SLEEP);
185 	if (mdb_vread(ap, sizeof (ipp_action_t), addr) == -1) {
186 		mdb_warn("failed to read ipp_action_t at %p", addr);
187 		rc = WALK_ERR;
188 		goto done;
189 	}
190 
191 	if (afp->af_flags & AF_VERBOSE)
192 		rc = action_dump(addr, ap, afp->af_banner);
193 	else
194 		rc = action_summary(addr, ap, afp->af_banner);
195 
196 	afp->af_banner = B_FALSE;
197 done:
198 	mdb_free(ap, sizeof (ipp_action_t));
199 	return (rc);
200 }
201 
202 /*ARGSUSED*/
203 static int
204 action_dump(
205 	uintptr_t	addr,
206 	ipp_action_t	*ap,
207 	boolean_t	banner)
208 {
209 	mdb_printf("%?p: %20s = %d\n", addr, "id", ap->ippa_id);
210 	if (!ap->ippa_nameless) {
211 		mdb_printf("%?s  %20s = %s\n", "", "name", ap->ippa_name);
212 	}
213 	mdb_printf("%?s  %20s = 0x%p\n", "", "mod", ap->ippa_mod);
214 	mdb_printf("%?s  %20s = 0x%p\n", "", "ref", ap->ippa_ref);
215 	mdb_printf("%?s  %20s = 0x%p\n", "", "refby", ap->ippa_refby);
216 	mdb_printf("%?s  %20s = 0x%p\n", "", "ptr", ap->ippa_ptr);
217 
218 	mdb_printf("%?s  %20s = ", "", "state");
219 	switch (ap->ippa_state) {
220 	case IPP_ASTATE_PROTO:
221 		mdb_printf("%s\n", "PROTO");
222 		break;
223 	case IPP_ASTATE_CONFIG_PENDING:
224 		mdb_printf("%s\n", "CONFIG_PENDING");
225 		break;
226 	case IPP_ASTATE_AVAILABLE:
227 		mdb_printf("%s\n", "AVAILABLE");
228 		break;
229 	default:
230 		mdb_printf("%s\n", "<unknown>");
231 		break;
232 	}
233 
234 	mdb_printf("%?s  %20s = %d\n", "", "packets", ap->ippa_packets);
235 	mdb_printf("%?s  %20s = %d\n", "", "hold_count", ap->ippa_hold_count);
236 	mdb_printf("%?s  %20s = %s\n", "", "destruct_pending",
237 	    (ap->ippa_destruct_pending) ? "TRUE" : "FALSE");
238 	mdb_printf("%?s  %20s = 0x%p\n", "", "lock",
239 	    addr + ((uintptr_t)ap->ippa_lock - (uintptr_t)ap));
240 	mdb_printf("%?s  %20s = 0x%p\n", "", "config_lock",
241 	    addr + ((uintptr_t)ap->ippa_config_lock - (uintptr_t)ap));
242 	mdb_printf("\n");
243 
244 	return (WALK_NEXT);
245 }
246 
247 static int
248 action_summary(
249 	uintptr_t	addr,
250 	ipp_action_t	*ap,
251 	boolean_t	banner)
252 {
253 	ipp_mod_t	*imp;
254 	uintptr_t	ptr;
255 
256 	if (banner)
257 		mdb_printf("%?s %<u>%20s %5s %20s%</u>\n",
258 		    "", "NAME", "ID", "MODNAME");
259 
260 	imp = mdb_alloc(sizeof (ipp_mod_t), UM_SLEEP);
261 	ptr = (uintptr_t)ap->ippa_mod;
262 	if (mdb_vread(imp, sizeof (ipp_mod_t), ptr) == -1) {
263 		mdb_warn("failed to read ipp_mod_t at %p", ptr);
264 		mdb_free(imp, sizeof (ipp_mod_t));
265 		return (WALK_ERR);
266 	}
267 
268 	mdb_printf("%?p:%20s %5d %20s\n", addr, ap->ippa_name, ap->ippa_id,
269 	    imp->ippm_name);
270 
271 	mdb_free(imp, sizeof (ipp_mod_t));
272 	return (WALK_NEXT);
273 }
274 
275 /*ARGSUSED*/
276 static int
277 cfglock(
278 	uintptr_t	addr,
279 	uint_t		flags,
280 	int		argc,
281 	const mdb_arg_t	*argv)
282 {
283 	cfglock_t	*clp;
284 
285 	if ((flags & DCMD_ADDRSPEC) == 0)
286 		return (DCMD_ERR);
287 
288 	clp = mdb_alloc(sizeof (cfglock_t), UM_SLEEP);
289 	if (mdb_vread(clp, sizeof (cfglock_t), addr) == -1) {
290 		mdb_warn("failed to read cfglock_t at %p", addr);
291 		mdb_free(clp, sizeof (cfglock_t));
292 		return (WALK_ERR);
293 	}
294 
295 	mdb_printf("%?p: %20s = %p\n", addr, "owner", clp->cl_owner);
296 	mdb_printf("%?s  %20s = %s\n", "", "reader",
297 	    clp->cl_reader ? "TRUE" : "FALSE");
298 	mdb_printf("%?s  %20s = %d\n", "", "writers", clp->cl_writers);
299 	mdb_printf("%?s  %20s = 0x%p\n", "", "mutex",
300 	    addr + ((uintptr_t)clp->cl_mutex - (uintptr_t)clp));
301 	mdb_printf("%?s  %20s = 0x%p\n", "", "cv",
302 	    addr + ((uintptr_t)clp->cl_cv - (uintptr_t)clp));
303 	mdb_printf("\n");
304 
305 	mdb_free(clp, sizeof (cfglock_t));
306 
307 	return (DCMD_OK);
308 }
309 
310 /*ARGSUSED*/
311 static int
312 mod(
313 	uintptr_t	addr,
314 	uint_t		flags,
315 	int		argc,
316 	const mdb_arg_t	*argv)
317 {
318 	int		status;
319 	int		rc = DCMD_OK;
320 	mfdata_t	*mfp;
321 
322 	mfp = mdb_zalloc(sizeof (mfdata_t), UM_SLEEP);
323 
324 	if (mdb_getopts(argc, argv,
325 	    'v', MDB_OPT_SETBITS, MF_VERBOSE, &mfp->mf_flags,
326 	    NULL) != argc)
327 		return (DCMD_USAGE);
328 
329 	if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP))
330 		mfp->mf_banner = B_TRUE;
331 
332 	if (flags & DCMD_ADDRSPEC) {
333 		status = mod_format(addr, NULL, mfp);
334 		rc = (status == WALK_NEXT) ? DCMD_OK : DCMD_ERR;
335 		goto cleanup;
336 	}
337 
338 	if (mdb_pwalk("ipp_byid", mod_format, mfp,
339 	    ipp_mod_byid) == -1) {
340 		mdb_warn("failed to execute ipp_byid walk");
341 		rc = DCMD_ERR;
342 	}
343 
344 cleanup:
345 	mdb_free(mfp, sizeof (mfdata_t));
346 
347 	return (rc);
348 }
349 
350 /*ARGSUSED*/
351 static int
352 mod_format(
353 	uintptr_t	addr,
354 	const void	*data,
355 	void		*arg)
356 {
357 	mfdata_t	*mfp = (mfdata_t *)arg;
358 	ipp_mod_t	*imp;
359 	int		rc;
360 
361 	imp = mdb_alloc(sizeof (ipp_mod_t), UM_SLEEP);
362 	if (mdb_vread(imp, sizeof (ipp_mod_t), addr) == -1) {
363 		mdb_warn("failed to read ipp_mod_t at %p", addr);
364 		rc = WALK_ERR;
365 		goto done;
366 	}
367 
368 	if (mfp->mf_flags & MF_VERBOSE)
369 		rc = mod_dump(addr, imp, mfp->mf_banner);
370 	else
371 		rc = mod_summary(addr, imp, mfp->mf_banner);
372 
373 	mfp->mf_banner = B_FALSE;
374 done:
375 	mdb_free(imp, sizeof (ipp_mod_t));
376 	return (rc);
377 }
378 
379 /*ARGSUSED*/
380 static int
381 mod_dump(
382 	uintptr_t	addr,
383 	ipp_mod_t	*imp,
384 	boolean_t	banner)
385 {
386 	mdb_printf("%?p: %20s = %d\n", addr, "id", imp->ippm_id);
387 	mdb_printf("%?s  %20s = %s\n", "", "name", imp->ippm_name);
388 	mdb_printf("%?s  %20s = 0x%p\n", "", "ops", imp->ippm_ops);
389 	mdb_printf("%?s  %20s = 0x%p\n", "", "action", imp->ippm_action);
390 
391 	mdb_printf("%?s  %20s = ", "", "state");
392 	switch (imp->ippm_state) {
393 	case IPP_MODSTATE_PROTO:
394 		mdb_printf("%s\n", "PROTO");
395 		break;
396 	case IPP_MODSTATE_AVAILABLE:
397 		mdb_printf("%s\n", "AVAILABLE");
398 		break;
399 	default:
400 		mdb_printf("%s\n", "<unknown>");
401 		break;
402 	}
403 
404 	mdb_printf("%?s  %20s = %d\n", "", "hold_count", imp->ippm_hold_count);
405 	mdb_printf("%?s  %20s = %s\n", "", "destruct_pending",
406 	    (imp->ippm_destruct_pending) ? "TRUE" : "FALSE");
407 	mdb_printf("%?s  %20s = 0x%p\n", "", "lock",
408 	    addr + ((uintptr_t)imp->ippm_lock - (uintptr_t)imp));
409 	mdb_printf("\n");
410 
411 	return (WALK_NEXT);
412 }
413 
414 static int
415 mod_summary(
416 	uintptr_t	addr,
417 	ipp_mod_t	*imp,
418 	boolean_t	banner)
419 {
420 	if (banner)
421 		mdb_printf("%?s %<u>%20s %5s%</u>\n",
422 		    "", "NAME", "ID");
423 
424 	mdb_printf("%?p:%20s %5d\n", addr, imp->ippm_name, imp->ippm_id);
425 
426 	return (WALK_NEXT);
427 }
428 
429 /*ARGSUSED*/
430 static int
431 ippops(
432 	uintptr_t	addr,
433 	uint_t		flags,
434 	int		argc,
435 	const mdb_arg_t	*argv)
436 {
437 	ipp_ops_t	*ippo;
438 	GElf_Sym	sym;
439 	char		buf[MDB_SYM_NAMLEN];
440 
441 	if ((flags & DCMD_ADDRSPEC) == 0)
442 		return (DCMD_ERR);
443 
444 	ippo = mdb_alloc(sizeof (ipp_ops_t), UM_SLEEP);
445 	if (mdb_vread(ippo, sizeof (ipp_ops_t), addr) == -1) {
446 		mdb_warn("failed to read ipp_ops_t at %p", addr);
447 		mdb_free(ippo, sizeof (ipp_ops_t));
448 		return (DCMD_ERR);
449 	}
450 
451 	mdb_printf("%?p: %20s = %d\n", addr, "rev", ippo->ippo_rev);
452 
453 	if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_create,
454 	    MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0)
455 		mdb_printf("%?s  %20s = %s\n", "", "action_create", buf);
456 	else
457 		mdb_printf("%?s  %20s = 0x%p\n", "", "action_create",
458 		    ippo->ippo_action_create);
459 
460 	if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_modify,
461 	    MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0)
462 		mdb_printf("%?s  %20s = %s\n", "", "action_modify", buf);
463 	else
464 		mdb_printf("%?s  %20s = 0x%p\n", "", "action_modify",
465 		    ippo->ippo_action_modify);
466 
467 	if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_destroy,
468 	    MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0)
469 		mdb_printf("%?s  %20s = %s\n", "", "action_destroy", buf);
470 	else
471 		mdb_printf("%?s  %20s = 0x%p\n", "", "action_destroy",
472 		    ippo->ippo_action_destroy);
473 
474 	if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_info,
475 	    MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0)
476 		mdb_printf("%?s  %20s = %s\n", "", "action_info", buf);
477 	else
478 		mdb_printf("%?s  %20s = 0x%p\n", "", "action_info",
479 		    ippo->ippo_action_info);
480 
481 	if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_invoke,
482 	    MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0)
483 		mdb_printf("%?s  %20s = %s\n", "", "action_invoke", buf);
484 	else
485 		mdb_printf("%?s  %20s = 0x%p\n", "", "action_invoke",
486 		    ippo->ippo_action_invoke);
487 
488 	mdb_printf("\n");
489 
490 	mdb_free(ippo, sizeof (ipp_ops_t));
491 	return (DCMD_OK);
492 }
493 
494 static int
495 ref_walk_init(
496 	mdb_walk_state_t *wsp)
497 {
498 	if (wsp->walk_addr == NULL)
499 		return (WALK_DONE);
500 
501 	return (WALK_NEXT);
502 }
503 
504 static int
505 ref_walk_step(
506 	mdb_walk_state_t *wsp)
507 {
508 	ipp_ref_t	*rp;
509 	int		status;
510 
511 	if (wsp->walk_addr == NULL)
512 		return (WALK_DONE);
513 
514 	rp = mdb_alloc(sizeof (ipp_ref_t), UM_SLEEP);
515 
516 	if (mdb_vread(rp, sizeof (ipp_ref_t), wsp->walk_addr) == -1) {
517 		mdb_warn("failed to read ipp_ref_t at %p", wsp->walk_addr);
518 		mdb_free(rp, sizeof (ipp_ref_t));
519 		return (WALK_ERR);
520 	}
521 
522 	status = wsp->walk_callback((uintptr_t)rp->ippr_ptr, NULL,
523 	    wsp->walk_cbdata);
524 
525 	wsp->walk_addr = (uintptr_t)(rp->ippr_nextp);
526 
527 	mdb_free(rp, sizeof (ipp_ref_t));
528 	return (status);
529 }
530 
531 /*ARGSUSED*/
532 static void
533 ref_walk_fini(
534 	mdb_walk_state_t *wsp)
535 {
536 }
537 
538 /*ARGSUSED*/
539 static int
540 packet(
541 	uintptr_t	addr,
542 	uint_t		flags,
543 	int		argc,
544 	const mdb_arg_t	*argv)
545 {
546 	ipp_packet_t	*pp;
547 
548 	if ((flags & DCMD_ADDRSPEC) == 0)
549 		return (DCMD_ERR);
550 
551 	pp = mdb_alloc(sizeof (ipp_packet_t), UM_SLEEP);
552 	if (mdb_vread(pp, sizeof (ipp_packet_t), addr) == -1) {
553 		mdb_warn("failed to read ipp_packet_t at %p", addr);
554 		mdb_free(pp, sizeof (ipp_packet_t));
555 		return (DCMD_ERR);
556 	}
557 
558 	mdb_printf("%?p: %20s = 0x%p\n", addr, "data", pp->ippp_data);
559 	mdb_printf("%?s  %20s = 0x%p\n", "", "private", pp->ippp_private);
560 	dump_classes((uintptr_t)pp->ippp_class_array, pp->ippp_class_windex);
561 	dump_log((uintptr_t)pp->ippp_log, pp->ippp_log_windex);
562 
563 	mdb_free(pp, sizeof (ipp_packet_t));
564 	return (DCMD_OK);
565 }
566 
567 static void
568 dump_classes(
569 	uintptr_t	ptr,
570 	uint_t		nelt)
571 {
572 	ipp_class_t	*array;
573 	ipp_class_t	*cp;
574 	uint_t		i;
575 	boolean_t	first_time = B_TRUE;
576 	char		buf[MAXNAMELEN];
577 
578 	array = mdb_alloc(sizeof (ipp_class_t) * nelt, UM_SLEEP);
579 	if (mdb_vread(array, sizeof (ipp_class_t) * nelt, ptr) == -1) {
580 		mdb_warn("failed to read ipp_class_t array at %p", ptr);
581 		return;
582 	}
583 
584 	for (i = 0; i < nelt; i++) {
585 		if (first_time) {
586 			mdb_printf("%20s  %?s   %<u>%15s %15s%</u>\n", "",
587 			    "classes", "NAME", "ACTION");
588 			first_time = B_FALSE;
589 		}
590 
591 		cp = &(array[i]);
592 		aid2aname(cp->ippc_aid, buf);
593 		mdb_printf("%20s  %?p:  %15s %15s%\n", "",
594 		    ptr + (i * sizeof (ipp_class_t)), cp->ippc_name, buf);
595 	}
596 
597 	mdb_free(cp, sizeof (ipp_class_t) * nelt);
598 }
599 
600 static void
601 dump_log(
602 	uintptr_t	ptr,
603 	uint_t		nelt)
604 {
605 	ipp_log_t	*array;
606 	ipp_log_t	*lp;
607 	uint_t		i;
608 	boolean_t	first_time = B_TRUE;
609 	char		buf[MAXNAMELEN];
610 
611 	array = mdb_alloc(sizeof (ipp_log_t) * nelt, UM_SLEEP);
612 	if (mdb_vread(array, sizeof (ipp_log_t) * nelt, ptr) == -1) {
613 		mdb_warn("failed to read ipp_log_t array at %p", ptr);
614 		return;
615 	}
616 
617 	for (i = 0; i < nelt; i++) {
618 		if (first_time) {
619 			mdb_printf("%20s  %?s   %<u>%15s %15s%</u>\n", "",
620 			    "log", "CLASS NAME", "ACTION");
621 			first_time = B_FALSE;
622 		}
623 
624 		lp = &(array[i]);
625 		aid2aname(lp->ippl_aid, buf);
626 		mdb_printf("%20s  %?p:  %15s %15s\n", "",
627 		    ptr + (i * sizeof (ipp_class_t)), lp->ippl_name, buf);
628 	}
629 
630 	mdb_free(lp, sizeof (ipp_log_t) * nelt);
631 }
632 
633 static void
634 aid2aname(
635 	ipp_action_id_t	aid,
636 	char		*buf)
637 {
638 	uintptr_t	addr;
639 	uintptr_t	ptr;
640 	ipp_action_t	*ap;
641 
642 	switch (aid) {
643 	case IPP_ACTION_INVAL:
644 		strcpy(buf, "invalid");
645 		break;
646 	case IPP_ACTION_CONT:
647 		strcpy(buf, "continue");
648 		break;
649 	case IPP_ACTION_DEFER:
650 		strcpy(buf, "defer");
651 		break;
652 	case IPP_ACTION_DROP:
653 		strcpy(buf, "drop");
654 		break;
655 	default:
656 		if (mdb_vread(&addr, sizeof (uintptr_t),
657 		    ipp_action_byid) == -1) {
658 			mdb_warn("failed to read from address %p",
659 			    ipp_action_byid);
660 			strcpy(buf, "???");
661 			break;
662 		}
663 
664 		addr += ((int32_t)aid * sizeof (void *));
665 		if (mdb_vread(&ptr, sizeof (uintptr_t), addr) == -1) {
666 			mdb_warn("failed to read from address %p", addr);
667 			strcpy(buf, "???");
668 			break;
669 		}
670 
671 		ap = mdb_alloc(sizeof (ipp_action_t), UM_SLEEP);
672 		if (mdb_vread(ap, sizeof (ipp_action_t), ptr) == -1) {
673 			mdb_warn("failed to read ipp_action_t at %p", ptr);
674 			mdb_free(ap, sizeof (ipp_action_t));
675 			strcpy(buf, "???");
676 			break;
677 		}
678 
679 		if (ap->ippa_id != aid) {
680 			mdb_warn("corrupt action at %p", ptr);
681 			mdb_free(ap, sizeof (ipp_action_t));
682 			strcpy(buf, "???");
683 			break;
684 		}
685 
686 		strcpy(buf, ap->ippa_name);
687 	}
688 }
689 
690 static const mdb_dcmd_t dcmds[] = {
691 	{ "ipp_action", "?[-v]",
692 	    "display ipp_action structure", action },
693 	{ "ipp_mod", "?[-v]",
694 	    "display ipp_mod structure", mod },
695 	{ "cfglock", ":",
696 	    "display cfglock structure", cfglock },
697 	{ "ippops", ":",
698 	    "display ipp_ops structure", ippops },
699 	{ "ipp_packet", ":",
700 	    "display ipp_packet structure", packet },
701 	{ NULL }
702 };
703 
704 static const mdb_walker_t walkers[] = {
705 	{ "ipp_byid", "walk byid array", byid_walk_init, byid_walk_step,
706 	    byid_walk_fini },
707 	{ "ipp_ref", "walk reference list", ref_walk_init, ref_walk_step,
708 	    ref_walk_fini },
709 	{ NULL }
710 };
711 
712 static const mdb_modinfo_t ipp_modinfo = { MDB_API_VERSION, dcmds, walkers };
713 
714 const mdb_modinfo_t *
715 _mdb_init(void)
716 {
717 	GElf_Sym sym;
718 
719 	if (mdb_lookup_by_name("ipp_action_byid", &sym) == -1) {
720 		mdb_warn("failed to lookup 'ipp_action_byid'");
721 		return (NULL);
722 	}
723 
724 	ipp_action_byid = (uintptr_t)sym.st_value;
725 
726 	if (mdb_lookup_by_name("ipp_mod_byid", &sym) == -1) {
727 		mdb_warn("failed to lookup 'ipp_mod_byid'");
728 		return (NULL);
729 	}
730 
731 	ipp_mod_byid = (uintptr_t)sym.st_value;
732 
733 	return (&ipp_modinfo);
734 }
735