xref: /netbsd-src/sys/ddb/db_examine.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: db_examine.c,v 1.13 1997/02/03 23:43:36 mycroft 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@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 #include <ddb/db_access.h>
42 #include <ddb/db_extern.h>
43 #include <ddb/db_interface.h>
44 
45 char	db_examine_format[TOK_STRING_SIZE] = "x";
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 void
73 db_examine(addr, fmt, count)
74 	register
75 	    db_addr_t	addr;
76 	char *		fmt;	/* format string */
77 	int		count;	/* repeat count */
78 {
79 	int		c;
80 	db_expr_t	value;
81 	int		size;
82 	int		width;
83 	char *		fp;
84 
85 	while (--count >= 0) {
86 		fp = fmt;
87 		size = 4;
88 		width = 12;
89 		while ((c = *fp++) != 0) {
90 			if (db_print_position() == 0) {
91 				/* Always print the address. */
92 				db_printsym(addr, DB_STGY_ANY);
93 				db_printf(":\t");
94 				db_prev = addr;
95 			}
96 			switch (c) {
97 			case 'b':	/* byte */
98 				size = 1;
99 				width = 4;
100 				break;
101 			case 'h':	/* half-word */
102 				size = 2;
103 				width = 8;
104 				break;
105 			case 'l':	/* long-word */
106 				size = 4;
107 				width = 12;
108 				break;
109 			case 'a':	/* address */
110 				db_printf("= 0x%lx\n", addr);
111 				break;
112 			case 'r':	/* signed, current radix */
113 				value = db_get_value(addr, size, TRUE);
114 				addr += size;
115 				db_printf("%-*lr", width, value);
116 				break;
117 			case 'x':	/* unsigned hex */
118 				value = db_get_value(addr, size, FALSE);
119 				addr += size;
120 				db_printf("%-*lx", width, value);
121 				break;
122 			case 'z':	/* signed hex */
123 				value = db_get_value(addr, size, TRUE);
124 				addr += size;
125 				db_printf("%-*lz", width, value);
126 				break;
127 			case 'd':	/* signed decimal */
128 				value = db_get_value(addr, size, TRUE);
129 				addr += size;
130 				db_printf("%-*ld", width, value);
131 				break;
132 			case 'u':	/* unsigned decimal */
133 				value = db_get_value(addr, size, FALSE);
134 				addr += size;
135 				db_printf("%-*lu", width, value);
136 				break;
137 			case 'o':	/* unsigned octal */
138 				value = db_get_value(addr, size, FALSE);
139 				addr += size;
140 				db_printf("%-*lo", width, value);
141 				break;
142 			case 'c':	/* character */
143 				value = db_get_value(addr, 1, FALSE);
144 				addr += 1;
145 				if (value >= ' ' && value <= '~')
146 					db_printf("%c", (char)value);
147 				else
148 					db_printf("\\%03lo", value);
149 				break;
150 			case 's':	/* null-terminated string */
151 				for (;;) {
152 					value = db_get_value(addr, 1, FALSE);
153 					addr += 1;
154 					if (value == 0)
155 						break;
156 					if (value >= ' ' && value <= '~')
157 						db_printf("%c", (char)value);
158 					else
159 						db_printf("\\%03lo", value);
160 				}
161 				break;
162 			case 'i':	/* instruction */
163 				addr = db_disasm(addr, FALSE);
164 				break;
165 			case 'I':	/* instruction, alternate form */
166 				addr = db_disasm(addr, TRUE);
167 				break;
168 			default:
169 				break;
170 			}
171 			if (db_print_position() != 0)
172 				db_end_line();
173 		}
174 	}
175 	db_next = addr;
176 }
177 
178 /*
179  * Print value.
180  */
181 char	db_print_format = 'x';
182 
183 /*ARGSUSED*/
184 void
185 db_print_cmd(addr, have_addr, count, modif)
186 	db_expr_t	addr;
187 	int		have_addr;
188 	db_expr_t	count;
189 	char *		modif;
190 {
191 	db_expr_t	value;
192 
193 	if (modif[0] != '\0')
194 		db_print_format = modif[0];
195 
196 	switch (db_print_format) {
197 	case 'a':
198 		db_printsym((db_addr_t)addr, DB_STGY_ANY);
199 		break;
200 	case 'r':
201 		db_printf("%11lr", addr);
202 		break;
203 	case 'x':
204 		db_printf("%8lx", addr);
205 		break;
206 	case 'z':
207 		db_printf("%8lz", addr);
208 		break;
209 	case 'd':
210 		db_printf("%11ld", addr);
211 		break;
212 	case 'u':
213 		db_printf("%11lu", addr);
214 		break;
215 	case 'o':
216 		db_printf("%16lo", addr);
217 		break;
218 	case 'c':
219 		value = addr & 0xFF;
220 		if (value >= ' ' && value <= '~')
221 			db_printf("%c", (char)value);
222 		else
223 			db_printf("\\%03lo", value);
224 		break;
225 	}
226 	db_printf("\n");
227 }
228 
229 void
230 db_print_loc_and_inst(loc)
231 	db_addr_t	loc;
232 {
233 	db_printsym(loc, DB_STGY_PROC);
234 	db_printf(":\t");
235 	(void) db_disasm(loc, FALSE);
236 }
237 
238 void
239 db_strcpy(dst, src)
240 	register char *dst;
241 	register char *src;
242 {
243 	while ((*dst++ = *src++) != '\0')
244 		;
245 }
246 
247 /*
248  * Search for a value in memory.
249  * Syntax: search [/bhl] addr value [mask] [,count]
250  */
251 /*ARGSUSED*/
252 void
253 db_search_cmd(daddr, have_addr, dcount, modif)
254 	db_expr_t	daddr;
255 	int		have_addr;
256 	db_expr_t	dcount;
257 	char *		modif;
258 {
259 	int		t;
260 	db_addr_t	addr;
261 	int		size;
262 	db_expr_t	value;
263 	db_expr_t	mask;
264 	db_expr_t	count;
265 
266 	t = db_read_token();
267 	if (t == tSLASH) {
268 		t = db_read_token();
269 		if (t != tIDENT) {
270 			bad_modifier:
271 			db_printf("Bad modifier\n");
272 			db_flush_lex();
273 			return;
274 		}
275 
276 		if (!strcmp(db_tok_string, "b"))
277 			size = 1;
278 		else if (!strcmp(db_tok_string, "h"))
279 			size = 2;
280 		else if (!strcmp(db_tok_string, "l"))
281 			size = 4;
282 		else
283 			goto bad_modifier;
284 	} else {
285 		db_unread_token(t);
286 		size = 4;
287 	}
288 
289 	if (!db_expression(&value)) {
290 		db_printf("Address missing\n");
291 		db_flush_lex();
292 		return;
293 	}
294 	addr = (db_addr_t) value;
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 = (int) ~0;
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 void
322 db_search(addr, size, value, mask, count)
323 	register
324 	db_addr_t	addr;
325 	int		size;
326 	db_expr_t	value;
327 	db_expr_t	mask;
328 	unsigned int	count;
329 {
330 	while (count-- != 0) {
331 		db_prev = addr;
332 		if ((db_get_value(addr, size, FALSE) & mask) == value)
333 			break;
334 		addr += size;
335 	}
336 	db_next = addr;
337 }
338