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