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