Annotation of sys/ddb/db_examine.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_examine.c,v 1.13 2007/03/15 17:10:22 miod Exp $ */
! 2: /* $NetBSD: db_examine.c,v 1.11 1996/03/30 22:30:07 christos Exp $ */
! 3:
! 4: /*
! 5: * Mach Operating System
! 6: * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
! 7: * All Rights Reserved.
! 8: *
! 9: * Permission to use, copy, modify and distribute this software and its
! 10: * documentation is hereby granted, provided that both the copyright
! 11: * notice and this permission notice appear in all copies of the
! 12: * software, derivative works or modified versions, and any portions
! 13: * thereof, and that both notices appear in supporting documentation.
! 14: *
! 15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
! 17: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 18: *
! 19: * Carnegie Mellon requests users of this software to return to
! 20: *
! 21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 22: * School of Computer Science
! 23: * Carnegie Mellon University
! 24: * Pittsburgh PA 15213-3890
! 25: *
! 26: * any improvements or extensions that they make and grant Carnegie Mellon
! 27: * the rights to redistribute these changes.
! 28: *
! 29: * Author: David B. Golub, Carnegie Mellon University
! 30: * Date: 7/90
! 31: */
! 32:
! 33: #include <sys/param.h>
! 34: #include <sys/proc.h>
! 35:
! 36: #include <uvm/uvm_extern.h>
! 37:
! 38: #include <machine/db_machdep.h> /* type definitions */
! 39:
! 40: #include <ddb/db_lex.h>
! 41: #include <ddb/db_output.h>
! 42: #include <ddb/db_command.h>
! 43: #include <ddb/db_sym.h>
! 44: #include <ddb/db_access.h>
! 45: #include <ddb/db_extern.h>
! 46: #include <ddb/db_interface.h>
! 47:
! 48: char db_examine_format[TOK_STRING_SIZE] = "x";
! 49:
! 50: /*
! 51: * Examine (print) data. Syntax is:
! 52: * x/[bhlq][cdiorsuxz]*
! 53: * For example, the command:
! 54: * x/bxxxx
! 55: * should print:
! 56: * address: 01 23 45 67
! 57: */
! 58: /*ARGSUSED*/
! 59: void
! 60: db_examine_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 61: {
! 62: if (modif[0] != '\0')
! 63: db_strlcpy(db_examine_format, modif, sizeof(db_examine_format));
! 64:
! 65: if (count == -1)
! 66: count = 1;
! 67:
! 68: db_examine((db_addr_t)addr, db_examine_format, count);
! 69: }
! 70:
! 71: void
! 72: db_examine(db_addr_t addr, char *fmt, int count)
! 73: {
! 74: int c;
! 75: db_expr_t value;
! 76: int size;
! 77: int width;
! 78: char * fp;
! 79:
! 80: while (--count >= 0) {
! 81: fp = fmt;
! 82: size = 4;
! 83: width = 12;
! 84: while ((c = *fp++) != 0) {
! 85: if (db_print_position() == 0) {
! 86: /* Always print the address. */
! 87: db_printsym(addr, DB_STGY_ANY, db_printf);
! 88: db_printf(":\t");
! 89: db_prev = addr;
! 90: }
! 91: switch (c) {
! 92: case 'b': /* byte */
! 93: size = 1;
! 94: width = 4;
! 95: break;
! 96: case 'h': /* half-word */
! 97: size = 2;
! 98: width = 8;
! 99: break;
! 100: case 'l': /* long-word */
! 101: size = 4;
! 102: width = 12;
! 103: break;
! 104: #ifdef __LP64__
! 105: case 'q': /* quad-word */
! 106: size = 8;
! 107: width = 20;
! 108: break;
! 109: #endif
! 110: case 'a': /* address */
! 111: db_printf("= 0x%lx\n", (long)addr);
! 112: break;
! 113: case 'r': /* signed, current radix */
! 114: value = db_get_value(addr, size, TRUE);
! 115: addr += size;
! 116: db_printf("%-*lr", width, (long)value);
! 117: break;
! 118: case 'x': /* unsigned hex */
! 119: value = db_get_value(addr, size, FALSE);
! 120: addr += size;
! 121: db_printf("%-*lx", width, (long)value);
! 122: break;
! 123: case 'z': /* signed hex */
! 124: value = db_get_value(addr, size, TRUE);
! 125: addr += size;
! 126: db_printf("%-*lz", width, (long)value);
! 127: break;
! 128: case 'd': /* signed decimal */
! 129: value = db_get_value(addr, size, TRUE);
! 130: addr += size;
! 131: db_printf("%-*ld", width, (long)value);
! 132: break;
! 133: case 'u': /* unsigned decimal */
! 134: value = db_get_value(addr, size, FALSE);
! 135: addr += size;
! 136: db_printf("%-*lu", width, (long)value);
! 137: break;
! 138: case 'o': /* unsigned octal */
! 139: value = db_get_value(addr, size, FALSE);
! 140: addr += size;
! 141: db_printf("%-*lo", width, value);
! 142: break;
! 143: case 'c': /* character */
! 144: value = db_get_value(addr, 1, FALSE);
! 145: addr += 1;
! 146: if (value >= ' ' && value <= '~')
! 147: db_printf("%c", value);
! 148: else
! 149: db_printf("\\%03o", value);
! 150: break;
! 151: case 's': /* null-terminated string */
! 152: for (;;) {
! 153: value = db_get_value(addr, 1, FALSE);
! 154: addr += 1;
! 155: if (value == 0)
! 156: break;
! 157: if (value >= ' ' && value <= '~')
! 158: db_printf("%c", value);
! 159: else
! 160: db_printf("\\%03o", value);
! 161: }
! 162: break;
! 163: case 'i': /* instruction */
! 164: addr = db_disasm(addr, FALSE);
! 165: break;
! 166: case 'I': /* instruction, alternate form */
! 167: addr = db_disasm(addr, TRUE);
! 168: break;
! 169: default:
! 170: break;
! 171: }
! 172: if (db_print_position() != 0)
! 173: db_end_line(width);
! 174: }
! 175: }
! 176: db_next = addr;
! 177: }
! 178:
! 179: /*
! 180: * Print value.
! 181: */
! 182: char db_print_format = 'x';
! 183:
! 184: /*ARGSUSED*/
! 185: void
! 186: db_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 187: {
! 188: db_expr_t value;
! 189:
! 190: if (modif[0] != '\0')
! 191: db_print_format = modif[0];
! 192:
! 193: switch (db_print_format) {
! 194: case 'a':
! 195: db_printsym((db_addr_t)addr, DB_STGY_ANY, db_printf);
! 196: break;
! 197: case 'r':
! 198: db_printf("%*r", sizeof(db_expr_t) * 2 * 6 / 5, addr);
! 199: break;
! 200: case 'x':
! 201: db_printf("%*x", sizeof(db_expr_t) * 2, addr);
! 202: break;
! 203: case 'z':
! 204: db_printf("%*z", sizeof(db_expr_t) * 2, addr);
! 205: break;
! 206: case 'd':
! 207: db_printf("%*d", sizeof(db_expr_t) * 2 * 6 / 5, addr);
! 208: break;
! 209: case 'u':
! 210: db_printf("%*u", sizeof(db_expr_t) * 2 * 6 / 5, addr);
! 211: break;
! 212: case 'o':
! 213: db_printf("%*o", sizeof(db_expr_t) * 2 * 4 / 3, addr);
! 214: break;
! 215: case 'c':
! 216: value = addr & 0xFF;
! 217: if (value >= ' ' && value <= '~')
! 218: db_printf("%c", value);
! 219: else
! 220: db_printf("\\%03o", value);
! 221: break;
! 222: }
! 223: db_printf("\n");
! 224: }
! 225:
! 226: void
! 227: db_print_loc_and_inst(db_addr_t loc)
! 228: {
! 229: db_printsym(loc, DB_STGY_PROC, db_printf);
! 230: db_printf(":\t");
! 231: (void) db_disasm(loc, FALSE);
! 232: }
! 233:
! 234: /* local copy is needed here so that we can trace strlcpy() in libkern */
! 235: size_t
! 236: db_strlcpy(char *dst, const char *src, size_t siz)
! 237: {
! 238: char *d = dst;
! 239: const char *s = src;
! 240: size_t n = siz;
! 241:
! 242: /* Copy as many bytes as will fit */
! 243: if (n != 0 && --n != 0) {
! 244: do {
! 245: if ((*d++ = *s++) == 0)
! 246: break;
! 247: } while (--n != 0);
! 248: }
! 249:
! 250: /* Not enough room in dst, add NUL and traverse rest of src */
! 251: if (n == 0) {
! 252: if (siz != 0)
! 253: *d = '\0'; /* NUL-terminate dst */
! 254: while (*s++)
! 255: ;
! 256: }
! 257:
! 258: return(s - src - 1); /* count does not include NUL */
! 259: }
! 260:
! 261: /*
! 262: * Search for a value in memory.
! 263: * Syntax: search [/bhl] addr value [mask] [,count]
! 264: */
! 265: /*ARGSUSED*/
! 266: void
! 267: db_search_cmd(db_expr_t daddr, int have_addr, db_expr_t dcount, char *modif)
! 268: {
! 269: int t;
! 270: db_addr_t addr;
! 271: int size;
! 272: db_expr_t value;
! 273: db_expr_t mask;
! 274: db_expr_t count;
! 275:
! 276: t = db_read_token();
! 277: if (t == tSLASH) {
! 278: t = db_read_token();
! 279: if (t != tIDENT) {
! 280: bad_modifier:
! 281: db_printf("Bad modifier\n");
! 282: db_flush_lex();
! 283: return;
! 284: }
! 285:
! 286: if (!strcmp(db_tok_string, "b"))
! 287: size = 1;
! 288: else if (!strcmp(db_tok_string, "h"))
! 289: size = 2;
! 290: else if (!strcmp(db_tok_string, "l"))
! 291: size = 4;
! 292: else
! 293: goto bad_modifier;
! 294: } else {
! 295: db_unread_token(t);
! 296: size = 4;
! 297: }
! 298:
! 299: if (!db_expression(&value)) {
! 300: db_printf("Address missing\n");
! 301: db_flush_lex();
! 302: return;
! 303: }
! 304: addr = (db_addr_t) value;
! 305:
! 306: if (!db_expression(&value)) {
! 307: db_printf("Value missing\n");
! 308: db_flush_lex();
! 309: return;
! 310: }
! 311:
! 312: if (!db_expression(&mask))
! 313: mask = (int) ~0;
! 314:
! 315: t = db_read_token();
! 316: if (t == tCOMMA) {
! 317: if (!db_expression(&count)) {
! 318: db_printf("Count missing\n");
! 319: db_flush_lex();
! 320: return;
! 321: }
! 322: } else {
! 323: db_unread_token(t);
! 324: count = -1; /* forever */
! 325: }
! 326: db_skip_to_eol();
! 327:
! 328: db_search(addr, size, value, mask, count);
! 329: }
! 330:
! 331: void
! 332: db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask,
! 333: db_expr_t count)
! 334: {
! 335: /* Negative counts means forever. */
! 336: while (count < 0 || count-- != 0) {
! 337: db_prev = addr;
! 338: if ((db_get_value(addr, size, FALSE) & mask) == value)
! 339: break;
! 340: addr += size;
! 341: }
! 342: db_next = addr;
! 343: }
CVSweb