Print this page
patch mdb-enums
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_print.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_print.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
28 28 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
29 29 */
30 30
31 31 #include <mdb/mdb_modapi.h>
32 32 #include <mdb/mdb_target.h>
33 33 #include <mdb/mdb_argvec.h>
34 34 #include <mdb/mdb_string.h>
35 35 #include <mdb/mdb_stdlib.h>
36 36 #include <mdb/mdb_err.h>
37 37 #include <mdb/mdb_debug.h>
38 38 #include <mdb/mdb_fmt.h>
39 39 #include <mdb/mdb_ctf.h>
40 40 #include <mdb/mdb_ctf_impl.h>
41 41 #include <mdb/mdb.h>
42 42 #include <mdb/mdb_tab.h>
43 43
44 44 #include <sys/isa_defs.h>
45 45 #include <sys/param.h>
46 46 #include <sys/sysmacros.h>
47 47 #include <netinet/in.h>
48 48 #include <strings.h>
49 49 #include <libctf.h>
50 50 #include <ctype.h>
51 51
52 52 typedef struct holeinfo {
53 53 ulong_t hi_offset; /* expected offset */
54 54 uchar_t hi_isunion; /* represents a union */
55 55 } holeinfo_t;
56 56
57 57 typedef struct printarg {
58 58 mdb_tgt_t *pa_tgt; /* current target */
59 59 mdb_tgt_t *pa_realtgt; /* real target (for -i) */
60 60 mdb_tgt_t *pa_immtgt; /* immediate target (for -i) */
61 61 mdb_tgt_as_t pa_as; /* address space to use for i/o */
62 62 mdb_tgt_addr_t pa_addr; /* base address for i/o */
63 63 ulong_t pa_armemlim; /* limit on array elements to print */
64 64 ulong_t pa_arstrlim; /* limit on array chars to print */
65 65 const char *pa_delim; /* element delimiter string */
66 66 const char *pa_prefix; /* element prefix string */
67 67 const char *pa_suffix; /* element suffix string */
68 68 holeinfo_t *pa_holes; /* hole detection information */
69 69 int pa_nholes; /* size of holes array */
70 70 int pa_flags; /* formatting flags (see below) */
71 71 int pa_depth; /* previous depth */
72 72 int pa_nest; /* array nesting depth */
73 73 int pa_tab; /* tabstop width */
74 74 uint_t pa_maxdepth; /* Limit max depth */
75 75 uint_t pa_nooutdepth; /* don't print output past this depth */
76 76 } printarg_t;
77 77
78 78 #define PA_SHOWTYPE 0x001 /* print type name */
79 79 #define PA_SHOWBASETYPE 0x002 /* print base type name */
80 80 #define PA_SHOWNAME 0x004 /* print member name */
81 81 #define PA_SHOWADDR 0x008 /* print address */
82 82 #define PA_SHOWVAL 0x010 /* print value */
83 83 #define PA_SHOWHOLES 0x020 /* print holes in structs */
84 84 #define PA_INTHEX 0x040 /* print integer values in hex */
85 85 #define PA_INTDEC 0x080 /* print integer values in decimal */
86 86 #define PA_NOSYMBOLIC 0x100 /* don't print ptrs as func+offset */
87 87
88 88 #define IS_CHAR(e) \
89 89 (((e).cte_format & (CTF_INT_CHAR | CTF_INT_SIGNED)) == \
90 90 (CTF_INT_CHAR | CTF_INT_SIGNED) && (e).cte_bits == NBBY)
91 91
92 92 #define COMPOSITE_MASK ((1 << CTF_K_STRUCT) | \
93 93 (1 << CTF_K_UNION) | (1 << CTF_K_ARRAY))
94 94 #define IS_COMPOSITE(k) (((1 << k) & COMPOSITE_MASK) != 0)
95 95
96 96 #define SOU_MASK ((1 << CTF_K_STRUCT) | (1 << CTF_K_UNION))
97 97 #define IS_SOU(k) (((1 << k) & SOU_MASK) != 0)
98 98
99 99 #define MEMBER_DELIM_ERR -1
100 100 #define MEMBER_DELIM_DONE 0
101 101 #define MEMBER_DELIM_PTR 1
102 102 #define MEMBER_DELIM_DOT 2
103 103 #define MEMBER_DELIM_LBR 3
104 104
105 105 typedef int printarg_f(const char *, const char *,
106 106 mdb_ctf_id_t, mdb_ctf_id_t, ulong_t, printarg_t *);
107 107
108 108 static int elt_print(const char *, mdb_ctf_id_t, mdb_ctf_id_t, ulong_t, int,
109 109 void *);
110 110 static void print_close_sou(printarg_t *, int);
111 111
112 112 /*
113 113 * Given an address, look up the symbol ID of the specified symbol in its
114 114 * containing module. We only support lookups for exact matches.
115 115 */
116 116 static const char *
117 117 addr_to_sym(mdb_tgt_t *t, uintptr_t addr, char *name, size_t namelen,
118 118 GElf_Sym *symp, mdb_syminfo_t *sip)
119 119 {
120 120 const mdb_map_t *mp;
121 121 const char *p;
122 122
123 123 if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name,
124 124 namelen, NULL, NULL) == -1)
125 125 return (NULL); /* address does not exactly match a symbol */
126 126
127 127 if ((p = strrsplit(name, '`')) != NULL) {
128 128 if (mdb_tgt_lookup_by_name(t, name, p, symp, sip) == -1)
129 129 return (NULL);
130 130 return (p);
131 131 }
132 132
133 133 if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL)
134 134 return (NULL); /* address does not fall within a mapping */
135 135
136 136 if (mdb_tgt_lookup_by_name(t, mp->map_name, name, symp, sip) == -1)
137 137 return (NULL);
138 138
139 139 return (name);
140 140 }
141 141
142 142 /*
143 143 * This lets dcmds be a little fancy with their processing of type arguments
144 144 * while still treating them more or less as a single argument.
145 145 * For example, if a command is invokes like this:
146 146 *
147 147 * ::<dcmd> proc_t ...
148 148 *
149 149 * this function will just copy "proc_t" into the provided buffer. If the
150 150 * command is instead invoked like this:
151 151 *
152 152 * ::<dcmd> struct proc ...
153 153 *
154 154 * this function will place the string "struct proc" into the provided buffer
155 155 * and increment the caller's argv and argc. This allows the caller to still
156 156 * treat the type argument logically as it would an other atomic argument.
157 157 */
158 158 int
159 159 args_to_typename(int *argcp, const mdb_arg_t **argvp, char *buf, size_t len)
160 160 {
161 161 int argc = *argcp;
162 162 const mdb_arg_t *argv = *argvp;
163 163
164 164 if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
165 165 return (DCMD_USAGE);
166 166
167 167 if (strcmp(argv->a_un.a_str, "struct") == 0 ||
168 168 strcmp(argv->a_un.a_str, "enum") == 0 ||
169 169 strcmp(argv->a_un.a_str, "union") == 0) {
170 170 if (argc <= 1) {
171 171 mdb_warn("%s is not a valid type\n", argv->a_un.a_str);
172 172 return (DCMD_ABORT);
173 173 }
174 174
175 175 if (argv[1].a_type != MDB_TYPE_STRING)
176 176 return (DCMD_USAGE);
177 177
178 178 (void) mdb_snprintf(buf, len, "%s %s",
179 179 argv[0].a_un.a_str, argv[1].a_un.a_str);
180 180
181 181 *argcp = argc - 1;
182 182 *argvp = argv + 1;
183 183 } else {
184 184 (void) mdb_snprintf(buf, len, "%s", argv[0].a_un.a_str);
185 185 }
186 186
187 187 return (0);
188 188 }
189 189
190 190 /*ARGSUSED*/
191 191 int
192 192 cmd_sizeof(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
193 193 {
194 194 mdb_ctf_id_t id;
195 195 char tn[MDB_SYM_NAMLEN];
196 196 int ret;
197 197
198 198 if (flags & DCMD_ADDRSPEC)
199 199 return (DCMD_USAGE);
200 200
201 201 if ((ret = args_to_typename(&argc, &argv, tn, sizeof (tn))) != 0)
202 202 return (ret);
203 203
204 204 if (argc != 1)
205 205 return (DCMD_USAGE);
206 206
207 207 if (mdb_ctf_lookup_by_name(tn, &id) != 0) {
208 208 mdb_warn("failed to look up type %s", tn);
209 209 return (DCMD_ERR);
210 210 }
211 211
212 212 if (flags & DCMD_PIPE_OUT)
213 213 mdb_printf("%#lr\n", mdb_ctf_type_size(id));
214 214 else
215 215 mdb_printf("sizeof (%s) = %#lr\n", tn, mdb_ctf_type_size(id));
216 216
217 217 return (DCMD_OK);
218 218 }
219 219
220 220 int
221 221 cmd_sizeof_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
222 222 const mdb_arg_t *argv)
223 223 {
224 224 char tn[MDB_SYM_NAMLEN];
225 225 int ret;
226 226
227 227 if (argc == 0 && !(flags & DCMD_TAB_SPACE))
228 228 return (0);
229 229
230 230 if (argc == 0 && (flags & DCMD_TAB_SPACE))
231 231 return (mdb_tab_complete_type(mcp, NULL, MDB_TABC_NOPOINT));
232 232
233 233 if ((ret = mdb_tab_typename(&argc, &argv, tn, sizeof (tn))) < 0)
234 234 return (ret);
235 235
236 236 if (argc == 1)
237 237 return (mdb_tab_complete_type(mcp, tn, MDB_TABC_NOPOINT));
238 238
239 239 return (0);
240 240 }
241 241
242 242 /*ARGSUSED*/
243 243 int
244 244 cmd_offsetof(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
245 245 {
246 246 const char *member;
247 247 mdb_ctf_id_t id;
248 248 ulong_t off;
249 249 char tn[MDB_SYM_NAMLEN];
250 250 ssize_t sz;
251 251 int ret;
252 252
253 253 if (flags & DCMD_ADDRSPEC)
254 254 return (DCMD_USAGE);
255 255
256 256 if ((ret = args_to_typename(&argc, &argv, tn, sizeof (tn))) != 0)
257 257 return (ret);
258 258
259 259 if (argc != 2 || argv[1].a_type != MDB_TYPE_STRING)
260 260 return (DCMD_USAGE);
261 261
262 262 if (mdb_ctf_lookup_by_name(tn, &id) != 0) {
263 263 mdb_warn("failed to look up type %s", tn);
264 264 return (DCMD_ERR);
265 265 }
266 266
267 267 member = argv[1].a_un.a_str;
268 268
269 269 if (mdb_ctf_member_info(id, member, &off, &id) != 0) {
270 270 mdb_warn("failed to find member %s of type %s", member, tn);
271 271 return (DCMD_ERR);
272 272 }
273 273
274 274 if (flags & DCMD_PIPE_OUT) {
275 275 if (off % NBBY != 0) {
276 276 mdb_warn("member %s of type %s is not byte-aligned\n",
277 277 member, tn);
278 278 return (DCMD_ERR);
279 279 }
280 280 mdb_printf("%#lr", off / NBBY);
281 281 return (DCMD_OK);
282 282 }
283 283
284 284 mdb_printf("offsetof (%s, %s) = %#lr",
285 285 tn, member, off / NBBY);
286 286 if (off % NBBY != 0)
287 287 mdb_printf(".%lr", off % NBBY);
288 288
289 289 if ((sz = mdb_ctf_type_size(id)) > 0)
290 290 mdb_printf(", sizeof (...->%s) = %#lr", member, sz);
291 291
292 292 mdb_printf("\n");
293 293
294 294 return (DCMD_OK);
295 295 }
296 296
297 297 /*ARGSUSED*/
298 298 static int
299 299 enum_prefix_scan_cb(const char *name, int value, void *arg)
300 300 {
301 301 char *str = arg;
302 302
303 303 /*
304 304 * This function is called with every name in the enum. We make
305 305 * "arg" be the common prefix, if any.
306 306 */
307 307 if (str[0] == 0) {
308 308 if (strlcpy(arg, name, MDB_SYM_NAMLEN) >= MDB_SYM_NAMLEN)
309 309 return (1);
310 310 return (0);
311 311 }
312 312
313 313 while (*name == *str) {
314 314 if (*str == 0) {
315 315 if (str != arg) {
316 316 str--; /* don't smother a name completely */
317 317 }
318 318 break;
319 319 }
320 320 name++;
321 321 str++;
322 322 }
323 323 *str = 0;
324 324
325 325 return (str == arg); /* only continue if prefix is non-empty */
326 326 }
327 327
328 328 struct enum_p2_info {
329 329 intmax_t e_value; /* value we're processing */
330 330 char *e_buf; /* buffer for holding names */
331 331 size_t e_size; /* size of buffer */
332 332 size_t e_prefix; /* length of initial prefix */
333 333 uint_t e_allprefix; /* apply prefix to first guy, too */
334 334 uint_t e_bits; /* bits seen */
335 335 uint8_t e_found; /* have we seen anything? */
336 336 uint8_t e_first; /* does buf contain the first one? */
337 337 uint8_t e_zero; /* have we seen a zero value? */
338 338 };
339 339
340 340 static int
341 341 enum_p2_cb(const char *name, int bit_arg, void *arg)
342 342 {
343 343 struct enum_p2_info *eiip = arg;
344 344 uintmax_t bit = bit_arg;
345 345
346 346 if (bit != 0 && !ISP2(bit))
347 347 return (1); /* non-power-of-2; abort processing */
348 348
349 349 if ((bit == 0 && eiip->e_zero) ||
350 350 (bit != 0 && (eiip->e_bits & bit) != 0)) {
351 351 return (0); /* already seen this value */
352 352 }
353 353
354 354 if (bit == 0)
355 355 eiip->e_zero = 1;
356 356 else
357 357 eiip->e_bits |= bit;
358 358
359 359 if (eiip->e_buf != NULL && (eiip->e_value & bit) != 0) {
360 360 char *buf = eiip->e_buf;
361 361 size_t prefix = eiip->e_prefix;
362 362
363 363 if (eiip->e_found) {
364 364 (void) strlcat(buf, "|", eiip->e_size);
365 365
366 366 if (eiip->e_first && !eiip->e_allprefix && prefix > 0) {
367 367 char c1 = buf[prefix];
368 368 char c2 = buf[prefix + 1];
369 369 buf[prefix] = '{';
370 370 buf[prefix + 1] = 0;
371 371 mdb_printf("%s", buf);
372 372 buf[prefix] = c1;
373 373 buf[prefix + 1] = c2;
374 374 mdb_printf("%s", buf + prefix);
375 375 } else {
376 376 mdb_printf("%s", buf);
377 377 }
378 378
379 379 }
380 380 /* skip the common prefix as necessary */
381 381 if ((eiip->e_found || eiip->e_allprefix) &&
382 382 strlen(name) > prefix)
383 383 name += prefix;
384 384
385 385 (void) strlcpy(eiip->e_buf, name, eiip->e_size);
386 386 eiip->e_first = !eiip->e_found;
387 387 eiip->e_found = 1;
388 388 }
389 389 return (0);
390 390 }
391 391
392 392 static int
393 393 enum_is_p2(mdb_ctf_id_t id)
394 394 {
395 395 struct enum_p2_info eii;
396 396 bzero(&eii, sizeof (eii));
397 397
398 398 return (mdb_ctf_type_kind(id) == CTF_K_ENUM &&
399 399 mdb_ctf_enum_iter(id, enum_p2_cb, &eii) == 0 &&
400 400 eii.e_bits != 0);
401 401 }
402 402
403 403 static int
404 404 enum_value_print_p2(mdb_ctf_id_t id, intmax_t value, uint_t allprefix)
405 405 {
406 406 struct enum_p2_info eii;
407 407 char prefix[MDB_SYM_NAMLEN + 2];
408 408 intmax_t missed;
409 409
410 410 bzero(&eii, sizeof (eii));
411 411
412 412 eii.e_value = value;
413 413 eii.e_buf = prefix;
414 414 eii.e_size = sizeof (prefix);
415 415 eii.e_allprefix = allprefix;
416 416
417 417 prefix[0] = 0;
418 418 if (mdb_ctf_enum_iter(id, enum_prefix_scan_cb, prefix) == 0)
419 419 eii.e_prefix = strlen(prefix);
420 420
421 421 if (mdb_ctf_enum_iter(id, enum_p2_cb, &eii) != 0 || eii.e_bits == 0)
422 422 return (-1);
423 423
424 424 missed = (value & ~(intmax_t)eii.e_bits);
425 425
426 426 if (eii.e_found) {
427 427 /* push out any final value, with a | if we missed anything */
428 428 if (!eii.e_first)
429 429 (void) strlcat(prefix, "}", sizeof (prefix));
430 430 if (missed != 0)
431 431 (void) strlcat(prefix, "|", sizeof (prefix));
432 432
433 433 mdb_printf("%s", prefix);
434 434 }
435 435
436 436 if (!eii.e_found || missed) {
437 437 mdb_printf("%#llx", missed);
438 438 }
439 439
440 440 return (0);
441 441 }
442 442
443 443 struct enum_cbinfo {
444 444 uint_t e_flags;
445 445 const char *e_string; /* NULL for value searches */
446 446 size_t e_prefix;
447 447 intmax_t e_value;
448 448 uint_t e_found;
449 449 mdb_ctf_id_t e_id;
450 450 };
451 451 #define E_PRETTY 0x01
452 452 #define E_HEX 0x02
453 453 #define E_SEARCH_STRING 0x04
454 454 #define E_SEARCH_VALUE 0x08
455 455 #define E_ELIDE_PREFIX 0x10
456 456
457 457 static void
458 458 enum_print(struct enum_cbinfo *info, const char *name, int value)
459 459 {
460 460 uint_t flags = info->e_flags;
461 461 uint_t elide_prefix = (info->e_flags & E_ELIDE_PREFIX);
462 462
463 463 if (name != NULL && info->e_prefix && strlen(name) > info->e_prefix)
464 464 name += info->e_prefix;
465 465
466 466 if (flags & E_PRETTY) {
467 467 uint_t indent = 5 + ((flags & E_HEX) ? 8 : 11);
468 468
469 469 mdb_printf((flags & E_HEX)? "%8x " : "%11d ", value);
470 470 (void) mdb_inc_indent(indent);
471 471 if (name != NULL) {
472 472 mdb_iob_puts(mdb.m_out, name);
473 473 } else {
474 474 (void) enum_value_print_p2(info->e_id, value,
475 475 elide_prefix);
476 476 }
477 477 (void) mdb_dec_indent(indent);
478 478 mdb_printf("\n");
479 479 } else {
480 480 mdb_printf("%#r\n", value);
481 481 }
482 482 }
483 483
484 484 static int
485 485 enum_cb(const char *name, int value, void *arg)
486 486 {
487 487 struct enum_cbinfo *info = arg;
488 488 uint_t flags = info->e_flags;
489 489
490 490 if (flags & E_SEARCH_STRING) {
491 491 if (strcmp(name, info->e_string) != 0)
492 492 return (0);
493 493
494 494 } else if (flags & E_SEARCH_VALUE) {
495 495 if (value != info->e_value)
496 496 return (0);
497 497 }
498 498
499 499 enum_print(info, name, value);
500 500
501 501 info->e_found = 1;
502 502 return (0);
503 503 }
504 504
505 505 void
506 506 enum_help(void)
507 507 {
508 508 mdb_printf("%s",
509 509 "Without an address and name, print all values for the enumeration \"enum\".\n"
510 510 "With an address, look up a particular value in \"enum\". With a name, look\n"
511 511 "up a particular name in \"enum\".\n");
512 512
513 513 (void) mdb_dec_indent(2);
514 514 mdb_printf("\n%<b>OPTIONS%</b>\n");
515 515 (void) mdb_inc_indent(2);
516 516
517 517 mdb_printf("%s",
518 518 " -e remove common prefixes from enum names\n"
519 519 " -x report enum values in hexadecimal\n");
520 520 }
521 521
522 522 /*ARGSUSED*/
523 523 int
524 524 cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
525 525 {
526 526 struct enum_cbinfo info;
527 527
528 528 char type[MDB_SYM_NAMLEN + sizeof ("enum ")];
529 529 char tn2[MDB_SYM_NAMLEN + sizeof ("enum ")];
530 530 char prefix[MDB_SYM_NAMLEN];
531 531 mdb_ctf_id_t id;
532 532 mdb_ctf_id_t idr;
533 533
534 534 int i;
535 535 intmax_t search;
536 536 uint_t isp2;
537 537
538 538 info.e_flags = (flags & DCMD_PIPE_OUT)? 0 : E_PRETTY;
539 539 info.e_string = NULL;
540 540 info.e_value = 0;
541 541 info.e_found = 0;
542 542
543 543 i = mdb_getopts(argc, argv,
544 544 'e', MDB_OPT_SETBITS, E_ELIDE_PREFIX, &info.e_flags,
545 545 'x', MDB_OPT_SETBITS, E_HEX, &info.e_flags,
546 546 NULL);
547 547
548 548 argc -= i;
549 549 argv += i;
550 550
551 551 if ((i = args_to_typename(&argc, &argv, type, MDB_SYM_NAMLEN)) != 0)
552 552 return (i);
553 553
554 554 if (strchr(type, ' ') == NULL) {
555 555 /*
556 556 * Check as an enumeration tag first, and fall back
557 557 * to checking for a typedef. Yes, this means that
558 558 * anonymous enumerations whose typedefs conflict with
559 559 * an enum tag can't be accessed. Don't do that.
560 560 */
561 561 (void) mdb_snprintf(tn2, sizeof (tn2), "enum %s", type);
562 562
563 563 if (mdb_ctf_lookup_by_name(tn2, &id) == 0) {
564 564 (void) strcpy(type, tn2);
565 565 } else if (mdb_ctf_lookup_by_name(type, &id) != 0) {
566 566 mdb_warn("types '%s', '%s'", tn2, type);
567 567 return (DCMD_ERR);
568 568 }
569 569 } else {
570 570 if (mdb_ctf_lookup_by_name(type, &id) != 0) {
571 571 mdb_warn("'%s'", type);
572 572 return (DCMD_ERR);
573 573 }
574 574 }
575 575
576 576 /* resolve it, and make sure we're looking at an enumeration */
577 577 if (mdb_ctf_type_resolve(id, &idr) == -1) {
578 578 mdb_warn("unable to resolve '%s'", type);
579 579 return (DCMD_ERR);
580 580 }
581 581 if (mdb_ctf_type_kind(idr) != CTF_K_ENUM) {
582 582 mdb_warn("'%s': not an enumeration\n", type);
583 583 return (DCMD_ERR);
584 584 }
585 585
586 586 info.e_id = idr;
587 587
588 588 if (argc > 2)
589 589 return (DCMD_USAGE);
590 590
591 591 if (argc == 2) {
592 592 if (flags & DCMD_ADDRSPEC) {
593 593 mdb_warn("may only specify one of: name, address\n");
594 594 return (DCMD_USAGE);
595 595 }
596 596
597 597 if (argv[1].a_type == MDB_TYPE_STRING) {
598 598 info.e_flags |= E_SEARCH_STRING;
599 599 info.e_string = argv[1].a_un.a_str;
600 600 } else if (argv[1].a_type == MDB_TYPE_IMMEDIATE) {
601 601 info.e_flags |= E_SEARCH_VALUE;
602 602 search = argv[1].a_un.a_val;
603 603 } else {
604 604 return (DCMD_USAGE);
605 605 }
606 606 }
607 607
608 608 if (flags & DCMD_ADDRSPEC) {
609 609 info.e_flags |= E_SEARCH_VALUE;
610 610 search = mdb_get_dot();
611 611 }
612 612
613 613 if (info.e_flags & E_SEARCH_VALUE) {
614 614 if ((int)search != search) {
615 615 mdb_warn("value '%lld' out of enumeration range\n",
616 616 search);
617 617 }
618 618 info.e_value = search;
619 619 }
620 620
621 621 isp2 = enum_is_p2(idr);
622 622 if (isp2)
623 623 info.e_flags |= E_HEX;
624 624
625 625 if (DCMD_HDRSPEC(flags) && (info.e_flags & E_PRETTY)) {
626 626 if (info.e_flags & E_HEX)
627 627 mdb_printf("%<u>%8s %-64s%</u>\n", "VALUE", "NAME");
628 628 else
629 629 mdb_printf("%<u>%11s %-64s%</u>\n", "VALUE", "NAME");
630 630 }
631 631
632 632 /* if the enum is a power-of-two one, process it that way */
633 633 if ((info.e_flags & E_SEARCH_VALUE) && isp2) {
634 634 enum_print(&info, NULL, info.e_value);
635 635 return (DCMD_OK);
636 636 }
637 637
638 638 prefix[0] = 0;
639 639 if ((info.e_flags & E_ELIDE_PREFIX) &&
640 640 mdb_ctf_enum_iter(id, enum_prefix_scan_cb, prefix) == 0)
641 641 info.e_prefix = strlen(prefix);
642 642
643 643 if (mdb_ctf_enum_iter(idr, enum_cb, &info) == -1) {
644 644 mdb_warn("cannot walk '%s' as enum", type);
645 645 return (DCMD_ERR);
646 646 }
647 647
648 648 if (info.e_found == 0 &&
649 649 (info.e_flags & (E_SEARCH_STRING | E_SEARCH_VALUE)) != 0) {
650 650 if (info.e_flags & E_SEARCH_STRING)
651 651 mdb_warn("name \"%s\" not in '%s'\n", info.e_string,
652 652 type);
653 653 else
654 654 mdb_warn("value %#lld not in '%s'\n", info.e_value,
655 655 type);
656 656
657 657 return (DCMD_ERR);
658 658 }
659 659
660 660 return (DCMD_OK);
661 661 }
662 662
663 663 static int
664 664 setup_vcb(const char *name, uintptr_t addr)
665 665 {
666 666 const char *p;
667 667 mdb_var_t *v;
668 668
669 669 if ((v = mdb_nv_lookup(&mdb.m_nv, name)) == NULL) {
670 670 if ((p = strbadid(name)) != NULL) {
671 671 mdb_warn("'%c' may not be used in a variable "
672 672 "name\n", *p);
673 673 return (DCMD_ABORT);
674 674 }
675 675
676 676 if ((v = mdb_nv_insert(&mdb.m_nv, name, NULL, addr, 0)) == NULL)
677 677 return (DCMD_ERR);
678 678 } else {
679 679 if (v->v_flags & MDB_NV_RDONLY) {
680 680 mdb_warn("variable %s is read-only\n", name);
681 681 return (DCMD_ABORT);
682 682 }
683 683 }
684 684
685 685 /*
686 686 * If there already exists a vcb for this variable, we may be
687 687 * calling the dcmd in a loop. We only create a vcb for this
688 688 * variable on the first invocation.
689 689 */
690 690 if (mdb_vcb_find(v, mdb.m_frame) == NULL)
691 691 mdb_vcb_insert(mdb_vcb_create(v), mdb.m_frame);
692 692
693 693 return (0);
694 694 }
695 695
696 696 /*ARGSUSED*/
697 697 int
698 698 cmd_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
699 699 {
700 700 int offset;
701 701 uintptr_t a, tmp;
702 702 int ret;
703 703
704 704 if (!(flags & DCMD_ADDRSPEC) || argc == 0)
705 705 return (DCMD_USAGE);
706 706
707 707 if (argv->a_type != MDB_TYPE_STRING) {
708 708 /*
709 709 * We are being given a raw offset in lieu of a type and
710 710 * member; confirm the number of arguments and argument
711 711 * type.
712 712 */
713 713 if (argc != 1 || argv->a_type != MDB_TYPE_IMMEDIATE)
714 714 return (DCMD_USAGE);
715 715
716 716 offset = argv->a_un.a_val;
717 717
718 718 argv++;
719 719 argc--;
720 720
721 721 if (offset % sizeof (uintptr_t)) {
722 722 mdb_warn("offset must fall on a word boundary\n");
723 723 return (DCMD_ABORT);
724 724 }
725 725 } else {
726 726 const char *member;
727 727 char buf[MDB_SYM_NAMLEN];
728 728 int ret;
729 729
730 730 /*
731 731 * Check that we were provided 2 arguments: a type name
732 732 * and a member of that type.
733 733 */
734 734 if (argc != 2)
735 735 return (DCMD_USAGE);
736 736
737 737 ret = args_to_typename(&argc, &argv, buf, sizeof (buf));
738 738 if (ret != 0)
739 739 return (ret);
740 740
741 741 argv++;
742 742 argc--;
743 743
744 744 member = argv->a_un.a_str;
745 745 offset = mdb_ctf_offsetof_by_name(buf, member);
746 746 if (offset == -1)
747 747 return (DCMD_ABORT);
748 748
749 749 argv++;
750 750 argc--;
751 751
752 752 if (offset % (sizeof (uintptr_t)) != 0) {
753 753 mdb_warn("%s is not a word-aligned member\n", member);
754 754 return (DCMD_ABORT);
755 755 }
756 756 }
757 757
758 758 /*
759 759 * If we have any unchewed arguments, a variable name must be present.
760 760 */
761 761 if (argc == 1) {
762 762 if (argv->a_type != MDB_TYPE_STRING)
763 763 return (DCMD_USAGE);
764 764
765 765 if ((ret = setup_vcb(argv->a_un.a_str, addr)) != 0)
766 766 return (ret);
767 767
768 768 } else if (argc != 0) {
769 769 return (DCMD_USAGE);
770 770 }
771 771
772 772 a = addr;
773 773
774 774 do {
775 775 mdb_printf("%lr\n", a);
776 776
777 777 if (mdb_vread(&tmp, sizeof (tmp), a + offset) == -1) {
778 778 mdb_warn("failed to read next pointer from object %p",
779 779 a);
780 780 return (DCMD_ERR);
781 781 }
782 782
783 783 a = tmp;
784 784 } while (a != addr && a != NULL);
785 785
786 786 return (DCMD_OK);
787 787 }
788 788
789 789 int
790 790 cmd_array(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
791 791 {
792 792 mdb_ctf_id_t id;
793 793 ssize_t elemsize = 0;
794 794 char tn[MDB_SYM_NAMLEN];
795 795 int ret, nelem = -1;
796 796
797 797 mdb_tgt_t *t = mdb.m_target;
798 798 GElf_Sym sym;
799 799 mdb_ctf_arinfo_t ar;
800 800 mdb_syminfo_t s_info;
801 801
802 802 if (!(flags & DCMD_ADDRSPEC))
803 803 return (DCMD_USAGE);
804 804
805 805 if (argc >= 2) {
806 806 ret = args_to_typename(&argc, &argv, tn, sizeof (tn));
807 807 if (ret != 0)
808 808 return (ret);
809 809
810 810 if (argc == 1) /* unquoted compound type without count */
811 811 return (DCMD_USAGE);
812 812
813 813 if (mdb_ctf_lookup_by_name(tn, &id) != 0) {
814 814 mdb_warn("failed to look up type %s", tn);
815 815 return (DCMD_ABORT);
816 816 }
817 817
818 818 if (argv[1].a_type == MDB_TYPE_IMMEDIATE)
819 819 nelem = argv[1].a_un.a_val;
820 820 else
821 821 nelem = mdb_strtoull(argv[1].a_un.a_str);
822 822
823 823 elemsize = mdb_ctf_type_size(id);
824 824 } else if (addr_to_sym(t, addr, tn, sizeof (tn), &sym, &s_info)
825 825 != NULL && mdb_ctf_lookup_by_symbol(&sym, &s_info, &id)
826 826 == 0 && mdb_ctf_type_kind(id) == CTF_K_ARRAY &&
827 827 mdb_ctf_array_info(id, &ar) != -1) {
828 828 elemsize = mdb_ctf_type_size(id) / ar.mta_nelems;
829 829 nelem = ar.mta_nelems;
830 830 } else {
831 831 mdb_warn("no symbol information for %a", addr);
832 832 return (DCMD_ERR);
833 833 }
834 834
835 835 if (argc == 3 || argc == 1) {
836 836 if (argv[argc - 1].a_type != MDB_TYPE_STRING)
837 837 return (DCMD_USAGE);
838 838
839 839 if ((ret = setup_vcb(argv[argc - 1].a_un.a_str, addr)) != 0)
840 840 return (ret);
841 841
842 842 } else if (argc > 3) {
843 843 return (DCMD_USAGE);
844 844 }
845 845
846 846 for (; nelem > 0; nelem--) {
847 847 mdb_printf("%lr\n", addr);
848 848 addr = addr + elemsize;
849 849 }
850 850
851 851 return (DCMD_OK);
852 852 }
853 853
854 854 /*
855 855 * Print an integer bitfield in hexadecimal by reading the enclosing byte(s)
856 856 * and then shifting and masking the data in the lower bits of a uint64_t.
857 857 */
858 858 static int
859 859 print_bitfield(ulong_t off, printarg_t *pap, ctf_encoding_t *ep)
860 860 {
861 861 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
862 862 size_t size = (ep->cte_bits + (NBBY - 1)) / NBBY;
863 863 uint64_t mask = (1ULL << ep->cte_bits) - 1;
864 864 uint64_t value = 0;
865 865 uint8_t *buf = (uint8_t *)&value;
866 866 uint8_t shift;
867 867
868 868 const char *format;
869 869
870 870 if (!(pap->pa_flags & PA_SHOWVAL))
871 871 return (0);
872 872
873 873 if (ep->cte_bits > sizeof (value) * NBBY - 1) {
874 874 mdb_printf("??? (invalid bitfield size %u)", ep->cte_bits);
875 875 return (0);
876 876 }
877 877
878 878 /*
879 879 * On big-endian machines, we need to adjust the buf pointer to refer
880 880 * to the lowest 'size' bytes in 'value', and we need shift based on
881 881 * the offset from the end of the data, not the offset of the start.
882 882 */
883 883 #ifdef _BIG_ENDIAN
884 884 buf += sizeof (value) - size;
885 885 off += ep->cte_bits;
886 886 #endif
887 887 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, buf, size, addr) != size) {
888 888 mdb_warn("failed to read %lu bytes at %llx",
889 889 (ulong_t)size, addr);
890 890 return (1);
891 891 }
892 892
893 893 shift = off % NBBY;
894 894
895 895 /*
896 896 * Offsets are counted from opposite ends on little- and
897 897 * big-endian machines.
898 898 */
899 899 #ifdef _BIG_ENDIAN
900 900 shift = NBBY - shift;
901 901 #endif
902 902
903 903 /*
904 904 * If the bits we want do not begin on a byte boundary, shift the data
905 905 * right so that the value is in the lowest 'cte_bits' of 'value'.
906 906 */
907 907 if (off % NBBY != 0)
908 908 value >>= shift;
909 909 value &= mask;
910 910
911 911 /*
912 912 * We default to printing signed bitfields as decimals,
913 913 * and unsigned bitfields in hexadecimal. If they specify
914 914 * hexadecimal, we treat the field as unsigned.
915 915 */
916 916 if ((pap->pa_flags & PA_INTHEX) ||
917 917 !(ep->cte_format & CTF_INT_SIGNED)) {
918 918 format = (pap->pa_flags & PA_INTDEC)? "%#llu" : "%#llx";
919 919 } else {
920 920 int sshift = sizeof (value) * NBBY - ep->cte_bits;
921 921
922 922 /* sign-extend value, and print as a signed decimal */
923 923 value = ((int64_t)value << sshift) >> sshift;
924 924 format = "%#lld";
925 925 }
926 926 mdb_printf(format, value);
927 927
928 928 return (0);
929 929 }
930 930
931 931 /*
932 932 * Print out a character or integer value. We use some simple heuristics,
933 933 * described below, to determine the appropriate radix to use for output.
934 934 */
935 935 static int
936 936 print_int_val(const char *type, ctf_encoding_t *ep, ulong_t off,
937 937 printarg_t *pap)
938 938 {
939 939 static const char *const sformat[] = { "%#d", "%#d", "%#d", "%#lld" };
940 940 static const char *const uformat[] = { "%#u", "%#u", "%#u", "%#llu" };
941 941 static const char *const xformat[] = { "%#x", "%#x", "%#x", "%#llx" };
942 942
943 943 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
944 944 const char *const *fsp;
945 945 size_t size;
946 946
947 947 union {
948 948 uint64_t i8;
949 949 uint32_t i4;
950 950 uint16_t i2;
951 951 uint8_t i1;
952 952 time_t t;
953 953 ipaddr_t I;
954 954 } u;
955 955
956 956 if (!(pap->pa_flags & PA_SHOWVAL))
957 957 return (0);
958 958
959 959 if (ep->cte_format & CTF_INT_VARARGS) {
960 960 mdb_printf("...\n");
961 961 return (0);
962 962 }
963 963
964 964 /*
965 965 * If the size is not a power-of-two number of bytes in the range 1-8
966 966 * then we assume it is a bitfield and print it as such.
967 967 */
968 968 size = ep->cte_bits / NBBY;
969 969 if (size > 8 || (ep->cte_bits % NBBY) != 0 || (size & (size - 1)) != 0)
970 970 return (print_bitfield(off, pap, ep));
971 971
972 972 if (IS_CHAR(*ep)) {
973 973 mdb_printf("'");
974 974 if (mdb_fmt_print(pap->pa_tgt, pap->pa_as,
975 975 addr, 1, 'C') == addr)
976 976 return (1);
977 977 mdb_printf("'");
978 978 return (0);
979 979 }
980 980
981 981 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.i8, size, addr) != size) {
982 982 mdb_warn("failed to read %lu bytes at %llx",
983 983 (ulong_t)size, addr);
984 984 return (1);
985 985 }
986 986
987 987 /*
988 988 * We pretty-print some integer based types. time_t values are
989 989 * printed as a calendar date and time, and IPv4 addresses as human
990 990 * readable dotted quads.
991 991 */
992 992 if (!(pap->pa_flags & (PA_INTHEX | PA_INTDEC))) {
993 993 if (strcmp(type, "time_t") == 0 && u.t != 0) {
994 994 mdb_printf("%Y", u.t);
995 995 return (0);
996 996 }
997 997 if (strcmp(type, "ipaddr_t") == 0 ||
998 998 strcmp(type, "in_addr_t") == 0) {
999 999 mdb_printf("%I", u.I);
1000 1000 return (0);
1001 1001 }
1002 1002 }
1003 1003
1004 1004 /*
1005 1005 * The default format is hexadecimal.
1006 1006 */
1007 1007 if (!(pap->pa_flags & PA_INTDEC))
1008 1008 fsp = xformat;
1009 1009 else if (ep->cte_format & CTF_INT_SIGNED)
1010 1010 fsp = sformat;
1011 1011 else
1012 1012 fsp = uformat;
1013 1013
1014 1014 switch (size) {
1015 1015 case sizeof (uint8_t):
1016 1016 mdb_printf(fsp[0], u.i1);
1017 1017 break;
1018 1018 case sizeof (uint16_t):
1019 1019 mdb_printf(fsp[1], u.i2);
1020 1020 break;
1021 1021 case sizeof (uint32_t):
1022 1022 mdb_printf(fsp[2], u.i4);
1023 1023 break;
1024 1024 case sizeof (uint64_t):
1025 1025 mdb_printf(fsp[3], u.i8);
1026 1026 break;
1027 1027 }
1028 1028 return (0);
1029 1029 }
1030 1030
1031 1031 /*ARGSUSED*/
1032 1032 static int
1033 1033 print_int(const char *type, const char *name, mdb_ctf_id_t id,
1034 1034 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1035 1035 {
1036 1036 ctf_encoding_t e;
1037 1037
1038 1038 if (!(pap->pa_flags & PA_SHOWVAL))
1039 1039 return (0);
1040 1040
1041 1041 if (mdb_ctf_type_encoding(base, &e) != 0) {
1042 1042 mdb_printf("??? (%s)", mdb_strerror(errno));
1043 1043 return (0);
1044 1044 }
1045 1045
1046 1046 return (print_int_val(type, &e, off, pap));
1047 1047 }
1048 1048
1049 1049 /*
1050 1050 * Print out a floating point value. We only provide support for floats in
1051 1051 * the ANSI-C float, double, and long double formats.
1052 1052 */
1053 1053 /*ARGSUSED*/
1054 1054 static int
1055 1055 print_float(const char *type, const char *name, mdb_ctf_id_t id,
1056 1056 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1057 1057 {
1058 1058 #ifndef _KMDB
1059 1059 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
1060 1060 ctf_encoding_t e;
1061 1061
1062 1062 union {
1063 1063 float f;
1064 1064 double d;
1065 1065 long double ld;
1066 1066 } u;
1067 1067
1068 1068 if (!(pap->pa_flags & PA_SHOWVAL))
1069 1069 return (0);
1070 1070
1071 1071 if (mdb_ctf_type_encoding(base, &e) == 0) {
1072 1072 if (e.cte_format == CTF_FP_SINGLE &&
1073 1073 e.cte_bits == sizeof (float) * NBBY) {
1074 1074 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.f,
1075 1075 sizeof (u.f), addr) != sizeof (u.f)) {
1076 1076 mdb_warn("failed to read float at %llx", addr);
1077 1077 return (1);
1078 1078 }
1079 1079 mdb_printf("%s", doubletos(u.f, 7, 'e'));
1080 1080
1081 1081 } else if (e.cte_format == CTF_FP_DOUBLE &&
1082 1082 e.cte_bits == sizeof (double) * NBBY) {
1083 1083 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.d,
1084 1084 sizeof (u.d), addr) != sizeof (u.d)) {
1085 1085 mdb_warn("failed to read float at %llx", addr);
1086 1086 return (1);
1087 1087 }
1088 1088 mdb_printf("%s", doubletos(u.d, 7, 'e'));
1089 1089
1090 1090 } else if (e.cte_format == CTF_FP_LDOUBLE &&
1091 1091 e.cte_bits == sizeof (long double) * NBBY) {
1092 1092 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.ld,
1093 1093 sizeof (u.ld), addr) != sizeof (u.ld)) {
1094 1094 mdb_warn("failed to read float at %llx", addr);
1095 1095 return (1);
1096 1096 }
1097 1097 mdb_printf("%s", longdoubletos(&u.ld, 16, 'e'));
1098 1098
1099 1099 } else {
1100 1100 mdb_printf("??? (unsupported FP format %u / %u bits\n",
1101 1101 e.cte_format, e.cte_bits);
1102 1102 }
1103 1103 } else
1104 1104 mdb_printf("??? (%s)", mdb_strerror(errno));
1105 1105 #else
1106 1106 mdb_printf("<FLOAT>");
1107 1107 #endif
1108 1108 return (0);
1109 1109 }
1110 1110
1111 1111
1112 1112 /*
1113 1113 * Print out a pointer value as a symbol name + offset or a hexadecimal value.
1114 1114 * If the pointer itself is a char *, we attempt to read a bit of the data
1115 1115 * referenced by the pointer and display it if it is a printable ASCII string.
1116 1116 */
1117 1117 /*ARGSUSED*/
1118 1118 static int
1119 1119 print_ptr(const char *type, const char *name, mdb_ctf_id_t id,
1120 1120 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1121 1121 {
1122 1122 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
1123 1123 ctf_encoding_t e;
1124 1124 uintptr_t value;
1125 1125 char buf[256];
1126 1126 ssize_t len;
1127 1127
1128 1128 if (!(pap->pa_flags & PA_SHOWVAL))
1129 1129 return (0);
1130 1130
1131 1131 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as,
1132 1132 &value, sizeof (value), addr) != sizeof (value)) {
1133 1133 mdb_warn("failed to read %s pointer at %llx", name, addr);
1134 1134 return (1);
1135 1135 }
1136 1136
1137 1137 if (pap->pa_flags & PA_NOSYMBOLIC) {
1138 1138 mdb_printf("%#lx", value);
1139 1139 return (0);
1140 1140 }
1141 1141
1142 1142 mdb_printf("%a", value);
1143 1143
1144 1144 if (value == NULL || strcmp(type, "caddr_t") == 0)
1145 1145 return (0);
1146 1146
1147 1147 if (mdb_ctf_type_kind(base) == CTF_K_POINTER &&
1148 1148 mdb_ctf_type_reference(base, &base) != -1 &&
1149 1149 mdb_ctf_type_resolve(base, &base) != -1 &&
1150 1150 mdb_ctf_type_encoding(base, &e) == 0 && IS_CHAR(e)) {
1151 1151 if ((len = mdb_tgt_readstr(pap->pa_realtgt, pap->pa_as,
1152 1152 buf, sizeof (buf), value)) >= 0 && strisprint(buf)) {
1153 1153 if (len == sizeof (buf))
1154 1154 (void) strabbr(buf, sizeof (buf));
1155 1155 mdb_printf(" \"%s\"", buf);
1156 1156 }
1157 1157 }
1158 1158
1159 1159 return (0);
1160 1160 }
1161 1161
1162 1162
1163 1163 /*
1164 1164 * Print out a fixed-size array. We special-case arrays of characters
1165 1165 * and attempt to print them out as ASCII strings if possible. For other
1166 1166 * arrays, we iterate over a maximum of pa_armemlim members and call
1167 1167 * mdb_ctf_type_visit() again on each element to print its value.
1168 1168 */
1169 1169 /*ARGSUSED*/
1170 1170 static int
1171 1171 print_array(const char *type, const char *name, mdb_ctf_id_t id,
1172 1172 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1173 1173 {
1174 1174 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
1175 1175 printarg_t pa = *pap;
1176 1176 ssize_t eltsize;
1177 1177 mdb_ctf_arinfo_t r;
1178 1178 ctf_encoding_t e;
1179 1179 uint_t i, kind, limit;
1180 1180 int d, sou;
1181 1181 char buf[8];
1182 1182 char *str;
1183 1183
1184 1184 if (!(pap->pa_flags & PA_SHOWVAL))
1185 1185 return (0);
1186 1186
1187 1187 if (pap->pa_depth == pap->pa_maxdepth) {
1188 1188 mdb_printf("[ ... ]");
1189 1189 return (0);
1190 1190 }
1191 1191
1192 1192 /*
1193 1193 * Determine the base type and size of the array's content. If this
1194 1194 * fails, we cannot print anything and just give up.
1195 1195 */
1196 1196 if (mdb_ctf_array_info(base, &r) == -1 ||
1197 1197 mdb_ctf_type_resolve(r.mta_contents, &base) == -1 ||
1198 1198 (eltsize = mdb_ctf_type_size(base)) == -1) {
1199 1199 mdb_printf("[ ??? ] (%s)", mdb_strerror(errno));
1200 1200 return (0);
1201 1201 }
1202 1202
1203 1203 /*
1204 1204 * Read a few bytes and determine if the content appears to be
1205 1205 * printable ASCII characters. If so, read the entire array and
1206 1206 * attempt to display it as a string if it is printable.
1207 1207 */
1208 1208 if ((pap->pa_arstrlim == MDB_ARR_NOLIMIT ||
1209 1209 r.mta_nelems <= pap->pa_arstrlim) &&
1210 1210 mdb_ctf_type_encoding(base, &e) == 0 && IS_CHAR(e) &&
1211 1211 mdb_tgt_readstr(pap->pa_tgt, pap->pa_as, buf,
1212 1212 MIN(sizeof (buf), r.mta_nelems), addr) > 0 && strisprint(buf)) {
1213 1213
1214 1214 str = mdb_alloc(r.mta_nelems + 1, UM_SLEEP | UM_GC);
1215 1215 str[r.mta_nelems] = '\0';
1216 1216
1217 1217 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, str,
1218 1218 r.mta_nelems, addr) != r.mta_nelems) {
1219 1219 mdb_warn("failed to read char array at %llx", addr);
1220 1220 return (1);
1221 1221 }
1222 1222
1223 1223 if (strisprint(str)) {
1224 1224 mdb_printf("[ \"%s\" ]", str);
1225 1225 return (0);
1226 1226 }
1227 1227 }
1228 1228
1229 1229 if (pap->pa_armemlim != MDB_ARR_NOLIMIT)
1230 1230 limit = MIN(r.mta_nelems, pap->pa_armemlim);
1231 1231 else
1232 1232 limit = r.mta_nelems;
1233 1233
1234 1234 if (limit == 0) {
1235 1235 mdb_printf("[ ... ]");
1236 1236 return (0);
1237 1237 }
1238 1238
1239 1239 kind = mdb_ctf_type_kind(base);
1240 1240 sou = IS_COMPOSITE(kind);
1241 1241
1242 1242 pa.pa_addr = addr; /* set base address to start of array */
1243 1243 pa.pa_maxdepth = pa.pa_maxdepth - pa.pa_depth - 1;
1244 1244 pa.pa_nest += pa.pa_depth + 1; /* nesting level is current depth + 1 */
1245 1245 pa.pa_depth = 0; /* reset depth to 0 for new scope */
1246 1246 pa.pa_prefix = NULL;
1247 1247
1248 1248 if (sou) {
1249 1249 pa.pa_delim = "\n";
1250 1250 mdb_printf("[\n");
1251 1251 } else {
1252 1252 pa.pa_flags &= ~(PA_SHOWTYPE | PA_SHOWNAME | PA_SHOWADDR);
1253 1253 pa.pa_delim = ", ";
1254 1254 mdb_printf("[ ");
1255 1255 }
1256 1256
1257 1257 for (i = 0; i < limit; i++, pa.pa_addr += eltsize) {
1258 1258 if (i == limit - 1 && !sou) {
1259 1259 if (limit < r.mta_nelems)
1260 1260 pa.pa_delim = ", ... ]";
1261 1261 else
1262 1262 pa.pa_delim = " ]";
1263 1263 }
1264 1264
1265 1265 if (mdb_ctf_type_visit(r.mta_contents, elt_print, &pa) == -1) {
1266 1266 mdb_warn("failed to print array data");
1267 1267 return (1);
1268 1268 }
1269 1269 }
1270 1270
1271 1271 if (sou) {
1272 1272 for (d = pa.pa_depth - 1; d >= 0; d--)
1273 1273 print_close_sou(&pa, d);
1274 1274
1275 1275 if (limit < r.mta_nelems) {
1276 1276 mdb_printf("%*s... ]",
1277 1277 (pap->pa_depth + pap->pa_nest) * pap->pa_tab, "");
1278 1278 } else {
1279 1279 mdb_printf("%*s]",
1280 1280 (pap->pa_depth + pap->pa_nest) * pap->pa_tab, "");
1281 1281 }
1282 1282 }
1283 1283
1284 1284 /* copy the hole array info, since it may have been grown */
1285 1285 pap->pa_holes = pa.pa_holes;
1286 1286 pap->pa_nholes = pa.pa_nholes;
1287 1287
1288 1288 return (0);
1289 1289 }
1290 1290
1291 1291 /*
1292 1292 * Print out a struct or union header. We need only print the open brace
1293 1293 * because mdb_ctf_type_visit() itself will automatically recurse through
1294 1294 * all members of the given struct or union.
1295 1295 */
1296 1296 /*ARGSUSED*/
1297 1297 static int
1298 1298 print_sou(const char *type, const char *name, mdb_ctf_id_t id,
1299 1299 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1300 1300 {
1301 1301 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
1302 1302
1303 1303 /*
1304 1304 * We have pretty-printing for some structures where displaying
1305 1305 * structure contents has no value.
1306 1306 */
1307 1307 if (pap->pa_flags & PA_SHOWVAL) {
1308 1308 if (strcmp(type, "in6_addr_t") == 0 ||
1309 1309 strcmp(type, "struct in6_addr") == 0) {
1310 1310 in6_addr_t in6addr;
1311 1311
1312 1312 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &in6addr,
1313 1313 sizeof (in6addr), addr) != sizeof (in6addr)) {
1314 1314 mdb_warn("failed to read %s pointer at %llx",
1315 1315 name, addr);
1316 1316 return (1);
1317 1317 }
1318 1318 mdb_printf("%N", &in6addr);
1319 1319 /*
1320 1320 * Don't print anything further down in the
1321 1321 * structure.
1322 1322 */
1323 1323 pap->pa_nooutdepth = pap->pa_depth;
1324 1324 return (0);
1325 1325 }
1326 1326 if (strcmp(type, "struct in_addr") == 0) {
1327 1327 in_addr_t inaddr;
1328 1328
1329 1329 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &inaddr,
1330 1330 sizeof (inaddr), addr) != sizeof (inaddr)) {
1331 1331 mdb_warn("failed to read %s pointer at %llx",
1332 1332 name, addr);
1333 1333 return (1);
1334 1334 }
1335 1335 mdb_printf("%I", inaddr);
1336 1336 pap->pa_nooutdepth = pap->pa_depth;
1337 1337 return (0);
1338 1338 }
1339 1339 }
1340 1340
1341 1341 if (pap->pa_depth == pap->pa_maxdepth)
1342 1342 mdb_printf("{ ... }");
1343 1343 else
1344 1344 mdb_printf("{");
1345 1345 pap->pa_delim = "\n";
1346 1346 return (0);
1347 1347 }
1348 1348
1349 1349 /*
1350 1350 * Print an enum value. We attempt to convert the value to the corresponding
1351 1351 * enum name and print that if possible.
1352 1352 */
1353 1353 /*ARGSUSED*/
1354 1354 static int
1355 1355 print_enum(const char *type, const char *name, mdb_ctf_id_t id,
1356 1356 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1357 1357 {
1358 1358 mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
1359 1359 const char *ename;
1360 1360 int value;
1361 1361 int isp2 = enum_is_p2(base);
1362 1362 int flags = pap->pa_flags | (isp2 ? PA_INTHEX : 0);
1363 1363
1364 1364 if (!(flags & PA_SHOWVAL))
1365 1365 return (0);
1366 1366
1367 1367 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as,
1368 1368 &value, sizeof (value), addr) != sizeof (value)) {
1369 1369 mdb_warn("failed to read %s integer at %llx", name, addr);
1370 1370 return (1);
1371 1371 }
1372 1372
1373 1373 if (flags & PA_INTHEX)
1374 1374 mdb_printf("%#x", value);
1375 1375 else
1376 1376 mdb_printf("%#d", value);
1377 1377
1378 1378 (void) mdb_inc_indent(8);
1379 1379 mdb_printf(" (");
1380 1380
1381 1381 if (!isp2 || enum_value_print_p2(base, value, 0) != 0) {
1382 1382 ename = mdb_ctf_enum_name(base, value);
1383 1383 if (ename == NULL) {
1384 1384 ename = "???";
1385 1385 }
1386 1386 mdb_printf("%s", ename);
1387 1387 }
1388 1388 mdb_printf(")");
1389 1389 (void) mdb_dec_indent(8);
1390 1390
1391 1391 return (0);
1392 1392 }
1393 1393
1394 1394 /*
1395 1395 * This will only get called if the structure isn't found in any available CTF
1396 1396 * data.
1397 1397 */
1398 1398 /*ARGSUSED*/
1399 1399 static int
1400 1400 print_tag(const char *type, const char *name, mdb_ctf_id_t id,
1401 1401 mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
1402 1402 {
1403 1403 char basename[MDB_SYM_NAMLEN];
1404 1404
1405 1405 if (pap->pa_flags & PA_SHOWVAL)
1406 1406 mdb_printf("; ");
1407 1407
1408 1408 if (mdb_ctf_type_name(base, basename, sizeof (basename)) != NULL)
1409 1409 mdb_printf("<forward declaration of %s>", basename);
1410 1410 else
1411 1411 mdb_printf("<forward declaration of unknown type>");
1412 1412
1413 1413 return (0);
1414 1414 }
1415 1415
1416 1416 static void
1417 1417 print_hole(printarg_t *pap, int depth, ulong_t off, ulong_t endoff)
1418 1418 {
1419 1419 ulong_t bits = endoff - off;
1420 1420 ulong_t size = bits / NBBY;
1421 1421 ctf_encoding_t e;
1422 1422
1423 1423 static const char *const name = "<<HOLE>>";
1424 1424 char type[MDB_SYM_NAMLEN];
1425 1425
1426 1426 int bitfield =
1427 1427 (off % NBBY != 0 ||
1428 1428 bits % NBBY != 0 ||
1429 1429 size > 8 ||
1430 1430 (size & (size - 1)) != 0);
1431 1431
1432 1432 ASSERT(off < endoff);
1433 1433
1434 1434 if (bits > NBBY * sizeof (uint64_t)) {
1435 1435 ulong_t end;
1436 1436
1437 1437 /*
1438 1438 * The hole is larger than the largest integer type. To
1439 1439 * handle this, we split up the hole at 8-byte-aligned
1440 1440 * boundaries, recursing to print each subsection. For
1441 1441 * normal C structures, we'll loop at most twice.
1442 1442 */
1443 1443 for (; off < endoff; off = end) {
1444 1444 end = P2END(off, NBBY * sizeof (uint64_t));
1445 1445 if (end > endoff)
1446 1446 end = endoff;
1447 1447
1448 1448 ASSERT((end - off) <= NBBY * sizeof (uint64_t));
1449 1449 print_hole(pap, depth, off, end);
1450 1450 }
1451 1451 ASSERT(end == endoff);
1452 1452
1453 1453 return;
1454 1454 }
1455 1455
1456 1456 if (bitfield)
1457 1457 (void) mdb_snprintf(type, sizeof (type), "unsigned");
1458 1458 else
1459 1459 (void) mdb_snprintf(type, sizeof (type), "uint%d_t", bits);
1460 1460
1461 1461 if (pap->pa_flags & (PA_SHOWTYPE | PA_SHOWNAME | PA_SHOWADDR))
1462 1462 mdb_printf("%*s", (depth + pap->pa_nest) * pap->pa_tab, "");
1463 1463
1464 1464 if (pap->pa_flags & PA_SHOWADDR) {
1465 1465 if (off % NBBY == 0)
1466 1466 mdb_printf("%llx ", pap->pa_addr + off / NBBY);
1467 1467 else
1468 1468 mdb_printf("%llx.%lx ",
1469 1469 pap->pa_addr + off / NBBY, off % NBBY);
1470 1470 }
1471 1471
1472 1472 if (pap->pa_flags & PA_SHOWTYPE)
1473 1473 mdb_printf("%s ", type);
1474 1474
1475 1475 if (pap->pa_flags & PA_SHOWNAME)
1476 1476 mdb_printf("%s", name);
1477 1477
1478 1478 if (bitfield && (pap->pa_flags & PA_SHOWTYPE))
1479 1479 mdb_printf(" :%d", bits);
1480 1480
1481 1481 mdb_printf("%s ", (pap->pa_flags & PA_SHOWVAL)? " =" : "");
1482 1482
1483 1483 /*
1484 1484 * We fake up a ctf_encoding_t, and use print_int_val() to print
1485 1485 * the value. Holes are always processed as unsigned integers.
1486 1486 */
1487 1487 bzero(&e, sizeof (e));
1488 1488 e.cte_format = 0;
1489 1489 e.cte_offset = 0;
1490 1490 e.cte_bits = bits;
1491 1491
1492 1492 if (print_int_val(type, &e, off, pap) != 0)
1493 1493 mdb_iob_discard(mdb.m_out);
1494 1494 else
1495 1495 mdb_iob_puts(mdb.m_out, pap->pa_delim);
1496 1496 }
1497 1497
1498 1498 /*
1499 1499 * The print_close_sou() function is called for each structure or union
1500 1500 * which has been completed. For structures, we detect and print any holes
1501 1501 * before printing the closing brace.
1502 1502 */
1503 1503 static void
1504 1504 print_close_sou(printarg_t *pap, int newdepth)
1505 1505 {
1506 1506 int d = newdepth + pap->pa_nest;
1507 1507
1508 1508 if ((pap->pa_flags & PA_SHOWHOLES) && !pap->pa_holes[d].hi_isunion) {
1509 1509 ulong_t end = pap->pa_holes[d + 1].hi_offset;
1510 1510 ulong_t expected = pap->pa_holes[d].hi_offset;
1511 1511
1512 1512 if (end < expected)
1513 1513 print_hole(pap, newdepth + 1, end, expected);
1514 1514 }
1515 1515 /* if the struct is an array element, print a comma after the } */
1516 1516 mdb_printf("%*s}%s\n", d * pap->pa_tab, "",
1517 1517 (newdepth == 0 && pap->pa_nest > 0)? "," : "");
1518 1518 }
1519 1519
1520 1520 static printarg_f *const printfuncs[] = {
1521 1521 print_int, /* CTF_K_INTEGER */
1522 1522 print_float, /* CTF_K_FLOAT */
1523 1523 print_ptr, /* CTF_K_POINTER */
1524 1524 print_array, /* CTF_K_ARRAY */
1525 1525 print_ptr, /* CTF_K_FUNCTION */
1526 1526 print_sou, /* CTF_K_STRUCT */
1527 1527 print_sou, /* CTF_K_UNION */
1528 1528 print_enum, /* CTF_K_ENUM */
1529 1529 print_tag /* CTF_K_FORWARD */
1530 1530 };
1531 1531
1532 1532 /*
1533 1533 * The elt_print function is used as the mdb_ctf_type_visit callback. For
1534 1534 * each element, we print an appropriate name prefix and then call the
1535 1535 * print subroutine for this type class in the array above.
1536 1536 */
1537 1537 static int
1538 1538 elt_print(const char *name, mdb_ctf_id_t id, mdb_ctf_id_t base,
1539 1539 ulong_t off, int depth, void *data)
1540 1540 {
1541 1541 char type[MDB_SYM_NAMLEN + sizeof (" <<12345678...>>")];
1542 1542 int kind, rc, d;
1543 1543 printarg_t *pap = data;
1544 1544
1545 1545 for (d = pap->pa_depth - 1; d >= depth; d--) {
1546 1546 if (d < pap->pa_nooutdepth)
1547 1547 print_close_sou(pap, d);
1548 1548 }
1549 1549
1550 1550 /*
1551 1551 * Reset pa_nooutdepth if we've come back out of the structure we
1552 1552 * didn't want to print.
1553 1553 */
1554 1554 if (depth <= pap->pa_nooutdepth)
1555 1555 pap->pa_nooutdepth = (uint_t)-1;
1556 1556
1557 1557 if (depth > pap->pa_maxdepth || depth > pap->pa_nooutdepth)
1558 1558 return (0);
1559 1559
1560 1560 if (!mdb_ctf_type_valid(base) ||
1561 1561 (kind = mdb_ctf_type_kind(base)) == -1)
1562 1562 return (-1); /* errno is set for us */
1563 1563
1564 1564 if (mdb_ctf_type_name(id, type, MDB_SYM_NAMLEN) == NULL)
1565 1565 (void) strcpy(type, "(?)");
1566 1566
1567 1567 if (pap->pa_flags & PA_SHOWBASETYPE) {
1568 1568 /*
1569 1569 * If basetype is different and informative, concatenate
1570 1570 * <<basetype>> (or <<baset...>> if it doesn't fit)
1571 1571 *
1572 1572 * We just use the end of the buffer to store the type name, and
1573 1573 * only connect it up if that's necessary.
1574 1574 */
1575 1575
1576 1576 char *type_end = type + strlen(type);
1577 1577 char *basetype;
1578 1578 size_t sz;
1579 1579
1580 1580 (void) strlcat(type, " <<", sizeof (type));
1581 1581
1582 1582 basetype = type + strlen(type);
1583 1583 sz = sizeof (type) - (basetype - type);
1584 1584
1585 1585 *type_end = '\0'; /* restore the end of type for strcmp() */
1586 1586
1587 1587 if (mdb_ctf_type_name(base, basetype, sz) != NULL &&
1588 1588 strcmp(basetype, type) != 0 &&
1589 1589 strcmp(basetype, "struct ") != 0 &&
1590 1590 strcmp(basetype, "enum ") != 0 &&
1591 1591 strcmp(basetype, "union ") != 0) {
1592 1592 type_end[0] = ' '; /* reconnect */
1593 1593 if (strlcat(type, ">>", sizeof (type)) >= sizeof (type))
1594 1594 (void) strlcpy(
1595 1595 type + sizeof (type) - 6, "...>>", 6);
1596 1596 }
1597 1597 }
1598 1598
1599 1599 if (pap->pa_flags & PA_SHOWHOLES) {
1600 1600 ctf_encoding_t e;
1601 1601 ssize_t nsize;
1602 1602 ulong_t newoff;
1603 1603 holeinfo_t *hole;
1604 1604 int extra = IS_COMPOSITE(kind)? 1 : 0;
1605 1605
1606 1606 /*
1607 1607 * grow the hole array, if necessary
1608 1608 */
1609 1609 if (pap->pa_nest + depth + extra >= pap->pa_nholes) {
1610 1610 int new = MAX(MAX(8, pap->pa_nholes * 2),
1611 1611 pap->pa_nest + depth + extra + 1);
1612 1612
1613 1613 holeinfo_t *nhi = mdb_zalloc(
1614 1614 sizeof (*nhi) * new, UM_NOSLEEP | UM_GC);
1615 1615
1616 1616 bcopy(pap->pa_holes, nhi,
1617 1617 pap->pa_nholes * sizeof (*nhi));
1618 1618
1619 1619 pap->pa_holes = nhi;
1620 1620 pap->pa_nholes = new;
1621 1621 }
1622 1622
1623 1623 hole = &pap->pa_holes[depth + pap->pa_nest];
1624 1624
1625 1625 if (depth != 0 && off > hole->hi_offset)
1626 1626 print_hole(pap, depth, hole->hi_offset, off);
1627 1627
1628 1628 /* compute the next expected offset */
1629 1629 if (kind == CTF_K_INTEGER &&
1630 1630 mdb_ctf_type_encoding(base, &e) == 0)
1631 1631 newoff = off + e.cte_bits;
1632 1632 else if ((nsize = mdb_ctf_type_size(base)) >= 0)
1633 1633 newoff = off + nsize * NBBY;
1634 1634 else {
1635 1635 /* something bad happened, disable hole checking */
1636 1636 newoff = -1UL; /* ULONG_MAX */
1637 1637 }
1638 1638
1639 1639 hole->hi_offset = newoff;
1640 1640
1641 1641 if (IS_COMPOSITE(kind)) {
1642 1642 hole->hi_isunion = (kind == CTF_K_UNION);
1643 1643 hole++;
1644 1644 hole->hi_offset = off;
1645 1645 }
1646 1646 }
1647 1647
1648 1648 if (pap->pa_flags & (PA_SHOWTYPE | PA_SHOWNAME | PA_SHOWADDR))
1649 1649 mdb_printf("%*s", (depth + pap->pa_nest) * pap->pa_tab, "");
1650 1650
1651 1651 if (pap->pa_flags & PA_SHOWADDR) {
1652 1652 if (off % NBBY == 0)
1653 1653 mdb_printf("%llx ", pap->pa_addr + off / NBBY);
1654 1654 else
1655 1655 mdb_printf("%llx.%lx ",
1656 1656 pap->pa_addr + off / NBBY, off % NBBY);
1657 1657 }
1658 1658
1659 1659 if ((pap->pa_flags & PA_SHOWTYPE)) {
1660 1660 mdb_printf("%s", type);
1661 1661 /*
1662 1662 * We want to avoid printing a trailing space when
1663 1663 * dealing with pointers in a structure, so we end
1664 1664 * up with:
1665 1665 *
1666 1666 * label_t *t_onfault = 0
1667 1667 *
1668 1668 * If depth is zero, always print the trailing space unless
1669 1669 * we also have a prefix.
1670 1670 */
1671 1671 if (type[strlen(type) - 1] != '*' ||
1672 1672 (depth == 0 && (!(pap->pa_flags & PA_SHOWNAME) ||
1673 1673 pap->pa_prefix == NULL)))
1674 1674 mdb_printf(" ");
1675 1675 }
1676 1676
1677 1677 if (pap->pa_flags & PA_SHOWNAME) {
1678 1678 if (pap->pa_prefix != NULL && depth <= 1)
1679 1679 mdb_printf("%s%s", pap->pa_prefix,
1680 1680 (depth == 0) ? "" : pap->pa_suffix);
1681 1681 mdb_printf("%s", name);
1682 1682 }
1683 1683
1684 1684 if ((pap->pa_flags & PA_SHOWTYPE) && kind == CTF_K_INTEGER) {
1685 1685 ctf_encoding_t e;
1686 1686
1687 1687 if (mdb_ctf_type_encoding(base, &e) == 0) {
1688 1688 ulong_t bits = e.cte_bits;
1689 1689 ulong_t size = bits / NBBY;
1690 1690
1691 1691 if (bits % NBBY != 0 ||
1692 1692 off % NBBY != 0 ||
1693 1693 size > 8 ||
1694 1694 size != mdb_ctf_type_size(base))
1695 1695 mdb_printf(" :%d", bits);
1696 1696 }
1697 1697 }
1698 1698
1699 1699 if (depth != 0 ||
1700 1700 ((pap->pa_flags & PA_SHOWNAME) && pap->pa_prefix != NULL))
1701 1701 mdb_printf("%s ", pap->pa_flags & PA_SHOWVAL ? " =" : "");
1702 1702
1703 1703 if (depth == 0 && pap->pa_prefix != NULL)
1704 1704 name = pap->pa_prefix;
1705 1705
1706 1706 pap->pa_depth = depth;
1707 1707 if (kind <= CTF_K_UNKNOWN || kind >= CTF_K_TYPEDEF) {
1708 1708 mdb_warn("unknown ctf for %s type %s kind %d\n",
1709 1709 name, type, kind);
1710 1710 return (-1);
1711 1711 }
1712 1712 rc = printfuncs[kind - 1](type, name, id, base, off, pap);
1713 1713
1714 1714 if (rc != 0)
1715 1715 mdb_iob_discard(mdb.m_out);
1716 1716 else
1717 1717 mdb_iob_puts(mdb.m_out, pap->pa_delim);
1718 1718
1719 1719 return (rc);
1720 1720 }
1721 1721
1722 1722 /*
1723 1723 * Special semantics for pipelines.
1724 1724 */
1725 1725 static int
1726 1726 pipe_print(mdb_ctf_id_t id, ulong_t off, void *data)
1727 1727 {
1728 1728 printarg_t *pap = data;
1729 1729 ssize_t size;
1730 1730 static const char *const fsp[] = { "%#r", "%#r", "%#r", "%#llr" };
1731 1731 uintptr_t value;
1732 1732 uintptr_t addr = pap->pa_addr + off / NBBY;
1733 1733 mdb_ctf_id_t base;
1734 1734 int enum_value;
1735 1735 ctf_encoding_t e;
1736 1736
1737 1737 union {
1738 1738 uint64_t i8;
1739 1739 uint32_t i4;
1740 1740 uint16_t i2;
1741 1741 uint8_t i1;
1742 1742 } u;
1743 1743
1744 1744 if (mdb_ctf_type_resolve(id, &base) == -1) {
1745 1745 mdb_warn("could not resolve type");
1746 1746 return (-1);
1747 1747 }
1748 1748
1749 1749 /*
1750 1750 * If the user gives -a, then always print out the address of the
1751 1751 * member.
1752 1752 */
1753 1753 if ((pap->pa_flags & PA_SHOWADDR)) {
1754 1754 mdb_printf("%#lr\n", addr);
1755 1755 return (0);
1756 1756 }
1757 1757
1758 1758 again:
1759 1759 switch (mdb_ctf_type_kind(base)) {
1760 1760 case CTF_K_POINTER:
1761 1761 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as,
1762 1762 &value, sizeof (value), addr) != sizeof (value)) {
1763 1763 mdb_warn("failed to read pointer at %p", addr);
1764 1764 return (-1);
1765 1765 }
1766 1766 mdb_printf("%#lr\n", value);
1767 1767 break;
1768 1768
1769 1769 case CTF_K_ENUM:
1770 1770 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &enum_value,
1771 1771 sizeof (enum_value), addr) != sizeof (enum_value)) {
1772 1772 mdb_warn("failed to read enum at %llx", addr);
1773 1773 return (-1);
1774 1774 }
1775 1775 mdb_printf("%#r\n", enum_value);
1776 1776 break;
1777 1777
1778 1778 case CTF_K_INTEGER:
1779 1779 if (mdb_ctf_type_encoding(base, &e) != 0) {
1780 1780 mdb_warn("could not get type encoding\n");
1781 1781 return (-1);
1782 1782 }
1783 1783
1784 1784 /*
1785 1785 * For immediate values, we just print out the value.
1786 1786 */
1787 1787 size = e.cte_bits / NBBY;
1788 1788 if (size > 8 || (e.cte_bits % NBBY) != 0 ||
1789 1789 (size & (size - 1)) != 0) {
1790 1790 return (print_bitfield(off, pap, &e));
1791 1791 }
1792 1792
1793 1793 if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.i8, size,
1794 1794 addr) != size) {
1795 1795 mdb_warn("failed to read %lu bytes at %p",
1796 1796 (ulong_t)size, pap->pa_addr);
1797 1797 return (-1);
1798 1798 }
1799 1799
1800 1800 switch (size) {
1801 1801 case sizeof (uint8_t):
1802 1802 mdb_printf(fsp[0], u.i1);
1803 1803 break;
1804 1804 case sizeof (uint16_t):
1805 1805 mdb_printf(fsp[1], u.i2);
1806 1806 break;
1807 1807 case sizeof (uint32_t):
1808 1808 mdb_printf(fsp[2], u.i4);
1809 1809 break;
1810 1810 case sizeof (uint64_t):
1811 1811 mdb_printf(fsp[3], u.i8);
1812 1812 break;
1813 1813 }
1814 1814 mdb_printf("\n");
1815 1815 break;
1816 1816
1817 1817 case CTF_K_FUNCTION:
1818 1818 case CTF_K_FLOAT:
1819 1819 case CTF_K_ARRAY:
1820 1820 case CTF_K_UNKNOWN:
1821 1821 case CTF_K_STRUCT:
1822 1822 case CTF_K_UNION:
1823 1823 case CTF_K_FORWARD:
1824 1824 /*
1825 1825 * For these types, always print the address of the member
1826 1826 */
1827 1827 mdb_printf("%#lr\n", addr);
1828 1828 break;
1829 1829
1830 1830 default:
1831 1831 mdb_warn("unknown type %d", mdb_ctf_type_kind(base));
1832 1832 break;
1833 1833 }
1834 1834
1835 1835 return (0);
1836 1836 }
1837 1837
1838 1838 static int
1839 1839 parse_delimiter(char **strp)
1840 1840 {
1841 1841 switch (**strp) {
1842 1842 case '\0':
1843 1843 return (MEMBER_DELIM_DONE);
1844 1844
1845 1845 case '.':
1846 1846 *strp = *strp + 1;
1847 1847 return (MEMBER_DELIM_DOT);
1848 1848
1849 1849 case '[':
1850 1850 *strp = *strp + 1;
1851 1851 return (MEMBER_DELIM_LBR);
1852 1852
1853 1853 case '-':
1854 1854 *strp = *strp + 1;
1855 1855 if (**strp == '>') {
1856 1856 *strp = *strp + 1;
1857 1857 return (MEMBER_DELIM_PTR);
1858 1858 }
1859 1859 *strp = *strp - 1;
1860 1860 /*FALLTHROUGH*/
1861 1861 default:
1862 1862 return (MEMBER_DELIM_ERR);
1863 1863 }
1864 1864 }
1865 1865
1866 1866 static int
1867 1867 deref(printarg_t *pap, size_t size)
1868 1868 {
1869 1869 uint32_t a32;
1870 1870 mdb_tgt_as_t as = pap->pa_as;
1871 1871 mdb_tgt_addr_t *ap = &pap->pa_addr;
1872 1872
1873 1873 if (size == sizeof (mdb_tgt_addr_t)) {
1874 1874 if (mdb_tgt_aread(mdb.m_target, as, ap, size, *ap) == -1) {
1875 1875 mdb_warn("could not dereference pointer %llx\n", *ap);
1876 1876 return (-1);
1877 1877 }
1878 1878 } else {
1879 1879 if (mdb_tgt_aread(mdb.m_target, as, &a32, size, *ap) == -1) {
1880 1880 mdb_warn("could not dereference pointer %x\n", *ap);
1881 1881 return (-1);
1882 1882 }
1883 1883
1884 1884 *ap = (mdb_tgt_addr_t)a32;
1885 1885 }
1886 1886
1887 1887 /*
1888 1888 * We've dereferenced at least once, we must be on the real
1889 1889 * target. If we were in the immediate target, reset to the real
1890 1890 * target; it's reset as needed when we return to the print
1891 1891 * routines.
1892 1892 */
1893 1893 if (pap->pa_tgt == pap->pa_immtgt)
1894 1894 pap->pa_tgt = pap->pa_realtgt;
1895 1895
1896 1896 return (0);
1897 1897 }
1898 1898
1899 1899 static int
1900 1900 parse_member(printarg_t *pap, const char *str, mdb_ctf_id_t id,
1901 1901 mdb_ctf_id_t *idp, ulong_t *offp, int *last_deref)
1902 1902 {
1903 1903 int delim;
1904 1904 char member[64];
1905 1905 char buf[128];
1906 1906 uint_t index;
1907 1907 char *start = (char *)str;
1908 1908 char *end;
1909 1909 ulong_t off = 0;
1910 1910 mdb_ctf_arinfo_t ar;
1911 1911 mdb_ctf_id_t rid;
1912 1912 int kind;
1913 1913 ssize_t size;
1914 1914 int non_array = FALSE;
1915 1915
1916 1916 /*
1917 1917 * id always has the unresolved type for printing error messages
1918 1918 * that include the type; rid always has the resolved type for
1919 1919 * use in mdb_ctf_* calls. It is possible for this command to fail,
1920 1920 * however, if the resolved type is in the parent and it is currently
1921 1921 * unavailable. Note that we also can't print out the name of the
1922 1922 * type, since that would also rely on looking up the resolved name.
1923 1923 */
1924 1924 if (mdb_ctf_type_resolve(id, &rid) != 0) {
1925 1925 mdb_warn("failed to resolve type");
1926 1926 return (-1);
1927 1927 }
1928 1928
1929 1929 delim = parse_delimiter(&start);
1930 1930 /*
1931 1931 * If the user fails to specify an initial delimiter, guess -> for
1932 1932 * pointer types and . for non-pointer types.
1933 1933 */
1934 1934 if (delim == MEMBER_DELIM_ERR)
1935 1935 delim = (mdb_ctf_type_kind(rid) == CTF_K_POINTER) ?
1936 1936 MEMBER_DELIM_PTR : MEMBER_DELIM_DOT;
1937 1937
1938 1938 *last_deref = FALSE;
1939 1939
1940 1940 while (delim != MEMBER_DELIM_DONE) {
1941 1941 switch (delim) {
1942 1942 case MEMBER_DELIM_PTR:
1943 1943 kind = mdb_ctf_type_kind(rid);
1944 1944 if (kind != CTF_K_POINTER) {
1945 1945 mdb_warn("%s is not a pointer type\n",
1946 1946 mdb_ctf_type_name(id, buf, sizeof (buf)));
1947 1947 return (-1);
1948 1948 }
1949 1949
1950 1950 size = mdb_ctf_type_size(id);
1951 1951 if (deref(pap, size) != 0)
1952 1952 return (-1);
1953 1953
1954 1954 (void) mdb_ctf_type_reference(rid, &id);
1955 1955 (void) mdb_ctf_type_resolve(id, &rid);
1956 1956
1957 1957 off = 0;
1958 1958 break;
1959 1959
1960 1960 case MEMBER_DELIM_DOT:
1961 1961 kind = mdb_ctf_type_kind(rid);
1962 1962 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
1963 1963 mdb_warn("%s is not a struct or union type\n",
1964 1964 mdb_ctf_type_name(id, buf, sizeof (buf)));
1965 1965 return (-1);
1966 1966 }
1967 1967 break;
1968 1968
1969 1969 case MEMBER_DELIM_LBR:
1970 1970 end = strchr(start, ']');
1971 1971 if (end == NULL) {
1972 1972 mdb_warn("no trailing ']'\n");
1973 1973 return (-1);
1974 1974 }
1975 1975
1976 1976 (void) mdb_snprintf(member, end - start + 1, "%s",
1977 1977 start);
1978 1978
1979 1979 index = mdb_strtoull(member);
1980 1980
1981 1981 switch (mdb_ctf_type_kind(rid)) {
1982 1982 case CTF_K_POINTER:
1983 1983 size = mdb_ctf_type_size(rid);
1984 1984
1985 1985 if (deref(pap, size) != 0)
1986 1986 return (-1);
1987 1987
1988 1988 (void) mdb_ctf_type_reference(rid, &id);
1989 1989 (void) mdb_ctf_type_resolve(id, &rid);
1990 1990
1991 1991 size = mdb_ctf_type_size(id);
1992 1992 if (size <= 0) {
1993 1993 mdb_warn("cannot dereference void "
1994 1994 "type\n");
1995 1995 return (-1);
1996 1996 }
1997 1997
1998 1998 pap->pa_addr += index * size;
1999 1999 off = 0;
2000 2000
2001 2001 if (index == 0 && non_array)
2002 2002 *last_deref = TRUE;
2003 2003 break;
2004 2004
2005 2005 case CTF_K_ARRAY:
2006 2006 (void) mdb_ctf_array_info(rid, &ar);
2007 2007
2008 2008 if (index >= ar.mta_nelems) {
2009 2009 mdb_warn("index %r is outside of "
2010 2010 "array bounds [0 .. %r]\n",
2011 2011 index, ar.mta_nelems - 1);
2012 2012 }
2013 2013
2014 2014 id = ar.mta_contents;
2015 2015 (void) mdb_ctf_type_resolve(id, &rid);
2016 2016
2017 2017 size = mdb_ctf_type_size(id);
2018 2018 if (size <= 0) {
2019 2019 mdb_warn("cannot dereference void "
2020 2020 "type\n");
2021 2021 return (-1);
2022 2022 }
2023 2023
2024 2024 pap->pa_addr += index * size;
2025 2025 off = 0;
2026 2026 break;
2027 2027
2028 2028 default:
2029 2029 mdb_warn("cannot index into non-array, "
2030 2030 "non-pointer type\n");
2031 2031 return (-1);
2032 2032 }
2033 2033
2034 2034 start = end + 1;
2035 2035 delim = parse_delimiter(&start);
2036 2036 continue;
2037 2037
2038 2038 case MEMBER_DELIM_ERR:
2039 2039 default:
2040 2040 mdb_warn("'%c' is not a valid delimiter\n", *start);
2041 2041 return (-1);
2042 2042 }
2043 2043
2044 2044 *last_deref = FALSE;
2045 2045 non_array = TRUE;
2046 2046
2047 2047 /*
2048 2048 * Find the end of the member name; assume that a member
2049 2049 * name is at least one character long.
2050 2050 */
2051 2051 for (end = start + 1; isalnum(*end) || *end == '_'; end++)
2052 2052 continue;
2053 2053
2054 2054 (void) mdb_snprintf(member, end - start + 1, "%s", start);
2055 2055
2056 2056 if (mdb_ctf_member_info(rid, member, &off, &id) != 0) {
2057 2057 mdb_warn("failed to find member %s of %s", member,
2058 2058 mdb_ctf_type_name(id, buf, sizeof (buf)));
2059 2059 return (-1);
2060 2060 }
2061 2061 (void) mdb_ctf_type_resolve(id, &rid);
2062 2062
2063 2063 pap->pa_addr += off / NBBY;
2064 2064
2065 2065 start = end;
2066 2066 delim = parse_delimiter(&start);
2067 2067 }
2068 2068
2069 2069 *idp = id;
2070 2070 *offp = off;
2071 2071
2072 2072 return (0);
2073 2073 }
2074 2074
2075 2075 static int
2076 2076 cmd_print_tab_common(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
2077 2077 const mdb_arg_t *argv)
2078 2078 {
2079 2079 char tn[MDB_SYM_NAMLEN];
2080 2080 char member[64];
2081 2081 int delim, kind;
2082 2082 int ret = 0;
2083 2083 mdb_ctf_id_t id, rid;
2084 2084 mdb_ctf_arinfo_t ar;
2085 2085 char *start, *end;
2086 2086 ulong_t dul;
2087 2087
2088 2088 if (argc == 0 && !(flags & DCMD_TAB_SPACE))
2089 2089 return (0);
2090 2090
2091 2091 if (argc == 0 && (flags & DCMD_TAB_SPACE))
2092 2092 return (mdb_tab_complete_type(mcp, NULL, MDB_TABC_NOPOINT |
2093 2093 MDB_TABC_NOARRAY));
2094 2094
2095 2095 if ((ret = mdb_tab_typename(&argc, &argv, tn, sizeof (tn))) < 0)
2096 2096 return (ret);
2097 2097
2098 2098 if (argc == 1 && (!(flags & DCMD_TAB_SPACE) || ret == 1))
2099 2099 return (mdb_tab_complete_type(mcp, tn, MDB_TABC_NOPOINT |
2100 2100 MDB_TABC_NOARRAY));
2101 2101
2102 2102 if (argc == 1 && (flags & DCMD_TAB_SPACE))
2103 2103 return (mdb_tab_complete_member(mcp, tn, NULL));
2104 2104
2105 2105 /*
2106 2106 * This is the reason that tab completion was created. We're going to go
2107 2107 * along and walk the delimiters until we find something a member that
2108 2108 * we don't recognize, at which point we'll try and tab complete it.
2109 2109 * Note that ::print takes multiple args, so this is going to operate on
2110 2110 * whatever the last arg that we have is.
2111 2111 */
2112 2112 if (mdb_ctf_lookup_by_name(tn, &id) != 0)
2113 2113 return (1);
2114 2114
2115 2115 (void) mdb_ctf_type_resolve(id, &rid);
2116 2116 start = (char *)argv[argc-1].a_un.a_str;
2117 2117 delim = parse_delimiter(&start);
2118 2118
2119 2119 /*
2120 2120 * If we hit the case where we actually have no delimiters, than we need
2121 2121 * to make sure that we properly set up the fields the loops would.
2122 2122 */
2123 2123 if (delim == MEMBER_DELIM_DONE)
2124 2124 (void) mdb_snprintf(member, sizeof (member), "%s", start);
2125 2125
2126 2126 while (delim != MEMBER_DELIM_DONE) {
2127 2127 switch (delim) {
2128 2128 case MEMBER_DELIM_PTR:
2129 2129 kind = mdb_ctf_type_kind(rid);
2130 2130 if (kind != CTF_K_POINTER)
2131 2131 return (1);
2132 2132
2133 2133 (void) mdb_ctf_type_reference(rid, &id);
2134 2134 (void) mdb_ctf_type_resolve(id, &rid);
2135 2135 break;
2136 2136 case MEMBER_DELIM_DOT:
2137 2137 kind = mdb_ctf_type_kind(rid);
2138 2138 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
2139 2139 return (1);
2140 2140 break;
2141 2141 case MEMBER_DELIM_LBR:
2142 2142 end = strchr(start, ']');
2143 2143 /*
2144 2144 * We're not going to try and tab complete the indexes
2145 2145 * here. So for now, punt on it. Also, we're not going
2146 2146 * to try and validate you're within the bounds, just
2147 2147 * that you get the type you asked for.
2148 2148 */
2149 2149 if (end == NULL)
2150 2150 return (1);
2151 2151
2152 2152 switch (mdb_ctf_type_kind(rid)) {
2153 2153 case CTF_K_POINTER:
2154 2154 (void) mdb_ctf_type_reference(rid, &id);
2155 2155 (void) mdb_ctf_type_resolve(id, &rid);
2156 2156 break;
2157 2157 case CTF_K_ARRAY:
2158 2158 (void) mdb_ctf_array_info(rid, &ar);
2159 2159 id = ar.mta_contents;
2160 2160 (void) mdb_ctf_type_resolve(id, &rid);
2161 2161 break;
2162 2162 default:
2163 2163 return (1);
2164 2164 }
2165 2165
2166 2166 start = end + 1;
2167 2167 delim = parse_delimiter(&start);
2168 2168 break;
2169 2169 case MEMBER_DELIM_ERR:
2170 2170 default:
2171 2171 break;
2172 2172 }
2173 2173
2174 2174 for (end = start + 1; isalnum(*end) || *end == '_'; end++)
2175 2175 continue;
2176 2176
2177 2177 (void) mdb_snprintf(member, end - start + 1, start);
2178 2178
2179 2179 /*
2180 2180 * We are going to try to resolve this name as a member. There
2181 2181 * are a few two different questions that we need to answer. The
2182 2182 * first is do we recognize this member. The second is are we at
2183 2183 * the end of the string. If we encounter a member that we don't
2184 2184 * recognize before the end, then we have to error out and can't
2185 2185 * complete it. But if there are no more delimiters then we can
2186 2186 * try and complete it.
2187 2187 */
2188 2188 ret = mdb_ctf_member_info(rid, member, &dul, &id);
2189 2189 start = end;
2190 2190 delim = parse_delimiter(&start);
2191 2191 if (ret != 0 && errno == EMDB_CTFNOMEMB) {
2192 2192 if (delim != MEMBER_DELIM_DONE)
2193 2193 return (1);
2194 2194 continue;
2195 2195 } else if (ret != 0)
2196 2196 return (1);
2197 2197
2198 2198 if (delim == MEMBER_DELIM_DONE)
2199 2199 return (mdb_tab_complete_member_by_id(mcp, rid,
2200 2200 member));
2201 2201
2202 2202 (void) mdb_ctf_type_resolve(id, &rid);
2203 2203 }
2204 2204
2205 2205 /*
2206 2206 * If we've reached here, then we need to try and tab complete the last
2207 2207 * field, which is currently member, based on the ctf type id that we
2208 2208 * already have in rid.
2209 2209 */
2210 2210 return (mdb_tab_complete_member_by_id(mcp, rid, member));
2211 2211 }
2212 2212
2213 2213 int
2214 2214 cmd_print_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
2215 2215 const mdb_arg_t *argv)
2216 2216 {
2217 2217 int i, dummy;
2218 2218
2219 2219 /*
2220 2220 * This getopts is only here to make the tab completion work better when
2221 2221 * including options in the ::print arguments. None of the values should
2222 2222 * be used. This should only be updated with additional arguments, if
2223 2223 * they are added to cmd_print.
2224 2224 */
2225 2225 i = mdb_getopts(argc, argv,
2226 2226 'a', MDB_OPT_SETBITS, PA_SHOWADDR, &dummy,
2227 2227 'C', MDB_OPT_SETBITS, TRUE, &dummy,
2228 2228 'c', MDB_OPT_UINTPTR, &dummy,
2229 2229 'd', MDB_OPT_SETBITS, PA_INTDEC, &dummy,
2230 2230 'h', MDB_OPT_SETBITS, PA_SHOWHOLES, &dummy,
2231 2231 'i', MDB_OPT_SETBITS, TRUE, &dummy,
2232 2232 'L', MDB_OPT_SETBITS, TRUE, &dummy,
2233 2233 'l', MDB_OPT_UINTPTR, &dummy,
2234 2234 'n', MDB_OPT_SETBITS, PA_NOSYMBOLIC, &dummy,
2235 2235 'p', MDB_OPT_SETBITS, TRUE, &dummy,
2236 2236 's', MDB_OPT_UINTPTR, &dummy,
2237 2237 'T', MDB_OPT_SETBITS, PA_SHOWTYPE | PA_SHOWBASETYPE, &dummy,
2238 2238 't', MDB_OPT_SETBITS, PA_SHOWTYPE, &dummy,
2239 2239 'x', MDB_OPT_SETBITS, PA_INTHEX, &dummy,
2240 2240 NULL);
2241 2241
2242 2242 argc -= i;
2243 2243 argv += i;
2244 2244
2245 2245 return (cmd_print_tab_common(mcp, flags, argc, argv));
2246 2246 }
2247 2247
2248 2248 /*
2249 2249 * Recursively descend a print a given data structure. We create a struct of
2250 2250 * the relevant print arguments and then call mdb_ctf_type_visit() to do the
2251 2251 * traversal, using elt_print() as the callback for each element.
2252 2252 */
2253 2253 /*ARGSUSED*/
2254 2254 int
2255 2255 cmd_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2256 2256 {
2257 2257 uintptr_t opt_c = MDB_ARR_NOLIMIT, opt_l = MDB_ARR_NOLIMIT;
2258 2258 uint_t opt_C = FALSE, opt_L = FALSE, opt_p = FALSE, opt_i = FALSE;
2259 2259 uintptr_t opt_s = (uintptr_t)-1ul;
2260 2260 int uflags = (flags & DCMD_ADDRSPEC) ? PA_SHOWVAL : 0;
2261 2261 mdb_ctf_id_t id;
2262 2262 int err = DCMD_OK;
2263 2263
2264 2264 mdb_tgt_t *t = mdb.m_target;
2265 2265 printarg_t pa;
2266 2266 int d, i;
2267 2267
2268 2268 char s_name[MDB_SYM_NAMLEN];
2269 2269 mdb_syminfo_t s_info;
2270 2270 GElf_Sym sym;
2271 2271
2272 2272 /*
2273 2273 * If a new option is added, make sure the getopts above in
2274 2274 * cmd_print_tab is also updated.
2275 2275 */
2276 2276 i = mdb_getopts(argc, argv,
2277 2277 'a', MDB_OPT_SETBITS, PA_SHOWADDR, &uflags,
2278 2278 'C', MDB_OPT_SETBITS, TRUE, &opt_C,
2279 2279 'c', MDB_OPT_UINTPTR, &opt_c,
2280 2280 'd', MDB_OPT_SETBITS, PA_INTDEC, &uflags,
2281 2281 'h', MDB_OPT_SETBITS, PA_SHOWHOLES, &uflags,
2282 2282 'i', MDB_OPT_SETBITS, TRUE, &opt_i,
2283 2283 'L', MDB_OPT_SETBITS, TRUE, &opt_L,
2284 2284 'l', MDB_OPT_UINTPTR, &opt_l,
2285 2285 'n', MDB_OPT_SETBITS, PA_NOSYMBOLIC, &uflags,
2286 2286 'p', MDB_OPT_SETBITS, TRUE, &opt_p,
2287 2287 's', MDB_OPT_UINTPTR, &opt_s,
2288 2288 'T', MDB_OPT_SETBITS, PA_SHOWTYPE | PA_SHOWBASETYPE, &uflags,
2289 2289 't', MDB_OPT_SETBITS, PA_SHOWTYPE, &uflags,
2290 2290 'x', MDB_OPT_SETBITS, PA_INTHEX, &uflags,
2291 2291 NULL);
2292 2292
2293 2293 if (uflags & PA_INTHEX)
2294 2294 uflags &= ~PA_INTDEC; /* -x and -d are mutually exclusive */
2295 2295
2296 2296 uflags |= PA_SHOWNAME;
2297 2297
2298 2298 if (opt_p && opt_i) {
2299 2299 mdb_warn("-p and -i options are incompatible\n");
2300 2300 return (DCMD_ERR);
2301 2301 }
2302 2302
2303 2303 argc -= i;
2304 2304 argv += i;
2305 2305
2306 2306 if (argc != 0 && argv->a_type == MDB_TYPE_STRING) {
2307 2307 const char *t_name = s_name;
2308 2308 int ret;
2309 2309
2310 2310 if (strchr("+-", argv->a_un.a_str[0]) != NULL)
2311 2311 return (DCMD_USAGE);
2312 2312
2313 2313 if ((ret = args_to_typename(&argc, &argv, s_name,
2314 2314 sizeof (s_name))) != 0)
2315 2315 return (ret);
2316 2316
2317 2317 if (mdb_ctf_lookup_by_name(t_name, &id) != 0) {
2318 2318 if (!(flags & DCMD_ADDRSPEC) || opt_i ||
2319 2319 addr_to_sym(t, addr, s_name, sizeof (s_name),
2320 2320 &sym, &s_info) == NULL ||
2321 2321 mdb_ctf_lookup_by_symbol(&sym, &s_info, &id) != 0) {
2322 2322
2323 2323 mdb_warn("failed to look up type %s", t_name);
2324 2324 return (DCMD_ABORT);
2325 2325 }
2326 2326 } else {
2327 2327 argc--;
2328 2328 argv++;
2329 2329 }
2330 2330
2331 2331 } else if (!(flags & DCMD_ADDRSPEC) || opt_i) {
2332 2332 return (DCMD_USAGE);
2333 2333
2334 2334 } else if (addr_to_sym(t, addr, s_name, sizeof (s_name),
2335 2335 &sym, &s_info) == NULL) {
2336 2336 mdb_warn("no symbol information for %a", addr);
2337 2337 return (DCMD_ERR);
2338 2338
2339 2339 } else if (mdb_ctf_lookup_by_symbol(&sym, &s_info, &id) != 0) {
2340 2340 mdb_warn("no type data available for %a [%u]", addr,
2341 2341 s_info.sym_id);
2342 2342 return (DCMD_ERR);
2343 2343 }
2344 2344
2345 2345 pa.pa_tgt = mdb.m_target;
2346 2346 pa.pa_realtgt = pa.pa_tgt;
2347 2347 pa.pa_immtgt = NULL;
2348 2348 pa.pa_as = opt_p ? MDB_TGT_AS_PHYS : MDB_TGT_AS_VIRT;
2349 2349 pa.pa_armemlim = mdb.m_armemlim;
2350 2350 pa.pa_arstrlim = mdb.m_arstrlim;
2351 2351 pa.pa_delim = "\n";
2352 2352 pa.pa_flags = uflags;
2353 2353 pa.pa_nest = 0;
2354 2354 pa.pa_tab = 4;
2355 2355 pa.pa_prefix = NULL;
2356 2356 pa.pa_suffix = NULL;
2357 2357 pa.pa_holes = NULL;
2358 2358 pa.pa_nholes = 0;
2359 2359 pa.pa_depth = 0;
2360 2360 pa.pa_maxdepth = opt_s;
2361 2361 pa.pa_nooutdepth = (uint_t)-1;
2362 2362
2363 2363 if ((flags & DCMD_ADDRSPEC) && !opt_i)
2364 2364 pa.pa_addr = opt_p ? mdb_get_dot() : addr;
2365 2365 else
2366 2366 pa.pa_addr = NULL;
2367 2367
2368 2368 if (opt_i) {
2369 2369 const char *vargv[2];
2370 2370 uintmax_t dot = mdb_get_dot();
2371 2371 size_t outsize = mdb_ctf_type_size(id);
2372 2372 vargv[0] = (const char *)˙
2373 2373 vargv[1] = (const char *)&outsize;
2374 2374 pa.pa_immtgt = mdb_tgt_create(mdb_value_tgt_create,
2375 2375 0, 2, vargv);
2376 2376 pa.pa_tgt = pa.pa_immtgt;
2377 2377 }
2378 2378
2379 2379 if (opt_c != MDB_ARR_NOLIMIT)
2380 2380 pa.pa_arstrlim = opt_c;
2381 2381 if (opt_C)
2382 2382 pa.pa_arstrlim = MDB_ARR_NOLIMIT;
2383 2383 if (opt_l != MDB_ARR_NOLIMIT)
2384 2384 pa.pa_armemlim = opt_l;
2385 2385 if (opt_L)
2386 2386 pa.pa_armemlim = MDB_ARR_NOLIMIT;
2387 2387
2388 2388 if (argc > 0) {
2389 2389 for (i = 0; i < argc; i++) {
2390 2390 mdb_ctf_id_t mid;
2391 2391 int last_deref;
2392 2392 ulong_t off;
2393 2393 int kind;
2394 2394 char buf[MDB_SYM_NAMLEN];
2395 2395
2396 2396 mdb_tgt_t *oldtgt = pa.pa_tgt;
2397 2397 mdb_tgt_as_t oldas = pa.pa_as;
2398 2398 mdb_tgt_addr_t oldaddr = pa.pa_addr;
2399 2399
2400 2400 if (argv->a_type == MDB_TYPE_STRING) {
2401 2401 const char *member = argv[i].a_un.a_str;
2402 2402 mdb_ctf_id_t rid;
2403 2403
2404 2404 if (parse_member(&pa, member, id, &mid,
2405 2405 &off, &last_deref) != 0) {
2406 2406 err = DCMD_ABORT;
2407 2407 goto out;
2408 2408 }
2409 2409
2410 2410 /*
2411 2411 * If the member string ends with a "[0]"
2412 2412 * (last_deref * is true) and the type is a
2413 2413 * structure or union, * print "->" rather
2414 2414 * than "[0]." in elt_print.
2415 2415 */
2416 2416 (void) mdb_ctf_type_resolve(mid, &rid);
2417 2417 kind = mdb_ctf_type_kind(rid);
2418 2418 if (last_deref && IS_SOU(kind)) {
2419 2419 char *end;
2420 2420 (void) mdb_snprintf(buf, sizeof (buf),
2421 2421 "%s", member);
2422 2422 end = strrchr(buf, '[');
2423 2423 *end = '\0';
2424 2424 pa.pa_suffix = "->";
2425 2425 member = &buf[0];
2426 2426 } else if (IS_SOU(kind)) {
2427 2427 pa.pa_suffix = ".";
2428 2428 } else {
2429 2429 pa.pa_suffix = "";
2430 2430 }
2431 2431
2432 2432 pa.pa_prefix = member;
2433 2433 } else {
2434 2434 ulong_t moff;
2435 2435
2436 2436 moff = (ulong_t)argv[i].a_un.a_val;
2437 2437
2438 2438 if (mdb_ctf_offset_to_name(id, moff * NBBY,
2439 2439 buf, sizeof (buf), 0, &mid, &off) == -1) {
2440 2440 mdb_warn("invalid offset %lx\n", moff);
2441 2441 err = DCMD_ABORT;
2442 2442 goto out;
2443 2443 }
2444 2444
2445 2445 pa.pa_prefix = buf;
2446 2446 pa.pa_addr += moff - off / NBBY;
2447 2447 pa.pa_suffix = strlen(buf) == 0 ? "" : ".";
2448 2448 }
2449 2449
2450 2450 off %= NBBY;
2451 2451 if (flags & DCMD_PIPE_OUT) {
2452 2452 if (pipe_print(mid, off, &pa) != 0) {
2453 2453 mdb_warn("failed to print type");
2454 2454 err = DCMD_ERR;
2455 2455 goto out;
2456 2456 }
2457 2457 } else if (off != 0) {
2458 2458 mdb_ctf_id_t base;
2459 2459 (void) mdb_ctf_type_resolve(mid, &base);
2460 2460
2461 2461 if (elt_print("", mid, base, off, 0,
2462 2462 &pa) != 0) {
2463 2463 mdb_warn("failed to print type");
2464 2464 err = DCMD_ERR;
2465 2465 goto out;
2466 2466 }
2467 2467 } else {
2468 2468 if (mdb_ctf_type_visit(mid, elt_print,
2469 2469 &pa) == -1) {
2470 2470 mdb_warn("failed to print type");
2471 2471 err = DCMD_ERR;
2472 2472 goto out;
2473 2473 }
2474 2474
2475 2475 for (d = pa.pa_depth - 1; d >= 0; d--)
2476 2476 print_close_sou(&pa, d);
2477 2477 }
2478 2478
2479 2479 pa.pa_depth = 0;
2480 2480 pa.pa_tgt = oldtgt;
2481 2481 pa.pa_as = oldas;
2482 2482 pa.pa_addr = oldaddr;
2483 2483 pa.pa_delim = "\n";
2484 2484 }
2485 2485
2486 2486 } else if (flags & DCMD_PIPE_OUT) {
2487 2487 if (pipe_print(id, 0, &pa) != 0) {
2488 2488 mdb_warn("failed to print type");
2489 2489 err = DCMD_ERR;
2490 2490 goto out;
2491 2491 }
2492 2492 } else {
2493 2493 if (mdb_ctf_type_visit(id, elt_print, &pa) == -1) {
2494 2494 mdb_warn("failed to print type");
2495 2495 err = DCMD_ERR;
2496 2496 goto out;
2497 2497 }
2498 2498
2499 2499 for (d = pa.pa_depth - 1; d >= 0; d--)
2500 2500 print_close_sou(&pa, d);
2501 2501 }
2502 2502
2503 2503 mdb_set_dot(addr + mdb_ctf_type_size(id));
2504 2504 err = DCMD_OK;
2505 2505 out:
2506 2506 if (pa.pa_immtgt)
2507 2507 mdb_tgt_destroy(pa.pa_immtgt);
2508 2508 return (err);
2509 2509 }
2510 2510
2511 2511 void
2512 2512 print_help(void)
2513 2513 {
2514 2514 mdb_printf(
2515 2515 "-a show address of object\n"
2516 2516 "-C unlimit the length of character arrays\n"
2517 2517 "-c limit limit the length of character arrays\n"
2518 2518 "-d output values in decimal\n"
2519 2519 "-h print holes in structures\n"
2520 2520 "-i interpret address as data of the given type\n"
2521 2521 "-L unlimit the length of standard arrays\n"
2522 2522 "-l limit limit the length of standard arrays\n"
2523 2523 "-n don't print pointers as symbol offsets\n"
2524 2524 "-p interpret address as a physical memory address\n"
2525 2525 "-s depth limit the recursion depth\n"
2526 2526 "-T show type and <<base type>> of object\n"
2527 2527 "-t show type of object\n"
2528 2528 "-x output values in hexadecimal\n"
2529 2529 "\n"
2530 2530 "type may be omitted if the C type of addr can be inferred.\n"
2531 2531 "\n"
2532 2532 "Members may be specified with standard C syntax using the\n"
2533 2533 "array indexing operator \"[index]\", structure member\n"
2534 2534 "operator \".\", or structure pointer operator \"->\".\n"
2535 2535 "\n"
2536 2536 "Offsets must use the $[ expression ] syntax\n");
2537 2537 }
2538 2538
2539 2539 static int
2540 2540 printf_signed(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt,
2541 2541 boolean_t sign)
2542 2542 {
2543 2543 ssize_t size;
2544 2544 mdb_ctf_id_t base;
2545 2545 ctf_encoding_t e;
2546 2546
2547 2547 union {
2548 2548 uint64_t ui8;
2549 2549 uint32_t ui4;
2550 2550 uint16_t ui2;
2551 2551 uint8_t ui1;
2552 2552 int64_t i8;
↓ open down ↓ |
2552 lines elided |
↑ open up ↑ |
2553 2553 int32_t i4;
2554 2554 int16_t i2;
2555 2555 int8_t i1;
2556 2556 } u;
2557 2557
2558 2558 if (mdb_ctf_type_resolve(id, &base) == -1) {
2559 2559 mdb_warn("could not resolve type");
2560 2560 return (DCMD_ABORT);
2561 2561 }
2562 2562
2563 - if (mdb_ctf_type_kind(base) != CTF_K_INTEGER) {
2564 - mdb_warn("expected integer type\n");
2565 - return (DCMD_ABORT);
2566 - }
2567 -
2568 - if (mdb_ctf_type_encoding(base, &e) != 0) {
2569 - mdb_warn("could not get type encoding");
2570 - return (DCMD_ABORT);
2563 + switch (mdb_ctf_type_kind(base)) {
2564 + case CTF_K_ENUM:
2565 + e.cte_format = CTF_INT_SIGNED;
2566 + e.cte_offset = 0;
2567 + e.cte_bits = sizeof(int) * NBBY; /* XXX: get size from CTF? */
2568 + break;
2569 + case CTF_K_INTEGER:
2570 + if (mdb_ctf_type_encoding(base, &e) != 0) {
2571 + mdb_warn("could not get type encoding");
2572 + return (DCMD_ABORT);
2573 + }
2574 + break;
2575 + default:
2576 + mdb_warn("expected integer type\n");
2577 + return (DCMD_ABORT);
2571 2578 }
2572 2579
2573 2580 if (sign)
2574 2581 sign = e.cte_format & CTF_INT_SIGNED;
2575 2582
2576 2583 size = e.cte_bits / NBBY;
2577 2584
2578 2585 /*
2579 2586 * Check to see if our life has been complicated by the presence of
2580 2587 * a bitfield. If it has, we will print it using logic that is only
2581 2588 * slightly different than that found in print_bitfield(), above. (In
2582 2589 * particular, see the comments there for an explanation of the
2583 2590 * endianness differences in this code.)
2584 2591 */
2585 2592 if (size > 8 || (e.cte_bits % NBBY) != 0 ||
2586 2593 (size & (size - 1)) != 0) {
2587 2594 uint64_t mask = (1ULL << e.cte_bits) - 1;
2588 2595 uint64_t value = 0;
2589 2596 uint8_t *buf = (uint8_t *)&value;
2590 2597 uint8_t shift;
2591 2598
2592 2599 /*
2593 2600 * Round our size up one byte.
2594 2601 */
2595 2602 size = (e.cte_bits + (NBBY - 1)) / NBBY;
2596 2603
2597 2604 if (e.cte_bits > sizeof (value) * NBBY - 1) {
2598 2605 mdb_printf("invalid bitfield size %u", e.cte_bits);
2599 2606 return (DCMD_ABORT);
2600 2607 }
2601 2608
2602 2609 #ifdef _BIG_ENDIAN
2603 2610 buf += sizeof (value) - size;
2604 2611 off += e.cte_bits;
2605 2612 #endif
2606 2613
2607 2614 if (mdb_vread(buf, size, addr) == -1) {
2608 2615 mdb_warn("failed to read %lu bytes at %p", size, addr);
2609 2616 return (DCMD_ERR);
2610 2617 }
2611 2618
2612 2619 shift = off % NBBY;
2613 2620 #ifdef _BIG_ENDIAN
2614 2621 shift = NBBY - shift;
2615 2622 #endif
2616 2623
2617 2624 /*
2618 2625 * If we have a bit offset within the byte, shift it down.
2619 2626 */
2620 2627 if (off % NBBY != 0)
2621 2628 value >>= shift;
2622 2629 value &= mask;
2623 2630
2624 2631 if (sign) {
2625 2632 int sshift = sizeof (value) * NBBY - e.cte_bits;
2626 2633 value = ((int64_t)value << sshift) >> sshift;
2627 2634 }
2628 2635
2629 2636 mdb_printf(fmt, value);
2630 2637 return (0);
2631 2638 }
2632 2639
2633 2640 if (mdb_vread(&u.i8, size, addr) == -1) {
2634 2641 mdb_warn("failed to read %lu bytes at %p", (ulong_t)size, addr);
2635 2642 return (DCMD_ERR);
2636 2643 }
2637 2644
2638 2645 switch (size) {
2639 2646 case sizeof (uint8_t):
2640 2647 mdb_printf(fmt, (uint64_t)(sign ? u.i1 : u.ui1));
2641 2648 break;
2642 2649 case sizeof (uint16_t):
2643 2650 mdb_printf(fmt, (uint64_t)(sign ? u.i2 : u.ui2));
2644 2651 break;
2645 2652 case sizeof (uint32_t):
2646 2653 mdb_printf(fmt, (uint64_t)(sign ? u.i4 : u.ui4));
2647 2654 break;
2648 2655 case sizeof (uint64_t):
2649 2656 mdb_printf(fmt, (uint64_t)(sign ? u.i8 : u.ui8));
2650 2657 break;
2651 2658 }
2652 2659
2653 2660 return (0);
2654 2661 }
2655 2662
2656 2663 static int
2657 2664 printf_int(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2658 2665 {
2659 2666 return (printf_signed(id, addr, off, fmt, B_TRUE));
2660 2667 }
2661 2668
2662 2669 static int
2663 2670 printf_uint(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2664 2671 {
2665 2672 return (printf_signed(id, addr, off, fmt, B_FALSE));
2666 2673 }
2667 2674
2668 2675 /*ARGSUSED*/
2669 2676 static int
2670 2677 printf_uint32(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2671 2678 {
2672 2679 mdb_ctf_id_t base;
2673 2680 ctf_encoding_t e;
2674 2681 uint32_t value;
2675 2682
2676 2683 if (mdb_ctf_type_resolve(id, &base) == -1) {
2677 2684 mdb_warn("could not resolve type\n");
2678 2685 return (DCMD_ABORT);
2679 2686 }
2680 2687
2681 2688 if (mdb_ctf_type_kind(base) != CTF_K_INTEGER ||
2682 2689 mdb_ctf_type_encoding(base, &e) != 0 ||
2683 2690 e.cte_bits / NBBY != sizeof (value)) {
2684 2691 mdb_warn("expected 32-bit integer type\n");
2685 2692 return (DCMD_ABORT);
2686 2693 }
2687 2694
2688 2695 if (mdb_vread(&value, sizeof (value), addr) == -1) {
2689 2696 mdb_warn("failed to read 32-bit value at %p", addr);
2690 2697 return (DCMD_ERR);
2691 2698 }
2692 2699
2693 2700 mdb_printf(fmt, value);
2694 2701
2695 2702 return (0);
2696 2703 }
2697 2704
2698 2705 /*ARGSUSED*/
2699 2706 static int
2700 2707 printf_ptr(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2701 2708 {
2702 2709 uintptr_t value;
2703 2710 mdb_ctf_id_t base;
2704 2711
2705 2712 if (mdb_ctf_type_resolve(id, &base) == -1) {
2706 2713 mdb_warn("could not resolve type\n");
2707 2714 return (DCMD_ABORT);
2708 2715 }
2709 2716
2710 2717 if (mdb_ctf_type_kind(base) != CTF_K_POINTER) {
2711 2718 mdb_warn("expected pointer type\n");
2712 2719 return (DCMD_ABORT);
2713 2720 }
2714 2721
2715 2722 if (mdb_vread(&value, sizeof (value), addr) == -1) {
2716 2723 mdb_warn("failed to read pointer at %llx", addr);
2717 2724 return (DCMD_ERR);
2718 2725 }
2719 2726
2720 2727 mdb_printf(fmt, value);
2721 2728
2722 2729 return (0);
2723 2730 }
2724 2731
2725 2732 /*ARGSUSED*/
2726 2733 static int
2727 2734 printf_string(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2728 2735 {
2729 2736 mdb_ctf_id_t base;
2730 2737 mdb_ctf_arinfo_t r;
2731 2738 char buf[1024];
2732 2739 ssize_t size;
2733 2740
2734 2741 if (mdb_ctf_type_resolve(id, &base) == -1) {
2735 2742 mdb_warn("could not resolve type");
2736 2743 return (DCMD_ABORT);
2737 2744 }
2738 2745
2739 2746 if (mdb_ctf_type_kind(base) == CTF_K_POINTER) {
2740 2747 uintptr_t value;
2741 2748
2742 2749 if (mdb_vread(&value, sizeof (value), addr) == -1) {
2743 2750 mdb_warn("failed to read pointer at %llx", addr);
↓ open down ↓ |
163 lines elided |
↑ open up ↑ |
2744 2751 return (DCMD_ERR);
2745 2752 }
2746 2753
2747 2754 if (mdb_readstr(buf, sizeof (buf) - 1, value) < 0) {
2748 2755 mdb_warn("failed to read string at %llx", value);
2749 2756 return (DCMD_ERR);
2750 2757 }
2751 2758
2752 2759 mdb_printf(fmt, buf);
2753 2760 return (0);
2761 + }
2762 +
2763 + if (mdb_ctf_type_kind(base) == CTF_K_ENUM) {
2764 + const char *strval;
2765 + int value;
2766 +
2767 + if (mdb_vread(&value, sizeof (value), addr) == -1) {
2768 + mdb_warn("failed to read pointer at %llx", addr);
2769 + return (DCMD_ERR);
2770 + }
2771 +
2772 + if ((strval = mdb_ctf_enum_name(id, value))) {
2773 + mdb_printf(fmt, strval);
2774 + } else {
2775 + mdb_snprintf(buf, sizeof (buf), "<%d>", value);
2776 + mdb_printf(fmt, buf);
2777 + }
2778 +
2779 + return (DCMD_OK);
2754 2780 }
2755 2781
2756 2782 if (mdb_ctf_type_kind(base) != CTF_K_ARRAY) {
2757 2783 mdb_warn("exepected pointer or array type\n");
2758 2784 return (DCMD_ABORT);
2759 2785 }
2760 2786
2761 2787 if (mdb_ctf_array_info(base, &r) == -1 ||
2762 2788 mdb_ctf_type_resolve(r.mta_contents, &base) == -1 ||
2763 2789 (size = mdb_ctf_type_size(base)) == -1) {
2764 2790 mdb_warn("can't determine array type");
2765 2791 return (DCMD_ABORT);
2766 2792 }
2767 2793
2768 2794 if (size != 1) {
2769 2795 mdb_warn("string format specifier requires "
2770 2796 "an array of characters\n");
2771 2797 return (DCMD_ABORT);
2772 2798 }
2773 2799
2774 2800 bzero(buf, sizeof (buf));
2775 2801
2776 2802 if (mdb_vread(buf, MIN(r.mta_nelems, sizeof (buf) - 1), addr) == -1) {
2777 2803 mdb_warn("failed to read array at %p", addr);
2778 2804 return (DCMD_ERR);
2779 2805 }
2780 2806
2781 2807 mdb_printf(fmt, buf);
2782 2808
2783 2809 return (0);
2784 2810 }
2785 2811
2786 2812 /*ARGSUSED*/
2787 2813 static int
2788 2814 printf_ipv6(mdb_ctf_id_t id, uintptr_t addr, ulong_t off, char *fmt)
2789 2815 {
2790 2816 mdb_ctf_id_t base;
2791 2817 mdb_ctf_id_t ipv6_type, ipv6_base;
2792 2818 in6_addr_t ipv6;
2793 2819
2794 2820 if (mdb_ctf_lookup_by_name("in6_addr_t", &ipv6_type) == -1) {
2795 2821 mdb_warn("could not resolve in6_addr_t type\n");
2796 2822 return (DCMD_ABORT);
2797 2823 }
2798 2824
2799 2825 if (mdb_ctf_type_resolve(id, &base) == -1) {
2800 2826 mdb_warn("could not resolve type\n");
2801 2827 return (DCMD_ABORT);
2802 2828 }
2803 2829
2804 2830 if (mdb_ctf_type_resolve(ipv6_type, &ipv6_base) == -1) {
2805 2831 mdb_warn("could not resolve in6_addr_t type\n");
2806 2832 return (DCMD_ABORT);
2807 2833 }
2808 2834
2809 2835 if (mdb_ctf_type_cmp(base, ipv6_base) != 0) {
2810 2836 mdb_warn("requires argument of type in6_addr_t\n");
2811 2837 return (DCMD_ABORT);
2812 2838 }
2813 2839
2814 2840 if (mdb_vread(&ipv6, sizeof (ipv6), addr) == -1) {
2815 2841 mdb_warn("couldn't read in6_addr_t at %p", addr);
2816 2842 return (DCMD_ERR);
2817 2843 }
2818 2844
2819 2845 mdb_printf(fmt, &ipv6);
2820 2846
2821 2847 return (0);
2822 2848 }
2823 2849
2824 2850 /*
2825 2851 * To validate the format string specified to ::printf, we run the format
2826 2852 * string through a very simple state machine that restricts us to a subset
2827 2853 * of mdb_printf() functionality.
2828 2854 */
2829 2855 enum {
2830 2856 PRINTF_NOFMT = 1, /* no current format specifier */
2831 2857 PRINTF_PERC, /* processed '%' */
2832 2858 PRINTF_FMT, /* processing format specifier */
2833 2859 PRINTF_LEFT, /* processed '-', expecting width */
2834 2860 PRINTF_WIDTH, /* processing width */
2835 2861 PRINTF_QUES /* processed '?', expecting format */
2836 2862 };
2837 2863
2838 2864 int
2839 2865 cmd_printf_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
2840 2866 const mdb_arg_t *argv)
2841 2867 {
2842 2868 int ii;
2843 2869 char *f;
2844 2870
2845 2871 /*
2846 2872 * If argc doesn't have more than what should be the format string,
2847 2873 * ignore it.
2848 2874 */
2849 2875 if (argc <= 1)
2850 2876 return (0);
2851 2877
2852 2878 /*
2853 2879 * Because we aren't leveraging the lex and yacc engine, we have to
2854 2880 * manually walk the arguments to find both the first and last
2855 2881 * open/close quote of the format string.
2856 2882 */
2857 2883 f = strchr(argv[0].a_un.a_str, '"');
2858 2884 if (f == NULL)
2859 2885 return (0);
2860 2886
2861 2887 f = strchr(f + 1, '"');
2862 2888 if (f != NULL) {
2863 2889 ii = 0;
2864 2890 } else {
2865 2891 for (ii = 1; ii < argc; ii++) {
2866 2892 if (argv[ii].a_type != MDB_TYPE_STRING)
2867 2893 continue;
2868 2894 f = strchr(argv[ii].a_un.a_str, '"');
2869 2895 if (f != NULL)
2870 2896 break;
2871 2897 }
2872 2898 /* Never found */
2873 2899 if (ii == argc)
2874 2900 return (0);
2875 2901 }
2876 2902
2877 2903 ii++;
2878 2904 argc -= ii;
2879 2905 argv += ii;
2880 2906
2881 2907 return (cmd_print_tab_common(mcp, flags, argc, argv));
2882 2908 }
2883 2909
2884 2910 int
2885 2911 cmd_printf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2886 2912 {
2887 2913 char type[MDB_SYM_NAMLEN];
2888 2914 int i, nfmts = 0, ret;
2889 2915 mdb_ctf_id_t id;
2890 2916 const char *fmt, *member;
2891 2917 char **fmts, *last, *dest, f;
2892 2918 int (**funcs)(mdb_ctf_id_t, uintptr_t, ulong_t, char *);
2893 2919 int state = PRINTF_NOFMT;
2894 2920 printarg_t pa;
2895 2921
2896 2922 if (!(flags & DCMD_ADDRSPEC))
2897 2923 return (DCMD_USAGE);
2898 2924
2899 2925 bzero(&pa, sizeof (pa));
2900 2926 pa.pa_as = MDB_TGT_AS_VIRT;
2901 2927 pa.pa_realtgt = pa.pa_tgt = mdb.m_target;
2902 2928
2903 2929 if (argc == 0 || argv[0].a_type != MDB_TYPE_STRING) {
2904 2930 mdb_warn("expected a format string\n");
2905 2931 return (DCMD_USAGE);
2906 2932 }
2907 2933
2908 2934 /*
2909 2935 * Our first argument is a format string; rip it apart and run it
2910 2936 * through our state machine to validate that our input is within the
2911 2937 * subset of mdb_printf() format strings that we allow.
2912 2938 */
2913 2939 fmt = argv[0].a_un.a_str;
2914 2940 /*
2915 2941 * 'dest' must be large enough to hold a copy of the format string,
2916 2942 * plus a NUL and up to 2 additional characters for each conversion
2917 2943 * in the format string. This gives us a bloat factor of 5/2 ~= 3.
2918 2944 * e.g. "%d" (strlen of 2) --> "%lld\0" (need 5 bytes)
2919 2945 */
2920 2946 dest = mdb_zalloc(strlen(fmt) * 3, UM_SLEEP | UM_GC);
2921 2947 fmts = mdb_zalloc(strlen(fmt) * sizeof (char *), UM_SLEEP | UM_GC);
2922 2948 funcs = mdb_zalloc(strlen(fmt) * sizeof (void *), UM_SLEEP | UM_GC);
2923 2949 last = dest;
2924 2950
2925 2951 for (i = 0; fmt[i] != '\0'; i++) {
2926 2952 *dest++ = f = fmt[i];
2927 2953
2928 2954 switch (state) {
2929 2955 case PRINTF_NOFMT:
2930 2956 state = f == '%' ? PRINTF_PERC : PRINTF_NOFMT;
2931 2957 break;
2932 2958
2933 2959 case PRINTF_PERC:
2934 2960 state = f == '-' ? PRINTF_LEFT :
2935 2961 f >= '0' && f <= '9' ? PRINTF_WIDTH :
2936 2962 f == '?' ? PRINTF_QUES :
2937 2963 f == '%' ? PRINTF_NOFMT : PRINTF_FMT;
2938 2964 break;
2939 2965
2940 2966 case PRINTF_LEFT:
2941 2967 state = f >= '0' && f <= '9' ? PRINTF_WIDTH :
2942 2968 f == '?' ? PRINTF_QUES : PRINTF_FMT;
2943 2969 break;
2944 2970
2945 2971 case PRINTF_WIDTH:
2946 2972 state = f >= '0' && f <= '9' ? PRINTF_WIDTH :
2947 2973 PRINTF_FMT;
2948 2974 break;
2949 2975
2950 2976 case PRINTF_QUES:
2951 2977 state = PRINTF_FMT;
2952 2978 break;
2953 2979 }
2954 2980
2955 2981 if (state != PRINTF_FMT)
2956 2982 continue;
2957 2983
2958 2984 dest--;
2959 2985
2960 2986 /*
2961 2987 * Now check that we have one of our valid format characters.
2962 2988 */
2963 2989 switch (f) {
2964 2990 case 'a':
2965 2991 case 'A':
2966 2992 case 'p':
2967 2993 funcs[nfmts] = printf_ptr;
2968 2994 break;
2969 2995
2970 2996 case 'd':
2971 2997 case 'q':
2972 2998 case 'R':
2973 2999 funcs[nfmts] = printf_int;
2974 3000 *dest++ = 'l';
2975 3001 *dest++ = 'l';
2976 3002 break;
2977 3003
2978 3004 case 'I':
2979 3005 funcs[nfmts] = printf_uint32;
2980 3006 break;
2981 3007
2982 3008 case 'N':
2983 3009 funcs[nfmts] = printf_ipv6;
2984 3010 break;
2985 3011
2986 3012 case 'H':
2987 3013 case 'o':
2988 3014 case 'r':
2989 3015 case 'u':
2990 3016 case 'x':
2991 3017 case 'X':
2992 3018 funcs[nfmts] = printf_uint;
2993 3019 *dest++ = 'l';
2994 3020 *dest++ = 'l';
2995 3021 break;
2996 3022
2997 3023 case 's':
2998 3024 funcs[nfmts] = printf_string;
2999 3025 break;
3000 3026
3001 3027 case 'Y':
3002 3028 funcs[nfmts] = sizeof (time_t) == sizeof (int) ?
3003 3029 printf_uint32 : printf_uint;
3004 3030 break;
3005 3031
3006 3032 default:
3007 3033 mdb_warn("illegal format string at or near "
3008 3034 "'%c' (position %d)\n", f, i + 1);
3009 3035 return (DCMD_ABORT);
3010 3036 }
3011 3037
3012 3038 *dest++ = f;
3013 3039 *dest++ = '\0';
3014 3040 fmts[nfmts++] = last;
3015 3041 last = dest;
3016 3042 state = PRINTF_NOFMT;
3017 3043 }
3018 3044
3019 3045 argc--;
3020 3046 argv++;
3021 3047
3022 3048 /*
3023 3049 * Now we expect a type name.
3024 3050 */
3025 3051 if ((ret = args_to_typename(&argc, &argv, type, sizeof (type))) != 0)
3026 3052 return (ret);
3027 3053
3028 3054 argv++;
3029 3055 argc--;
3030 3056
3031 3057 if (mdb_ctf_lookup_by_name(type, &id) != 0) {
3032 3058 mdb_warn("failed to look up type %s", type);
3033 3059 return (DCMD_ABORT);
3034 3060 }
3035 3061
3036 3062 if (argc == 0) {
3037 3063 mdb_warn("at least one member must be specified\n");
3038 3064 return (DCMD_USAGE);
3039 3065 }
3040 3066
3041 3067 if (argc != nfmts) {
3042 3068 mdb_warn("%s format specifiers (found %d, expected %d)\n",
3043 3069 argc > nfmts ? "missing" : "extra", nfmts, argc);
3044 3070 return (DCMD_ABORT);
3045 3071 }
3046 3072
3047 3073 for (i = 0; i < argc; i++) {
3048 3074 mdb_ctf_id_t mid;
3049 3075 ulong_t off;
3050 3076 int ignored;
3051 3077
3052 3078 if (argv[i].a_type != MDB_TYPE_STRING) {
3053 3079 mdb_warn("expected only type member arguments\n");
3054 3080 return (DCMD_ABORT);
3055 3081 }
3056 3082
3057 3083 if (strcmp((member = argv[i].a_un.a_str), ".") == 0) {
3058 3084 /*
3059 3085 * We allow "." to be specified to denote the current
3060 3086 * value of dot.
3061 3087 */
3062 3088 if (funcs[i] != printf_ptr && funcs[i] != printf_uint &&
3063 3089 funcs[i] != printf_int) {
3064 3090 mdb_warn("expected integer or pointer format "
3065 3091 "specifier for '.'\n");
3066 3092 return (DCMD_ABORT);
3067 3093 }
3068 3094
3069 3095 mdb_printf(fmts[i], mdb_get_dot());
3070 3096 continue;
3071 3097 }
3072 3098
3073 3099 pa.pa_addr = addr;
3074 3100
3075 3101 if (parse_member(&pa, member, id, &mid, &off, &ignored) != 0)
3076 3102 return (DCMD_ABORT);
3077 3103
3078 3104 if ((ret = funcs[i](mid, pa.pa_addr, off, fmts[i])) != 0) {
3079 3105 mdb_warn("failed to print member '%s'\n", member);
3080 3106 return (ret);
3081 3107 }
3082 3108 }
3083 3109
3084 3110 mdb_printf("%s", last);
3085 3111
3086 3112 return (DCMD_OK);
3087 3113 }
3088 3114
3089 3115 static char _mdb_printf_help[] =
3090 3116 "The format string argument is a printf(3C)-like format string that is a\n"
3091 3117 "subset of the format strings supported by mdb_printf(). The type argument\n"
3092 3118 "is the name of a type to be used to interpret the memory referenced by dot.\n"
3093 3119 "The member should either be a field in the specified structure, or the\n"
3094 3120 "special member '.', denoting the value of dot (and treated as a pointer).\n"
3095 3121 "The number of members must match the number of format specifiers in the\n"
3096 3122 "format string.\n"
3097 3123 "\n"
3098 3124 "The following format specifiers are recognized by ::printf:\n"
3099 3125 "\n"
3100 3126 " %% Prints the '%' symbol.\n"
3101 3127 " %a Prints the member in symbolic form.\n"
3102 3128 " %d Prints the member as a decimal integer. If the member is a signed\n"
3103 3129 " integer type, the output will be signed.\n"
3104 3130 " %H Prints the member as a human-readable size.\n"
3105 3131 " %I Prints the member as an IPv4 address (must be 32-bit integer type).\n"
3106 3132 " %N Prints the member as an IPv6 address (must be of type in6_addr_t).\n"
3107 3133 " %o Prints the member as an unsigned octal integer.\n"
3108 3134 " %p Prints the member as a pointer, in hexadecimal.\n"
3109 3135 " %q Prints the member in signed octal. Honk if you ever use this!\n"
3110 3136 " %r Prints the member as an unsigned value in the current output radix.\n"
3111 3137 " %R Prints the member as a signed value in the current output radix.\n"
3112 3138 " %s Prints the member as a string (requires a pointer or an array of\n"
3113 3139 " characters).\n"
3114 3140 " %u Prints the member as an unsigned decimal integer.\n"
3115 3141 " %x Prints the member in hexadecimal.\n"
3116 3142 " %X Prints the member in hexadecimal, using the characters A-F as the\n"
3117 3143 " digits for the values 10-15.\n"
3118 3144 " %Y Prints the member as a time_t as the string "
3119 3145 "'year month day HH:MM:SS'.\n"
3120 3146 "\n"
3121 3147 "The following field width specifiers are recognized by ::printf:\n"
3122 3148 "\n"
3123 3149 " %n Field width is set to the specified decimal value.\n"
3124 3150 " %? Field width is set to the maximum width of a hexadecimal pointer\n"
3125 3151 " value. This is 8 in an ILP32 environment, and 16 in an LP64\n"
3126 3152 " environment.\n"
3127 3153 "\n"
3128 3154 "The following flag specifers are recognized by ::printf:\n"
3129 3155 "\n"
3130 3156 " %- Left-justify the output within the specified field width. If the\n"
3131 3157 " width of the output is less than the specified field width, the\n"
3132 3158 " output will be padded with blanks on the right-hand side. Without\n"
3133 3159 " %-, values are right-justified by default.\n"
3134 3160 "\n"
3135 3161 " %0 Zero-fill the output field if the output is right-justified and the\n"
3136 3162 " width of the output is less than the specified field width. Without\n"
3137 3163 " %0, right-justified values are prepended with blanks in order to\n"
3138 3164 " fill the field.\n"
3139 3165 "\n"
3140 3166 "Examples: \n"
3141 3167 "\n"
3142 3168 " ::walk proc | "
3143 3169 "::printf \"%-6d %s\\n\" proc_t p_pidp->pid_id p_user.u_psargs\n"
3144 3170 " ::walk thread | "
3145 3171 "::printf \"%?p %3d %a\\n\" kthread_t . t_pri t_startpc\n"
3146 3172 " ::walk zone | "
3147 3173 "::printf \"%-40s %20s\\n\" zone_t zone_name zone_nodename\n"
3148 3174 " ::walk ire | "
3149 3175 "::printf \"%Y %I\\n\" ire_t ire_create_time ire_u.ire4_u.ire4_addr\n"
3150 3176 "\n";
3151 3177
3152 3178 void
3153 3179 printf_help(void)
3154 3180 {
3155 3181 mdb_printf("%s", _mdb_printf_help);
3156 3182 }
↓ open down ↓ |
393 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX