|
|
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: */ 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; 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: { 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: 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.