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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Copyright 2019 Joyent, Inc. 27 */ 28 29 #include <sys/mdb_modapi.h> 30 31 #include <lut.h> 32 #include <itree.h> 33 #include "ipath_impl.h" 34 #include "lut_impl.h" 35 #include "config_impl.h" 36 #include "stats_impl.h" 37 38 #define LUT_SIZE_INIT 300 39 #define LUT_SIZE_INCR 100 40 41 struct lut_cp { 42 uintptr_t lutcp_addr; 43 struct lut lutcp_lut; 44 }; 45 46 #define LCPSZ sizeof (struct lut_cp) 47 48 struct lut_dump_desc { 49 struct lut_cp *ld_array; 50 int ld_arraysz; 51 int ld_nents; 52 }; 53 54 static void 55 lut_dump_array_alloc(struct lut_dump_desc *lddp) 56 { 57 struct lut_cp *new; 58 59 if (lddp->ld_array == NULL) { 60 lddp->ld_arraysz = LUT_SIZE_INIT; 61 lddp->ld_array = mdb_zalloc(LUT_SIZE_INIT * LCPSZ, UM_SLEEP); 62 return; 63 } 64 65 new = mdb_zalloc((lddp->ld_arraysz + LUT_SIZE_INCR) * LCPSZ, UM_SLEEP); 66 bcopy(lddp->ld_array, new, lddp->ld_arraysz * LCPSZ); 67 mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ); 68 lddp->ld_array = new; 69 lddp->ld_arraysz += LUT_SIZE_INCR; 70 } 71 72 static void 73 lut_dump_array_free(struct lut_dump_desc *lddp) 74 { 75 if (lddp->ld_array != NULL) { 76 mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ); 77 lddp->ld_array = NULL; 78 } 79 } 80 81 static void 82 lut_collect_addent(uintptr_t addr, struct lut *ent, struct lut_dump_desc *lddp) 83 { 84 struct lut_cp *lcp; 85 86 if (lddp->ld_nents == lddp->ld_arraysz) 87 lut_dump_array_alloc(lddp); 88 89 lcp = &lddp->ld_array[lddp->ld_nents++]; 90 91 lcp->lutcp_addr = addr; 92 bcopy(ent, &lcp->lutcp_lut, sizeof (struct lut)); 93 } 94 95 static int 96 eft_lut_walk(uintptr_t root, struct lut_dump_desc *lddp) 97 { 98 struct lut lutent; 99 100 if (root) { 101 if (mdb_vread(&lutent, sizeof (struct lut), root) != 102 sizeof (struct lut)) { 103 mdb_warn("failed to read struct lut at %p", root); 104 return (WALK_ERR); 105 } 106 107 if (eft_lut_walk((uintptr_t)lutent.lut_left, lddp) != WALK_NEXT) 108 return (WALK_ERR); 109 110 lut_collect_addent(root, &lutent, lddp); 111 112 if (eft_lut_walk((uintptr_t)lutent.lut_right, lddp) != 113 WALK_NEXT) 114 return (WALK_ERR); 115 } 116 return (WALK_NEXT); 117 } 118 119 static int 120 lut_collect(uintptr_t addr, struct lut_dump_desc *lddp) 121 { 122 lut_dump_array_alloc(lddp); 123 124 if (eft_lut_walk(addr, lddp) != WALK_NEXT) { 125 lut_dump_array_free(lddp); 126 return (WALK_ERR); 127 } else { 128 return (WALK_NEXT); /* caller must free dump array */ 129 } 130 } 131 132 static int 133 lut_walk_init(mdb_walk_state_t *wsp) 134 { 135 if (wsp->walk_addr == 0) { 136 mdb_warn("lut walker requires a lut table address\n"); 137 return (WALK_ERR); 138 } 139 140 wsp->walk_data = mdb_zalloc(sizeof (struct lut_dump_desc), UM_SLEEP); 141 wsp->walk_arg = 0; 142 143 if (lut_collect(wsp->walk_addr, wsp->walk_data) == WALK_NEXT) { 144 return (WALK_NEXT); 145 } else { 146 mdb_warn("failed to suck in full lut\n"); 147 mdb_free(wsp->walk_data, sizeof (struct lut_dump_desc)); 148 return (WALK_ERR); 149 } 150 } 151 152 static int 153 lut_walk_step(mdb_walk_state_t *wsp) 154 { 155 struct lut_dump_desc *lddp = wsp->walk_data; 156 int *ip = (int *)&wsp->walk_arg; 157 struct lut_cp *lcp = &lddp->ld_array[*ip]; 158 159 if (*ip == lddp->ld_nents) 160 return (WALK_DONE); 161 162 ++*ip; 163 164 return (wsp->walk_callback(lcp->lutcp_addr, &lcp->lutcp_lut, 165 wsp->walk_cbdata)); 166 } 167 168 static int 169 ipath_walk_init(mdb_walk_state_t *wsp) 170 { 171 struct ipath *ipath; 172 173 ipath = mdb_alloc(sizeof (struct ipath), UM_SLEEP); 174 175 if (mdb_vread((void *)ipath, sizeof (struct ipath), 176 wsp->walk_addr) != sizeof (struct ipath)) { 177 mdb_warn("failed to read struct ipath at %p", wsp->walk_addr); 178 return (WALK_ERR); 179 } 180 wsp->walk_data = (void *)ipath; 181 182 if (ipath->s == NULL) 183 return (WALK_DONE); 184 else 185 return (WALK_NEXT); 186 } 187 188 static void 189 ipath_walk_fini(mdb_walk_state_t *wsp) 190 { 191 mdb_free(wsp->walk_data, sizeof (struct ipath)); 192 } 193 194 static int 195 ipath_walk_step(mdb_walk_state_t *wsp) 196 { 197 int status; 198 struct ipath *ipath = (struct ipath *)wsp->walk_data; 199 struct ipath *ip = (struct ipath *)wsp->walk_addr; 200 201 if (ip == NULL || ipath->s == NULL) 202 return (WALK_DONE); 203 204 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 205 wsp->walk_cbdata); 206 207 wsp->walk_addr = (uintptr_t)(ip + 1); 208 209 if (mdb_vread(wsp->walk_data, sizeof (struct ipath), 210 wsp->walk_addr) != sizeof (struct ipath)) { 211 mdb_warn("failed to read struct ipath at %p", wsp->walk_addr); 212 return (WALK_ERR); 213 } 214 215 return (status); 216 } 217 218 static void 219 lut_walk_fini(mdb_walk_state_t *wsp) 220 { 221 struct lut_dump_desc *lddp = wsp->walk_data; 222 223 lut_dump_array_free(lddp); 224 mdb_free(lddp, sizeof (struct lut_dump_desc)); 225 } 226 227 /*ARGSUSED*/ 228 static int 229 ipath_node(uintptr_t addr, const void *data, void *arg) 230 { 231 struct ipath *ipath = (struct ipath *)data; 232 char buf[128]; 233 234 if (mdb_readstr(buf, (size_t)sizeof (buf), (uintptr_t)ipath->s) < 0) 235 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 236 ipath->s); 237 238 mdb_printf("/%s=%d", buf, ipath->i); 239 return (DCMD_OK); 240 } 241 242 /*ARGSUSED*/ 243 static int 244 ipath(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 245 { 246 if (argc) 247 return (DCMD_USAGE); 248 if (!(flags & DCMD_ADDRSPEC)) 249 addr = mdb_get_dot(); 250 if (mdb_pwalk("eft_ipath", ipath_node, NULL, addr) != 0) 251 return (DCMD_ERR); 252 return (DCMD_OK); 253 } 254 255 /*ARGSUSED*/ 256 static int 257 eft_count(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 258 { 259 struct lut lut; 260 struct istat_entry istat_entry; 261 struct stats count; 262 GElf_Sym sym; 263 char buf[128]; 264 265 if (argc) 266 return (DCMD_USAGE); 267 if (!(flags & DCMD_ADDRSPEC)) { 268 if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "Istats", &sym) == -1 || 269 sym.st_size != sizeof (addr)) 270 return (DCMD_ERR); 271 if (mdb_vread(&addr, sizeof (addr), 272 (uintptr_t)sym.st_value) != sizeof (addr)) 273 return (DCMD_ERR); 274 if (addr == 0) 275 return (DCMD_OK); 276 if (mdb_pwalk_dcmd("lut", "eft_count", argc, argv, addr) != 0) 277 return (DCMD_ERR); 278 return (DCMD_OK); 279 } 280 281 if (mdb_vread(&lut, sizeof (struct lut), addr) != sizeof (struct lut)) { 282 mdb_warn("failed to read struct lut at %p", addr); 283 return (DCMD_ERR); 284 } 285 if (mdb_vread(&istat_entry, sizeof (struct istat_entry), 286 (uintptr_t)lut.lut_lhs) != sizeof (struct istat_entry)) { 287 mdb_warn("failed to read struct istat_entry at %p", addr); 288 return (DCMD_ERR); 289 } 290 if (mdb_vread(&count, sizeof (struct stats), 291 (uintptr_t)lut.lut_rhs) != sizeof (struct stats)) { 292 mdb_warn("failed to read struct stats at %p", addr); 293 return (DCMD_ERR); 294 } 295 296 if (mdb_readstr(buf, (size_t)sizeof (buf), 297 (uintptr_t)istat_entry.ename) < 0) 298 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 299 istat_entry.ename); 300 301 mdb_printf("%s@", buf); 302 (void) ipath((uintptr_t)istat_entry.ipath, DCMD_ADDRSPEC, 0, NULL); 303 mdb_printf(" %d\n", count.fmd_stats.fmds_value.i32); 304 return (DCMD_OK); 305 } 306 307 /*ARGSUSED*/ 308 static int 309 eft_time(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 310 { 311 unsigned long long val; 312 unsigned long long ull; 313 int opt_p = 0; 314 315 if (!(flags & DCMD_ADDRSPEC)) 316 addr = mdb_get_dot(); 317 ull = addr; 318 if (argc) { 319 if (mdb_getopts(argc, argv, 320 'l', MDB_OPT_UINT64, &ull, 321 'p', MDB_OPT_SETBITS, TRUE, &opt_p, MDB_OPT_UINT64, 322 NULL) != argc) { 323 return (DCMD_USAGE); 324 } 325 } 326 if (opt_p) { 327 if (mdb_vread(&ull, sizeof (ull), addr) != sizeof (ull)) { 328 mdb_warn("failed to read timeval at %p", addr); 329 return (DCMD_ERR); 330 } 331 } 332 #define NOREMAINDER(den, num, val) (((val) = ((den) / (num))) * (num) == (den)) 333 if (ull == 0) 334 mdb_printf("0us"); 335 else if (ull >= TIMEVAL_EVENTUALLY) 336 mdb_printf("infinity"); 337 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*365, val)) 338 mdb_printf("%lluyear%s", val, (val == 1) ? "" : "s"); 339 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*30, val)) 340 mdb_printf("%llumonth%s", val, (val == 1) ? "" : "s"); 341 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*7, val)) 342 mdb_printf("%lluweek%s", val, (val == 1) ? "" : "s"); 343 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24, val)) 344 mdb_printf("%lluday%s", val, (val == 1) ? "" : "s"); 345 else if (NOREMAINDER(ull, 1000000000ULL*60*60, val)) 346 mdb_printf("%lluhour%s", val, (val == 1) ? "" : "s"); 347 else if (NOREMAINDER(ull, 1000000000ULL*60, val)) 348 mdb_printf("%lluminute%s", val, (val == 1) ? "" : "s"); 349 else if (NOREMAINDER(ull, 1000000000ULL, val)) 350 mdb_printf("%llusecond%s", val, (val == 1) ? "" : "s"); 351 else if (NOREMAINDER(ull, 1000000ULL, val)) 352 mdb_printf("%llums", val); 353 else if (NOREMAINDER(ull, 1000ULL, val)) 354 mdb_printf("%lluus", val); 355 else 356 mdb_printf("%lluns", ull); 357 358 return (DCMD_OK); 359 } 360 361 /*ARGSUSED*/ 362 static int 363 eft_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 364 { 365 struct node node; 366 int opt_v = 0; 367 char buf[128]; 368 369 if (!(flags & DCMD_ADDRSPEC)) 370 addr = mdb_get_dot(); 371 if (argc) { 372 if (mdb_getopts(argc, argv, 373 'v', MDB_OPT_SETBITS, TRUE, &opt_v, 374 NULL) != argc) { 375 return (DCMD_USAGE); 376 } 377 } 378 if (addr == 0) 379 return (DCMD_OK); 380 if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) { 381 mdb_warn("failed to read struct node at %p", addr); 382 return (DCMD_ERR); 383 } 384 if (opt_v) { 385 if (mdb_readstr(buf, (size_t)sizeof (buf), 386 (uintptr_t)node.file) < 0) 387 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 388 node.file); 389 390 mdb_printf("%s len %d\n", buf, node.line); 391 } 392 switch (node.t) { 393 case T_NOTHING: /* used to keep going on error cases */ 394 mdb_printf("nothing"); 395 break; 396 case T_NAME: /* identifiers, sometimes chained */ 397 if (mdb_readstr(buf, (size_t)sizeof (buf), 398 (uintptr_t)node.u.name.s) < 0) 399 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 400 node.u.name.s); 401 402 mdb_printf("%s", buf); 403 if (node.u.name.cp) { 404 struct config cp; 405 if (mdb_vread(&cp, sizeof (cp), 406 (uintptr_t)node.u.name.cp) != sizeof (cp)) { 407 mdb_warn("failed to read struct config at %p", 408 node.u.name.cp); 409 return (DCMD_ERR); 410 } 411 mdb_printf("%d", cp.num); 412 } else if (node.u.name.it == IT_HORIZONTAL) { 413 if (node.u.name.child && !node.u.name.childgen) { 414 mdb_printf("<"); 415 (void) eft_node((uintptr_t)node.u.name.child, 416 DCMD_ADDRSPEC, 0, NULL); 417 mdb_printf(">"); 418 } else { 419 mdb_printf("<> "); 420 } 421 } else if (node.u.name.child) { 422 mdb_printf("["); 423 (void) eft_node((uintptr_t)node.u.name.child, 424 DCMD_ADDRSPEC, 0, NULL); 425 mdb_printf("]"); 426 } 427 if (node.u.name.next) { 428 if (node.u.name.it == IT_ENAME) 429 mdb_printf("."); 430 else 431 mdb_printf("/"); 432 (void) eft_node((uintptr_t)node.u.name.next, 433 DCMD_ADDRSPEC, 0, NULL); 434 } 435 break; 436 case T_GLOBID: /* globals (e.g. $a) */ 437 if (mdb_readstr(buf, (size_t)sizeof (buf), 438 (uintptr_t)node.u.globid.s) < 0) 439 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 440 node.u.globid.s); 441 442 mdb_printf("$%s", buf); 443 break; 444 case T_EVENT: /* class@path{expr} */ 445 (void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0, 446 NULL); 447 mdb_printf("@"); 448 (void) eft_node((uintptr_t)node.u.event.epname, DCMD_ADDRSPEC, 449 0, NULL); 450 if (node.u.event.eexprlist) { 451 mdb_printf(" { "); 452 (void) eft_node((uintptr_t)node.u.event.eexprlist, 453 DCMD_ADDRSPEC, 0, NULL); 454 mdb_printf(" }"); 455 } 456 break; 457 case T_ENGINE: /* upset threshold engine (e.g. SERD) */ 458 mdb_printf("engine "); 459 (void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0, 460 NULL); 461 break; 462 case T_ASRU: /* ASRU declaration */ 463 mdb_printf("asru "); 464 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 465 NULL); 466 if (node.u.stmt.nvpairs) { 467 mdb_printf(" "); 468 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 469 DCMD_ADDRSPEC, 0, NULL); 470 471 } 472 break; 473 case T_FRU: /* FRU declaration */ 474 mdb_printf("fru "); 475 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 476 NULL); 477 if (node.u.stmt.nvpairs) { 478 mdb_printf(" "); 479 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 480 DCMD_ADDRSPEC, 0, NULL); 481 482 } 483 break; 484 case T_TIMEVAL: /* num w/time suffix (ns internally) */ 485 { 486 mdb_arg_t mdb_arg[2]; 487 mdb_arg[0].a_type = MDB_TYPE_STRING; 488 mdb_arg[0].a_un.a_str = "-l"; 489 mdb_arg[1].a_type = MDB_TYPE_IMMEDIATE; 490 mdb_arg[1].a_un.a_val = node.u.ull; 491 (void) eft_time((uintptr_t)0, 0, 2, mdb_arg); 492 break; 493 } 494 case T_NUM: /* num (ull internally) */ 495 mdb_printf("%llu", node.u.ull); 496 break; 497 case T_QUOTE: /* quoted string */ 498 if (mdb_readstr(buf, (size_t)sizeof (buf), 499 (uintptr_t)node.u.quote.s) < 0) 500 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 501 node.u.quote.s); 502 503 mdb_printf("\"%s\"", buf); 504 break; 505 case T_FUNC: /* func(arglist) */ 506 if (mdb_readstr(buf, (size_t)sizeof (buf), 507 (uintptr_t)node.u.func.s) < 0) 508 (void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>", 509 node.u.func.s); 510 511 mdb_printf("%s(", buf); 512 (void) eft_node((uintptr_t)node.u.func.arglist, DCMD_ADDRSPEC, 513 0, NULL); 514 mdb_printf(")"); 515 break; 516 case T_NVPAIR: /* name=value pair in decl */ 517 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 518 NULL); 519 mdb_printf(" = "); 520 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 521 NULL); 522 break; 523 case T_ASSIGN: /* assignment statement */ 524 mdb_printf("("); 525 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 526 NULL); 527 mdb_printf(" = "); 528 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 529 NULL); 530 mdb_printf(")"); 531 break; 532 case T_CONDIF: /* a and T_CONDELSE in (a ? b : c ) */ 533 mdb_printf("("); 534 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 535 NULL); 536 mdb_printf(" ? "); 537 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 538 NULL); 539 mdb_printf(")"); 540 break; 541 case T_CONDELSE: /* lists b and c in (a ? b : c ) */ 542 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 543 NULL); 544 mdb_printf(" : "); 545 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 546 NULL); 547 break; 548 case T_NOT: /* boolean ! operator */ 549 mdb_printf("!"); 550 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 551 NULL); 552 break; 553 case T_AND: /* boolean && operator */ 554 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 555 NULL); 556 mdb_printf(" && "); 557 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 558 NULL); 559 break; 560 case T_OR: /* boolean || operator */ 561 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 562 NULL); 563 mdb_printf(" || "); 564 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 565 NULL); 566 break; 567 case T_EQ: /* boolean == operator */ 568 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 569 NULL); 570 mdb_printf(" == "); 571 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 572 NULL); 573 break; 574 case T_NE: /* boolean != operator */ 575 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 576 NULL); 577 mdb_printf(" != "); 578 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 579 NULL); 580 break; 581 case T_SUB: /* integer - operator */ 582 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 583 NULL); 584 mdb_printf(" - "); 585 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 586 NULL); 587 break; 588 case T_ADD: /* integer + operator */ 589 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 590 NULL); 591 mdb_printf(" + "); 592 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 593 NULL); 594 break; 595 case T_MUL: /* integer * operator */ 596 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 597 NULL); 598 mdb_printf(" * "); 599 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 600 NULL); 601 break; 602 case T_DIV: /* integer / operator */ 603 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 604 NULL); 605 mdb_printf(" / "); 606 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 607 NULL); 608 break; 609 case T_MOD: /* integer % operator */ 610 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 611 NULL); 612 mdb_printf(" % "); 613 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 614 NULL); 615 break; 616 case T_LT: /* boolean < operator */ 617 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 618 NULL); 619 mdb_printf(" < "); 620 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 621 NULL); 622 break; 623 case T_LE: /* boolean <= operator */ 624 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 625 NULL); 626 mdb_printf(" <= "); 627 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 628 NULL); 629 break; 630 case T_GT: /* boolean > operator */ 631 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 632 NULL); 633 mdb_printf(" > "); 634 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 635 NULL); 636 break; 637 case T_GE: /* boolean >= operator */ 638 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 639 NULL); 640 mdb_printf(" >= "); 641 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 642 NULL); 643 break; 644 case T_BITAND: /* bitwise & operator */ 645 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 646 NULL); 647 mdb_printf(" & "); 648 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 649 NULL); 650 break; 651 case T_BITOR: /* bitwise | operator */ 652 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 653 NULL); 654 mdb_printf(" | "); 655 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 656 NULL); 657 break; 658 case T_BITXOR: /* bitwise ^ operator */ 659 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 660 NULL); 661 mdb_printf(" ^ "); 662 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 663 NULL); 664 break; 665 case T_BITNOT: /* bitwise ~ operator */ 666 mdb_printf(" ~"); 667 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 668 NULL); 669 break; 670 case T_LSHIFT: /* bitwise << operator */ 671 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 672 NULL); 673 mdb_printf(" << "); 674 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 675 NULL); 676 break; 677 case T_RSHIFT: /* bitwise >> operator */ 678 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 679 NULL); 680 mdb_printf(" >> "); 681 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 682 NULL); 683 break; 684 case T_ARROW: /* lhs (N)->(K) rhs */ 685 (void) eft_node((uintptr_t)node.u.arrow.lhs, DCMD_ADDRSPEC, 0, 686 NULL); 687 if (node.u.arrow.nnp) { 688 mdb_printf("("); 689 (void) eft_node((uintptr_t)node.u.arrow.nnp, 690 DCMD_ADDRSPEC, 0, NULL); 691 mdb_printf(")"); 692 } 693 mdb_printf("->"); 694 if (node.u.arrow.knp) { 695 mdb_printf("("); 696 (void) eft_node((uintptr_t)node.u.arrow.knp, 697 DCMD_ADDRSPEC, 0, NULL); 698 mdb_printf(")"); 699 } 700 (void) eft_node((uintptr_t)node.u.arrow.rhs, DCMD_ADDRSPEC, 0, 701 NULL); 702 break; 703 case T_LIST: /* comma-separated list */ 704 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 705 NULL); 706 mdb_printf(", "); 707 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 708 NULL); 709 break; 710 case T_FAULT: /* fault declaration */ 711 mdb_printf("fault."); 712 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 713 NULL); 714 if (node.u.stmt.nvpairs) { 715 mdb_printf(" "); 716 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 717 DCMD_ADDRSPEC, 0, NULL); 718 719 } 720 break; 721 case T_UPSET: /* upset declaration */ 722 mdb_printf("upset."); 723 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 724 NULL); 725 if (node.u.stmt.nvpairs) { 726 mdb_printf(" "); 727 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 728 DCMD_ADDRSPEC, 0, NULL); 729 730 } 731 break; 732 case T_DEFECT: /* defect declaration */ 733 mdb_printf("defect."); 734 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 735 NULL); 736 if (node.u.stmt.nvpairs) { 737 mdb_printf(" "); 738 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 739 DCMD_ADDRSPEC, 0, NULL); 740 741 } 742 break; 743 case T_ERROR: /* error declaration */ 744 mdb_printf("error."); 745 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 746 NULL); 747 if (node.u.stmt.nvpairs) { 748 mdb_printf(" "); 749 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 750 DCMD_ADDRSPEC, 0, NULL); 751 752 } 753 break; 754 case T_EREPORT: /* ereport declaration */ 755 mdb_printf("ereport."); 756 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 757 NULL); 758 if (node.u.stmt.nvpairs) { 759 mdb_printf(" "); 760 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 761 DCMD_ADDRSPEC, 0, NULL); 762 763 } 764 break; 765 case T_SERD: /* SERD engine declaration */ 766 mdb_printf("serd."); 767 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 768 NULL); 769 if (node.u.stmt.nvpairs) { 770 mdb_printf(" "); 771 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 772 DCMD_ADDRSPEC, 0, NULL); 773 774 } else if (node.u.stmt.lutp) { 775 if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL, 776 (uintptr_t)node.u.stmt.lutp) != 0) 777 return (DCMD_ERR); 778 } 779 break; 780 case T_STAT: /* STAT engine declaration */ 781 mdb_printf("stat."); 782 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 783 NULL); 784 if (node.u.stmt.nvpairs) { 785 mdb_printf(" "); 786 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 787 DCMD_ADDRSPEC, 0, NULL); 788 789 } else if (node.u.stmt.lutp) { 790 if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL, 791 (uintptr_t)node.u.stmt.lutp) != 0) 792 return (DCMD_ERR); 793 } 794 break; 795 case T_PROP: /* prop statement */ 796 mdb_printf("prop "); 797 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 798 NULL); 799 break; 800 case T_MASK: /* mask statement */ 801 mdb_printf("mask "); 802 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 803 NULL); 804 break; 805 case T_CONFIG: /* config statement */ 806 mdb_printf("config "); 807 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 808 NULL); 809 if (node.u.stmt.nvpairs) { 810 mdb_printf(" "); 811 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 812 DCMD_ADDRSPEC, 0, NULL); 813 814 } 815 break; 816 default: 817 mdb_printf("not a eversholt node\n"); 818 break; 819 } 820 return (DCMD_OK); 821 } 822 823 static const mdb_walker_t walkers[] = { 824 { "lut", "walk a lookup table", lut_walk_init, lut_walk_step, 825 lut_walk_fini, NULL }, 826 { "eft_ipath", "walk ipath", ipath_walk_init, ipath_walk_step, 827 ipath_walk_fini, NULL }, 828 { NULL, NULL, NULL, NULL, NULL, NULL } 829 }; 830 831 static const mdb_dcmd_t dcmds[] = { 832 { "eft_ipath", "?", "print an ipath", ipath }, 833 { "eft_count", "?", "print eversholt stats", eft_count }, 834 { "eft_node", "?[-v]", "print eversholt node", eft_node }, 835 { "eft_time", "?[-p][-l time]", "print eversholt timeval", eft_time }, 836 { NULL } 837 }; 838 839 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 840 841 const mdb_modinfo_t * 842 _mdb_init(void) 843 { 844 return (&modinfo); 845 } 846