Print this page
10921 mdb_nicenum() needs smatch fix
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_modapi.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_modapi.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
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2013 by Delphix. All rights reserved.
25 25 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26 + * Copyright 2019 Joyent, Inc.
26 27 */
27 28
28 29 #include <mdb/mdb_modapi.h>
29 30 #include <mdb/mdb_module.h>
30 31 #include <mdb/mdb_string.h>
31 32 #include <mdb/mdb_debug.h>
32 33 #include <mdb/mdb_callb.h>
33 34 #include <mdb/mdb_dump.h>
34 35 #include <mdb/mdb_err.h>
35 36 #include <mdb/mdb_io.h>
36 37 #include <mdb/mdb_lex.h>
37 38 #include <mdb/mdb_frame.h>
38 39 #include <mdb/mdb.h>
39 40
40 41 /*
41 42 * Private callback structure for implementing mdb_walk_dcmd, below.
42 43 */
43 44 typedef struct {
44 45 mdb_idcmd_t *dw_dcmd;
45 46 mdb_argvec_t dw_argv;
46 47 uint_t dw_flags;
47 48 } dcmd_walk_arg_t;
48 49
49 50 /*
50 51 * Global properties which modules are allowed to look at. These are
51 52 * re-initialized by the target activation callbacks.
52 53 */
53 54 int mdb_prop_postmortem = FALSE; /* Are we examining a dump? */
54 55 int mdb_prop_kernel = FALSE; /* Are we examining a kernel? */
55 56 int mdb_prop_datamodel = 0; /* Data model (see mdb_target_impl.h) */
56 57
57 58 static int
58 59 call_idcmd(mdb_idcmd_t *idcp, uintmax_t addr, uintmax_t count,
59 60 uint_t flags, mdb_argvec_t *argv);
60 61
61 62 int
62 63 mdb_snprintfrac(char *buf, int len,
63 64 uint64_t numerator, uint64_t denom, int frac_digits)
64 65 {
65 66 int mul = 1;
66 67 int whole, frac, i;
67 68
68 69 for (i = frac_digits; i; i--)
69 70 mul *= 10;
70 71 whole = numerator / denom;
71 72 frac = mul * numerator / denom - mul * whole;
72 73 return (mdb_snprintf(buf, len, "%u.%0*u", whole, frac_digits, frac));
73 74 }
74 75
75 76 void
76 77 mdb_nicenum(uint64_t num, char *buf)
77 78 {
78 79 uint64_t n = num;
79 80 int index = 0;
80 81 char *u;
81 82
82 83 while (n >= 1024) {
83 84 n = (n + (1024 / 2)) / 1024; /* Round up or down */
84 85 index++;
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
85 86 }
86 87
87 88 u = &" \0K\0M\0G\0T\0P\0E\0"[index*2];
88 89
89 90 if (index == 0) {
90 91 (void) mdb_snprintf(buf, MDB_NICENUM_BUFLEN, "%llu",
91 92 (u_longlong_t)n);
92 93 } else if (n < 10 && (num & (num - 1)) != 0) {
93 94 (void) mdb_snprintfrac(buf, MDB_NICENUM_BUFLEN,
94 95 num, 1ULL << 10 * index, 2);
95 - strcat(buf, u);
96 + (void) strcat(buf, u);
96 97 } else if (n < 100 && (num & (num - 1)) != 0) {
97 98 (void) mdb_snprintfrac(buf, MDB_NICENUM_BUFLEN,
98 99 num, 1ULL << 10 * index, 1);
99 - strcat(buf, u);
100 + (void) strcat(buf, u);
100 101 } else {
101 102 (void) mdb_snprintf(buf, MDB_NICENUM_BUFLEN, "%llu%s",
102 103 (u_longlong_t)n, u);
103 104 }
104 105 }
105 106
106 107 ssize_t
107 108 mdb_vread(void *buf, size_t nbytes, uintptr_t addr)
108 109 {
109 110 ssize_t rbytes = mdb_tgt_vread(mdb.m_target, buf, nbytes, addr);
110 111
111 112 if (rbytes > 0 && rbytes < nbytes)
112 113 return (set_errbytes(rbytes, nbytes));
113 114
114 115 return (rbytes);
115 116 }
116 117
117 118 ssize_t
118 119 mdb_vwrite(const void *buf, size_t nbytes, uintptr_t addr)
119 120 {
120 121 return (mdb_tgt_vwrite(mdb.m_target, buf, nbytes, addr));
121 122 }
122 123
123 124 ssize_t
124 125 mdb_aread(void *buf, size_t nbytes, uintptr_t addr, void *as)
125 126 {
126 127 ssize_t rbytes = mdb_tgt_aread(mdb.m_target, as, buf, nbytes, addr);
127 128
128 129 if (rbytes > 0 && rbytes < nbytes)
129 130 return (set_errbytes(rbytes, nbytes));
130 131
131 132 return (rbytes);
132 133 }
133 134
134 135 ssize_t
135 136 mdb_awrite(const void *buf, size_t nbytes, uintptr_t addr, void *as)
136 137 {
137 138 return (mdb_tgt_awrite(mdb.m_target, as, buf, nbytes, addr));
138 139 }
139 140
140 141 ssize_t
141 142 mdb_fread(void *buf, size_t nbytes, uintptr_t addr)
142 143 {
143 144 ssize_t rbytes = mdb_tgt_fread(mdb.m_target, buf, nbytes, addr);
144 145
145 146 if (rbytes > 0 && rbytes < nbytes)
146 147 return (set_errbytes(rbytes, nbytes));
147 148
148 149 return (rbytes);
149 150 }
150 151
151 152 ssize_t
152 153 mdb_fwrite(const void *buf, size_t nbytes, uintptr_t addr)
153 154 {
154 155 return (mdb_tgt_fwrite(mdb.m_target, buf, nbytes, addr));
155 156 }
156 157
157 158 ssize_t
158 159 mdb_pread(void *buf, size_t nbytes, physaddr_t addr)
159 160 {
160 161 ssize_t rbytes = mdb_tgt_pread(mdb.m_target, buf, nbytes, addr);
161 162
162 163 if (rbytes > 0 && rbytes < nbytes)
163 164 return (set_errbytes(rbytes, nbytes));
164 165
165 166 return (rbytes);
166 167 }
167 168
168 169 ssize_t
169 170 mdb_pwrite(const void *buf, size_t nbytes, physaddr_t addr)
170 171 {
171 172 return (mdb_tgt_pwrite(mdb.m_target, buf, nbytes, addr));
172 173 }
173 174
174 175 ssize_t
175 176 mdb_readstr(char *buf, size_t nbytes, uintptr_t addr)
176 177 {
177 178 return (mdb_tgt_readstr(mdb.m_target, MDB_TGT_AS_VIRT,
178 179 buf, nbytes, addr));
179 180 }
180 181
181 182 ssize_t
182 183 mdb_writestr(const char *buf, uintptr_t addr)
183 184 {
184 185 return (mdb_tgt_writestr(mdb.m_target, MDB_TGT_AS_VIRT, buf, addr));
185 186 }
186 187
187 188 ssize_t
188 189 mdb_readsym(void *buf, size_t nbytes, const char *name)
189 190 {
190 191 ssize_t rbytes = mdb_tgt_readsym(mdb.m_target, MDB_TGT_AS_VIRT,
191 192 buf, nbytes, MDB_TGT_OBJ_EVERY, name);
192 193
193 194 if (rbytes > 0 && rbytes < nbytes)
194 195 return (set_errbytes(rbytes, nbytes));
195 196
196 197 return (rbytes);
197 198 }
198 199
199 200 ssize_t
200 201 mdb_writesym(const void *buf, size_t nbytes, const char *name)
201 202 {
202 203 return (mdb_tgt_writesym(mdb.m_target, MDB_TGT_AS_VIRT,
203 204 buf, nbytes, MDB_TGT_OBJ_EVERY, name));
204 205 }
205 206
206 207 ssize_t
207 208 mdb_readvar(void *buf, const char *name)
208 209 {
209 210 GElf_Sym sym;
210 211
211 212 if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EVERY,
212 213 name, &sym, NULL))
213 214 return (-1);
214 215
215 216 if (mdb_tgt_vread(mdb.m_target, buf, sym.st_size,
216 217 (uintptr_t)sym.st_value) == sym.st_size)
217 218 return ((ssize_t)sym.st_size);
218 219
219 220 return (-1);
220 221 }
221 222
222 223 ssize_t
223 224 mdb_writevar(const void *buf, const char *name)
224 225 {
225 226 GElf_Sym sym;
226 227
227 228 if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EVERY,
228 229 name, &sym, NULL))
229 230 return (-1);
230 231
231 232 if (mdb_tgt_vwrite(mdb.m_target, buf, sym.st_size,
232 233 (uintptr_t)sym.st_value) == sym.st_size)
233 234 return ((ssize_t)sym.st_size);
234 235
235 236 return (-1);
236 237 }
237 238
238 239 int
239 240 mdb_lookup_by_name(const char *name, GElf_Sym *sym)
240 241 {
241 242 return (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, sym));
242 243 }
243 244
244 245 int
245 246 mdb_lookup_by_obj(const char *obj, const char *name, GElf_Sym *sym)
246 247 {
247 248 return (mdb_tgt_lookup_by_name(mdb.m_target, obj, name, sym, NULL));
248 249 }
249 250
250 251 int
251 252 mdb_lookup_by_addr(uintptr_t addr, uint_t flags, char *buf,
252 253 size_t nbytes, GElf_Sym *sym)
253 254 {
254 255 return (mdb_tgt_lookup_by_addr(mdb.m_target, addr, flags,
255 256 buf, nbytes, sym, NULL));
256 257 }
257 258
258 259 int
259 260 mdb_getareg(mdb_tid_t tid, const char *rname, mdb_reg_t *rp)
260 261 {
261 262 return (mdb_tgt_getareg(mdb.m_target, tid, rname, rp));
262 263 }
263 264
264 265 u_longlong_t
265 266 mdb_strtoull(const char *s)
266 267 {
267 268 int radix = mdb.m_radix;
268 269
269 270 if (s[0] == '0') {
270 271 switch (s[1]) {
271 272 case 'I':
272 273 case 'i':
273 274 radix = 2;
274 275 s += 2;
275 276 break;
276 277 case 'O':
277 278 case 'o':
278 279 radix = 8;
279 280 s += 2;
280 281 break;
281 282 case 'T':
282 283 case 't':
283 284 radix = 10;
284 285 s += 2;
285 286 break;
286 287 case 'X':
287 288 case 'x':
288 289 radix = 16;
289 290 s += 2;
290 291 break;
291 292 }
292 293 }
293 294
294 295 return (mdb_strtonum(s, radix));
295 296 }
296 297
297 298 size_t
298 299 mdb_snprintf(char *buf, size_t nbytes, const char *format, ...)
299 300 {
300 301 va_list alist;
301 302
302 303 va_start(alist, format);
303 304 nbytes = mdb_iob_vsnprintf(buf, nbytes, format, alist);
304 305 va_end(alist);
305 306
306 307 return (nbytes);
307 308 }
308 309
309 310 void
310 311 mdb_printf(const char *format, ...)
311 312 {
312 313 va_list alist;
313 314
314 315 va_start(alist, format);
315 316 mdb_iob_vprintf(mdb.m_out, format, alist);
316 317 va_end(alist);
317 318 }
318 319
319 320 void
320 321 mdb_warn(const char *format, ...)
321 322 {
322 323 va_list alist;
323 324
324 325 va_start(alist, format);
325 326 vwarn(format, alist);
326 327 va_end(alist);
327 328 }
328 329
329 330 void
330 331 mdb_flush(void)
331 332 {
332 333 mdb_iob_flush(mdb.m_out);
333 334 }
334 335
335 336 /*
336 337 * Convert an object of len bytes pointed to by srcraw between
337 338 * network-order and host-order and store in dstraw. The length len must
338 339 * be the actual length of the objects pointed to by srcraw and dstraw (or
339 340 * zero) or the results are undefined. srcraw and dstraw may be the same,
340 341 * in which case the object is converted in-place. Note that this routine
341 342 * will convert from host-order to network-order or network-order to
342 343 * host-order, since the conversion is the same in either case.
343 344 */
344 345 /* ARGSUSED */
345 346 void
346 347 mdb_nhconvert(void *dstraw, const void *srcraw, size_t len)
347 348 {
348 349 #ifdef _LITTLE_ENDIAN
349 350 uint8_t b1, b2;
350 351 uint8_t *dst, *src;
351 352 size_t i;
352 353
353 354 dst = (uint8_t *)dstraw;
354 355 src = (uint8_t *)srcraw;
355 356 for (i = 0; i < len / 2; i++) {
356 357 b1 = src[i];
357 358 b2 = src[len - i - 1];
358 359 dst[i] = b2;
359 360 dst[len - i - 1] = b1;
360 361 }
361 362 #else
362 363 if (dstraw != srcraw)
363 364 bcopy(srcraw, dstraw, len);
364 365 #endif
365 366 }
366 367
367 368
368 369 /*
369 370 * Bit formatting functions: Note the interesting use of UM_GC here to
370 371 * allocate a buffer for the caller which will be automatically freed
371 372 * when the dcmd completes or is forcibly aborted.
372 373 */
373 374
374 375 #define NBNB (NBBY / 2) /* number of bits per nibble */
375 376 #define SETBIT(buf, j, c) { \
376 377 if (((j) + 1) % (NBNB + 1) == 0) \
377 378 (buf)[(j)++] = ' '; \
378 379 (buf)[(j)++] = (c); \
379 380 }
380 381
381 382 const char *
382 383 mdb_one_bit(int width, int bit, int on)
383 384 {
384 385 int i, j = 0;
385 386 char *buf;
386 387
387 388 buf = mdb_zalloc(width + (width / NBNB) + 2, UM_GC | UM_SLEEP);
388 389
389 390 for (i = --width; i > bit; i--)
390 391 SETBIT(buf, j, '.');
391 392
392 393 SETBIT(buf, j, on ? '1' : '0');
393 394
394 395 for (i = bit - 1; i >= 0; i--)
395 396 SETBIT(buf, j, '.');
396 397
397 398 return (buf);
398 399 }
399 400
400 401 const char *
401 402 mdb_inval_bits(int width, int start, int stop)
402 403 {
403 404 int i, j = 0;
404 405 char *buf;
405 406
406 407 buf = mdb_zalloc(width + (width / NBNB) + 2, UM_GC | UM_SLEEP);
407 408
408 409 for (i = --width; i > stop; i--)
409 410 SETBIT(buf, j, '.');
410 411
411 412 for (i = stop; i >= start; i--)
412 413 SETBIT(buf, j, 'x');
413 414
414 415 for (; i >= 0; i--)
415 416 SETBIT(buf, j, '.');
416 417
417 418 return (buf);
418 419 }
419 420
420 421 ulong_t
421 422 mdb_inc_indent(ulong_t i)
422 423 {
423 424 if (mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT) {
424 425 ulong_t margin = mdb_iob_getmargin(mdb.m_out);
425 426 mdb_iob_margin(mdb.m_out, margin + i);
426 427 return (margin);
427 428 }
428 429
429 430 mdb_iob_margin(mdb.m_out, i);
430 431 mdb_iob_setflags(mdb.m_out, MDB_IOB_INDENT);
431 432 return (0);
432 433 }
433 434
434 435 ulong_t
435 436 mdb_dec_indent(ulong_t i)
436 437 {
437 438 if (mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT) {
438 439 ulong_t margin = mdb_iob_getmargin(mdb.m_out);
439 440
440 441 if (margin < i || margin - i == 0) {
441 442 mdb_iob_clrflags(mdb.m_out, MDB_IOB_INDENT);
442 443 mdb_iob_margin(mdb.m_out, MDB_IOB_DEFMARGIN);
443 444 } else
444 445 mdb_iob_margin(mdb.m_out, margin - i);
445 446
446 447 return (margin);
447 448 }
448 449
449 450 return (0);
450 451 }
451 452
452 453 int
453 454 mdb_eval(const char *s)
454 455 {
455 456 mdb_frame_t *ofp = mdb.m_fmark;
456 457 mdb_frame_t *fp = mdb.m_frame;
457 458 int err;
458 459
459 460 if (s == NULL)
460 461 return (set_errno(EINVAL));
461 462
462 463 /*
463 464 * Push m_in down onto the input stack, then set m_in to point to the
464 465 * i/o buffer for our command string, and reset the frame marker.
465 466 * The mdb_run() function returns when the new m_in iob reaches EOF.
466 467 */
467 468 mdb_iob_stack_push(&fp->f_istk, mdb.m_in, yylineno);
468 469 mdb.m_in = mdb_iob_create(mdb_strio_create(s), MDB_IOB_RDONLY);
469 470
470 471 mdb.m_fmark = NULL;
471 472 err = mdb_run();
472 473 mdb.m_fmark = ofp;
473 474
474 475 /*
475 476 * Now pop the old standard input stream and restore mdb.m_in and
476 477 * the parser's saved current line number.
477 478 */
478 479 mdb.m_in = mdb_iob_stack_pop(&fp->f_istk);
479 480 yylineno = mdb_iob_lineno(mdb.m_in);
480 481
481 482 /*
482 483 * If mdb_run() returned an error, propagate this backward
483 484 * up the stack of debugger environment frames.
484 485 */
485 486 if (MDB_ERR_IS_FATAL(err))
486 487 longjmp(fp->f_pcb, err);
487 488
488 489 if (err == MDB_ERR_PAGER || err == MDB_ERR_SIGINT)
489 490 return (set_errno(EMDB_CANCEL));
490 491
491 492 if (err != 0)
492 493 return (set_errno(EMDB_EVAL));
493 494
494 495 return (0);
495 496 }
496 497
497 498 void
498 499 mdb_set_dot(uintmax_t addr)
499 500 {
500 501 mdb_nv_set_value(mdb.m_dot, addr);
501 502 mdb.m_incr = 0;
502 503 }
503 504
504 505 uintmax_t
505 506 mdb_get_dot(void)
506 507 {
507 508 return (mdb_nv_get_value(mdb.m_dot));
508 509 }
509 510
510 511 static int
511 512 walk_step(mdb_wcb_t *wcb)
512 513 {
513 514 mdb_wcb_t *nwcb = wcb->w_lyr_head;
514 515 int status;
515 516
516 517 /*
517 518 * If the control block has no layers, we just invoke the walker's
518 519 * step function and return status indicating whether to continue
519 520 * or stop. If the control block has layers, we need to invoke
520 521 * ourself recursively for the next layer, until eventually we
521 522 * percolate down to an unlayered walk.
522 523 */
523 524 if (nwcb == NULL)
524 525 return (wcb->w_walker->iwlk_step(&wcb->w_state));
525 526
526 527 if ((status = walk_step(nwcb)) != WALK_NEXT) {
527 528 wcb->w_lyr_head = nwcb->w_lyr_link;
528 529 nwcb->w_lyr_link = NULL;
529 530 mdb_wcb_destroy(nwcb);
530 531 }
531 532
532 533 if (status == WALK_DONE && wcb->w_lyr_head != NULL)
533 534 return (WALK_NEXT);
534 535
535 536 return (status);
536 537 }
537 538
538 539 static int
539 540 walk_common(mdb_wcb_t *wcb)
540 541 {
541 542 int status, rval = 0;
542 543 mdb_frame_t *pfp;
543 544
544 545 /*
545 546 * Enter the control block in the active list so that mdb can clean
546 547 * up after it in case we abort out of the current command.
547 548 */
548 549 if ((pfp = mdb_list_prev(mdb.m_frame)) != NULL && pfp->f_pcmd != NULL)
549 550 mdb_wcb_insert(wcb, pfp);
550 551 else
551 552 mdb_wcb_insert(wcb, mdb.m_frame);
552 553
553 554 /*
554 555 * The per-walk constructor performs private buffer initialization
555 556 * and locates whatever symbols are necessary.
556 557 */
557 558 if ((status = wcb->w_walker->iwlk_init(&wcb->w_state)) != WALK_NEXT) {
558 559 if (status != WALK_DONE)
559 560 rval = set_errno(EMDB_WALKINIT);
560 561 goto done;
561 562 }
562 563
563 564 /*
564 565 * Mark wcb to indicate that walk_init has been called (which means
565 566 * we can call walk_fini if the walk is aborted at this point).
566 567 */
567 568 wcb->w_inited = TRUE;
568 569
569 570 while (walk_step(wcb) == WALK_NEXT)
570 571 continue;
571 572 done:
572 573 if ((pfp = mdb_list_prev(mdb.m_frame)) != NULL && pfp->f_pcmd != NULL)
573 574 mdb_wcb_delete(wcb, pfp);
574 575 else
575 576 mdb_wcb_delete(wcb, mdb.m_frame);
576 577
577 578 mdb_wcb_destroy(wcb);
578 579 return (rval);
579 580 }
580 581
581 582 typedef struct pwalk_step {
582 583 mdb_walk_cb_t ps_cb;
583 584 void *ps_private;
584 585 } pwalk_step_t;
585 586
586 587 static int
587 588 pwalk_step(uintptr_t addr, const void *data, void *private)
588 589 {
589 590 pwalk_step_t *psp = private;
590 591 int ret;
591 592
592 593 mdb.m_frame->f_cbactive = B_TRUE;
593 594 ret = psp->ps_cb(addr, data, psp->ps_private);
594 595 mdb.m_frame->f_cbactive = B_FALSE;
595 596
596 597 return (ret);
597 598 }
598 599
599 600 int
600 601 mdb_pwalk(const char *name, mdb_walk_cb_t func, void *private, uintptr_t addr)
601 602 {
602 603 mdb_iwalker_t *iwp = mdb_walker_lookup(name);
603 604 pwalk_step_t p;
604 605
605 606 if (func == NULL)
606 607 return (set_errno(EINVAL));
607 608
608 609 p.ps_cb = func;
609 610 p.ps_private = private;
610 611
611 612 if (iwp != NULL) {
612 613 int ret;
613 614 int cbactive = mdb.m_frame->f_cbactive;
614 615 mdb.m_frame->f_cbactive = B_FALSE;
615 616 ret = walk_common(mdb_wcb_create(iwp, pwalk_step, &p, addr));
616 617 mdb.m_frame->f_cbactive = cbactive;
617 618 return (ret);
618 619 }
619 620
620 621 return (-1); /* errno is set for us */
621 622 }
622 623
623 624 int
624 625 mdb_walk(const char *name, mdb_walk_cb_t func, void *data)
625 626 {
626 627 return (mdb_pwalk(name, func, data, 0));
627 628 }
628 629
629 630 /*ARGSUSED*/
630 631 static int
631 632 walk_dcmd(uintptr_t addr, const void *ignored, dcmd_walk_arg_t *dwp)
632 633 {
633 634 int status;
634 635
635 636 mdb.m_frame->f_cbactive = B_TRUE;
636 637 status = call_idcmd(dwp->dw_dcmd, addr, 1, dwp->dw_flags,
637 638 &dwp->dw_argv);
638 639 mdb.m_frame->f_cbactive = B_FALSE;
639 640
640 641 if (status == DCMD_USAGE || status == DCMD_ABORT)
641 642 return (WALK_ERR);
642 643
643 644 dwp->dw_flags &= ~DCMD_LOOPFIRST;
644 645 return (WALK_NEXT);
645 646 }
646 647
647 648 int
648 649 mdb_pwalk_dcmd(const char *wname, const char *dcname,
649 650 int argc, const mdb_arg_t *argv, uintptr_t addr)
650 651 {
651 652 mdb_argvec_t args;
652 653 dcmd_walk_arg_t dw;
653 654 mdb_iwalker_t *iwp;
654 655 mdb_wcb_t *wcb;
655 656 int status;
656 657
657 658 if (wname == NULL || dcname == NULL)
658 659 return (set_errno(EINVAL));
659 660
660 661 if ((dw.dw_dcmd = mdb_dcmd_lookup(dcname)) == NULL)
661 662 return (-1); /* errno is set for us */
662 663
663 664 if ((iwp = mdb_walker_lookup(wname)) == NULL)
664 665 return (-1); /* errno is set for us */
665 666
666 667 args.a_data = (mdb_arg_t *)argv;
667 668 args.a_nelems = args.a_size = argc;
668 669
669 670 mdb_argvec_create(&dw.dw_argv);
670 671 mdb_argvec_copy(&dw.dw_argv, &args);
671 672 dw.dw_flags = DCMD_LOOP | DCMD_LOOPFIRST | DCMD_ADDRSPEC;
672 673
673 674 wcb = mdb_wcb_create(iwp, (mdb_walk_cb_t)walk_dcmd, &dw, addr);
674 675 status = walk_common(wcb);
675 676
676 677 mdb_argvec_zero(&dw.dw_argv);
677 678 mdb_argvec_destroy(&dw.dw_argv);
678 679
679 680 return (status);
680 681 }
681 682
682 683 int
683 684 mdb_walk_dcmd(const char *wname, const char *dcname,
684 685 int argc, const mdb_arg_t *argv)
685 686 {
686 687 return (mdb_pwalk_dcmd(wname, dcname, argc, argv, 0));
687 688 }
688 689
689 690 /*ARGSUSED*/
690 691 static int
691 692 layered_walk_step(uintptr_t addr, const void *data, mdb_wcb_t *wcb)
692 693 {
693 694 /*
694 695 * Prior to calling the top-level walker's step function, reset its
695 696 * mdb_walk_state_t walk_addr and walk_layer members to refer to the
696 697 * target virtual address and data buffer of the underlying object.
697 698 */
698 699 wcb->w_state.walk_addr = addr;
699 700 wcb->w_state.walk_layer = data;
700 701
701 702 return (wcb->w_walker->iwlk_step(&wcb->w_state));
702 703 }
703 704
704 705 int
705 706 mdb_layered_walk(const char *wname, mdb_walk_state_t *wsp)
706 707 {
707 708 mdb_wcb_t *cwcb, *wcb;
708 709 mdb_iwalker_t *iwp;
709 710
710 711 if (wname == NULL || wsp == NULL)
711 712 return (set_errno(EINVAL));
712 713
713 714 if ((iwp = mdb_walker_lookup(wname)) == NULL)
714 715 return (-1); /* errno is set for us */
715 716
716 717 if ((cwcb = mdb_wcb_from_state(wsp)) == NULL)
717 718 return (set_errno(EMDB_BADWCB));
718 719
719 720 if (cwcb->w_walker == iwp)
720 721 return (set_errno(EMDB_WALKLOOP));
721 722
722 723 wcb = mdb_wcb_create(iwp, (mdb_walk_cb_t)layered_walk_step,
723 724 cwcb, wsp->walk_addr);
724 725
725 726 if (iwp->iwlk_init(&wcb->w_state) != WALK_NEXT) {
726 727 mdb_wcb_destroy(wcb);
727 728 return (set_errno(EMDB_WALKINIT));
728 729 }
729 730
730 731 wcb->w_inited = TRUE;
731 732
732 733 mdb_dprintf(MDB_DBG_WALK, "added %s`%s as %s`%s layer\n",
733 734 iwp->iwlk_modp->mod_name, iwp->iwlk_name,
734 735 cwcb->w_walker->iwlk_modp->mod_name, cwcb->w_walker->iwlk_name);
735 736
736 737 if (cwcb->w_lyr_head != NULL) {
737 738 for (cwcb = cwcb->w_lyr_head; cwcb->w_lyr_link != NULL; )
738 739 cwcb = cwcb->w_lyr_link;
739 740 cwcb->w_lyr_link = wcb;
740 741 } else
741 742 cwcb->w_lyr_head = wcb;
742 743
743 744 return (0);
744 745 }
745 746
746 747 int
747 748 mdb_call_dcmd(const char *name, uintptr_t dot, uint_t flags,
748 749 int argc, const mdb_arg_t *argv)
749 750 {
750 751 mdb_idcmd_t *idcp;
751 752 mdb_argvec_t args;
752 753 int status;
753 754
754 755 if (name == NULL || argc < 0)
755 756 return (set_errno(EINVAL));
756 757
757 758 if ((idcp = mdb_dcmd_lookup(name)) == NULL)
758 759 return (-1); /* errno is set for us */
759 760
760 761 args.a_data = (mdb_arg_t *)argv;
761 762 args.a_nelems = args.a_size = argc;
762 763 status = call_idcmd(idcp, dot, 1, flags, &args);
763 764
764 765 if (status == DCMD_ERR || status == DCMD_ABORT)
765 766 return (set_errno(EMDB_DCFAIL));
766 767
767 768 if (status == DCMD_USAGE)
768 769 return (set_errno(EMDB_DCUSAGE));
769 770
770 771 return (0);
771 772 }
772 773
773 774 /*
774 775 * When dcmds or walkers call a dcmd that might be in another module,
775 776 * we need to set mdb.m_frame->f_cp to an mdb_cmd that represents the
776 777 * dcmd we're currently executing, otherwise mdb_get_module gets the
777 778 * module of the caller instead of the module for the current dcmd.
778 779 */
779 780 static int
780 781 call_idcmd(mdb_idcmd_t *idcp, uintmax_t addr, uintmax_t count,
781 782 uint_t flags, mdb_argvec_t *argv)
782 783 {
783 784 mdb_cmd_t *save_cp;
784 785 mdb_cmd_t cmd;
785 786 int ret;
786 787
787 788 bzero(&cmd, sizeof (cmd));
788 789 cmd.c_dcmd = idcp;
789 790 cmd.c_argv = *argv;
790 791
791 792 save_cp = mdb.m_frame->f_cp;
792 793 mdb.m_frame->f_cp = &cmd;
793 794
794 795 ret = mdb_call_idcmd(cmd.c_dcmd, addr, count, flags,
795 796 &cmd.c_argv, NULL, NULL);
796 797
797 798 mdb.m_frame->f_cp = save_cp;
798 799
799 800 return (ret);
800 801 }
801 802
802 803 int
803 804 mdb_add_walker(const mdb_walker_t *wp)
804 805 {
805 806 mdb_module_t *mp;
806 807
807 808 if (mdb.m_lmod == NULL) {
808 809 mdb_cmd_t *cp = mdb.m_frame->f_cp;
809 810 mp = cp->c_dcmd->idc_modp;
810 811 } else
811 812 mp = mdb.m_lmod;
812 813
813 814 return (mdb_module_add_walker(mp, wp, 0));
814 815 }
815 816
816 817 int
817 818 mdb_remove_walker(const char *name)
818 819 {
819 820 mdb_module_t *mp;
820 821
821 822 if (mdb.m_lmod == NULL) {
822 823 mdb_cmd_t *cp = mdb.m_frame->f_cp;
823 824 mp = cp->c_dcmd->idc_modp;
824 825 } else
825 826 mp = mdb.m_lmod;
826 827
827 828 return (mdb_module_remove_walker(mp, name));
828 829 }
829 830
830 831 void
831 832 mdb_get_pipe(mdb_pipe_t *p)
832 833 {
833 834 mdb_cmd_t *cp = mdb.m_frame->f_cp;
834 835 mdb_addrvec_t *adp = &cp->c_addrv;
835 836
836 837 if (p == NULL) {
837 838 warn("dcmd failure: mdb_get_pipe invoked with NULL pointer\n");
838 839 longjmp(mdb.m_frame->f_pcb, MDB_ERR_API);
839 840 }
840 841
841 842 if (adp->ad_nelems != 0) {
842 843 ASSERT(adp->ad_ndx != 0);
843 844 p->pipe_data = &adp->ad_data[adp->ad_ndx - 1];
844 845 p->pipe_len = adp->ad_nelems - adp->ad_ndx + 1;
845 846 adp->ad_ndx = adp->ad_nelems;
846 847 } else {
847 848 p->pipe_data = NULL;
848 849 p->pipe_len = 0;
849 850 }
850 851 }
851 852
852 853 void
853 854 mdb_set_pipe(const mdb_pipe_t *p)
854 855 {
855 856 mdb_cmd_t *cp = mdb.m_frame->f_pcmd;
856 857
857 858 if (p == NULL) {
858 859 warn("dcmd failure: mdb_set_pipe invoked with NULL pointer\n");
859 860 longjmp(mdb.m_frame->f_pcb, MDB_ERR_API);
860 861 }
861 862
862 863 if (cp != NULL) {
863 864 size_t nbytes = sizeof (uintptr_t) * p->pipe_len;
864 865
865 866 mdb_cmd_reset(cp);
866 867 cp->c_addrv.ad_data = mdb_alloc(nbytes, UM_SLEEP);
867 868 bcopy(p->pipe_data, cp->c_addrv.ad_data, nbytes);
868 869 cp->c_addrv.ad_nelems = p->pipe_len;
869 870 cp->c_addrv.ad_size = p->pipe_len;
870 871 }
871 872 }
872 873
873 874 ssize_t
874 875 mdb_get_xdata(const char *name, void *buf, size_t nbytes)
875 876 {
876 877 return (mdb_tgt_getxdata(mdb.m_target, name, buf, nbytes));
877 878 }
878 879
879 880 /*
880 881 * Private callback structure for implementing mdb_object_iter, below.
881 882 */
882 883 typedef struct {
883 884 mdb_object_cb_t oi_cb;
884 885 void *oi_arg;
885 886 int oi_rval;
886 887 } object_iter_arg_t;
887 888
888 889 /*ARGSUSED*/
889 890 static int
890 891 mdb_object_cb(void *data, const mdb_map_t *map, const char *fullname)
891 892 {
892 893 object_iter_arg_t *arg = data;
893 894 mdb_object_t obj;
894 895
895 896 if (arg->oi_rval != 0)
896 897 return (0);
897 898
898 899 bzero(&obj, sizeof (obj));
899 900 obj.obj_base = map->map_base;
900 901 obj.obj_name = strbasename(map->map_name);
901 902 obj.obj_size = map->map_size;
902 903 obj.obj_fullname = fullname;
903 904
904 905 arg->oi_rval = arg->oi_cb(&obj, arg->oi_arg);
905 906
906 907 return (0);
907 908 }
908 909
909 910 int
910 911 mdb_object_iter(mdb_object_cb_t cb, void *data)
911 912 {
912 913 object_iter_arg_t arg;
913 914
914 915 arg.oi_cb = cb;
915 916 arg.oi_arg = data;
916 917 arg.oi_rval = 0;
917 918
918 919 if (mdb_tgt_object_iter(mdb.m_target, mdb_object_cb, &arg) != 0)
919 920 return (-1);
920 921
921 922 return (arg.oi_rval);
922 923 }
923 924
924 925 /*
925 926 * Private callback structure for implementing mdb_symbol_iter, below.
926 927 */
927 928 typedef struct {
928 929 mdb_symbol_cb_t si_cb;
929 930 void *si_arg;
930 931 int si_rval;
931 932 } symbol_iter_arg_t;
932 933
933 934 /*ARGSUSED*/
934 935 static int
935 936 mdb_symbol_cb(void *data, const GElf_Sym *gsym, const char *name,
936 937 const mdb_syminfo_t *sip, const char *obj)
937 938 {
938 939 symbol_iter_arg_t *arg = data;
939 940 mdb_symbol_t sym;
940 941
941 942 if (arg->si_rval != 0)
942 943 return (0);
943 944
944 945 bzero(&sym, sizeof (sym));
945 946 sym.sym_name = name;
946 947 sym.sym_object = obj;
947 948 sym.sym_sym = gsym;
948 949 sym.sym_table = sip->sym_table;
949 950 sym.sym_id = sip->sym_id;
950 951
951 952 arg->si_rval = arg->si_cb(&sym, arg->si_arg);
952 953
953 954 return (0);
954 955 }
955 956
956 957 int
957 958 mdb_symbol_iter(const char *obj, uint_t which, uint_t type,
958 959 mdb_symbol_cb_t cb, void *data)
959 960 {
960 961 symbol_iter_arg_t arg;
961 962
962 963 arg.si_cb = cb;
963 964 arg.si_arg = data;
964 965 arg.si_rval = 0;
965 966
966 967 if (mdb_tgt_symbol_iter(mdb.m_target, obj, which, type,
967 968 mdb_symbol_cb, &arg) != 0)
968 969 return (-1);
969 970
970 971 return (arg.si_rval);
971 972 }
972 973
973 974 /*
974 975 * Private structure and function for implementing mdb_dumpptr on top
975 976 * of mdb_dump_internal
976 977 */
977 978 typedef struct dptrdat {
978 979 mdb_dumpptr_cb_t func;
979 980 void *arg;
980 981 } dptrdat_t;
981 982
982 983 static ssize_t
983 984 mdb_dump_aux_ptr(void *buf, size_t nbyte, uint64_t offset, void *arg)
984 985 {
985 986 dptrdat_t *dat = arg;
986 987
987 988 return (dat->func(buf, nbyte, offset, dat->arg));
988 989 }
989 990
990 991 /*
991 992 * Private structure and function for handling callbacks which return
992 993 * EMDB_PARTIAL
993 994 */
994 995 typedef struct d64dat {
995 996 mdb_dump64_cb_t func;
996 997 void *arg;
997 998 } d64dat_t;
998 999
999 1000 static ssize_t
1000 1001 mdb_dump_aux_partial(void *buf, size_t nbyte, uint64_t offset, void *arg)
1001 1002 {
1002 1003 d64dat_t *dat = arg;
1003 1004 int result;
1004 1005 int count;
1005 1006
1006 1007 result = dat->func(buf, nbyte, offset, dat->arg);
1007 1008 if (result == -1 && errno == EMDB_PARTIAL) {
1008 1009 count = 0;
1009 1010 do {
1010 1011 result = dat->func((char *)buf + count, 1,
1011 1012 offset + count, dat->arg);
1012 1013 if (result == 1)
1013 1014 count++;
1014 1015 } while (count < nbyte && result == 1);
1015 1016 if (count)
1016 1017 result = count;
1017 1018 }
1018 1019
1019 1020 return (result);
1020 1021 }
1021 1022
1022 1023 int
1023 1024 mdb_dumpptr(uintptr_t addr, size_t len, uint_t flags, mdb_dumpptr_cb_t fp,
1024 1025 void *arg)
1025 1026 {
1026 1027 dptrdat_t dat;
1027 1028 d64dat_t dat64;
1028 1029
1029 1030 dat.func = fp;
1030 1031 dat.arg = arg;
1031 1032 dat64.func = mdb_dump_aux_ptr;
1032 1033 dat64.arg = &dat;
1033 1034 return (mdb_dump_internal(addr, len, flags, mdb_dump_aux_partial,
1034 1035 &dat64, sizeof (uintptr_t)));
1035 1036 }
1036 1037
1037 1038 int
1038 1039 mdb_dump64(uint64_t addr, uint64_t len, uint_t flags, mdb_dump64_cb_t fp,
1039 1040 void *arg)
1040 1041 {
1041 1042 d64dat_t dat64;
1042 1043
1043 1044 dat64.func = fp;
1044 1045 dat64.arg = arg;
1045 1046 return (mdb_dump_internal(addr, len, flags, mdb_dump_aux_partial,
1046 1047 &dat64, sizeof (uint64_t)));
1047 1048 }
1048 1049
1049 1050 int
1050 1051 mdb_get_state(void)
1051 1052 {
1052 1053 mdb_tgt_status_t ts;
1053 1054
1054 1055 (void) mdb_tgt_status(mdb.m_target, &ts);
1055 1056
1056 1057 return (ts.st_state);
1057 1058 }
1058 1059
1059 1060 void *
1060 1061 mdb_callback_add(int class, mdb_callback_f fp, void *arg)
1061 1062 {
1062 1063 mdb_module_t *m;
1063 1064
1064 1065 if (class != MDB_CALLBACK_STCHG && class != MDB_CALLBACK_PROMPT) {
1065 1066 (void) set_errno(EINVAL);
1066 1067 return (NULL);
1067 1068 }
1068 1069
1069 1070 if (mdb.m_lmod != NULL)
1070 1071 m = mdb.m_lmod;
1071 1072 else
1072 1073 m = mdb.m_frame->f_cp->c_dcmd->idc_modp;
1073 1074
1074 1075 return (mdb_callb_add(m, class, fp, arg));
1075 1076 }
1076 1077
1077 1078 void
1078 1079 mdb_callback_remove(void *hdl)
1079 1080 {
1080 1081 mdb_callb_remove(hdl);
1081 1082 }
↓ open down ↓ |
972 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX