FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_examine.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 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
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 Software.Distribution@CS.CMU.EDU
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 the
24 * rights to redistribute these changes.
25 *
26 * $FreeBSD$
27 */
28
29 /*
30 * Author: David B. Golub, Carnegie Mellon University
31 * Date: 7/90
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36
37 #include <ddb/ddb.h>
38
39 #include <ddb/db_lex.h>
40 #include <ddb/db_output.h>
41 #include <ddb/db_command.h>
42 #include <ddb/db_sym.h>
43 #include <ddb/db_access.h>
44
45 static char db_examine_format[TOK_STRING_SIZE] = "x";
46
47 static void db_examine __P((db_addr_t, char *, int));
48 static void db_search __P((db_addr_t, int, db_expr_t, db_expr_t, u_int));
49
50 /*
51 * Examine (print) data.
52 */
53 /*ARGSUSED*/
54 void
55 db_examine_cmd(addr, have_addr, count, modif)
56 db_expr_t addr;
57 boolean_t have_addr;
58 db_expr_t count;
59 char * modif;
60 {
61 if (modif[0] != '\0')
62 db_strcpy(db_examine_format, modif);
63
64 if (count == -1)
65 count = 1;
66
67 db_examine((db_addr_t) addr, db_examine_format, count);
68 }
69
70 static void
71 db_examine(addr, fmt, count)
72 register
73 db_addr_t addr;
74 char * fmt; /* format string */
75 int count; /* repeat count */
76 {
77 int c;
78 db_expr_t value;
79 int size;
80 int width;
81 char * fp;
82
83 while (--count >= 0) {
84 fp = fmt;
85 size = 4;
86 width = 16;
87 while ((c = *fp++) != 0) {
88 switch (c) {
89 case 'b':
90 size = 1;
91 width = 4;
92 break;
93 case 'h':
94 size = 2;
95 width = 8;
96 break;
97 case 'l':
98 size = 4;
99 width = 16;
100 break;
101 case 'g':
102 size = 8;
103 width = 32;
104 break;
105 case 'a': /* address */
106 /* always forces a new line */
107 if (db_print_position() != 0)
108 db_printf("\n");
109 db_prev = addr;
110 db_printsym(addr, DB_STGY_ANY);
111 db_printf(":\t");
112 break;
113 default:
114 if (db_print_position() == 0) {
115 /* Print the address. */
116 db_printsym(addr, DB_STGY_ANY);
117 db_printf(":\t");
118 db_prev = addr;
119 }
120
121 switch (c) {
122 case 'r': /* signed, current radix */
123 value = db_get_value(addr, size, TRUE);
124 addr += size;
125 db_printf("%+-*lr", width, (long)value);
126 break;
127 case 'x': /* unsigned hex */
128 value = db_get_value(addr, size, FALSE);
129 addr += size;
130 db_printf("%-*lx", width, (long)value);
131 break;
132 case 'z': /* signed hex */
133 value = db_get_value(addr, size, TRUE);
134 addr += size;
135 db_printf("%-*lz", width, (long)value);
136 break;
137 case 'd': /* signed decimal */
138 value = db_get_value(addr, size, TRUE);
139 addr += size;
140 db_printf("%-*ld", width, (long)value);
141 break;
142 case 'u': /* unsigned decimal */
143 value = db_get_value(addr, size, FALSE);
144 addr += size;
145 db_printf("%-*lu", width, (long)value);
146 break;
147 case 'o': /* unsigned octal */
148 value = db_get_value(addr, size, FALSE);
149 addr += size;
150 db_printf("%-*lo", width, (long)value);
151 break;
152 case 'c': /* character */
153 value = db_get_value(addr, 1, FALSE);
154 addr += 1;
155 if (value >= ' ' && value <= '~')
156 db_printf("%c", (int)value);
157 else
158 db_printf("\\%03o", (int)value);
159 break;
160 case 's': /* null-terminated string */
161 for (;;) {
162 value = db_get_value(addr, 1, FALSE);
163 addr += 1;
164 if (value == 0)
165 break;
166 if (value >= ' ' && value <= '~')
167 db_printf("%c", (int)value);
168 else
169 db_printf("\\%03o", (int)value);
170 }
171 break;
172 case 'i': /* instruction */
173 addr = db_disasm(addr, FALSE);
174 break;
175 case 'I': /* instruction, alternate form */
176 addr = db_disasm(addr, TRUE);
177 break;
178 default:
179 break;
180 }
181 if (db_print_position() != 0)
182 db_end_line();
183 break;
184 }
185 }
186 }
187 db_next = addr;
188 }
189
190 /*
191 * Print value.
192 */
193 static char db_print_format = 'x';
194
195 /*ARGSUSED*/
196 void
197 db_print_cmd(addr, have_addr, count, modif)
198 db_expr_t addr;
199 boolean_t have_addr;
200 db_expr_t count;
201 char * modif;
202 {
203 db_expr_t value;
204
205 if (modif[0] != '\0')
206 db_print_format = modif[0];
207
208 switch (db_print_format) {
209 case 'a':
210 db_printsym((db_addr_t)addr, DB_STGY_ANY);
211 break;
212 case 'r':
213 db_printf("%+11lr", (long)addr);
214 break;
215 case 'x':
216 db_printf("%8lx", (unsigned long)addr);
217 break;
218 case 'z':
219 db_printf("%8lz", (long)addr);
220 break;
221 case 'd':
222 db_printf("%11ld", (long)addr);
223 break;
224 case 'u':
225 db_printf("%11lu", (unsigned long)addr);
226 break;
227 case 'o':
228 db_printf("%16lo", (unsigned long)addr);
229 break;
230 case 'c':
231 value = addr & 0xFF;
232 if (value >= ' ' && value <= '~')
233 db_printf("%c", (int)value);
234 else
235 db_printf("\\%03o", (int)value);
236 break;
237 }
238 db_printf("\n");
239 }
240
241 void
242 db_print_loc_and_inst(loc)
243 db_addr_t loc;
244 {
245 db_printsym(loc, DB_STGY_PROC);
246 db_printf(":\t");
247 (void) db_disasm(loc, TRUE);
248 }
249
250 /*
251 * Search for a value in memory.
252 * Syntax: search [/bhl] addr value [mask] [,count]
253 */
254 void
255 db_search_cmd(dummy1, dummy2, dummy3, dummy4)
256 db_expr_t dummy1;
257 boolean_t dummy2;
258 db_expr_t dummy3;
259 char * dummy4;
260 {
261 int t;
262 db_addr_t addr;
263 int size;
264 db_expr_t value;
265 db_expr_t mask;
266 db_expr_t count;
267
268 t = db_read_token();
269 if (t == tSLASH) {
270 t = db_read_token();
271 if (t != tIDENT) {
272 bad_modifier:
273 db_printf("Bad modifier\n");
274 db_flush_lex();
275 return;
276 }
277
278 if (!strcmp(db_tok_string, "b"))
279 size = 1;
280 else if (!strcmp(db_tok_string, "h"))
281 size = 2;
282 else if (!strcmp(db_tok_string, "l"))
283 size = 4;
284 else
285 goto bad_modifier;
286 } else {
287 db_unread_token(t);
288 size = 4;
289 }
290
291 if (!db_expression((db_expr_t *)&addr)) {
292 db_printf("Address missing\n");
293 db_flush_lex();
294 return;
295 }
296
297 if (!db_expression(&value)) {
298 db_printf("Value missing\n");
299 db_flush_lex();
300 return;
301 }
302
303 if (!db_expression(&mask))
304 mask = 0xffffffffUL;
305
306 t = db_read_token();
307 if (t == tCOMMA) {
308 if (!db_expression(&count)) {
309 db_printf("Count missing\n");
310 db_flush_lex();
311 return;
312 }
313 } else {
314 db_unread_token(t);
315 count = -1; /* effectively forever */
316 }
317 db_skip_to_eol();
318
319 db_search(addr, size, value, mask, count);
320 }
321
322 static void
323 db_search(addr, size, value, mask, count)
324 register
325 db_addr_t addr;
326 int size;
327 db_expr_t value;
328 db_expr_t mask;
329 unsigned int count;
330 {
331 while (count-- != 0) {
332 db_prev = addr;
333 if ((db_get_value(addr, size, FALSE) & mask) == value)
334 break;
335 addr += size;
336 }
337 db_next = addr;
338 }
Cache object: ccc64bfdd192f403e6a37bd232f9ef87
|