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