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