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
lut_dump_array_alloc(struct lut_dump_desc * lddp)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
lut_dump_array_free(struct lut_dump_desc * lddp)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
lut_collect_addent(uintptr_t addr,struct lut * ent,struct lut_dump_desc * lddp)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
eft_lut_walk(uintptr_t root,struct lut_dump_desc * lddp)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
lut_collect(uintptr_t addr,struct lut_dump_desc * lddp)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
lut_walk_init(mdb_walk_state_t * wsp)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
lut_walk_step(mdb_walk_state_t * wsp)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
ipath_walk_init(mdb_walk_state_t * wsp)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
ipath_walk_fini(mdb_walk_state_t * wsp)189 ipath_walk_fini(mdb_walk_state_t *wsp)
190 {
191 mdb_free(wsp->walk_data, sizeof (struct ipath));
192 }
193
194 static int
ipath_walk_step(mdb_walk_state_t * wsp)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
lut_walk_fini(mdb_walk_state_t * wsp)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
ipath_node(uintptr_t addr,const void * data,void * arg)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
ipath(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
eft_count(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
eft_time(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
eft_node(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
_mdb_init(void)842 _mdb_init(void)
843 {
844 return (&modinfo);
845 }
846