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