db_examine.c revision 623
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@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 *	$Id$
27 */
28
29/*
30 *	Author: David B. Golub, Carnegie Mellon University
31 *	Date:	7/90
32 */
33#include "param.h"
34#include "proc.h"
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
42char	db_examine_format[TOK_STRING_SIZE] = "x";
43
44extern	db_addr_t db_disasm(/* db_addr_t, boolean_t */);
45			/* instruction disassembler */
46
47/*
48 * Examine (print) data.
49 */
50/*ARGSUSED*/
51void
52db_examine_cmd(addr, have_addr, count, modif)
53	db_expr_t	addr;
54	int		have_addr;
55	db_expr_t	count;
56	char *		modif;
57{
58	if (modif[0] != '\0')
59	    db_strcpy(db_examine_format, modif);
60
61	if (count == -1)
62	    count = 1;
63
64	db_examine((db_addr_t) addr, db_examine_format, count);
65}
66
67db_examine(addr, fmt, count)
68	register
69	db_addr_t	addr;
70	char *		fmt;	/* format string */
71	int		count;	/* repeat count */
72{
73	int		c;
74	db_expr_t	value;
75	int		size;
76	int		width;
77	char *		fp;
78
79	while (--count >= 0) {
80	    fp = fmt;
81	    size = 4;
82	    width = 16;
83	    while ((c = *fp++) != 0) {
84		switch (c) {
85		    case 'b':
86			size = 1;
87			width = 4;
88			break;
89		    case 'h':
90			size = 2;
91			width = 8;
92			break;
93		    case 'l':
94			size = 4;
95			width = 16;
96			break;
97		    case 'a':	/* address */
98			/* always forces a new line */
99			if (db_print_position() != 0)
100			    db_printf("\n");
101			db_prev = addr;
102			db_printsym(addr, DB_STGY_ANY);
103			db_printf(":\t");
104			break;
105		    default:
106			if (db_print_position() == 0) {
107			    /* If we hit a new symbol, print it */
108			    char *	name;
109			    db_expr_t	off;
110
111			    db_find_sym_and_offset(addr, &name, &off);
112			    if (off == 0)
113				db_printf("%s:\t", name);
114			    else
115				db_printf("\t\t");
116
117			    db_prev = addr;
118			}
119
120			switch (c) {
121			    case 'r':	/* signed, current radix */
122				value = db_get_value(addr, size, TRUE);
123				addr += size;
124				db_printf("%-*r", width, value);
125				break;
126			    case 'x':	/* unsigned hex */
127				value = db_get_value(addr, size, FALSE);
128				addr += size;
129				db_printf("%-*x", width, value);
130				break;
131			    case 'z':	/* signed hex */
132				value = db_get_value(addr, size, TRUE);
133				addr += size;
134				db_printf("%-*z", width, value);
135				break;
136			    case 'd':	/* signed decimal */
137				value = db_get_value(addr, size, TRUE);
138				addr += size;
139				db_printf("%-*d", width, value);
140				break;
141			    case 'u':	/* unsigned decimal */
142				value = db_get_value(addr, size, FALSE);
143				addr += size;
144				db_printf("%-*u", width, value);
145				break;
146			    case 'o':	/* unsigned octal */
147				value = db_get_value(addr, size, FALSE);
148				addr += size;
149				db_printf("%-*o", width, value);
150				break;
151			    case 'c':	/* character */
152				value = db_get_value(addr, 1, FALSE);
153				addr += 1;
154				if (value >= ' ' && value <= '~')
155				    db_printf("%c", value);
156				else
157				    db_printf("\\%03o", value);
158				break;
159			    case 's':	/* null-terminated string */
160				for (;;) {
161				    value = db_get_value(addr, 1, FALSE);
162				    addr += 1;
163				    if (value == 0)
164					break;
165				    if (value >= ' ' && value <= '~')
166					db_printf("%c", value);
167				    else
168					db_printf("\\%03o", value);
169				}
170				break;
171			    case 'i':	/* instruction */
172				addr = db_disasm(addr, FALSE);
173				break;
174			    case 'I':	/* instruction, alternate form */
175				addr = db_disasm(addr, TRUE);
176				break;
177			    default:
178				break;
179			}
180			if (db_print_position() != 0)
181			    db_end_line();
182			break;
183		}
184	    }
185	}
186	db_next = addr;
187}
188
189/*
190 * Print value.
191 */
192char	db_print_format = 'x';
193
194/*ARGSUSED*/
195void
196db_print_cmd(addr, have_addr, count, modif)
197	db_expr_t	addr;
198	int		have_addr;
199	db_expr_t	count;
200	char *		modif;
201{
202	db_expr_t	value;
203
204	if (modif[0] != '\0')
205	    db_print_format = modif[0];
206
207	switch (db_print_format) {
208	    case 'a':
209		db_printsym((db_addr_t)addr, DB_STGY_ANY);
210		break;
211	    case 'r':
212		db_printf("%11r", addr);
213		break;
214	    case 'x':
215		db_printf("%8x", addr);
216		break;
217	    case 'z':
218		db_printf("%8z", addr);
219		break;
220	    case 'd':
221		db_printf("%11d", addr);
222		break;
223	    case 'u':
224		db_printf("%11u", addr);
225		break;
226	    case 'o':
227		db_printf("%16o", addr);
228		break;
229	    case 'c':
230		value = addr & 0xFF;
231		if (value >= ' ' && value <= '~')
232		    db_printf("%c", value);
233		else
234		    db_printf("\\%03o", value);
235		break;
236	}
237	db_printf("\n");
238}
239
240db_print_loc_and_inst(loc)
241	db_addr_t	loc;
242{
243	db_printsym(loc, DB_STGY_PROC);
244	db_printf(":\t");
245	(void) db_disasm(loc, TRUE);
246}
247
248db_strcpy(dst, src)
249	register char *dst;
250	register char *src;
251{
252	while (*dst++ = *src++)
253	    ;
254}
255
256/*
257 * Search for a value in memory.
258 * Syntax: search [/bhl] addr value [mask] [,count]
259 */
260void
261db_search_cmd()
262{
263	int		t;
264	db_addr_t	addr;
265	int		size;
266	db_expr_t	value;
267	db_expr_t	mask;
268	unsigned int	count;
269
270	t = db_read_token();
271	if (t == tSLASH) {
272	    t = db_read_token();
273	    if (t != tIDENT) {
274	      bad_modifier:
275		db_printf("Bad modifier\n");
276		db_flush_lex();
277		return;
278	    }
279
280	    if (!strcmp(db_tok_string, "b"))
281		size = 1;
282	    else if (!strcmp(db_tok_string, "h"))
283		size = 2;
284	    else if (!strcmp(db_tok_string, "l"))
285		size = 4;
286	    else
287		goto bad_modifier;
288	} else {
289	    db_unread_token(t);
290	    size = 4;
291	}
292
293	if (!db_expression(&addr)) {
294	    db_printf("Address missing\n");
295	    db_flush_lex();
296	    return;
297	}
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 = 0xffffffff;
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
324db_search(addr, size, value, mask, count)
325	register
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