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