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