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