db_examine.c revision 1.2.4.1 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 (at) 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 /*
27 * $Id: db_examine.c,v 1.2.4.1 1993/11/14 22:48:31 mycroft Exp $
28 *
29 * HISTORY
30 * $Log: db_examine.c,v $
31 * Revision 1.2.4.1 1993/11/14 22:48:31 mycroft
32 * Canonicalize all #includes.
33 *
34 * Revision 1.2 1993/05/20 03:39:12 cgd
35 * add explicit rcs id
36 *
37 * Revision 1.1.1.1 1993/03/21 09:46:26 cgd
38 * initial import of 386bsd-0.1 sources
39 *
40 * Revision 1.1 1992/03/25 21:45:07 pace
41 * Initial revision
42 *
43 * Revision 2.4 91/02/05 17:06:20 mrt
44 * Changed to new Mach copyright
45 * [91/01/31 16:17:37 mrt]
46 *
47 * Revision 2.3 90/11/07 16:49:23 rpd
48 * Added db_search_cmd, db_search.
49 * [90/11/06 rpd]
50 *
51 * Revision 2.2 90/08/27 21:50:38 dbg
52 * Add 'r', 'z' to print and examine formats.
53 * Change calling sequence of db_disasm.
54 * db_examine sets db_prev and db_next instead of explicitly
55 * advancing dot.
56 * [90/08/20 dbg]
57 * Reflected changes in db_printsym()'s calling seq.
58 * [90/08/20 af]
59 * Reduce lint.
60 * [90/08/07 dbg]
61 * Created.
62 * [90/07/25 dbg]
63 *
64 */
65 /*
66 * Author: David B. Golub, Carnegie Mellon University
67 * Date: 7/90
68 */
69 #include <sys/param.h>
70 #include <sys/proc.h>
71 #include <machine/db_machdep.h> /* type definitions */
72
73 #include <ddb/db_lex.h>
74 #include <ddb/db_output.h>
75 #include <ddb/db_command.h>
76 #include <ddb/db_sym.h>
77
78 char db_examine_format[TOK_STRING_SIZE] = "x";
79
80 extern db_addr_t db_disasm(/* db_addr_t, boolean_t */);
81 /* instruction disassembler */
82
83 /*
84 * Examine (print) data.
85 */
86 /*ARGSUSED*/
87 void
88 db_examine_cmd(addr, have_addr, count, modif)
89 db_expr_t addr;
90 int have_addr;
91 db_expr_t count;
92 char * modif;
93 {
94 if (modif[0] != '\0')
95 db_strcpy(db_examine_format, modif);
96
97 if (count == -1)
98 count = 1;
99
100 db_examine((db_addr_t) addr, db_examine_format, count);
101 }
102
103 db_examine(addr, fmt, count)
104 register
105 db_addr_t addr;
106 char * fmt; /* format string */
107 int count; /* repeat count */
108 {
109 int c;
110 db_expr_t value;
111 int size;
112 int width;
113 char * fp;
114
115 while (--count >= 0) {
116 fp = fmt;
117 size = 4;
118 width = 16;
119 while ((c = *fp++) != 0) {
120 switch (c) {
121 case 'b':
122 size = 1;
123 width = 4;
124 break;
125 case 'h':
126 size = 2;
127 width = 8;
128 break;
129 case 'l':
130 size = 4;
131 width = 16;
132 break;
133 case 'a': /* address */
134 /* always forces a new line */
135 if (db_print_position() != 0)
136 db_printf("\n");
137 db_prev = addr;
138 db_printsym(addr, DB_STGY_ANY);
139 db_printf(":\t");
140 break;
141 default:
142 if (db_print_position() == 0) {
143 /* If we hit a new symbol, print it */
144 char * name;
145 db_expr_t off;
146
147 db_find_sym_and_offset(addr, &name, &off);
148 if (off == 0)
149 db_printf("%s:\t", name);
150 else
151 db_printf("\t\t");
152
153 db_prev = addr;
154 }
155
156 switch (c) {
157 case 'r': /* signed, current radix */
158 value = db_get_value(addr, size, TRUE);
159 addr += size;
160 db_printf("%-*r", width, value);
161 break;
162 case 'x': /* unsigned hex */
163 value = db_get_value(addr, size, FALSE);
164 addr += size;
165 db_printf("%-*x", width, value);
166 break;
167 case 'z': /* signed hex */
168 value = db_get_value(addr, size, TRUE);
169 addr += size;
170 db_printf("%-*z", width, value);
171 break;
172 case 'd': /* signed decimal */
173 value = db_get_value(addr, size, TRUE);
174 addr += size;
175 db_printf("%-*d", width, value);
176 break;
177 case 'u': /* unsigned decimal */
178 value = db_get_value(addr, size, FALSE);
179 addr += size;
180 db_printf("%-*u", width, value);
181 break;
182 case 'o': /* unsigned octal */
183 value = db_get_value(addr, size, FALSE);
184 addr += size;
185 db_printf("%-*o", width, value);
186 break;
187 case 'c': /* character */
188 value = db_get_value(addr, 1, FALSE);
189 addr += 1;
190 if (value >= ' ' && value <= '~')
191 db_printf("%c", value);
192 else
193 db_printf("\\%03o", value);
194 break;
195 case 's': /* null-terminated string */
196 for (;;) {
197 value = db_get_value(addr, 1, FALSE);
198 addr += 1;
199 if (value == 0)
200 break;
201 if (value >= ' ' && value <= '~')
202 db_printf("%c", value);
203 else
204 db_printf("\\%03o", value);
205 }
206 break;
207 case 'i': /* instruction */
208 addr = db_disasm(addr, FALSE);
209 break;
210 case 'I': /* instruction, alternate form */
211 addr = db_disasm(addr, TRUE);
212 break;
213 default:
214 break;
215 }
216 if (db_print_position() != 0)
217 db_end_line();
218 break;
219 }
220 }
221 }
222 db_next = addr;
223 }
224
225 /*
226 * Print value.
227 */
228 char db_print_format = 'x';
229
230 /*ARGSUSED*/
231 void
232 db_print_cmd(addr, have_addr, count, modif)
233 db_expr_t addr;
234 int have_addr;
235 db_expr_t count;
236 char * modif;
237 {
238 db_expr_t value;
239
240 if (modif[0] != '\0')
241 db_print_format = modif[0];
242
243 switch (db_print_format) {
244 case 'a':
245 db_printsym((db_addr_t)addr, DB_STGY_ANY);
246 break;
247 case 'r':
248 db_printf("%11r", addr);
249 break;
250 case 'x':
251 db_printf("%8x", addr);
252 break;
253 case 'z':
254 db_printf("%8z", addr);
255 break;
256 case 'd':
257 db_printf("%11d", addr);
258 break;
259 case 'u':
260 db_printf("%11u", addr);
261 break;
262 case 'o':
263 db_printf("%16o", addr);
264 break;
265 case 'c':
266 value = addr & 0xFF;
267 if (value >= ' ' && value <= '~')
268 db_printf("%c", value);
269 else
270 db_printf("\\%03o", value);
271 break;
272 }
273 db_printf("\n");
274 }
275
276 db_print_loc_and_inst(loc)
277 db_addr_t loc;
278 {
279 db_printsym(loc, DB_STGY_PROC);
280 db_printf(":\t");
281 (void) db_disasm(loc, TRUE);
282 }
283
284 db_strcpy(dst, src)
285 register char *dst;
286 register char *src;
287 {
288 while (*dst++ = *src++)
289 ;
290 }
291
292 /*
293 * Search for a value in memory.
294 * Syntax: search [/bhl] addr value [mask] [,count]
295 */
296 void
297 db_search_cmd()
298 {
299 int t;
300 db_addr_t addr;
301 int size;
302 db_expr_t value;
303 db_expr_t mask;
304 unsigned int count;
305
306 t = db_read_token();
307 if (t == tSLASH) {
308 t = db_read_token();
309 if (t != tIDENT) {
310 bad_modifier:
311 db_printf("Bad modifier\n");
312 db_flush_lex();
313 return;
314 }
315
316 if (!strcmp(db_tok_string, "b"))
317 size = 1;
318 else if (!strcmp(db_tok_string, "h"))
319 size = 2;
320 else if (!strcmp(db_tok_string, "l"))
321 size = 4;
322 else
323 goto bad_modifier;
324 } else {
325 db_unread_token(t);
326 size = 4;
327 }
328
329 if (!db_expression(&addr)) {
330 db_printf("Address missing\n");
331 db_flush_lex();
332 return;
333 }
334
335 if (!db_expression(&value)) {
336 db_printf("Value missing\n");
337 db_flush_lex();
338 return;
339 }
340
341 if (!db_expression(&mask))
342 mask = 0xffffffff;
343
344 t = db_read_token();
345 if (t == tCOMMA) {
346 if (!db_expression(&count)) {
347 db_printf("Count missing\n");
348 db_flush_lex();
349 return;
350 }
351 } else {
352 db_unread_token(t);
353 count = -1; /* effectively forever */
354 }
355 db_skip_to_eol();
356
357 db_search(addr, size, value, mask, count);
358 }
359
360 db_search(addr, size, value, mask, count)
361 register
362 db_addr_t addr;
363 int size;
364 db_expr_t value;
365 db_expr_t mask;
366 unsigned int count;
367 {
368 while (count-- != 0) {
369 db_prev = addr;
370 if ((db_get_value(addr, size, FALSE) & mask) == value)
371 break;
372 addr += size;
373 }
374 db_next = addr;
375 }
376