Annotation of sys/ddb/db_examine.c, Revision 1.1.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