]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/db_examine.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ddb / db_examine.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * @OSF_COPYRIGHT@
27 */
de355530
A
28/*
29 * HISTORY
30 *
31 * Revision 1.1.1.1 1998/09/22 21:05:47 wsanchez
32 * Import of Mac OS X kernel (~semeria)
33 *
34 * Revision 1.2 1998/04/24 19:34:23 semeria
35 * KDP and KDB support
36 *
37 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
38 * Import of OSF Mach kernel (~mburg)
39 *
40 * Revision 1.2.42.2 1997/09/12 17:15:15 stephen
41 * make x/x do zero fill right justified hex display
42 * [1997/09/12 16:31:04 stephen]
43 *
44 * Revision 1.2.42.1 1997/03/27 18:46:31 barbou
45 * Add 'p' option to the "examine" command - values in
46 * memory treated as addresses and rendered as sym+offset
47 * [1995/12/29 21:32:33 mod]
48 * ri-osc CR1560: make search command output address of any matching
49 * data it finds (so user knows it did something).
50 * [1995/09/20 15:24:55 bolinger]
51 * [97/02/25 barbou]
52 *
53 * Revision 1.2.25.5 1996/01/09 19:15:38 devrcs
54 * Add db_print_loc() & db_print_inst() functions.
55 * Make 'l' display 32 bits and new 'q' to display 64 bits.
56 * Allow 'u' to display unsigned decimal values (same as 'U').
57 * Changed declarations of 'register foo' to 'register int foo'.
58 * [1995/12/01 21:42:03 jfraser]
59 *
60 * Merged '64-bit safe' changes from DEC alpha port.
61 * [1995/11/21 18:02:58 jfraser]
62 *
63 * Revision 1.2.25.4 1995/06/13 18:21:27 sjs
64 * Merge with flipc_shared.
65 * [95/05/22 sjs]
66 *
67 * Revision 1.2.30.1 1995/04/03 17:35:17 randys
68 * Minor change; allow a repeat count to work properly when multiple
69 * modifier flags are given to the ddb 'x' command. This allows,
70 * for instance, examination of multiple words in activations other
71 * than the current one.
72 * [95/04/03 randys]
73 *
74 * Revision 1.2.25.3 1995/01/06 19:10:09 devrcs
75 * mk6 CR668 - 1.3b26 merge
76 * * Revision 1.2.6.7 1994/05/06 18:39:09 tmt
77 * Merged osc1.3dec/shared with osc1.3b19
78 * Merge Alpha changes into osc1.312b source code.
79 * 64bit cleanup.
80 * * End1.3merge
81 * [1994/11/04 08:49:22 dwm]
82 *
83 * Revision 1.2.25.2 1994/09/23 01:18:44 ezf
84 * change marker to not FREE
85 * [1994/09/22 21:09:44 ezf]
86 *
87 * Revision 1.2.25.1 1994/06/11 21:11:43 bolinger
88 * Merge up to NMK17.2.
89 * [1994/06/11 20:01:31 bolinger]
90 *
91 * Revision 1.2.23.1 1994/02/08 10:57:47 bernadat
92 * Fixed output of an examine command to have a power of 2
93 * number of fields.
94 * [93/09/29 paire]
95 *
96 * Added dump of hexadecimal address in each line of examine command.
97 * Fixed beginning of line to be always located at position 0.
98 * [93/08/11 paire]
99 * [94/02/07 bernadat]
100 *
101 * Revision 1.2.21.4 1994/03/17 22:35:27 dwm
102 * The infamous name change: thread_activation + thread_shuttle = thread.
103 * [1994/03/17 21:25:43 dwm]
104 *
105 * Revision 1.2.21.3 1994/01/12 17:50:40 dwm
106 * Coloc: initial restructuring to follow Utah model.
107 * [1994/01/12 17:13:08 dwm]
108 *
109 * Revision 1.2.21.2 1993/10/12 16:38:58 dwm
110 * Print '\n' in x/s statements. [rwd]
111 * [1993/10/12 16:14:41 dwm]
112 *
113 * Revision 1.2.6.5 1993/08/11 20:37:37 elliston
114 * Add ANSI Prototypes. CR #9523.
115 * [1993/08/11 03:33:05 elliston]
116 *
117 * Revision 1.2.6.4 1993/08/09 19:34:42 dswartz
118 * Add ANSI prototypes - CR#9523
119 * [1993/08/06 15:47:32 dswartz]
120 *
121 * Revision 1.2.6.3 1993/07/27 18:27:07 elliston
122 * Add ANSI prototypes. CR #9523.
123 * [1993/07/27 18:11:21 elliston]
124 *
125 * Revision 1.2.6.2 1993/06/09 02:20:00 gm
126 * Added to OSF/1 R1.3 from NMK15.0.
127 * [1993/06/02 20:56:10 jeffc]
128 *
129 * Revision 1.2 1993/04/19 16:01:58 devrcs
130 * Changes from mk78:
131 * Added void type to functions that needed it.
132 * Added init to 'size' in db_search_cmd(). Removed unused variables.
133 * Other cleanup to quiet gcc warnings.
134 * [92/05/16 jfriedl]
135 * x/u now examines current user space. x/t still examines user
136 * space of the the specified thread. x/tu is redundant.
137 * To examine an value as unsigned decimal, use x/U.
138 * [92/04/18 danner]
139 * [93/02/02 bruel]
140 *
141 * Remember count argument when repeating commands instead of the
142 * default command, also apply all the formats to current address
143 * instead of incrementing addresses when switching to next format.
144 * [barbou@gr.osf.org]
145 *
146 * Support 'A' format for print 'p' command [barbou@gr.osf.org]
147 * [92/12/03 bernadat]
148 *
149 * Revision 1.1 1992/09/30 02:01:01 robert
150 * Initial revision
151 *
152 * $EndLog$
153 */
154/* CMU_HIST */
155/*
156 * Revision 2.7 91/10/09 15:59:28 af
157 * Revision 2.6.1.1 91/10/05 13:05:49 jeffreyh
158 * Supported non current task space data examination and search.
159 * Added 'm' format and db_xcdump to print with hex and characters.
160 * Added db_examine_{forward, backward}.
161 * Changed db_print_cmd to support variable number of parameters
162 * including string constant.
163 * Included "db_access.h".
164 * [91/08/29 tak]
165 *
166 * Revision 2.6.1.1 91/10/05 13:05:49 jeffreyh
167 * Supported non current task space data examination and search.
168 * Added 'm' format and db_xcdump to print with hex and characters.
169 * Added db_examine_{forward, backward}.
170 * Changed db_print_cmd to support variable number of parameters
171 * including string constant.
172 * Included "db_access.h".
173 * [91/08/29 tak]
174 *
175 * Revision 2.6 91/08/28 11:11:01 jsb
176 * Added 'A' flag to examine: just like 'a' (address), but prints addr
177 * as a procedure type, thus printing file/line info if available.
178 * Useful when called as 'x/Ai'.
179 * [91/08/13 18:14:55 jsb]
180 *
181 * Revision 2.5 91/05/14 15:33:31 mrt
182 * Correcting copyright
183 *
184 * Revision 2.4 91/02/05 17:06:20 mrt
185 * Changed to new Mach copyright
186 * [91/01/31 16:17:37 mrt]
187 *
188 * Revision 2.3 90/11/07 16:49:23 rpd
189 * Added db_search_cmd, db_search.
190 * [90/11/06 rpd]
191 *
192 * Revision 2.2 90/08/27 21:50:38 dbg
193 * Add 'r', 'z' to print and examine formats.
194 * Change calling sequence of db_disasm.
195 * db_examine sets db_prev and db_next instead of explicitly
196 * advancing dot.
197 * [90/08/20 dbg]
198 * Reflected changes in db_printsym()'s calling seq.
199 * [90/08/20 af]
200 * Reduce lint.
201 * [90/08/07 dbg]
202 * Created.
203 * [90/07/25 dbg]
204 *
205 */
206/* CMU_ENDHIST */
1c79356b
A
207/*
208 * Mach Operating System
209 * Copyright (c) 1991,1990 Carnegie Mellon University
210 * All Rights Reserved.
211 *
212 * Permission to use, copy, modify and distribute this software and its
213 * documentation is hereby granted, provided that both the copyright
214 * notice and this permission notice appear in all copies of the
215 * software, derivative works or modified versions, and any portions
216 * thereof, and that both notices appear in supporting documentation.
217 *
218 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
219 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
220 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
221 *
222 * Carnegie Mellon requests users of this software to return to
223 *
224 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
225 * School of Computer Science
226 * Carnegie Mellon University
227 * Pittsburgh PA 15213-3890
228 *
229 * any improvements or extensions that they make and grant Carnegie Mellon
230 * the rights to redistribute these changes.
231 */
232/*
233 */
234/*
235 * Author: David B. Golub, Carnegie Mellon University
236 * Date: 7/90
237 */
238#include <string.h> /* For strcpy() */
239#include <mach/boolean.h>
240#include <machine/db_machdep.h>
241
242#include <ddb/db_access.h>
243#include <ddb/db_lex.h>
244#include <ddb/db_output.h>
245#include <ddb/db_command.h>
246#include <ddb/db_sym.h>
247#include <ddb/db_task_thread.h>
248#include <ddb/db_command.h> /* For db_option() */
249#include <ddb/db_examine.h>
250#include <ddb/db_expr.h>
251#include <kern/thread.h>
252#include <kern/task.h>
253#include <mach/vm_param.h>
254
255#define db_act_to_task(thr_act) ((thr_act)? thr_act->task: TASK_NULL)
256
257char db_examine_format[TOK_STRING_SIZE] = "x";
258int db_examine_count = 1;
259db_addr_t db_examine_prev_addr = 0;
260thread_act_t db_examine_act = THR_ACT_NULL;
261
262extern int db_max_width;
263
264
265/* Prototypes for functions local to this file. XXX -- should be static!
266 */
267int db_xcdump(
268 db_addr_t addr,
269 int size,
270 int count,
271 task_t task);
272
273int db_examine_width(
274 int size,
275 int *items,
276 int *remainder);
277
278/*
279 * Examine (print) data.
280 */
281void
282db_examine_cmd(
283 db_expr_t addr,
284 int have_addr,
285 db_expr_t count,
286 char * modif)
287{
288 thread_act_t thr_act;
289 extern char db_last_modifier[];
290
291 if (modif[0] != '\0')
292 strcpy(db_examine_format, modif);
293
294 if (count == -1)
295 count = 1;
296 db_examine_count = count;
297 if (db_option(modif, 't')) {
298 if (modif == db_last_modifier)
299 thr_act = db_examine_act;
300 else if (!db_get_next_act(&thr_act, 0))
301 return;
302 } else
303 if (db_option(modif,'u'))
304 thr_act = current_act();
305 else
306 thr_act = THR_ACT_NULL;
307
308 db_examine_act = thr_act;
309 db_examine((db_addr_t) addr, db_examine_format, count,
310 db_act_to_task(thr_act));
311}
312
313void
314db_examine_forward(
315 db_expr_t addr,
316 int have_addr,
317 db_expr_t count,
318 char * modif)
319{
320 db_examine(db_next, db_examine_format, db_examine_count,
321 db_act_to_task(db_examine_act));
322}
323
324void
325db_examine_backward(
326 db_expr_t addr,
327 int have_addr,
328 db_expr_t count,
329 char * modif)
330{
331 db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
332 db_examine_format, db_examine_count,
333 db_act_to_task(db_examine_act));
334}
335
336int
337db_examine_width(
338 int size,
339 int *items,
340 int *remainder)
341{
342 int sz;
343 int entry;
344 int width;
345
346 width = size * 2 + 1;
347 sz = (db_max_width - (sizeof (void *) * 2 + 4)) / width;
348 for (entry = 1; (entry << 1) < sz; entry <<= 1)
349 continue;
350
351 sz = sizeof (void *) * 2 + 4 + entry * width;
352 while (sz + entry < db_max_width) {
353 width++;
354 sz += entry;
355 }
356 *remainder = (db_max_width - sz + 1) / 2;
357 *items = entry;
358 return width;
359}
360
361void
362db_examine(
363 db_addr_t addr,
364 char * fmt, /* format string */
365 int count, /* repeat count */
366 task_t task)
367{
368 int c;
369 db_expr_t value;
370 int size;
371 int width;
372 int leader;
373 int items;
374 int nitems;
375 char * fp;
376 db_addr_t next_addr;
377 int sz;
378
379 db_examine_prev_addr = addr;
380 while (--count >= 0) {
381 fp = fmt;
382 size = sizeof(int);
383 width = db_examine_width(size, &items, &leader);
384 while ((c = *fp++) != 0) {
385 switch (c) {
386 case 'b':
387 size = sizeof(char);
388 width = db_examine_width(size, &items, &leader);
389 break;
390 case 'h':
391 size = sizeof(short);
392 width = db_examine_width(size, &items, &leader);
393 break;
394 case 'l':
395 size = sizeof(int);
396 width = db_examine_width(size, &items, &leader);
397 break;
398 case 'q':
399 size = sizeof(long);
400 width = db_examine_width(size, &items, &leader);
401 break;
402 case 'a': /* address */
403 case 'A': /* function address */
404 /* always forces a new line */
405 if (db_print_position() != 0)
406 db_printf("\n");
407 db_prev = addr;
408 next_addr = addr + 4;
409 db_task_printsym(addr,
410 (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
411 task);
412 db_printf(":\t");
413 break;
414 case 'm':
415 db_next = db_xcdump(addr, size, count+1, task);
416 return;
417 case 't':
418 case 'u':
419 break;
420 default:
421 restart:
422 /* Reset next_addr in case we are printing in
423 multiple formats. */
424 next_addr = addr;
425 if (db_print_position() == 0) {
426 /* If we hit a new symbol, print it */
427 char * name;
428 db_addr_t off;
429
430 db_find_task_sym_and_offset(addr,&name,&off,task);
431 if (off == 0)
432 db_printf("\r%s:\n", name);
433 db_printf("%#n: ", addr);
434 for (sz = 0; sz < leader; sz++)
435 db_putchar(' ');
436 db_prev = addr;
437 nitems = items;
438 }
439
440 switch (c) {
441 case 'p': /* Addrs rendered symbolically. */
442 if( size == sizeof(void *) ) {
443 char *symName;
444 db_addr_t offset;
445
446 items = 1;
447 value = db_get_task_value( next_addr,
448 sizeof(db_expr_t), FALSE, task );
449 db_find_task_sym_and_offset( value,
450 &symName, &offset, task);
de355530 451 db_printf("\n\t*%8x(%8X) = %s",
1c79356b
A
452 next_addr, value, symName );
453 if( offset ) {
de355530 454 db_printf("+%X", offset );
1c79356b
A
455 }
456 next_addr += size;
457 }
458 break;
459 case 'r': /* signed, current radix */
460 for (sz = size, next_addr = addr;
461 sz >= sizeof (db_expr_t);
462 sz -= sizeof (db_expr_t)) {
463 if (nitems-- == 0) {
464 db_putchar('\n');
465 goto restart;
466 }
467 value = db_get_task_value(next_addr,
468 sizeof (db_expr_t),
469 TRUE,task);
de355530 470 db_printf("%-*r", width, value);
1c79356b
A
471 next_addr += sizeof (db_expr_t);
472 }
473 if (sz > 0) {
474 if (nitems-- == 0) {
475 db_putchar('\n');
476 goto restart;
477 }
478 value = db_get_task_value(next_addr, sz,
479 TRUE, task);
de355530 480 db_printf("%-*R", width, value);
1c79356b
A
481 next_addr += sz;
482 }
483 break;
de355530 484#ifdef APPLE
1c79356b 485 case 'X': /* unsigned hex */
de355530 486#endif
1c79356b
A
487 case 'x': /* unsigned hex */
488 for (sz = size, next_addr = addr;
489 sz >= sizeof (db_expr_t);
490 sz -= sizeof (db_expr_t)) {
491 if (nitems-- == 0) {
492 db_putchar('\n');
493 goto restart;
494 }
495 value = db_get_task_value(next_addr,
496 sizeof (db_expr_t),
497 FALSE,task);
de355530 498#ifdef APPLE
1c79356b 499 if ( c == 'X')
de355530 500 db_printf("%0*X ", 2*size, value);
1c79356b 501 else
de355530
A
502 db_printf("%-*x", width, value);
503#else
504 db_printf("%-*x", width, value);
505#endif
1c79356b
A
506 next_addr += sizeof (db_expr_t);
507 }
508 if (sz > 0) {
509 if (nitems-- == 0) {
510 db_putchar('\n');
511 goto restart;
512 }
513 value = db_get_task_value(next_addr, sz,
514 FALSE, task);
de355530 515#ifdef APPLE
1c79356b 516 if ( c == 'X')
de355530 517 db_printf("%0*X ", 2*size, value);
1c79356b 518 else
de355530
A
519 db_printf("%-*X", width, value);
520#else
521 db_printf("%-*X", width, value);
522#endif
1c79356b
A
523 next_addr += sz;
524 }
525 break;
526 case 'z': /* signed hex */
527 for (sz = size, next_addr = addr;
528 sz >= sizeof (db_expr_t);
529 sz -= sizeof (db_expr_t)) {
530 if (nitems-- == 0) {
531 db_putchar('\n');
532 goto restart;
533 }
534 value = db_get_task_value(next_addr,
535 sizeof (db_expr_t),
536 TRUE, task);
de355530 537 db_printf("%-*z", width, value);
1c79356b
A
538 next_addr += sizeof (db_expr_t);
539 }
540 if (sz > 0) {
541 if (nitems-- == 0) {
542 db_putchar('\n');
543 goto restart;
544 }
545 value = db_get_task_value(next_addr,sz,
546 TRUE,task);
de355530 547 db_printf("%-*Z", width, value);
1c79356b
A
548 next_addr += sz;
549 }
550 break;
551 case 'd': /* signed decimal */
552 for (sz = size, next_addr = addr;
553 sz >= sizeof (db_expr_t);
554 sz -= sizeof (db_expr_t)) {
555 if (nitems-- == 0) {
556 db_putchar('\n');
557 goto restart;
558 }
559 value = db_get_task_value(next_addr,
560 sizeof (db_expr_t),
561 TRUE,task);
de355530 562 db_printf("%-*d", width, value);
1c79356b
A
563 next_addr += sizeof (db_expr_t);
564 }
565 if (sz > 0) {
566 if (nitems-- == 0) {
567 db_putchar('\n');
568 goto restart;
569 }
570 value = db_get_task_value(next_addr, sz,
571 TRUE, task);
de355530 572 db_printf("%-*D", width, value);
1c79356b
A
573 next_addr += sz;
574 }
575 break;
576 case 'U': /* unsigned decimal */
577 case 'u':
578 for (sz = size, next_addr = addr;
579 sz >= sizeof (db_expr_t);
580 sz -= sizeof (db_expr_t)) {
581 if (nitems-- == 0) {
582 db_putchar('\n');
583 goto restart;
584 }
585 value = db_get_task_value(next_addr,
586 sizeof (db_expr_t),
587 FALSE,task);
de355530 588 db_printf("%-*u", width, value);
1c79356b
A
589 next_addr += sizeof (db_expr_t);
590 }
591 if (sz > 0) {
592 if (nitems-- == 0) {
593 db_putchar('\n');
594 goto restart;
595 }
596 value = db_get_task_value(next_addr, sz,
597 FALSE, task);
de355530 598 db_printf("%-*U", width, value);
1c79356b
A
599 next_addr += sz;
600 }
601 break;
602 case 'o': /* unsigned octal */
603 for (sz = size, next_addr = addr;
604 sz >= sizeof (db_expr_t);
605 sz -= sizeof (db_expr_t)) {
606 if (nitems-- == 0) {
607 db_putchar('\n');
608 goto restart;
609 }
610 value = db_get_task_value(next_addr,
611 sizeof (db_expr_t),
612 FALSE,task);
de355530 613 db_printf("%-*o", width, value);
1c79356b
A
614 next_addr += sizeof (db_expr_t);
615 }
616 if (sz > 0) {
617 if (nitems-- == 0) {
618 db_putchar('\n');
619 goto restart;
620 }
621 value = db_get_task_value(next_addr, sz,
622 FALSE, task);
de355530 623 db_printf("%-*o", width, value);
1c79356b
A
624 next_addr += sz;
625 }
626 break;
627 case 'c': /* character */
628 for (sz = 0, next_addr = addr;
629 sz < size;
630 sz++, next_addr++) {
631 value = db_get_task_value(next_addr,1,
632 FALSE,task);
633 if ((value >= ' ' && value <= '~') ||
634 value == '\n' ||
635 value == '\t')
de355530 636 db_printf("%c", value);
1c79356b 637 else
de355530 638 db_printf("\\%03o", value);
1c79356b
A
639 }
640 break;
641 case 's': /* null-terminated string */
642 size = 0;
643 for (;;) {
644 value = db_get_task_value(next_addr,1,
645 FALSE,task);
646 next_addr += 1;
647 size++;
648 if (value == 0)
649 break;
650 if (value >= ' ' && value <= '~')
de355530 651 db_printf("%c", value);
1c79356b 652 else
de355530 653 db_printf("\\%03o", value);
1c79356b
A
654 }
655 break;
656 case 'i': /* instruction */
657 next_addr = db_disasm(addr, FALSE, task);
658 size = next_addr - addr;
659 break;
660 case 'I': /* instruction, alternate form */
661 next_addr = db_disasm(addr, TRUE, task);
662 size = next_addr - addr;
663 break;
664 default:
665 break;
666 }
667 if (db_print_position() != 0)
668 db_end_line();
669 break;
670 }
671 }
672 addr = next_addr;
673 }
674 db_next = addr;
675}
676
677/*
678 * Print value.
679 */
680char db_print_format = 'x';
681
682void
683db_print_cmd(void)
684{
685 db_expr_t value;
686 int t;
687 task_t task = TASK_NULL;
688
689 if ((t = db_read_token()) == tSLASH) {
690 if (db_read_token() != tIDENT) {
691 db_printf("Bad modifier \"/%s\"\n", db_tok_string);
692 db_error(0);
693 /* NOTREACHED */
694 }
695 if (db_tok_string[0])
696 db_print_format = db_tok_string[0];
697 if (db_option(db_tok_string, 't')) {
698 if (db_default_act)
699 task = db_default_act->task;
700 if (db_print_format == 't')
701 db_print_format = db_tok_string[1];
702 }
703 } else
704 db_unread_token(t);
705
706 for ( ; ; ) {
707 t = db_read_token();
708 if (t == tSTRING) {
709 db_printf("%s", db_tok_string);
710 continue;
711 }
712 db_unread_token(t);
713 if (!db_expression(&value))
714 break;
715 switch (db_print_format) {
716 case 'a':
717 case 'A':
718 db_task_printsym((db_addr_t)value,
719 (db_print_format == 'a') ? DB_STGY_ANY:
720 DB_STGY_PROC,
721 task);
722 break;
723 case 'r':
de355530 724 db_printf("%11r", value);
1c79356b
A
725 break;
726 case 'x':
de355530 727 db_printf("%08x", value);
1c79356b
A
728 break;
729 case 'z':
de355530 730 db_printf("%8z", value);
1c79356b
A
731 break;
732 case 'd':
de355530 733 db_printf("%11d", value);
1c79356b
A
734 break;
735 case 'u':
de355530 736 db_printf("%11u", value);
1c79356b
A
737 break;
738 case 'o':
de355530 739 db_printf("%16o", value);
1c79356b
A
740 break;
741 case 'c':
742 value = value & 0xFF;
743 if (value >= ' ' && value <= '~')
de355530 744 db_printf("%c", value);
1c79356b 745 else
de355530 746 db_printf("\\%03o", value);
1c79356b
A
747 break;
748 default:
749 db_printf("Unknown format %c\n", db_print_format);
750 db_print_format = 'x';
751 db_error(0);
752 }
753 }
754}
755
756void
757db_print_loc(
758 db_addr_t loc,
759 task_t task)
760{
761 db_task_printsym(loc, DB_STGY_PROC, task);
762}
763
764void
765db_print_inst(
766 db_addr_t loc,
767 task_t task)
768{
769 (void) db_disasm(loc, TRUE, task);
770}
771
772void
773db_print_loc_and_inst(
774 db_addr_t loc,
775 task_t task)
776{
777 db_task_printsym(loc, DB_STGY_PROC, task);
778 db_printf(":\t");
779 (void) db_disasm(loc, TRUE, task);
780}
781
782/*
783 * Search for a value in memory.
784 * Syntax: search [/bhl] addr value [mask] [,count] [thread]
785 */
786void
787db_search_cmd(void)
788{
789 int t;
790 db_addr_t addr;
791 int size = 0;
792 db_expr_t value;
793 db_expr_t mask;
794 db_addr_t count;
795 thread_act_t thr_act;
796 boolean_t thread_flag = FALSE;
797 register char *p;
798
799 t = db_read_token();
800 if (t == tSLASH) {
801 t = db_read_token();
802 if (t != tIDENT) {
803 bad_modifier:
804 db_printf("Bad modifier \"/%s\"\n", db_tok_string);
805 db_flush_lex();
806 return;
807 }
808
809 for (p = db_tok_string; *p; p++) {
810 switch(*p) {
811 case 'b':
812 size = sizeof(char);
813 break;
814 case 'h':
815 size = sizeof(short);
816 break;
817 case 'l':
818 size = sizeof(long);
819 break;
820 case 't':
821 thread_flag = TRUE;
822 break;
823 default:
824 goto bad_modifier;
825 }
826 }
827 } else {
828 db_unread_token(t);
829 size = sizeof(int);
830 }
831
832 if (!db_expression((db_expr_t *) &addr)) {
833 db_printf("Address missing\n");
834 db_flush_lex();
835 return;
836 }
837
838 if (!db_expression(&value)) {
839 db_printf("Value missing\n");
840 db_flush_lex();
841 return;
842 }
843
844 if (!db_expression(&mask))
845 mask = ~0;
846
847 t = db_read_token();
848 if (t == tCOMMA) {
849 if (!db_expression((db_expr_t *) &count)) {
850 db_printf("Count missing\n");
851 db_flush_lex();
852 return;
853 }
854 } else {
855 db_unread_token(t);
856 count = -1; /* effectively forever */
857 }
858 if (thread_flag) {
859 if (!db_get_next_act(&thr_act, 0))
860 return;
861 } else
862 thr_act = THR_ACT_NULL;
863
864 db_search(addr, size, value, mask, count, db_act_to_task(thr_act));
865}
866
867void
868db_search(
869 db_addr_t addr,
870 int size,
871 db_expr_t value,
872 db_expr_t mask,
873 unsigned int count,
874 task_t task)
875{
876 while (count-- != 0) {
877 db_prev = addr;
878 if ((db_get_task_value(addr,size,FALSE,task) & mask) == value)
879 break;
880 addr += size;
881 }
882 db_printf("0x%x: ", addr);
883 db_next = addr;
884}
885
886#define DB_XCDUMP_NC 16
887
888int
889db_xcdump(
890 db_addr_t addr,
891 int size,
892 int count,
893 task_t task)
894{
895 register int i, n;
896 db_expr_t value;
897 int bcount;
898 db_addr_t off;
899 char *name;
900 char data[DB_XCDUMP_NC];
901
902 db_find_task_sym_and_offset(addr, &name, &off, task);
903 for (n = count*size; n > 0; n -= bcount) {
904 db_prev = addr;
905 if (off == 0) {
906 db_printf("%s:\n", name);
907 off = -1;
908 }
de355530 909 db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
1c79356b
A
910 (size != 1) ? " " : "" );
911 bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
de355530
A
912 if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
913 db_addr_t next_page_addr = trunc_page(addr+bcount-1);
1c79356b
A
914 if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
915 bcount = next_page_addr - addr;
916 }
917 db_read_bytes((vm_offset_t)addr, bcount, data, task);
918 for (i = 0; i < bcount && off != 0; i += size) {
919 if (i % 4 == 0)
920 db_printf(" ");
921 value = db_get_task_value(addr, size, FALSE, task);
de355530 922 db_printf("%0*x ", size*2, value);
1c79356b
A
923 addr += size;
924 db_find_task_sym_and_offset(addr, &name, &off, task);
925 }
926 db_printf("%*s",
927 ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
928 "");
929 bcount = i;
930 db_printf("%s*", (size != 1)? " ": "");
931 for (i = 0; i < bcount; i++) {
932 value = data[i];
de355530 933 db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
1c79356b
A
934 }
935 db_printf("*\n");
936 }
937 return(addr);
938}