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