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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/mdb_modapi.h> 27 #include <limits.h> 28 29 #include <fmd_trace.h> 30 #include <fmd_module.h> 31 #include <fmd_thread.h> 32 #include <fmd_ustat.h> 33 #include <fmd_event.h> 34 #include <fmd_case.h> 35 #include <fmd_buf.h> 36 #include <fmd_asru.h> 37 #include <fmd_ckpt.h> 38 #include <fmd_timerq.h> 39 #include <fmd_xprt.h> 40 41 #include <fmd.h> 42 43 typedef struct trwalk_state { 44 struct trwalk_state *trw_next; 45 fmd_tracebuf_t trw_data; 46 pthread_t trw_tid; 47 uintptr_t trw_base; 48 const fmd_tracerec_t *trw_stop; 49 fmd_tracerec_t *trw_xrec; 50 } trwalk_state_t; 51 52 typedef struct hashwalk_data { 53 uintptr_t *hw_hash; 54 uint_t hw_hashlen; 55 uint_t hw_hashidx; 56 const char *hw_name; 57 void *hw_data; 58 size_t hw_size; 59 size_t hw_next; 60 } hashwalk_data_t; 61 62 static int fmd_stat(uintptr_t, uint_t, int, const mdb_arg_t *); 63 static int fmd_ustat(uintptr_t, uint_t, int, const mdb_arg_t *); 64 65 static int 66 trwalk_init(mdb_walk_state_t *wsp) 67 { 68 uintptr_t addr; 69 fmd_thread_t thr; 70 fmd_t F; 71 72 if (wsp->walk_addr != NULL) { 73 mdb_warn("fmd_trace only supports global walks\n"); 74 return (WALK_ERR); 75 } 76 77 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 78 mdb_warn("failed to read fmd meta-data"); 79 return (WALK_ERR); 80 } 81 82 for (addr = (uintptr_t)F.d_thr_list.l_next; addr != NULL; 83 addr = (uintptr_t)thr.thr_list.l_next) { 84 85 size_t len, ptr_off, end_off; 86 fmd_tracerec_t *buf; 87 trwalk_state_t *t; 88 89 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) { 90 mdb_warn("failed to read thread at %p " 91 "(some trace data will be unavailable)", addr); 92 break; 93 } 94 95 t = mdb_zalloc(sizeof (trwalk_state_t), UM_SLEEP); 96 t->trw_next = wsp->walk_data; 97 wsp->walk_data = t; 98 99 (void) mdb_vread(&t->trw_data, 100 sizeof (t->trw_data), (uintptr_t)thr.thr_trdata); 101 102 if (t->trw_data.tb_recs == 0) 103 continue; /* no trace buffer allocated for thread */ 104 105 len = t->trw_data.tb_recs * t->trw_data.tb_size; 106 buf = mdb_alloc(len, UM_SLEEP); 107 108 t->trw_tid = thr.thr_tid; 109 t->trw_base = (uintptr_t)t->trw_data.tb_buf; 110 111 if (mdb_vread(buf, len, t->trw_base) == -1) { 112 mdb_warn("failed to read buffer for t%u", t->trw_tid); 113 bzero(buf, len); 114 } 115 116 end_off = (uintptr_t)t->trw_data.tb_end - t->trw_base; 117 ptr_off = (uintptr_t)t->trw_data.tb_ptr - t->trw_base; 118 119 t->trw_data.tb_buf = buf; 120 t->trw_data.tb_end = (void *)((uintptr_t)buf + end_off); 121 t->trw_data.tb_ptr = (void *)((uintptr_t)buf + ptr_off); 122 123 if (t->trw_data.tb_ptr < t->trw_data.tb_buf || 124 t->trw_data.tb_ptr > t->trw_data.tb_end) { 125 mdb_warn("trace record ptr for t%u is corrupt " 126 "(some data may be unavailable)\n", t->trw_tid); 127 t->trw_data.tb_ptr = t->trw_data.tb_buf; 128 } 129 130 t->trw_stop = t->trw_data.tb_ptr; 131 t->trw_xrec = mdb_alloc( 132 t->trw_data.tb_size + sizeof (uintptr_t), UM_SLEEP); 133 } 134 135 return (WALK_NEXT); 136 } 137 138 static fmd_tracerec_t * 139 trwalk_nextrec(trwalk_state_t *t) 140 { 141 if (t->trw_stop == NULL) 142 return (t->trw_data.tb_ptr); 143 144 if (t->trw_data.tb_ptr == t->trw_data.tb_buf) 145 t->trw_data.tb_ptr = t->trw_data.tb_end; 146 else 147 t->trw_data.tb_ptr = (fmd_tracerec_t *) 148 ((uintptr_t)t->trw_data.tb_ptr - t->trw_data.tb_size); 149 150 if (t->trw_data.tb_ptr == t->trw_stop) 151 t->trw_stop = NULL; /* mark buffer as empty */ 152 153 return (t->trw_data.tb_ptr); 154 } 155 156 static int 157 trwalk_step(mdb_walk_state_t *wsp) 158 { 159 trwalk_state_t *t, *oldest_t; 160 hrtime_t oldest_time = 0; 161 fmd_tracerec_t *trp; 162 int status; 163 164 for (t = wsp->walk_data; t != NULL; t = t->trw_next) { 165 for (trp = t->trw_data.tb_ptr; t->trw_stop != NULL && 166 trp->tr_time == 0; trp = trwalk_nextrec(t)) 167 continue; 168 169 if (t->trw_stop == NULL) 170 continue; /* buffer has been emptied */ 171 172 if (trp->tr_time > oldest_time) { 173 oldest_time = trp->tr_time; 174 oldest_t = t; 175 } 176 } 177 178 if (oldest_time == 0) 179 return (WALK_DONE); 180 181 t = oldest_t; 182 trp = t->trw_data.tb_ptr; 183 184 bcopy(trp, t->trw_xrec, t->trw_data.tb_size); 185 t->trw_xrec->tr_depth = MIN(trp->tr_depth, t->trw_data.tb_frames); 186 t->trw_xrec->tr_stack[t->trw_xrec->tr_depth] = t->trw_tid; 187 188 status = wsp->walk_callback((uintptr_t)trp - (uintptr_t) 189 t->trw_data.tb_buf + t->trw_base, t->trw_xrec, wsp->walk_cbdata); 190 191 (void) trwalk_nextrec(t); 192 return (status); 193 } 194 195 static void 196 trwalk_fini(mdb_walk_state_t *wsp) 197 { 198 trwalk_state_t *t, *u; 199 200 for (t = wsp->walk_data; t != NULL; t = u) { 201 u = t->trw_next; 202 mdb_free(t->trw_data.tb_buf, 203 t->trw_data.tb_recs * t->trw_data.tb_size); 204 mdb_free(t->trw_xrec, t->trw_data.tb_size + sizeof (uintptr_t)); 205 mdb_free(t, sizeof (trwalk_state_t)); 206 } 207 } 208 209 /*ARGSUSED*/ 210 static int 211 trprint_msg(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 212 { 213 if (tid == 0) 214 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]); 215 else if (trp->tr_stack[trp->tr_depth] != tid) 216 return (WALK_NEXT); 217 218 mdb_printf("%016llx %04x %-5u %s\n", 219 trp->tr_time, 1 << trp->tr_tag, trp->tr_errno, trp->tr_msg); 220 221 return (WALK_NEXT); 222 } 223 224 /*ARGSUSED*/ 225 static int 226 trprint_cpp(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 227 { 228 char file[64]; 229 230 if (tid == 0) 231 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]); 232 else if (trp->tr_stack[trp->tr_depth] != tid) 233 return (WALK_NEXT); 234 235 if (mdb_readstr(file, sizeof (file), (uintptr_t)trp->tr_file) <= 0) 236 (void) strcpy(file, "???"); 237 238 mdb_printf("%016llx %04x %s: %u\n", 239 trp->tr_time, 1 << trp->tr_tag, file, trp->tr_line); 240 241 return (WALK_NEXT); 242 } 243 244 static void 245 trprint_stack(const fmd_tracerec_t *trp) 246 { 247 uint8_t i; 248 249 for (i = 0; i < trp->tr_depth; i++) 250 mdb_printf("\t%a\n", trp->tr_stack[i]); 251 252 if (trp->tr_depth != 0) 253 mdb_printf("\n"); 254 } 255 256 static int 257 trprint_msg_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 258 { 259 int status = trprint_msg(addr, trp, tid); 260 trprint_stack(trp); 261 return (status); 262 } 263 264 static int 265 trprint_cpp_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 266 { 267 int status = trprint_cpp(addr, trp, tid); 268 trprint_stack(trp); 269 return (status); 270 } 271 272 static int 273 fmd_trace(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) 274 { 275 int (*func)(uintptr_t, const fmd_tracerec_t *, uintptr_t); 276 uint_t opt_c = FALSE, opt_s = FALSE; 277 278 if (mdb_getopts(argc, argv, 279 'c', MDB_OPT_SETBITS, TRUE, &opt_c, 280 's', MDB_OPT_SETBITS, TRUE, &opt_s, NULL) != argc) 281 return (DCMD_USAGE); 282 283 if (!(flags & DCMD_ADDRSPEC)) { 284 mdb_printf("TID "); 285 tid = 0; 286 } 287 288 if (opt_c) { 289 mdb_printf("%-16s %-4s FILE:LINE\n", "TIME", "TAG"); 290 func = opt_s ? trprint_cpp_stack : trprint_cpp; 291 } else { 292 mdb_printf("%-16s %-4s %-5s MSG\n", "TIME", "TAG", "ERRNO"); 293 func = opt_s ? trprint_msg_stack : trprint_msg; 294 } 295 296 if (mdb_walk("fmd_trace", (mdb_walk_cb_t)func, (void *)tid) == -1) { 297 mdb_warn("failed to walk fmd_trace"); 298 return (DCMD_ERR); 299 } 300 301 return (DCMD_OK); 302 } 303 304 static int 305 hash_walk_init(mdb_walk_state_t *wsp, uintptr_t addr, uint_t hashlen, 306 const char *name, size_t size, size_t next) 307 { 308 hashwalk_data_t *hwp; 309 size_t len = sizeof (uintptr_t) * hashlen; 310 311 if (len == 0) { 312 mdb_warn("failed to walk hash: invalid hash length\n"); 313 return (WALK_ERR); 314 } 315 316 hwp = mdb_alloc(sizeof (hashwalk_data_t), UM_SLEEP); 317 hwp->hw_hash = mdb_zalloc(len, UM_SLEEP); 318 (void) mdb_vread(hwp->hw_hash, len, addr); 319 hwp->hw_hashlen = hashlen; 320 hwp->hw_hashidx = 0; 321 hwp->hw_name = name; 322 hwp->hw_data = mdb_zalloc(size, UM_SLEEP); 323 hwp->hw_size = size; 324 hwp->hw_next = next; 325 326 wsp->walk_addr = hwp->hw_hash[0]; 327 wsp->walk_data = hwp; 328 329 return (WALK_NEXT); 330 } 331 332 static int 333 hash_walk_step(mdb_walk_state_t *wsp) 334 { 335 hashwalk_data_t *hwp = wsp->walk_data; 336 int rv; 337 338 while (wsp->walk_addr == NULL) { 339 if (++hwp->hw_hashidx < hwp->hw_hashlen) 340 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 341 else 342 return (WALK_DONE); 343 } 344 345 if (mdb_vread(hwp->hw_data, hwp->hw_size, wsp->walk_addr) == -1) { 346 mdb_warn("failed to read %s at %p", 347 hwp->hw_name, wsp->walk_addr); 348 return (WALK_ERR); 349 } 350 351 rv = wsp->walk_callback(wsp->walk_addr, hwp->hw_data, wsp->walk_cbdata); 352 wsp->walk_addr = *(uintptr_t *)((uintptr_t)hwp->hw_data + hwp->hw_next); 353 return (rv); 354 } 355 356 static void 357 hash_walk_fini(mdb_walk_state_t *wsp) 358 { 359 hashwalk_data_t *hwp = wsp->walk_data; 360 361 mdb_free(hwp->hw_hash, sizeof (uintptr_t) * hwp->hw_hashlen); 362 mdb_free(hwp->hw_data, hwp->hw_size); 363 mdb_free(hwp, sizeof (hashwalk_data_t)); 364 } 365 366 static int 367 ustat_walk_init(mdb_walk_state_t *wsp) 368 { 369 fmd_ustat_t us; 370 371 if (mdb_vread(&us, sizeof (us), wsp->walk_addr) != sizeof (us)) { 372 mdb_warn("failed to read fmd_ustat_t at %p", wsp->walk_addr); 373 return (WALK_ERR); 374 } 375 376 return (hash_walk_init(wsp, 377 (uintptr_t)us.us_hash, us.us_hashlen, NULL, 0, 0)); 378 } 379 380 static int 381 ustat_walk_step(mdb_walk_state_t *wsp) 382 { 383 hashwalk_data_t *hwp = wsp->walk_data; 384 fmd_ustat_elem_t ue; 385 fmd_stat_t s; 386 387 while (wsp->walk_addr == NULL) { 388 if (++hwp->hw_hashidx < hwp->hw_hashlen) 389 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 390 else 391 return (WALK_DONE); 392 } 393 394 if (mdb_vread(&ue, sizeof (ue), wsp->walk_addr) != sizeof (ue) || 395 mdb_vread(&s, sizeof (s), (uintptr_t)ue.use_stat) != sizeof (s)) { 396 mdb_warn("failed to read stat element at %p", wsp->walk_addr); 397 return (WALK_ERR); 398 } 399 400 wsp->walk_addr = (uintptr_t)ue.use_next; 401 402 return (wsp->walk_callback( 403 (uintptr_t)ue.use_stat, &s, wsp->walk_cbdata)); 404 } 405 406 struct fmd_cmd_data { 407 int argc; 408 const mdb_arg_t *argv; 409 }; 410 411 /* ARGSUSED */ 412 static int 413 module_ustat(uintptr_t addr, const void *data, void *wsp) 414 { 415 fmd_module_t *modp = (fmd_module_t *)data; 416 char name[PATH_MAX]; 417 const struct fmd_cmd_data *udp = wsp; 418 419 if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0) 420 (void) mdb_snprintf(name, sizeof (name), "<%p>", 421 modp->mod_name); 422 mdb_printf("%s\n", name); 423 (void) fmd_ustat((uintptr_t)modp->mod_ustat, 424 DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv); 425 return (WALK_NEXT); 426 } 427 428 static int 429 fmd_ustat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 430 { 431 if (!(flags & DCMD_ADDRSPEC)) { 432 struct fmd_cmd_data ud; 433 434 ud.argc = argc; 435 ud.argv = argv; 436 if (mdb_walk("fmd_module", module_ustat, &ud) == -1) { 437 mdb_warn("failed to walk 'fmd_module'"); 438 return (DCMD_ERR); 439 } 440 return (DCMD_OK); 441 } 442 443 if (mdb_pwalk_dcmd("fmd_ustat", "fmd_stat", argc, argv, addr) != 0) { 444 mdb_warn("failed to walk fmd_ustat at %p", addr); 445 return (DCMD_ERR); 446 } 447 448 return (DCMD_OK); 449 } 450 451 /* ARGSUSED */ 452 static int 453 module_stat(uintptr_t addr, const void *data, void *wsp) 454 { 455 fmd_module_t *modp = (fmd_module_t *)data; 456 char name[PATH_MAX]; 457 const struct fmd_cmd_data *udp = wsp; 458 fmd_modstat_t *mod_stats; 459 460 if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0) { 461 (void) mdb_snprintf(name, sizeof (name), "<%p>", 462 modp->mod_name); 463 } 464 mdb_printf("%s\n", name); 465 mod_stats = modp->mod_stats; 466 (void) fmd_stat((uintptr_t)&mod_stats->ms_loadtime, 467 DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv); 468 (void) fmd_stat((uintptr_t)&mod_stats->ms_snaptime, 469 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 470 (void) fmd_stat((uintptr_t)&mod_stats->ms_accepted, 471 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 472 (void) fmd_stat((uintptr_t)&mod_stats->ms_debugdrop, 473 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 474 (void) fmd_stat((uintptr_t)&mod_stats->ms_memtotal, 475 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 476 (void) fmd_stat((uintptr_t)&mod_stats->ms_memlimit, 477 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 478 (void) fmd_stat((uintptr_t)&mod_stats->ms_buftotal, 479 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 480 (void) fmd_stat((uintptr_t)&mod_stats->ms_buflimit, 481 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 482 (void) fmd_stat((uintptr_t)&mod_stats->ms_thrtotal, 483 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 484 (void) fmd_stat((uintptr_t)&mod_stats->ms_thrlimit, 485 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 486 (void) fmd_stat((uintptr_t)&mod_stats->ms_caseopen, 487 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 488 (void) fmd_stat((uintptr_t)&mod_stats->ms_casesolved, 489 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 490 (void) fmd_stat((uintptr_t)&mod_stats->ms_caseclosed, 491 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 492 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_save, 493 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 494 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_restore, 495 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 496 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_zeroed, 497 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 498 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_cnt, 499 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 500 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_time, 501 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 502 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtopen, 503 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 504 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtlimit, 505 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 506 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtqlimit, 507 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 508 return (WALK_NEXT); 509 } 510 511 /*ARGSUSED*/ 512 static int 513 fmd_stat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 514 { 515 char buf[512]; 516 fmd_stat_t s; 517 518 if (argc != 0) 519 return (DCMD_USAGE); 520 521 if (DCMD_HDRSPEC(flags)) 522 mdb_printf("%<u>%-11s %-4s %-32s %s%</u>\n", 523 "ADDR", "TYPE", "NAME", "VALUE"); 524 525 if (!(flags & DCMD_ADDRSPEC)) { 526 struct fmd_cmd_data ud; 527 528 ud.argc = argc; 529 ud.argv = argv; 530 531 if (mdb_walk("fmd_module", module_stat, &ud) == -1) { 532 mdb_warn("failed to walk 'fmd_module'"); 533 return (DCMD_ERR); 534 } 535 return (DCMD_OK); 536 } 537 538 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 539 mdb_warn("failed to read statistic at %p", addr); 540 return (DCMD_ERR); 541 } 542 543 switch (s.fmds_type) { 544 case FMD_TYPE_BOOL: 545 mdb_printf("%-11p %-4s %-32s %s\n", addr, "bool", 546 s.fmds_name, s.fmds_value.bool ? "true" : "false"); 547 break; 548 case FMD_TYPE_INT32: 549 mdb_printf("%-11p %-4s %-32s %d\n", addr, "i32", 550 s.fmds_name, s.fmds_value.i32); 551 break; 552 case FMD_TYPE_UINT32: 553 mdb_printf("%-11p %-4s %-32s %u\n", addr, "ui32", 554 s.fmds_name, s.fmds_value.i32); 555 break; 556 case FMD_TYPE_INT64: 557 mdb_printf("%-11p %-4s %-32s %lld\n", addr, "i64", 558 s.fmds_name, s.fmds_value.i64); 559 break; 560 case FMD_TYPE_UINT64: 561 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "ui64", 562 s.fmds_name, s.fmds_value.ui64); 563 break; 564 case FMD_TYPE_STRING: 565 if (mdb_readstr(buf, sizeof (buf), 566 (uintptr_t)s.fmds_value.str) < 0) { 567 (void) mdb_snprintf(buf, sizeof (buf), "<%p>", 568 s.fmds_value.str); 569 } 570 mdb_printf("%-11p %-4s %-32s %s\n", addr, "str", 571 s.fmds_name, buf); 572 break; 573 case FMD_TYPE_TIME: 574 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "time", 575 s.fmds_name, s.fmds_value.ui64); 576 break; 577 case FMD_TYPE_SIZE: 578 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "size", 579 s.fmds_name, s.fmds_value.ui64); 580 break; 581 default: 582 mdb_printf("%-11p %-4u %-32s ???\n", addr, 583 s.fmds_type, s.fmds_name); 584 break; 585 } 586 587 return (DCMD_OK); 588 } 589 590 /*ARGSUSED*/ 591 static int 592 fmd_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 593 { 594 char type[16], name[16]; 595 fmd_event_impl_t ev; 596 597 if (argc != 0) 598 return (DCMD_USAGE); 599 600 if (mdb_vread(&ev, sizeof (ev), addr) != sizeof (ev)) { 601 mdb_warn("failed to read fmd_event at %p", addr); 602 return (DCMD_ERR); 603 } 604 605 if (DCMD_HDRSPEC(flags)) { 606 mdb_printf("%<u>%-11s %-4s %-5s %-3s %-?s%</u>\n", 607 "ADDR", "TYPE", "STATE", "REF", "NVPAIR"); 608 } 609 610 switch (ev.ev_type) { 611 case FMD_EVT_PROTOCOL: 612 (void) strcpy(type, "PROT"); 613 break; 614 case FMD_EVT_GC: 615 (void) strcpy(type, "GC"); 616 break; 617 case FMD_EVT_CLOSE: 618 (void) strcpy(type, "CLSE"); 619 break; 620 case FMD_EVT_TIMEOUT: 621 (void) strcpy(type, "TIME"); 622 break; 623 case FMD_EVT_STATS: 624 (void) strcpy(type, "STAT"); 625 break; 626 case FMD_EVT_PUBLISH: 627 (void) strcpy(type, "PUBL"); 628 break; 629 case FMD_EVT_TOPO: 630 (void) strcpy(type, "TOPO"); 631 break; 632 default: 633 (void) mdb_snprintf(type, sizeof (type), "%u", ev.ev_type); 634 } 635 636 switch (ev.ev_state) { 637 case FMD_EVS_RECEIVED: 638 (void) strcpy(name, "RECVD"); 639 break; 640 case FMD_EVS_ACCEPTED: 641 (void) strcpy(name, "ACCPT"); 642 break; 643 case FMD_EVS_DISCARDED: 644 (void) strcpy(name, "DSCRD"); 645 break; 646 case FMD_EVS_DIAGNOSED: 647 (void) strcpy(name, "DIAGN"); 648 break; 649 default: 650 (void) mdb_snprintf(name, sizeof (name), "%u", ev.ev_state); 651 } 652 653 mdb_printf("%-11p %-4s %-5s %-3u %p\n", 654 addr, type, name, ev.ev_refs, ev.ev_nvl); 655 656 return (DCMD_OK); 657 } 658 659 static int 660 thread_walk_init(mdb_walk_state_t *wsp) 661 { 662 fmd_t F; 663 664 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 665 mdb_warn("failed to read fmd meta-data"); 666 return (WALK_ERR); 667 } 668 669 wsp->walk_addr = (uintptr_t)F.d_thr_list.l_next; 670 return (WALK_NEXT); 671 } 672 673 static int 674 thread_walk_step(mdb_walk_state_t *wsp) 675 { 676 uintptr_t addr = wsp->walk_addr; 677 fmd_thread_t t; 678 679 if (addr == NULL) 680 return (WALK_DONE); 681 682 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 683 mdb_warn("failed to read fmd_thread at %p", addr); 684 return (WALK_ERR); 685 } 686 687 wsp->walk_addr = (uintptr_t)t.thr_list.l_next; 688 return (wsp->walk_callback(addr, &t, wsp->walk_cbdata)); 689 } 690 691 static int 692 fmd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 693 { 694 fmd_thread_t thr; 695 696 if (!(flags & DCMD_ADDRSPEC)) 697 return (mdb_walk_dcmd("fmd_thread", "fmd_thread", argc, argv)); 698 699 if (argc != 0) 700 return (DCMD_USAGE); 701 702 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) { 703 mdb_warn("failed to read fmd_thread at %p", addr); 704 return (DCMD_ERR); 705 } 706 707 if (DCMD_HDRSPEC(flags)) { 708 mdb_printf("%<u>%-11s %-11s %-8s %-16s%</u>\n", 709 "ADDR", "MOD", "TID", "FUNC"); 710 } 711 712 mdb_printf("%-11p %-11p %-8u %a\n", 713 addr, thr.thr_mod, thr.thr_tid, thr.thr_func); 714 715 return (DCMD_OK); 716 } 717 718 static int 719 mod_walk_init(mdb_walk_state_t *wsp) 720 { 721 fmd_t F; 722 723 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 724 mdb_warn("failed to read fmd meta-data"); 725 return (WALK_ERR); 726 } 727 728 wsp->walk_addr = (uintptr_t)F.d_mod_list.l_next; 729 return (WALK_NEXT); 730 } 731 732 static int 733 mod_walk_step(mdb_walk_state_t *wsp) 734 { 735 uintptr_t addr = wsp->walk_addr; 736 fmd_module_t m; 737 738 if (addr == NULL) 739 return (WALK_DONE); 740 741 if (mdb_vread(&m, sizeof (m), addr) != sizeof (m)) { 742 mdb_warn("failed to read fmd_module at %p", addr); 743 return (WALK_ERR); 744 } 745 746 wsp->walk_addr = (uintptr_t)m.mod_list.l_next; 747 return (wsp->walk_callback(addr, &m, wsp->walk_cbdata)); 748 } 749 750 static int 751 fmd_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 752 { 753 fmd_module_t mod; 754 char name[PATH_MAX]; 755 756 if (!(flags & DCMD_ADDRSPEC)) 757 return (mdb_walk_dcmd("fmd_module", "fmd_module", argc, argv)); 758 759 if (argc != 0) 760 return (DCMD_USAGE); 761 762 if (mdb_vread(&mod, sizeof (mod), addr) != sizeof (mod)) { 763 mdb_warn("failed to read fmd_module at %p", addr); 764 return (DCMD_ERR); 765 } 766 767 if (DCMD_HDRSPEC(flags)) { 768 mdb_printf("%<u>%-11s %-16s %-11s %-4s %-?s %-16s%</u>\n", 769 "ADDR", "OPS", "DATA", "FLAG", "USTAT", "NAME"); 770 } 771 772 if (mdb_readstr(name, sizeof (name), (uintptr_t)mod.mod_name) <= 0) 773 (void) mdb_snprintf(name, sizeof (name), "<%p>", mod.mod_name); 774 775 mdb_printf("%-11p %-16a %-11p 0x%02x %-?p %s\n", addr, 776 mod.mod_ops, mod.mod_data, mod.mod_flags, mod.mod_ustat, name); 777 778 return (DCMD_OK); 779 } 780 781 static int 782 case_walk_init(mdb_walk_state_t *wsp) 783 { 784 fmd_module_t mod; 785 fmd_case_hash_t ch; 786 fmd_t F; 787 788 if (wsp->walk_addr != NULL) { 789 if (mdb_vread(&mod, sizeof (mod), wsp->walk_addr) == -1) { 790 mdb_warn("failed to read module at %p", wsp->walk_addr); 791 return (WALK_ERR); 792 } 793 794 wsp->walk_addr = (uintptr_t)mod.mod_cases.l_next; 795 return (WALK_NEXT); 796 } 797 798 if (mdb_readvar(&F, "fmd") != sizeof (F) || 799 mdb_vread(&ch, sizeof (ch), (uintptr_t)F.d_cases) != sizeof (ch)) { 800 mdb_warn("failed to read fmd meta-data"); 801 return (WALK_ERR); 802 } 803 804 return (hash_walk_init(wsp, (uintptr_t)ch.ch_hash, ch.ch_hashlen, 805 "fmd_case", sizeof (fmd_case_impl_t), 806 OFFSETOF(fmd_case_impl_t, ci_next))); 807 } 808 809 static int 810 case_walk_step(mdb_walk_state_t *wsp) 811 { 812 uintptr_t addr = wsp->walk_addr; 813 fmd_case_impl_t ci; 814 815 if (wsp->walk_data != NULL) 816 return (hash_walk_step(wsp)); 817 818 if (addr == NULL) 819 return (WALK_DONE); 820 821 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 822 mdb_warn("failed to read fmd_case at %p", addr); 823 return (WALK_ERR); 824 } 825 826 wsp->walk_addr = (uintptr_t)ci.ci_list.l_next; 827 return (wsp->walk_callback(addr, &ci, wsp->walk_cbdata)); 828 } 829 830 static void 831 case_walk_fini(mdb_walk_state_t *wsp) 832 { 833 if (wsp->walk_data != NULL) 834 hash_walk_fini(wsp); 835 } 836 837 static int 838 fmd_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 839 { 840 char uuid[48], name[16]; 841 fmd_case_impl_t ci; 842 843 if (!(flags & DCMD_ADDRSPEC)) { 844 if (mdb_walk_dcmd("fmd_case", "fmd_case", argc, argv) != 0) { 845 mdb_warn("failed to walk fmd_case hash"); 846 return (DCMD_ERR); 847 } 848 return (DCMD_OK); 849 } 850 851 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 852 mdb_warn("failed to read fmd_case at %p", addr); 853 return (DCMD_ERR); 854 } 855 856 if (DCMD_HDRSPEC(flags)) { 857 mdb_printf("%<u>%-11s %-5s %-3s %-?s %-36s%</u>\n", 858 "ADDR", "STATE", "REF", "DATA", "UUID"); 859 } 860 861 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)ci.ci_uuid) <= 0) 862 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", ci.ci_uuid); 863 864 switch (ci.ci_state) { 865 case FMD_CASE_UNSOLVED: 866 (void) strcpy(name, "UNSLV"); 867 break; 868 case FMD_CASE_SOLVED: 869 (void) strcpy(name, "SOLVE"); 870 break; 871 case FMD_CASE_CLOSE_WAIT: 872 (void) strcpy(name, "CWAIT"); 873 break; 874 case FMD_CASE_CLOSED: 875 (void) strcpy(name, "CLOSE"); 876 break; 877 case FMD_CASE_REPAIRED: 878 (void) strcpy(name, "RPAIR"); 879 break; 880 default: 881 (void) mdb_snprintf(name, sizeof (name), "%u", ci.ci_state); 882 } 883 884 mdb_printf("%-11p %-5s %-3u %-?p %s\n", 885 addr, name, ci.ci_refs, ci.ci_data, uuid); 886 887 return (DCMD_OK); 888 } 889 890 static int 891 buf_walk_init(mdb_walk_state_t *wsp) 892 { 893 fmd_buf_hash_t bh; 894 895 if (mdb_vread(&bh, sizeof (bh), wsp->walk_addr) != sizeof (bh)) { 896 mdb_warn("failed to read fmd_buf_hash_t at %p", wsp->walk_addr); 897 return (WALK_ERR); 898 } 899 900 return (hash_walk_init(wsp, (uintptr_t)bh.bh_hash, bh.bh_hashlen, 901 "fmd_buf", sizeof (fmd_buf_t), OFFSETOF(fmd_buf_t, buf_next))); 902 } 903 904 /*ARGSUSED*/ 905 static int 906 fmd_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 907 { 908 char name[PATH_MAX]; 909 fmd_buf_t b; 910 911 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 912 return (DCMD_USAGE); 913 914 if (mdb_vread(&b, sizeof (b), addr) != sizeof (b)) { 915 mdb_warn("failed to read fmd_buf at %p", addr); 916 return (DCMD_ERR); 917 } 918 919 if (DCMD_HDRSPEC(flags)) { 920 mdb_printf("%<u>%-11s %-32s %-5s %-?s %s%</u>\n", 921 "ADDR", "NAME", "FLAGS", "DATA", "SIZE"); 922 } 923 924 if (mdb_readstr(name, sizeof (name), (uintptr_t)b.buf_name) <= 0) 925 (void) mdb_snprintf(name, sizeof (name), "<%p>", b.buf_name); 926 927 mdb_printf("%-11p %-32s %-#5x %-?p %lu\n", 928 addr, name, b.buf_flags, b.buf_data, b.buf_size); 929 930 return (DCMD_OK); 931 } 932 933 static int 934 serd_walk_init(mdb_walk_state_t *wsp) 935 { 936 fmd_serd_hash_t sh; 937 938 if (mdb_vread(&sh, sizeof (sh), wsp->walk_addr) != sizeof (sh)) { 939 mdb_warn("failed to read fmd_serd_hash at %p", wsp->walk_addr); 940 return (WALK_ERR); 941 } 942 943 return (hash_walk_init(wsp, (uintptr_t)sh.sh_hash, sh.sh_hashlen, 944 "fmd_serd_eng", sizeof (fmd_serd_eng_t), 945 OFFSETOF(fmd_serd_eng_t, sg_next))); 946 } 947 948 /* ARGSUSED */ 949 static int 950 module_serd(uintptr_t addr, const void *data, void *wsp) 951 { 952 fmd_module_t *modp = (fmd_module_t *)data; 953 954 if (modp->mod_serds.sh_count != 0) { 955 modp = (fmd_module_t *)addr; 956 (void) mdb_pwalk_dcmd("fmd_serd", "fmd_serd", 0, 0, 957 (uintptr_t)&modp->mod_serds); 958 } 959 return (WALK_NEXT); 960 } 961 962 /*ARGSUSED*/ 963 static int 964 fmd_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 965 { 966 char name[PATH_MAX]; 967 fmd_serd_eng_t sg; 968 969 if (argc != 0) 970 return (DCMD_USAGE); 971 if (!(flags & DCMD_ADDRSPEC)) { 972 if (mdb_walk("fmd_module", module_serd, 0) == -1) { 973 mdb_warn("failed to walk 'fmd_module'"); 974 return (DCMD_ERR); 975 } 976 return (DCMD_OK); 977 } 978 979 if (mdb_vread(&sg, sizeof (sg), addr) != sizeof (sg)) { 980 mdb_warn("failed to read fmd_serd_eng at %p", addr); 981 return (DCMD_ERR); 982 } 983 984 if (DCMD_HDRSPEC(flags)) { 985 mdb_printf("%<u>%-11s %-32s %-3s F >%-2s %-16s%</u>\n", 986 "ADDR", "NAME", "CNT", "N", "T"); 987 } 988 989 if (mdb_readstr(name, sizeof (name), (uintptr_t)sg.sg_name) <= 0) 990 (void) mdb_snprintf(name, sizeof (name), "<%p>", sg.sg_name); 991 992 mdb_printf("%-11p %-32s %-3u %c >%-2u %lluns\n", 993 addr, name, sg.sg_count, (sg.sg_flags & FMD_SERD_FIRED) ? 'F' : ' ', 994 sg.sg_n, (u_longlong_t)sg.sg_t); 995 996 return (DCMD_OK); 997 } 998 999 static int 1000 asru_walk_init(mdb_walk_state_t *wsp) 1001 { 1002 fmd_asru_hash_t ah; 1003 fmd_t F; 1004 1005 if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) { 1006 mdb_warn("failed to read fmd meta-data"); 1007 return (WALK_ERR); 1008 } 1009 1010 if (wsp->walk_addr == NULL) 1011 wsp->walk_addr = (uintptr_t)F.d_asrus; 1012 1013 if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) { 1014 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr); 1015 return (WALK_ERR); 1016 } 1017 1018 return (hash_walk_init(wsp, (uintptr_t)ah.ah_hash, ah.ah_hashlen, 1019 "fmd_asru", sizeof (fmd_asru_t), OFFSETOF(fmd_asru_t, asru_next))); 1020 } 1021 1022 static int 1023 fmd_asru(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1024 { 1025 char uuid[48], name[PATH_MAX]; 1026 fmd_asru_t a; 1027 1028 if (!(flags & DCMD_ADDRSPEC)) { 1029 if (mdb_walk_dcmd("fmd_asru", "fmd_asru", argc, argv) != 0) { 1030 mdb_warn("failed to walk fmd_asru hash"); 1031 return (DCMD_ERR); 1032 } 1033 return (DCMD_OK); 1034 } 1035 1036 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 1037 mdb_warn("failed to read fmd_asru at %p", addr); 1038 return (DCMD_ERR); 1039 } 1040 1041 if (DCMD_HDRSPEC(flags)) 1042 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME"); 1043 1044 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.asru_uuid) <= 0) 1045 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.asru_uuid); 1046 if (mdb_readstr(name, sizeof (name), (uintptr_t)a.asru_name) <= 0) 1047 (void) mdb_snprintf(name, sizeof (name), "<%p>", a.asru_name); 1048 1049 mdb_printf("%-8p %-36s %s\n", addr, uuid, name); 1050 return (DCMD_OK); 1051 } 1052 1053 static int 1054 al_walk_init(mdb_walk_state_t *wsp) 1055 { 1056 fmd_asru_hash_t ah; 1057 fmd_t F; 1058 1059 if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) { 1060 mdb_warn("failed to read fmd meta-data"); 1061 return (WALK_ERR); 1062 } 1063 1064 if (wsp->walk_addr == NULL) 1065 wsp->walk_addr = (uintptr_t)F.d_asrus; 1066 1067 if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) { 1068 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr); 1069 return (WALK_ERR); 1070 } 1071 1072 return (hash_walk_init(wsp, (uintptr_t)ah.ah_rsrc_hash, ah.ah_hashlen, 1073 "fmd_asru_link", sizeof (fmd_asru_link_t), OFFSETOF(fmd_asru_link_t, 1074 al_rsrc_next))); 1075 } 1076 1077 static int 1078 fmd_asru_link(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1079 { 1080 char uuid[48], name[PATH_MAX]; 1081 fmd_asru_link_t a; 1082 1083 if (!(flags & DCMD_ADDRSPEC)) { 1084 if (mdb_walk_dcmd("fmd_asru_link", "fmd_asru_link", argc, 1085 argv) != 0) { 1086 mdb_warn("failed to walk fmd_asru_link hash"); 1087 return (DCMD_ERR); 1088 } 1089 return (DCMD_OK); 1090 } 1091 1092 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 1093 mdb_warn("failed to read fmd_asru_link at %p", addr); 1094 return (DCMD_ERR); 1095 } 1096 1097 if (DCMD_HDRSPEC(flags)) 1098 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME"); 1099 1100 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.al_uuid) <= 0) 1101 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.al_uuid); 1102 if (mdb_readstr(name, sizeof (name), (uintptr_t)a.al_rsrc_name) <= 0) 1103 (void) mdb_snprintf(name, sizeof (name), "<%p>", 1104 a.al_rsrc_name); 1105 1106 mdb_printf("%-8p %-36s %s\n", addr, uuid, name); 1107 return (DCMD_OK); 1108 } 1109 1110 /*ARGSUSED*/ 1111 static int 1112 fcf_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1113 { 1114 fcf_hdr_t h; 1115 1116 if (argc != 0) 1117 return (DCMD_USAGE); 1118 1119 if (!(flags & DCMD_ADDRSPEC)) 1120 addr = 0; /* assume base of file in file target */ 1121 1122 if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 1123 mdb_warn("failed to read header at %p", addr); 1124 return (DCMD_ERR); 1125 } 1126 1127 mdb_printf("fcfh_ident.id_magic = 0x%x, %c, %c, %c\n", 1128 h.fcfh_ident[FCF_ID_MAG0], h.fcfh_ident[FCF_ID_MAG1], 1129 h.fcfh_ident[FCF_ID_MAG2], h.fcfh_ident[FCF_ID_MAG3]); 1130 1131 switch (h.fcfh_ident[FCF_ID_MODEL]) { 1132 case FCF_MODEL_ILP32: 1133 mdb_printf("fcfh_ident.id_model = ILP32\n"); 1134 break; 1135 case FCF_MODEL_LP64: 1136 mdb_printf("fcfh_ident.id_model = LP64\n"); 1137 break; 1138 default: 1139 mdb_printf("fcfh_ident.id_model = 0x%x\n", 1140 h.fcfh_ident[FCF_ID_MODEL]); 1141 } 1142 1143 switch (h.fcfh_ident[FCF_ID_ENCODING]) { 1144 case FCF_ENCODE_LSB: 1145 mdb_printf("fcfh_ident.id_encoding = LSB\n"); 1146 break; 1147 case FCF_ENCODE_MSB: 1148 mdb_printf("fcfh_ident.id_encoding = MSB\n"); 1149 break; 1150 default: 1151 mdb_printf("fcfh_ident.id_encoding = 0x%x\n", 1152 h.fcfh_ident[FCF_ID_ENCODING]); 1153 } 1154 1155 mdb_printf("fcfh_ident.id_version = %u\n", 1156 h.fcfh_ident[FCF_ID_VERSION]); 1157 1158 mdb_printf("fcfh_flags = 0x%x\n", h.fcfh_flags); 1159 mdb_printf("fcfh_hdrsize = %u\n", h.fcfh_hdrsize); 1160 mdb_printf("fcfh_secsize = %u\n", h.fcfh_secsize); 1161 mdb_printf("fcfh_secnum = %u\n", h.fcfh_secnum); 1162 mdb_printf("fcfh_secoff = %llu\n", h.fcfh_secoff); 1163 mdb_printf("fcfh_filesz = %llu\n", h.fcfh_filesz); 1164 mdb_printf("fcfh_cgen = %llu\n", h.fcfh_cgen); 1165 1166 return (DCMD_OK); 1167 } 1168 1169 static int fcf_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 1170 /*ARGSUSED*/ 1171 static int 1172 fcf_sec_one(uintptr_t addr, void *ignored, uint_t *secp) 1173 { 1174 1175 mdb_printf("%3d ", (*secp)++); 1176 (void) fcf_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 1177 return (WALK_NEXT); 1178 } 1179 1180 /*ARGSUSED*/ 1181 static int 1182 fcf_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1183 { 1184 static const char *const types[] = { 1185 "none", /* FCF_SECT_NONE */ 1186 "strtab", /* FCF_SECT_STRTAB */ 1187 "module", /* FCF_SECT_MODULE */ 1188 "case", /* FCF_SECT_CASE */ 1189 "bufs", /* FCF_SECT_BUFS */ 1190 "buffer", /* FCF_SECT_BUFFER */ 1191 "serd", /* FCF_SECT_SERD */ 1192 "events", /* FCF_SECT_EVENTS */ 1193 "nvlists", /* FCF_SECT_NVLISTS */ 1194 }; 1195 1196 uint_t sec = 0; 1197 fcf_sec_t s; 1198 1199 if (!(flags & DCMD_ADDRSPEC)) 1200 mdb_printf("%<u>%-3s ", "NDX"); 1201 1202 if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 1203 mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 1204 "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFF", "SIZE"); 1205 } 1206 1207 if (!(flags & DCMD_ADDRSPEC)) { 1208 if (mdb_walk("fcf_sec", (mdb_walk_cb_t)fcf_sec_one, &sec) < 0) { 1209 mdb_warn("failed to walk fcf_sec"); 1210 return (DCMD_ERR); 1211 } 1212 return (DCMD_OK); 1213 } 1214 1215 if (argc != 0) 1216 return (DCMD_USAGE); 1217 1218 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 1219 mdb_warn("failed to read section header at %p", addr); 1220 return (DCMD_ERR); 1221 } 1222 1223 mdb_printf("%?p ", addr); 1224 1225 if (s.fcfs_type < sizeof (types) / sizeof (types[0])) 1226 mdb_printf("%-10s ", types[s.fcfs_type]); 1227 else 1228 mdb_printf("%-10u ", s.fcfs_type); 1229 1230 mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.fcfs_align, 1231 s.fcfs_flags, s.fcfs_entsize, s.fcfs_offset, s.fcfs_size); 1232 1233 return (DCMD_OK); 1234 } 1235 1236 static int 1237 fcf_sec_walk_init(mdb_walk_state_t *wsp) 1238 { 1239 fcf_hdr_t h, *hp; 1240 size_t size; 1241 1242 if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 1243 mdb_warn("failed to read FCF header at %p", wsp->walk_addr); 1244 return (WALK_ERR); 1245 } 1246 1247 size = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * h.fcfh_secnum; 1248 hp = mdb_alloc(size, UM_SLEEP); 1249 1250 if (mdb_vread(hp, size, wsp->walk_addr) != size) { 1251 mdb_warn("failed to read FCF sections at %p", wsp->walk_addr); 1252 mdb_free(hp, size); 1253 return (WALK_ERR); 1254 } 1255 1256 wsp->walk_data = hp; 1257 wsp->walk_arg = 0; 1258 1259 return (WALK_NEXT); 1260 } 1261 1262 static int 1263 fcf_sec_walk_step(mdb_walk_state_t *wsp) 1264 { 1265 uint_t i = (uint_t)wsp->walk_arg; 1266 size_t off = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * i; 1267 fcf_hdr_t *hp = wsp->walk_data; 1268 fcf_sec_t *sp = (fcf_sec_t *)((uintptr_t)hp + off); 1269 1270 if (i >= hp->fcfh_secnum) 1271 return (WALK_DONE); 1272 1273 wsp->walk_arg = (void *)(i + 1); 1274 return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 1275 } 1276 1277 static void 1278 fcf_sec_walk_fini(mdb_walk_state_t *wsp) 1279 { 1280 fcf_hdr_t *hp = wsp->walk_data; 1281 mdb_free(hp, sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * hp->fcfh_secnum); 1282 } 1283 1284 /*ARGSUSED*/ 1285 static int 1286 fcf_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1287 { 1288 fcf_case_t fcfc; 1289 1290 if (argc != 0) 1291 return (DCMD_USAGE); 1292 1293 if (mdb_vread(&fcfc, sizeof (fcfc), addr) != sizeof (fcfc)) { 1294 mdb_warn("failed to read case at %p", addr); 1295 return (DCMD_ERR); 1296 } 1297 1298 mdb_printf("fcfc_uuid = 0x%x\n", fcfc.fcfc_uuid); 1299 mdb_printf("fcfc_state = %u\n", fcfc.fcfc_state); 1300 mdb_printf("fcfc_bufs = %u\n", fcfc.fcfc_bufs); 1301 mdb_printf("fcfc_events = %u\n", fcfc.fcfc_events); 1302 mdb_printf("fcfc_suspects = %u\n", fcfc.fcfc_suspects); 1303 1304 return (DCMD_OK); 1305 } 1306 1307 /*ARGSUSED*/ 1308 static int 1309 fcf_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1310 { 1311 fcf_event_t fcfe; 1312 1313 if (argc != 0) 1314 return (DCMD_USAGE); 1315 1316 if (mdb_vread(&fcfe, sizeof (fcfe), addr) != sizeof (fcfe)) { 1317 mdb_warn("failed to read event at %p", addr); 1318 return (DCMD_ERR); 1319 } 1320 1321 mdb_printf("fcfe_todsec = %llu (%Y)\n", 1322 fcfe.fcfe_todsec, (time_t)fcfe.fcfe_todsec); 1323 mdb_printf("fcfe_todnsec = %llu\n", fcfe.fcfe_todnsec); 1324 mdb_printf("fcfe_major = %u\n", fcfe.fcfe_major); 1325 mdb_printf("fcfe_minor = %u\n", fcfe.fcfe_minor); 1326 mdb_printf("fcfe_inode = %llu\n", fcfe.fcfe_inode); 1327 mdb_printf("fcfe_offset = %llu\n", fcfe.fcfe_offset); 1328 1329 return (DCMD_OK); 1330 } 1331 1332 /*ARGSUSED*/ 1333 static int 1334 fcf_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1335 { 1336 fcf_serd_t fcfd; 1337 1338 if (argc != 0) 1339 return (DCMD_USAGE); 1340 1341 if (mdb_vread(&fcfd, sizeof (fcfd), addr) != sizeof (fcfd)) { 1342 mdb_warn("failed to read serd at %p", addr); 1343 return (DCMD_ERR); 1344 } 1345 1346 mdb_printf("fcfd_name = 0x%x\n", fcfd.fcfd_name); 1347 mdb_printf("fcfd_events = %u\n", fcfd.fcfd_events); 1348 mdb_printf("fcfd_n = >%u\n", fcfd.fcfd_n); 1349 mdb_printf("fcfd_t = %lluns\n", fcfd.fcfd_t); 1350 1351 return (DCMD_OK); 1352 } 1353 1354 static int 1355 tmq_walk_init(mdb_walk_state_t *wsp) 1356 { 1357 fmd_timerq_t tmq; 1358 fmd_t F; 1359 1360 if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) { 1361 mdb_warn("failed to read fmd meta-data"); 1362 return (WALK_ERR); 1363 } 1364 1365 if (wsp->walk_addr == NULL) 1366 wsp->walk_addr = (uintptr_t)F.d_timers; 1367 1368 if (mdb_vread(&tmq, sizeof (tmq), wsp->walk_addr) != sizeof (tmq)) { 1369 mdb_warn("failed to read timerq at %p", wsp->walk_addr); 1370 return (WALK_ERR); 1371 } 1372 1373 wsp->walk_addr = (uintptr_t)tmq.tmq_list.l_next; 1374 return (WALK_NEXT); 1375 } 1376 1377 static int 1378 tmq_walk_step(mdb_walk_state_t *wsp) 1379 { 1380 uintptr_t addr = wsp->walk_addr; 1381 fmd_timer_t tmr; 1382 1383 if (addr == NULL) 1384 return (WALK_DONE); 1385 1386 if (mdb_vread(&tmr, sizeof (tmr), addr) != sizeof (tmr)) { 1387 mdb_warn("failed to read fmd_timer at %p", addr); 1388 return (WALK_ERR); 1389 } 1390 1391 wsp->walk_addr = (uintptr_t)tmr.tmr_list.l_next; 1392 return (wsp->walk_callback(addr, &tmr, wsp->walk_cbdata)); 1393 } 1394 1395 static int 1396 fmd_timer(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1397 { 1398 char name[32], func[MDB_SYM_NAMLEN]; 1399 fmd_timer_t t; 1400 1401 if (!(flags & DCMD_ADDRSPEC)) { 1402 if (mdb_walk_dcmd("fmd_timerq", "fmd_timer", argc, argv) != 0) { 1403 mdb_warn("failed to walk fmd_timerq"); 1404 return (DCMD_ERR); 1405 } 1406 return (DCMD_OK); 1407 } 1408 1409 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 1410 mdb_warn("failed to read fmd_timer at %p", addr); 1411 return (DCMD_ERR); 1412 } 1413 1414 if (DCMD_HDRSPEC(flags)) { 1415 mdb_printf("%<u>%-8s %-20s %-4s %-18s %-8s %s%</u>\n", 1416 "ADDR", "MODULE", "ID", "HRTIME", "ARG", "FUNC"); 1417 } 1418 1419 if (mdb_readstr(name, sizeof (name), (uintptr_t) 1420 t.tmr_ids + OFFSETOF(fmd_idspace_t, ids_name)) <= 0) 1421 (void) mdb_snprintf(name, sizeof (name), "<%p>", t.tmr_ids); 1422 1423 if (mdb_lookup_by_addr((uintptr_t)t.tmr_func, MDB_SYM_FUZZY, 1424 func, sizeof (func), NULL) != 0) 1425 (void) mdb_snprintf(func, sizeof (func), "<%p>", t.tmr_func); 1426 1427 mdb_printf("%-8p %-20s %4d 0x%-16llx %-8p %s\n", 1428 addr, name, t.tmr_id, t.tmr_hrt, t.tmr_arg, func); 1429 return (DCMD_OK); 1430 } 1431 1432 static int 1433 xprt_walk_init(mdb_walk_state_t *wsp) 1434 { 1435 fmd_module_t m; 1436 1437 if (wsp->walk_addr == NULL) { 1438 mdb_warn("transport walker requires fmd_module_t address\n"); 1439 return (WALK_ERR); 1440 } 1441 1442 if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) { 1443 mdb_warn("failed to read module at %p", wsp->walk_addr); 1444 return (WALK_ERR); 1445 } 1446 1447 wsp->walk_addr = (uintptr_t)m.mod_transports.l_next; 1448 return (WALK_NEXT); 1449 } 1450 1451 static int 1452 xprt_walk_step(mdb_walk_state_t *wsp) 1453 { 1454 uintptr_t addr = wsp->walk_addr; 1455 fmd_xprt_impl_t xi; 1456 1457 if (addr == NULL) 1458 return (WALK_DONE); 1459 1460 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1461 mdb_warn("failed to read fmd_xprt at %p", addr); 1462 return (WALK_ERR); 1463 } 1464 1465 wsp->walk_addr = (uintptr_t)xi.xi_list.l_next; 1466 return (wsp->walk_callback(addr, &xi, wsp->walk_cbdata)); 1467 } 1468 1469 static int 1470 xpc_walk_init(mdb_walk_state_t *wsp) 1471 { 1472 fmd_xprt_class_hash_t xch; 1473 1474 if (mdb_vread(&xch, sizeof (xch), wsp->walk_addr) != sizeof (xch)) { 1475 mdb_warn("failed to read fmd_xprt_class_hash at %p", 1476 wsp->walk_addr); 1477 return (WALK_ERR); 1478 } 1479 1480 return (hash_walk_init(wsp, (uintptr_t)xch.xch_hash, xch.xch_hashlen, 1481 "fmd_xprt_class", sizeof (fmd_xprt_class_t), 1482 OFFSETOF(fmd_xprt_class_t, xc_next))); 1483 } 1484 1485 /*ARGSUSED*/ 1486 static int 1487 fmd_xprt_class(uintptr_t addr, const void *data, void *arg) 1488 { 1489 const fmd_xprt_class_t *xcp = data; 1490 char name[1024]; 1491 1492 if (mdb_readstr(name, sizeof (name), (uintptr_t)xcp->xc_class) <= 0) 1493 (void) mdb_snprintf(name, sizeof (name), "<%p>", xcp->xc_class); 1494 1495 mdb_printf("%-8p %-4u %s\n", addr, xcp->xc_refs, name); 1496 return (WALK_NEXT); 1497 } 1498 1499 static int 1500 fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1501 { 1502 uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE; 1503 fmd_xprt_impl_t xi; 1504 1505 if (mdb_getopts(argc, argv, 1506 'l', MDB_OPT_SETBITS, TRUE, &opt_l, 1507 'r', MDB_OPT_SETBITS, TRUE, &opt_r, 1508 's', MDB_OPT_SETBITS, TRUE, &opt_s, 1509 'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc) 1510 return (DCMD_USAGE); 1511 1512 if (!(flags & DCMD_ADDRSPEC)) { 1513 if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) { 1514 mdb_warn("failed to walk fmd_xprt"); 1515 return (DCMD_ERR); 1516 } 1517 return (DCMD_OK); 1518 } 1519 1520 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1521 mdb_warn("failed to read fmd_xprt at %p", addr); 1522 return (DCMD_ERR); 1523 } 1524 1525 if (DCMD_HDRSPEC(flags)) { 1526 mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n", 1527 "ADDR", "ID", "VERS", "FLAGS", "STATE"); 1528 } 1529 1530 mdb_printf("%-8p %-4d %-4u %-5x %a\n", 1531 addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state); 1532 1533 if (opt_l | opt_s) { 1534 (void) mdb_inc_indent(4); 1535 mdb_printf("Local subscriptions requested by peer:\n"); 1536 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1537 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1538 addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub)); 1539 (void) mdb_dec_indent(4); 1540 } 1541 1542 if (opt_r | opt_s) { 1543 (void) mdb_inc_indent(4); 1544 mdb_printf("Remote subscriptions requested of peer:\n"); 1545 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1546 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1547 addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub)); 1548 (void) mdb_dec_indent(4); 1549 } 1550 1551 if (opt_u | opt_s) { 1552 (void) mdb_inc_indent(4); 1553 mdb_printf("Pending unsubscription acknowledgements:\n"); 1554 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1555 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1556 addr + OFFSETOF(fmd_xprt_impl_t, xi_usub)); 1557 (void) mdb_dec_indent(4); 1558 } 1559 1560 return (DCMD_OK); 1561 } 1562 1563 static int 1564 tsnap_walk_init(mdb_walk_state_t *wsp) 1565 { 1566 fmd_t F; 1567 1568 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 1569 mdb_warn("failed to read fmd meta-data"); 1570 return (WALK_ERR); 1571 } 1572 1573 wsp->walk_addr = (uintptr_t)F.d_topo_list.l_next; 1574 return (WALK_NEXT); 1575 } 1576 1577 static int 1578 tsnap_walk_step(mdb_walk_state_t *wsp) 1579 { 1580 uintptr_t addr = wsp->walk_addr; 1581 fmd_topo_t ftp; 1582 1583 if (addr == NULL) 1584 return (WALK_DONE); 1585 1586 if (mdb_vread(&ftp, sizeof (ftp), addr) != sizeof (ftp)) { 1587 mdb_warn("failed to read fmd_topo_t at %p", addr); 1588 return (WALK_ERR); 1589 } 1590 1591 wsp->walk_addr = (uintptr_t)ftp.ft_list.l_next; 1592 return (wsp->walk_callback(addr, &ftp, wsp->walk_cbdata)); 1593 } 1594 1595 static int 1596 mq_walk_init(mdb_walk_state_t *wsp) 1597 { 1598 fmd_module_t m; 1599 struct fmd_eventq eq; 1600 1601 if (wsp->walk_addr == NULL) { 1602 mdb_warn("NULL fmd_module_t passed in"); 1603 return (WALK_ERR); 1604 } 1605 1606 if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) { 1607 mdb_warn("failed to read fmd_module_t at %p", wsp->walk_addr); 1608 return (WALK_ERR); 1609 } 1610 if (mdb_vread(&eq, sizeof (eq), (uintptr_t)m.mod_queue) 1611 != sizeof (eq)) { 1612 mdb_warn("failed to read fmd_eventq at %p", wsp->walk_addr); 1613 return (WALK_ERR); 1614 } 1615 1616 wsp->walk_addr = (uintptr_t)eq.eq_list.l_next; 1617 1618 return (WALK_NEXT); 1619 } 1620 1621 static int 1622 mq_walk_step(mdb_walk_state_t *wsp) 1623 { 1624 uintptr_t addr = wsp->walk_addr; 1625 fmd_eventqelem_t eqe; 1626 1627 if (addr == NULL) 1628 return (WALK_DONE); 1629 1630 if (mdb_vread(&eqe, sizeof (eqe), addr) != sizeof (eqe)) { 1631 mdb_warn("failed to read fmd_eventqelem_t at %p", addr); 1632 return (WALK_ERR); 1633 } 1634 1635 wsp->walk_addr = (uintptr_t)eqe.eqe_list.l_next; 1636 return (wsp->walk_callback(addr, &eqe, wsp->walk_cbdata)); 1637 } 1638 1639 static const mdb_dcmd_t dcmds[] = { 1640 { "fcf_case", "?", "print a FCF case", fcf_case }, 1641 { "fcf_event", "?", "print a FCF event", fcf_event }, 1642 { "fcf_hdr", "?", "print a FCF header", fcf_hdr }, 1643 { "fcf_sec", ":", "print a FCF section header", fcf_sec }, 1644 { "fcf_serd", "?", "print a FCF serd engine", fcf_serd }, 1645 { "fmd_trace", "?[-cs]", "display thread trace buffer(s)", fmd_trace }, 1646 { "fmd_ustat", "[:]", "display statistics collection", fmd_ustat }, 1647 { "fmd_stat", "[:]", "display statistic structure", fmd_stat }, 1648 { "fmd_event", NULL, "display event structure", fmd_event }, 1649 { "fmd_thread", "?", "display thread or list of threads", fmd_thread }, 1650 { "fmd_module", "?", "display module or list of modules", fmd_module }, 1651 { "fmd_case", ":", "display case file structure", fmd_case }, 1652 { "fmd_buf", ":", "display buffer structure", fmd_buf }, 1653 { "fmd_serd", "[:]", "display serd engine structure", fmd_serd }, 1654 { "fmd_asru", "?", "display asru resource structure", fmd_asru }, 1655 { "fmd_asru_link", "?", "display resource structure", fmd_asru_link }, 1656 { "fmd_timer", "?", "display pending timer(s)", fmd_timer }, 1657 { "fmd_xprt", "?[-lrsu]", "display event transport(s)", fmd_xprt }, 1658 { NULL } 1659 }; 1660 1661 static const mdb_walker_t walkers[] = { 1662 { "fcf_sec", "walk FCF section header table given header address", 1663 fcf_sec_walk_init, fcf_sec_walk_step, fcf_sec_walk_fini }, 1664 { "fmd_trace", "walk per-thread trace buffers", 1665 trwalk_init, trwalk_step, trwalk_fini }, 1666 { "fmd_ustat", "walk per-collection statistics", 1667 ustat_walk_init, ustat_walk_step, hash_walk_fini }, 1668 { "fmd_thread", "walk list of all fmd_thread_t's", 1669 thread_walk_init, thread_walk_step, NULL }, 1670 { "fmd_module", "walk list of all fmd_module_t's", 1671 mod_walk_init, mod_walk_step, NULL }, 1672 { "fmd_case", "walk per-module case objects", 1673 case_walk_init, case_walk_step, case_walk_fini }, 1674 { "fmd_buf", "walk per-buf_hash buffers", 1675 buf_walk_init, hash_walk_step, hash_walk_fini }, 1676 { "fmd_serd", "walk per-serd_hash engines", 1677 serd_walk_init, hash_walk_step, hash_walk_fini }, 1678 { "fmd_asru", "walk asru resource hash", 1679 asru_walk_init, hash_walk_step, hash_walk_fini }, 1680 { "fmd_asru_link", "walk resource hash", 1681 al_walk_init, hash_walk_step, hash_walk_fini }, 1682 { "fmd_timerq", "walk timer queue", 1683 tmq_walk_init, tmq_walk_step, NULL }, 1684 { "fmd_xprt", "walk per-module list of transports", 1685 xprt_walk_init, xprt_walk_step, NULL }, 1686 { "fmd_xprt_class", "walk hash table of subscription classes", 1687 xpc_walk_init, hash_walk_step, hash_walk_fini }, 1688 { "fmd_topo", "walk fmd's list of topo snapshots", 1689 tsnap_walk_init, tsnap_walk_step, NULL }, 1690 { "fmd_mod_queue", "walk per-module event queue", 1691 mq_walk_init, mq_walk_step, NULL }, 1692 { NULL, NULL, NULL, NULL, NULL } 1693 }; 1694 1695 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1696 1697 const mdb_modinfo_t * 1698 _mdb_init(void) 1699 { 1700 return (&modinfo); 1701 } 1702