|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1992,1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 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. ! 11: * ! 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. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 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: */ ! 30: #include "mach_kdb.h" ! 31: #if MACH_KDB ! 32: ! 33: #include <mach/boolean.h> ! 34: #include <machine/db_machdep.h> ! 35: ! 36: #include <ddb/db_access.h> ! 37: #include <ddb/db_lex.h> ! 38: #include <ddb/db_output.h> ! 39: #include <ddb/db_command.h> ! 40: #include <ddb/db_sym.h> ! 41: #include <ddb/db_task_thread.h> ! 42: #include <kern/thread.h> ! 43: #include <kern/task.h> ! 44: #include <mach/vm_param.h> ! 45: ! 46: #define db_thread_to_task(thread) ((thread)? thread->task: TASK_NULL) ! 47: ! 48: char db_examine_format[TOK_STRING_SIZE] = "x"; ! 49: int db_examine_count = 1; ! 50: db_addr_t db_examine_prev_addr = 0; ! 51: thread_t db_examine_thread = THREAD_NULL; ! 52: ! 53: extern db_addr_t db_disasm(db_addr_t pc, boolean_t altform, task_t task); ! 54: /* instruction disassembler */ ! 55: ! 56: void db_examine();/*forwards*/ ! 57: void db_strcpy(); ! 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; ! 79: if (db_option(modif, 't')) ! 80: { ! 81: if (!db_get_next_thread(&thread, 0)) ! 82: return; ! 83: } ! 84: else ! 85: if (db_option(modif,'u')) ! 86: thread = current_thread(); ! 87: else ! 88: thread = THREAD_NULL; ! 89: ! 90: db_examine_thread = thread; ! 91: db_examine((db_addr_t) addr, db_examine_format, count, ! 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; ! 160: db_task_printsym(addr, ! 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); ! 281: ! 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: { ! 343: while (*dst++ = *src++) ! 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: { ! 461: register i, n; ! 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: } ! 483: db_read_bytes((char *)addr, bcount, data, task); ! 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: ! 506: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.