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