xref: /openbsd-src/sys/ddb/db_examine.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: db_examine.c,v 1.8 1997/07/19 22:31:16 niklas Exp $	*/
2 /*	$NetBSD: db_examine.c,v 1.11 1996/03/30 22:30:07 christos Exp $	*/
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie Mellon
27  * the rights to redistribute these changes.
28  *
29  *	Author: David B. Golub, Carnegie Mellon University
30  *	Date:	7/90
31  */
32 
33 #include <sys/param.h>
34 #include <sys/proc.h>
35 
36 #include <vm/vm.h>
37 
38 #include <machine/db_machdep.h>		/* type definitions */
39 
40 #include <ddb/db_lex.h>
41 #include <ddb/db_output.h>
42 #include <ddb/db_command.h>
43 #include <ddb/db_sym.h>
44 #include <ddb/db_access.h>
45 #include <ddb/db_extern.h>
46 #include <ddb/db_interface.h>
47 
48 char	db_examine_format[TOK_STRING_SIZE] = "x";
49 
50 /*
51  * Examine (print) data.  Syntax is:
52  *		x/[bhlq][cdiorsuxz]*
53  * For example, the command:
54  *  	x/bxxxx
55  * should print:
56  *  	address:  01  23  45  67
57  */
58 /*ARGSUSED*/
59 void
60 db_examine_cmd(addr, have_addr, count, modif)
61 	db_expr_t	addr;
62 	int		have_addr;
63 	db_expr_t	count;
64 	char *		modif;
65 {
66 	if (modif[0] != '\0')
67 		db_strcpy(db_examine_format, modif);
68 
69 	if (count == -1)
70 		count = 1;
71 
72 	db_examine((db_addr_t)addr, db_examine_format, count);
73 }
74 
75 void
76 db_examine(addr, fmt, count)
77 	db_addr_t	addr;
78 	char *		fmt;	/* format string */
79 	int		count;	/* repeat count */
80 {
81 	int		c;
82 	db_expr_t	value;
83 	int		size;
84 	int		width;
85 	char *		fp;
86 
87 	while (--count >= 0) {
88 		fp = fmt;
89 		size = 4;
90 		width = 12;
91 		while ((c = *fp++) != 0) {
92 			if (db_print_position() == 0) {
93 				/* Always print the address. */
94 				db_printsym(addr, DB_STGY_ANY);
95 				db_printf(":\t");
96 				db_prev = addr;
97 			}
98 			switch (c) {
99 			case 'b':	/* byte */
100 				size = 1;
101 				width = 4;
102 				break;
103 			case 'h':	/* half-word */
104 				size = 2;
105 				width = 8;
106 				break;
107 			case 'l':	/* long-word */
108 				size = 4;
109 				width = 12;
110 				break;
111 			case 'q':	/* quad-word */
112 				size = 8;
113 				width = 20;
114 				break;
115 			case 'a':	/* address */
116 				db_printf("= 0x%lx\n", (long)addr);
117 				break;
118 			case 'r':	/* signed, current radix */
119 				value = db_get_value(addr, size, TRUE);
120 				addr += size;
121 				db_printf("%-*lr", width, (long)value);
122 				break;
123 			case 'x':	/* unsigned hex */
124 				value = db_get_value(addr, size, FALSE);
125 				addr += size;
126 				db_printf("%-*lx", width, (long)value);
127 				break;
128 			case 'z':	/* signed hex */
129 				value = db_get_value(addr, size, TRUE);
130 				addr += size;
131 				db_printf("%-*lz", width, (long)value);
132 				break;
133 			case 'd':	/* signed decimal */
134 				value = db_get_value(addr, size, TRUE);
135 				addr += size;
136 				db_printf("%-*ld", width, (long)value);
137 				break;
138 			case 'u':	/* unsigned decimal */
139 				value = db_get_value(addr, size, FALSE);
140 				addr += size;
141 				db_printf("%-*lu", width, (long)value);
142 				break;
143 			case 'o':	/* unsigned octal */
144 				value = db_get_value(addr, size, FALSE);
145 				addr += size;
146 				db_printf("%-*lo", width, value);
147 				break;
148 			case 'c':	/* character */
149 				value = db_get_value(addr, 1, FALSE);
150 				addr += 1;
151 				if (value >= ' ' && value <= '~')
152 					db_printf("%c", value);
153 				else
154 					db_printf("\\%03o", value);
155 				break;
156 			case 's':	/* null-terminated string */
157 				for (;;) {
158 					value = db_get_value(addr, 1, FALSE);
159 					addr += 1;
160 					if (value == 0)
161 						break;
162 					if (value >= ' ' && value <= '~')
163 						db_printf("%c", value);
164 					else
165 						db_printf("\\%03o", value);
166 				}
167 				break;
168 			case 'i':	/* instruction */
169 				addr = db_disasm(addr, FALSE);
170 				break;
171 			case 'I':	/* instruction, alternate form */
172 				addr = db_disasm(addr, TRUE);
173 				break;
174 			default:
175 				break;
176 			}
177 			if (db_print_position() != 0)
178 				db_end_line(width);
179 		}
180 	}
181 	db_next = addr;
182 }
183 
184 /*
185  * Print value.
186  */
187 char	db_print_format = 'x';
188 
189 /*ARGSUSED*/
190 void
191 db_print_cmd(addr, have_addr, count, modif)
192 	db_expr_t	addr;
193 	int		have_addr;
194 	db_expr_t	count;
195 	char *		modif;
196 {
197 	db_expr_t	value;
198 
199 	if (modif[0] != '\0')
200 		db_print_format = modif[0];
201 
202 	switch (db_print_format) {
203 	case 'a':
204 		db_printsym((db_addr_t)addr, DB_STGY_ANY);
205 		break;
206 	case 'r':
207 		db_printf("%*r", sizeof(db_expr_t) * 2 * 6 / 5, addr);
208 		break;
209 	case 'x':
210 		db_printf("%*x", sizeof(db_expr_t) * 2, addr);
211 		break;
212 	case 'z':
213 		db_printf("%*z", sizeof(db_expr_t) * 2, addr);
214 		break;
215 	case 'd':
216 		db_printf("%*d", sizeof(db_expr_t) * 2 * 6 / 5, addr);
217 		break;
218 	case 'u':
219 		db_printf("%*u", sizeof(db_expr_t) * 2 * 6 / 5, addr);
220 		break;
221 	case 'o':
222 		db_printf("%*o", sizeof(db_expr_t) * 2 * 4 / 3, addr);
223 		break;
224 	case 'c':
225 		value = addr & 0xFF;
226 		if (value >= ' ' && value <= '~')
227 			db_printf("%c", value);
228 		else
229 			db_printf("\\%03o", value);
230 		break;
231 	}
232 	db_printf("\n");
233 }
234 
235 void
236 db_print_loc_and_inst(loc)
237 	db_addr_t	loc;
238 {
239 	db_printsym(loc, DB_STGY_PROC);
240 	db_printf(":\t");
241 	(void) db_disasm(loc, FALSE);
242 }
243 
244 void
245 db_strcpy(dst, src)
246 	register char *dst;
247 	register char *src;
248 {
249 	while ((*dst++ = *src++) != '\0')
250 		;
251 }
252 
253 /*
254  * Search for a value in memory.
255  * Syntax: search [/bhl] addr value [mask] [,count]
256  */
257 /*ARGSUSED*/
258 void
259 db_search_cmd(daddr, have_addr, dcount, modif)
260 	db_expr_t	daddr;
261 	int		have_addr;
262 	db_expr_t	dcount;
263 	char *		modif;
264 {
265 	int		t;
266 	db_addr_t	addr;
267 	int		size;
268 	db_expr_t	value;
269 	db_expr_t	mask;
270 	db_expr_t	count;
271 
272 	t = db_read_token();
273 	if (t == tSLASH) {
274 		t = db_read_token();
275 		if (t != tIDENT) {
276 			bad_modifier:
277 			db_printf("Bad modifier\n");
278 			db_flush_lex();
279 			return;
280 		}
281 
282 		if (!strcmp(db_tok_string, "b"))
283 			size = 1;
284 		else if (!strcmp(db_tok_string, "h"))
285 			size = 2;
286 		else if (!strcmp(db_tok_string, "l"))
287 			size = 4;
288 		else
289 			goto bad_modifier;
290 	} else {
291 		db_unread_token(t);
292 		size = 4;
293 	}
294 
295 	if (!db_expression(&value)) {
296 		db_printf("Address missing\n");
297 		db_flush_lex();
298 		return;
299 	}
300 	addr = (db_addr_t) value;
301 
302 	if (!db_expression(&value)) {
303 		db_printf("Value missing\n");
304 		db_flush_lex();
305 		return;
306 	}
307 
308 	if (!db_expression(&mask))
309 		mask = (int) ~0;
310 
311 	t = db_read_token();
312 	if (t == tCOMMA) {
313 		if (!db_expression(&count)) {
314 			db_printf("Count missing\n");
315 			db_flush_lex();
316 			return;
317 		}
318 	} else {
319 		db_unread_token(t);
320 		count = -1;		/* forever */
321 	}
322 	db_skip_to_eol();
323 
324 	db_search(addr, size, value, mask, count);
325 }
326 
327 void
328 db_search(addr, size, value, mask, count)
329 	register
330 	db_addr_t	addr;
331 	int		size;
332 	db_expr_t	value;
333 	db_expr_t	mask;
334 	db_expr_t	count;
335 {
336 	/* Negative counts means forever.  */
337 	while (count < 0 || count-- != 0) {
338 		db_prev = addr;
339 		if ((db_get_value(addr, size, FALSE) & mask) == value)
340 			break;
341 		addr += size;
342 	}
343 	db_next = addr;
344 }
345