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