|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1992,1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
1.1.1.2 root 5: *
1.1 root 6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
1.1.1.2 root 11: *
1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2 root 15: *
1.1 root 16: * Carnegie Mellon requests users of this software to return to
1.1.1.2 root 17: *
1.1 root 18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
1.1.1.2 root 22: *
1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Author: David B. Golub, Carnegie Mellon University
28: * Date: 7/90
29: */
1.1.1.3 ! root 30:
1.1 root 31: #if MACH_KDB
32:
33: #include <mach/boolean.h>
34: #include <machine/db_machdep.h>
1.1.1.3 ! root 35: #include <machine/db_interface.h>
1.1 root 36:
37: #include <ddb/db_access.h>
38: #include <ddb/db_lex.h>
39: #include <ddb/db_output.h>
40: #include <ddb/db_command.h>
41: #include <ddb/db_sym.h>
42: #include <ddb/db_task_thread.h>
1.1.1.3 ! root 43: #include <ddb/db_examine.h>
! 44: #include <ddb/db_expr.h>
1.1 root 45: #include <kern/thread.h>
46: #include <kern/task.h>
47: #include <mach/vm_param.h>
48:
49: #define db_thread_to_task(thread) ((thread)? thread->task: TASK_NULL)
50:
51: char db_examine_format[TOK_STRING_SIZE] = "x";
52: int db_examine_count = 1;
53: db_addr_t db_examine_prev_addr = 0;
54: thread_t db_examine_thread = THREAD_NULL;
55:
56: extern db_addr_t db_disasm(db_addr_t pc, boolean_t altform, task_t task);
57: /* instruction disassembler */
58:
59: /*
60: * Examine (print) data.
61: */
62: /*ARGSUSED*/
63: void
64: db_examine_cmd(addr, have_addr, count, modif)
65: db_expr_t addr;
66: int have_addr;
67: db_expr_t count;
68: char * modif;
69: {
70: thread_t thread;
71: boolean_t db_option();
72:
73: if (modif[0] != '\0')
74: db_strcpy(db_examine_format, modif);
75:
76: if (count == -1)
77: count = 1;
78: db_examine_count = count;
1.1.1.2 root 79: if (db_option(modif, 't'))
1.1 root 80: {
81: if (!db_get_next_thread(&thread, 0))
82: return;
83: }
1.1.1.2 root 84: else
1.1 root 85: if (db_option(modif,'u'))
86: thread = current_thread();
87: else
88: thread = THREAD_NULL;
1.1.1.2 root 89:
1.1 root 90: db_examine_thread = thread;
1.1.1.2 root 91: db_examine((db_addr_t) addr, db_examine_format, count,
1.1 root 92: db_thread_to_task(thread));
93: }
94:
95: /* ARGSUSED */
96: void
97: db_examine_forward(addr, have_addr, count, modif)
98: db_expr_t addr;
99: int have_addr;
100: db_expr_t count;
101: char * modif;
102: {
103: db_examine(db_next, db_examine_format, db_examine_count,
104: db_thread_to_task(db_examine_thread));
105: }
106:
107: /* ARGSUSED */
108: void
109: db_examine_backward(addr, have_addr, count, modif)
110: db_expr_t addr;
111: int have_addr;
112: db_expr_t count;
113: char * modif;
114: {
115:
116: db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
117: db_examine_format, db_examine_count,
118: db_thread_to_task(db_examine_thread));
119: }
120:
121: void
122: db_examine(addr, fmt, count, task)
123: register
124: db_addr_t addr;
125: char * fmt; /* format string */
126: int count; /* repeat count */
127: task_t task;
128: {
129: int c;
130: db_expr_t value;
131: int size; /* in bytes */
132: int width;
133: char * fp;
134:
135: db_examine_prev_addr = addr;
136: while (--count >= 0) {
137: fp = fmt;
138: size = sizeof(int);
139: width = 4*size;
140: while ((c = *fp++) != 0) {
141: switch (c) {
142: case 'b':
143: size = sizeof(char);
144: width = 4*size;
145: break;
146: case 'h':
147: size = sizeof(short);
148: width = 4*size;
149: break;
150: case 'l':
151: size = sizeof(long);
152: width = 4*size;
153: break;
154: case 'a': /* address */
155: case 'A': /* function address */
156: /* always forces a new line */
157: if (db_print_position() != 0)
158: db_printf("\n");
159: db_prev = addr;
1.1.1.2 root 160: db_task_printsym(addr,
1.1 root 161: (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
162: task);
163: db_printf(":\t");
164: break;
165: case 'm':
166: db_next = db_xcdump(addr, size, count+1, task);
167: return;
168: default:
169: if (db_print_position() == 0) {
170: /* If we hit a new symbol, print it */
171: char * name;
172: db_addr_t off;
173:
174: db_find_task_sym_and_offset(addr,&name,&off,task);
175: if (off == 0)
176: db_printf("%s:\t", name);
177: else
178: db_printf("\t\t");
179:
180: db_prev = addr;
181: }
182:
183: switch (c) {
184: case ',': /* skip one unit w/o printing */
185: addr += size;
186: break;
187:
188: case 'r': /* signed, current radix */
189: value = db_get_task_value(addr,size,TRUE,task);
190: addr += size;
191: db_printf("%-*R", width, value);
192: break;
193: case 'x': /* unsigned hex */
194: value = db_get_task_value(addr,size,FALSE,task);
195: addr += size;
196: db_printf("%-*X", width, value);
197: break;
198: case 'z': /* signed hex */
199: value = db_get_task_value(addr,size,TRUE,task);
200: addr += size;
201: db_printf("%-*Z", width, value);
202: break;
203: case 'd': /* signed decimal */
204: value = db_get_task_value(addr,size,TRUE,task);
205: addr += size;
206: db_printf("%-*D", width, value);
207: break;
208: case 'U': /* unsigned decimal */
209: value = db_get_task_value(addr,size,FALSE,task);
210: addr += size;
211: db_printf("%-*U", width, value);
212: break;
213: case 'o': /* unsigned octal */
214: value = db_get_task_value(addr,size,FALSE,task);
215: addr += size;
216: db_printf("%-*O", width, value);
217: break;
218: case 'c': /* character */
219: value = db_get_task_value(addr,1,FALSE,task);
220: addr += 1;
221: if (value >= ' ' && value <= '~')
222: db_printf("%c", value);
223: else
224: db_printf("\\%03o", value);
225: break;
226: case 's': /* null-terminated string */
227: for (;;) {
228: value = db_get_task_value(addr,1,FALSE,task);
229: addr += 1;
230: if (value == 0)
231: break;
232: if (value >= ' ' && value <= '~')
233: db_printf("%c", value);
234: else
235: db_printf("\\%03o", value);
236: }
237: break;
238: case 'i': /* instruction */
239: addr = db_disasm(addr, FALSE, task);
240: break;
241: case 'I': /* instruction, alternate form */
242: addr = db_disasm(addr, TRUE, task);
243: break;
244: default:
245: break;
246: }
247: if (db_print_position() != 0)
248: db_end_line();
249: break;
250: }
251: }
252: }
253: db_next = addr;
254: }
255:
256: /*
257: * Print value.
258: */
259: char db_print_format = 'x';
260:
261: /*ARGSUSED*/
262: void
263: db_print_cmd()
264: {
265: db_expr_t value;
266: int t;
267: task_t task = TASK_NULL;
268:
269: if ((t = db_read_token()) == tSLASH) {
270: if (db_read_token() != tIDENT) {
271: db_printf("Bad modifier \"/%s\"\n", db_tok_string);
272: db_error(0);
273: /* NOTREACHED */
274: }
275: if (db_tok_string[0])
276: db_print_format = db_tok_string[0];
277: if (db_option(db_tok_string, 't') && db_default_thread)
278: task = db_default_thread->task;
279: } else
280: db_unread_token(t);
1.1.1.2 root 281:
1.1 root 282: for ( ; ; ) {
283: t = db_read_token();
284: if (t == tSTRING) {
285: db_printf("%s", db_tok_string);
286: continue;
287: }
288: db_unread_token(t);
289: if (!db_expression(&value))
290: break;
291: switch (db_print_format) {
292: case 'a':
293: db_task_printsym((db_addr_t)value, DB_STGY_ANY, task);
294: break;
295: case 'r':
296: db_printf("%*r", 3+2*sizeof(db_expr_t), value);
297: break;
298: case 'x':
299: db_printf("%*x", 2*sizeof(db_expr_t), value);
300: break;
301: case 'z':
302: db_printf("%*z", 2*sizeof(db_expr_t), value);
303: break;
304: case 'd':
305: db_printf("%*d", 3+2*sizeof(db_expr_t), value);
306: break;
307: case 'u':
308: db_printf("%*u", 3+2*sizeof(db_expr_t), value);
309: break;
310: case 'o':
311: db_printf("%o", 4*sizeof(db_expr_t), value);
312: break;
313: case 'c':
314: value = value & 0xFF;
315: if (value >= ' ' && value <= '~')
316: db_printf("%c", value);
317: else
318: db_printf("\\%03o", value);
319: break;
320: default:
321: db_printf("Unknown format %c\n", db_print_format);
322: db_print_format = 'x';
323: db_error(0);
324: }
325: }
326: }
327:
328: void
329: db_print_loc_and_inst(loc, task)
330: db_addr_t loc;
331: task_t task;
332: {
333: db_task_printsym(loc, DB_STGY_PROC, task);
334: db_printf(":\t");
335: (void) db_disasm(loc, TRUE, task);
336: }
337:
338: void
339: db_strcpy(dst, src)
340: register char *dst;
341: register char *src;
342: {
1.1.1.3 ! root 343: while ((*dst++ = *src++))
1.1 root 344: ;
345: }
346:
347: void db_search(); /*forward*/
348: /*
349: * Search for a value in memory.
350: * Syntax: search [/bhl] addr value [mask] [,count] [thread]
351: */
352: void
353: db_search_cmd()
354: {
355: int t;
356: db_addr_t addr;
357: int size = 0;
358: db_expr_t value;
359: db_expr_t mask;
360: db_addr_t count;
361: thread_t thread;
362: boolean_t thread_flag = FALSE;
363: register char *p;
364:
365: t = db_read_token();
366: if (t == tSLASH) {
367: t = db_read_token();
368: if (t != tIDENT) {
369: bad_modifier:
370: db_printf("Bad modifier \"/%s\"\n", db_tok_string);
371: db_flush_lex();
372: return;
373: }
374:
375: for (p = db_tok_string; *p; p++) {
376: switch(*p) {
377: case 'b':
378: size = sizeof(char);
379: break;
380: case 'h':
381: size = sizeof(short);
382: break;
383: case 'l':
384: size = sizeof(long);
385: break;
386: case 't':
387: thread_flag = TRUE;
388: break;
389: default:
390: goto bad_modifier;
391: }
392: }
393: } else {
394: db_unread_token(t);
395: size = sizeof(int);
396: }
397:
398: if (!db_expression(&addr)) {
399: db_printf("Address missing\n");
400: db_flush_lex();
401: return;
402: }
403:
404: if (!db_expression(&value)) {
405: db_printf("Value missing\n");
406: db_flush_lex();
407: return;
408: }
409:
410: if (!db_expression(&mask))
411: mask = ~0;
412:
413: t = db_read_token();
414: if (t == tCOMMA) {
415: if (!db_expression(&count)) {
416: db_printf("Count missing\n");
417: db_flush_lex();
418: return;
419: }
420: } else {
421: db_unread_token(t);
422: count = -1; /* effectively forever */
423: }
424: if (thread_flag) {
425: if (!db_get_next_thread(&thread, 0))
426: return;
427: } else
428: thread = THREAD_NULL;
429:
430: db_search(addr, size, value, mask, count, db_thread_to_task(thread));
431: }
432:
433: void
434: db_search(addr, size, value, mask, count, task)
435: register
436: db_addr_t addr;
437: int size;
438: db_expr_t value;
439: db_expr_t mask;
440: unsigned int count;
441: task_t task;
442: {
443: while (count-- != 0) {
444: db_prev = addr;
445: if ((db_get_task_value(addr,size,FALSE,task) & mask) == value)
446: break;
447: addr += size;
448: }
449: db_next = addr;
450: }
451:
452: #define DB_XCDUMP_NC 16
453:
454: int
455: db_xcdump(addr, size, count, task)
456: db_addr_t addr;
457: int size;
458: int count;
459: task_t task;
460: {
1.1.1.3 ! root 461: register int i, n;
1.1 root 462: db_expr_t value;
463: int bcount;
464: db_addr_t off;
465: char *name;
466: char data[DB_XCDUMP_NC];
467:
468: db_find_task_sym_and_offset(addr, &name, &off, task);
469: for (n = count*size; n > 0; n -= bcount) {
470: db_prev = addr;
471: if (off == 0) {
472: db_printf("%s:\n", name);
473: off = -1;
474: }
475: db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
476: (size != 1)? " ": "");
477: bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
478: if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
479: db_addr_t next_page_addr = trunc_page(addr+bcount-1);
480: if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
481: bcount = next_page_addr - addr;
482: }
1.1.1.3 ! root 483: db_read_bytes(addr, bcount, data, task);
1.1 root 484: for (i = 0; i < bcount && off != 0; i += size) {
485: if (i % 4 == 0)
486: db_printf(" ");
487: value = db_get_task_value(addr, size, FALSE, task);
488: db_printf("%0*x ", size*2, value);
489: addr += size;
490: db_find_task_sym_and_offset(addr, &name, &off, task);
491: }
492: db_printf("%*s",
493: ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
494: "");
495: bcount = i;
496: db_printf("%s*", (size != 1)? " ": "");
497: for (i = 0; i < bcount; i++) {
498: value = data[i];
499: db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
500: }
501: db_printf("*\n");
502: }
503: return(addr);
504: }
505:
1.1.1.2 root 506: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.