|
|
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: /*
57: * Examine (print) data.
58: */
59: /*ARGSUSED*/
60: void
61: db_examine_cmd(addr, have_addr, count, modif)
62: db_expr_t addr;
63: int have_addr;
64: db_expr_t count;
1.1.1.4 ! root 65: const char * modif;
1.1 root 66: {
67: thread_t thread;
68:
69: if (modif[0] != '\0')
70: db_strcpy(db_examine_format, modif);
71:
72: if (count == -1)
73: count = 1;
74: db_examine_count = count;
1.1.1.2 root 75: if (db_option(modif, 't'))
1.1 root 76: {
77: if (!db_get_next_thread(&thread, 0))
78: return;
79: }
1.1.1.2 root 80: else
1.1.1.4 ! root 81: if (db_option(modif, 'u'))
1.1 root 82: thread = current_thread();
83: else
84: thread = THREAD_NULL;
1.1.1.2 root 85:
1.1 root 86: db_examine_thread = thread;
1.1.1.2 root 87: db_examine((db_addr_t) addr, db_examine_format, count,
1.1 root 88: db_thread_to_task(thread));
89: }
90:
91: /* ARGSUSED */
92: void
93: db_examine_forward(addr, have_addr, count, modif)
94: db_expr_t addr;
95: int have_addr;
96: db_expr_t count;
1.1.1.4 ! root 97: const char * modif;
1.1 root 98: {
99: db_examine(db_next, db_examine_format, db_examine_count,
100: db_thread_to_task(db_examine_thread));
101: }
102:
103: /* ARGSUSED */
104: void
105: db_examine_backward(addr, have_addr, count, modif)
106: db_expr_t addr;
107: int have_addr;
108: db_expr_t count;
1.1.1.4 ! root 109: const char * modif;
1.1 root 110: {
111:
112: db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
113: db_examine_format, db_examine_count,
114: db_thread_to_task(db_examine_thread));
115: }
116:
117: void
118: db_examine(addr, fmt, count, task)
119: db_addr_t addr;
1.1.1.4 ! root 120: const char * fmt; /* format string */
1.1 root 121: int count; /* repeat count */
122: task_t task;
123: {
124: int c;
125: db_expr_t value;
126: int size; /* in bytes */
127: int width;
1.1.1.4 ! root 128: const char * fp;
1.1 root 129:
130: db_examine_prev_addr = addr;
131: while (--count >= 0) {
132: fp = fmt;
133: size = sizeof(int);
134: width = 4*size;
135: while ((c = *fp++) != 0) {
136: switch (c) {
137: case 'b':
138: size = sizeof(char);
139: width = 4*size;
140: break;
141: case 'h':
142: size = sizeof(short);
143: width = 4*size;
144: break;
145: case 'l':
146: size = sizeof(long);
147: width = 4*size;
148: break;
149: case 'a': /* address */
150: case 'A': /* function address */
151: /* always forces a new line */
152: if (db_print_position() != 0)
153: db_printf("\n");
154: db_prev = addr;
1.1.1.2 root 155: db_task_printsym(addr,
1.1 root 156: (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
157: task);
158: db_printf(":\t");
159: break;
160: case 'm':
1.1.1.4 ! root 161: db_next = db_xcdump(addr, size, count + 1, task);
1.1 root 162: return;
163: default:
164: if (db_print_position() == 0) {
165: /* If we hit a new symbol, print it */
166: char * name;
167: db_addr_t off;
168:
1.1.1.4 ! root 169: db_find_task_sym_and_offset(addr, &name, &off, task);
1.1 root 170: if (off == 0)
171: db_printf("%s:\t", name);
172: else
173: db_printf("\t\t");
174:
175: db_prev = addr;
176: }
177:
178: switch (c) {
179: case ',': /* skip one unit w/o printing */
180: addr += size;
181: break;
182:
183: case 'r': /* signed, current radix */
184: value = db_get_task_value(addr,size,TRUE,task);
185: addr += size;
186: db_printf("%-*R", width, value);
187: break;
188: case 'x': /* unsigned hex */
189: value = db_get_task_value(addr,size,FALSE,task);
190: addr += size;
191: db_printf("%-*X", width, value);
192: break;
193: case 'z': /* signed hex */
194: value = db_get_task_value(addr,size,TRUE,task);
195: addr += size;
196: db_printf("%-*Z", width, value);
197: break;
198: case 'd': /* signed decimal */
199: value = db_get_task_value(addr,size,TRUE,task);
200: addr += size;
201: db_printf("%-*D", width, value);
202: break;
203: case 'U': /* unsigned decimal */
204: value = db_get_task_value(addr,size,FALSE,task);
205: addr += size;
206: db_printf("%-*U", width, value);
207: break;
208: case 'o': /* unsigned octal */
209: value = db_get_task_value(addr,size,FALSE,task);
210: addr += size;
211: db_printf("%-*O", width, value);
212: break;
213: case 'c': /* character */
214: value = db_get_task_value(addr,1,FALSE,task);
215: addr += 1;
216: if (value >= ' ' && value <= '~')
217: db_printf("%c", value);
218: else
219: db_printf("\\%03o", value);
220: break;
221: case 's': /* null-terminated string */
222: for (;;) {
223: value = db_get_task_value(addr,1,FALSE,task);
224: addr += 1;
225: if (value == 0)
226: break;
227: if (value >= ' ' && value <= '~')
228: db_printf("%c", value);
229: else
230: db_printf("\\%03o", value);
231: }
232: break;
233: case 'i': /* instruction */
234: addr = db_disasm(addr, FALSE, task);
235: break;
236: case 'I': /* instruction, alternate form */
237: addr = db_disasm(addr, TRUE, task);
238: break;
239: default:
240: break;
241: }
242: if (db_print_position() != 0)
243: db_end_line();
244: break;
245: }
246: }
247: }
248: db_next = addr;
249: }
250:
251: /*
252: * Print value.
253: */
254: char db_print_format = 'x';
255:
256: /*ARGSUSED*/
257: void
1.1.1.4 ! root 258: db_print_cmd(void)
1.1 root 259: {
260: db_expr_t value;
261: int t;
262: task_t task = TASK_NULL;
263:
264: if ((t = db_read_token()) == tSLASH) {
265: if (db_read_token() != tIDENT) {
266: db_printf("Bad modifier \"/%s\"\n", db_tok_string);
267: db_error(0);
268: /* NOTREACHED */
269: }
270: if (db_tok_string[0])
271: db_print_format = db_tok_string[0];
272: if (db_option(db_tok_string, 't') && db_default_thread)
273: task = db_default_thread->task;
274: } else
275: db_unread_token(t);
1.1.1.2 root 276:
1.1 root 277: for ( ; ; ) {
278: t = db_read_token();
279: if (t == tSTRING) {
280: db_printf("%s", db_tok_string);
281: continue;
282: }
283: db_unread_token(t);
284: if (!db_expression(&value))
285: break;
286: switch (db_print_format) {
287: case 'a':
288: db_task_printsym((db_addr_t)value, DB_STGY_ANY, task);
289: break;
290: case 'r':
291: db_printf("%*r", 3+2*sizeof(db_expr_t), value);
292: break;
293: case 'x':
294: db_printf("%*x", 2*sizeof(db_expr_t), value);
295: break;
296: case 'z':
297: db_printf("%*z", 2*sizeof(db_expr_t), value);
298: break;
299: case 'd':
300: db_printf("%*d", 3+2*sizeof(db_expr_t), value);
301: break;
302: case 'u':
303: db_printf("%*u", 3+2*sizeof(db_expr_t), value);
304: break;
305: case 'o':
306: db_printf("%o", 4*sizeof(db_expr_t), value);
307: break;
308: case 'c':
309: value = value & 0xFF;
310: if (value >= ' ' && value <= '~')
311: db_printf("%c", value);
312: else
313: db_printf("\\%03o", value);
314: break;
315: default:
316: db_printf("Unknown format %c\n", db_print_format);
317: db_print_format = 'x';
318: db_error(0);
319: }
320: }
321: }
322:
323: void
1.1.1.4 ! root 324: db_print_loc_and_inst(
! 325: db_addr_t loc,
! 326: task_t task)
1.1 root 327: {
328: db_task_printsym(loc, DB_STGY_PROC, task);
329: db_printf(":\t");
330: (void) db_disasm(loc, TRUE, task);
331: }
332:
333: void
334: db_strcpy(dst, src)
1.1.1.4 ! root 335: char *dst;
! 336: const char *src;
1.1 root 337: {
1.1.1.3 root 338: while ((*dst++ = *src++))
1.1 root 339: ;
340: }
341:
342: /*
343: * Search for a value in memory.
344: * Syntax: search [/bhl] addr value [mask] [,count] [thread]
345: */
346: void
1.1.1.4 ! root 347: db_search_cmd(void)
1.1 root 348: {
349: int t;
350: db_addr_t addr;
351: int size = 0;
352: db_expr_t value;
353: db_expr_t mask;
354: db_addr_t count;
355: thread_t thread;
356: boolean_t thread_flag = FALSE;
1.1.1.4 ! root 357: char *p;
1.1 root 358:
359: t = db_read_token();
360: if (t == tSLASH) {
361: t = db_read_token();
362: if (t != tIDENT) {
363: bad_modifier:
364: db_printf("Bad modifier \"/%s\"\n", db_tok_string);
365: db_flush_lex();
366: return;
367: }
368:
369: for (p = db_tok_string; *p; p++) {
370: switch(*p) {
371: case 'b':
372: size = sizeof(char);
373: break;
374: case 'h':
375: size = sizeof(short);
376: break;
377: case 'l':
378: size = sizeof(long);
379: break;
380: case 't':
381: thread_flag = TRUE;
382: break;
383: default:
384: goto bad_modifier;
385: }
386: }
387: } else {
388: db_unread_token(t);
389: size = sizeof(int);
390: }
391:
1.1.1.4 ! root 392: if (!db_expression((db_expr_t *)&addr)) {
1.1 root 393: db_printf("Address missing\n");
394: db_flush_lex();
395: return;
396: }
397:
398: if (!db_expression(&value)) {
399: db_printf("Value missing\n");
400: db_flush_lex();
401: return;
402: }
403:
404: if (!db_expression(&mask))
405: mask = ~0;
406:
407: t = db_read_token();
408: if (t == tCOMMA) {
1.1.1.4 ! root 409: if (!db_expression((db_expr_t *)&count)) {
1.1 root 410: db_printf("Count missing\n");
411: db_flush_lex();
412: return;
413: }
414: } else {
415: db_unread_token(t);
416: count = -1; /* effectively forever */
417: }
418: if (thread_flag) {
419: if (!db_get_next_thread(&thread, 0))
420: return;
421: } else
422: thread = THREAD_NULL;
423:
424: db_search(addr, size, value, mask, count, db_thread_to_task(thread));
425: }
426:
427: void
1.1.1.4 ! root 428: db_search(
! 429: db_addr_t addr,
! 430: int size,
! 431: db_expr_t value,
! 432: db_expr_t mask,
! 433: unsigned int count,
! 434: task_t task)
1.1 root 435: {
436: while (count-- != 0) {
437: db_prev = addr;
1.1.1.4 ! root 438: if ((db_get_task_value(addr, size, FALSE, task) & mask) == value)
1.1 root 439: break;
440: addr += size;
441: }
442: db_next = addr;
443: }
444:
445: #define DB_XCDUMP_NC 16
446:
447: int
1.1.1.4 ! root 448: db_xcdump(
! 449: db_addr_t addr,
! 450: int size,
! 451: int count,
! 452: task_t task)
1.1 root 453: {
1.1.1.4 ! root 454: int i, n;
1.1 root 455: db_expr_t value;
456: int bcount;
457: db_addr_t off;
458: char *name;
459: char data[DB_XCDUMP_NC];
460:
461: db_find_task_sym_and_offset(addr, &name, &off, task);
462: for (n = count*size; n > 0; n -= bcount) {
463: db_prev = addr;
464: if (off == 0) {
465: db_printf("%s:\n", name);
466: off = -1;
467: }
468: db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
469: (size != 1)? " ": "");
470: bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
471: if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
472: db_addr_t next_page_addr = trunc_page(addr+bcount-1);
473: if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
474: bcount = next_page_addr - addr;
475: }
1.1.1.3 root 476: db_read_bytes(addr, bcount, data, task);
1.1 root 477: for (i = 0; i < bcount && off != 0; i += size) {
478: if (i % 4 == 0)
479: db_printf(" ");
480: value = db_get_task_value(addr, size, FALSE, task);
481: db_printf("%0*x ", size*2, value);
482: addr += size;
483: db_find_task_sym_and_offset(addr, &name, &off, task);
484: }
485: db_printf("%*s",
486: ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
487: "");
488: bcount = i;
489: db_printf("%s*", (size != 1)? " ": "");
490: for (i = 0; i < bcount; i++) {
491: value = data[i];
492: db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
493: }
494: db_printf("*\n");
495: }
496: return(addr);
497: }
498:
1.1.1.2 root 499: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.