1 /* $NetBSD: db_examine.c,v 1.33 2008/11/16 19:34:29 pooka Exp $ */
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
28 * Author: David B. Golub, Carnegie Mellon University
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: db_examine.c,v 1.33 2008/11/16 19:34:29 pooka Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
42 static char db_examine_format
[TOK_STRING_SIZE
] = "x";
44 static void db_examine(db_addr_t
, char *, int);
45 static void db_search(db_addr_t
, int, db_expr_t
, db_expr_t
, unsigned int);
48 * Examine (print) data. Syntax is:
50 * For example, the command:
53 * address: 01 23 45 67
57 db_examine_cmd(db_expr_t addr
, bool have_addr
, db_expr_t count
,
61 strlcpy(db_examine_format
, modif
, sizeof(db_examine_format
));
66 db_examine((db_addr_t
) addr
, db_examine_format
, count
);
70 db_examine(db_addr_t addr
, char *fmt
, int count
)
80 while (--count
>= 0) {
84 while ((c
= *fp
++) != 0) {
85 if (db_print_position() == 0) {
86 /* Always print the address. */
87 db_printsym(addr
, DB_STGY_ANY
, db_printf
);
96 case 'h': /* half-word */
100 case 'l': /* long-word */
104 case 'L': /* implementation maximum */
106 width
= 12 * (sizeof value
/ 4);
108 case 'a': /* address */
109 db_printf("= 0x%lx\n", (long)addr
);
111 case 'r': /* signed, current radix */
112 value
= db_get_value(addr
, size
, true);
114 db_format_radix(tbuf
, 24, value
, false);
115 db_printf("%-*s", width
, tbuf
);
117 case 'x': /* unsigned hex */
118 value
= db_get_value(addr
, size
, false);
120 db_printf(DB_EXPR_T_IS_QUAD
? "%-*qx" : "%-*lx",
123 case 'm': /* hex dump */
125 * Print off in chunks of size. Try to print 16
126 * bytes at a time into 4 columns. This
127 * loops modify's count extra times in order
128 * to get the nicely formatted lines.
133 for (i
= 0; i
< size
; i
++) {
135 db_get_value(addr
+bytes
, 1,
138 DB_EXPR_T_IS_QUAD
? "%02qx":
144 } while ((bytes
!= 16) && count
--);
145 /* True up the columns before continuing */
146 for (i
= 4; i
>= (bytes
/ 4); i
--)
148 /* Print chars, use . for non-printable's. */
150 value
= db_get_value(addr
, 1, false);
152 if (value
>= ' ' && value
<= '~')
153 db_printf("%c", (char)value
);
159 case 'z': /* signed hex */
160 value
= db_get_value(addr
, size
, true);
162 db_format_hex(tbuf
, 24, value
, false);
163 db_printf("%-*s", width
, tbuf
);
165 case 'd': /* signed decimal */
166 value
= db_get_value(addr
, size
, true);
168 db_printf(DB_EXPR_T_IS_QUAD
? "%-*qd" : "%-*ld",
171 case 'u': /* unsigned decimal */
172 value
= db_get_value(addr
, size
, false);
174 db_printf(DB_EXPR_T_IS_QUAD
? "%-*qu" : "%-*lu",
177 case 'o': /* unsigned octal */
178 value
= db_get_value(addr
, size
, false);
180 db_printf(DB_EXPR_T_IS_QUAD
? "%-*qo" : "%-*lo",
183 case 'c': /* character */
184 value
= db_get_value(addr
, 1, false);
186 if (value
>= ' ' && value
<= '~')
187 db_printf("%c", (char)value
);
189 db_printf("\\%03o", (int)value
);
191 case 's': /* null-terminated string */
193 value
= db_get_value(addr
, 1, false);
197 if (value
>= ' ' && value
<= '~')
198 db_printf("%c", (char)value
);
200 db_printf("\\%03o", (int)value
);
203 case 'i': /* instruction */
204 addr
= db_disasm(addr
, false);
206 case 'I': /* instruction, alternate form */
207 addr
= db_disasm(addr
, true);
212 if (db_print_position() != 0)
222 static char db_print_format
= 'x';
226 db_print_cmd(db_expr_t addr
, bool have_addr
, db_expr_t count
,
231 if (modif
[0] != '\0')
232 db_print_format
= modif
[0];
234 switch (db_print_format
) {
236 db_printsym((db_addr_t
)addr
, DB_STGY_ANY
, db_printf
);
242 db_format_radix(tbuf
, 24, addr
, false);
243 db_printf("%11s", tbuf
);
247 db_printf(DB_EXPR_T_IS_QUAD
? "%16qx" : "%8lx", addr
);
253 db_format_hex(tbuf
, 24, addr
, false);
254 db_printf("%8s", tbuf
);
258 db_printf(DB_EXPR_T_IS_QUAD
? "%11qd" : "%11ld", addr
);
261 db_printf(DB_EXPR_T_IS_QUAD
? "%11qu" : "%11lu", addr
);
264 db_printf(DB_EXPR_T_IS_QUAD
? "%15qo" : "%16lo", addr
);
268 if (value
>= ' ' && value
<= '~')
269 db_printf("%c", (char)value
);
271 db_printf("\\%03o", (int)value
);
278 db_print_loc_and_inst(db_addr_t loc
)
281 db_printsym(loc
, DB_STGY_PROC
, db_printf
);
283 (void) db_disasm(loc
, false);
287 * Search for a value in memory.
288 * Syntax: search [/bhl] addr value [mask] [,count]
292 db_search_cmd(db_expr_t daddr
, bool have_addr
,
293 db_expr_t dcount
, const char *modif
)
307 db_printf("Bad modifier\n");
312 if (!strcmp(db_tok_string
, "b"))
314 else if (!strcmp(db_tok_string
, "h"))
316 else if (!strcmp(db_tok_string
, "l"))
325 if (!db_expression(&value
)) {
326 db_printf("Address missing\n");
330 addr
= (db_addr_t
) value
;
332 if (!db_expression(&value
)) {
333 db_printf("Value missing\n");
338 if (!db_expression(&mask
))
343 if (!db_expression(&count
)) {
344 db_printf("Count missing\n");
350 count
= -1; /* effectively forever */
354 db_search(addr
, size
, value
, mask
, count
);
358 db_search(db_addr_t addr
, int size
, db_expr_t value
, db_expr_t mask
,
361 while (count
-- != 0) {
363 if ((db_get_value(addr
, size
, false) & mask
) == value
)