]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/ddb/db_examine.c
THIS BRANCH IS OBSOLETE, PLEASE READ:
[FreeBSD/FreeBSD.git] / sys / ddb / db_examine.c
1 /*-
2  * SPDX-License-Identifier: MIT-CMU
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
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 /*
29  *      Author: David B. Golub, Carnegie Mellon University
30  *      Date:   7/90
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38
39 #include <ddb/ddb.h>
40
41 #include <ddb/db_lex.h>
42 #include <ddb/db_output.h>
43 #include <ddb/db_command.h>
44 #include <ddb/db_sym.h>
45 #include <ddb/db_access.h>
46
47 static char     db_examine_format[TOK_STRING_SIZE] = "x";
48
49 static void     db_examine(db_addr_t, char *, int);
50 static void     db_search(db_addr_t, int, db_expr_t, db_expr_t, u_int);
51
52 /*
53  * Examine (print) data.
54  */
55 /*ARGSUSED*/
56 void
57 db_examine_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
58 {
59         if (modif[0] != '\0')
60             db_strcpy(db_examine_format, modif);
61
62         if (count == -1)
63             count = 1;
64
65         db_examine((db_addr_t) addr, db_examine_format, count);
66 }
67
68 static void
69 db_examine(db_addr_t addr, char *fmt, int count)
70 {
71         int             c;
72         db_expr_t       value;
73         int             size;
74         int             width;
75         char *          fp;
76
77         while (--count >= 0 && !db_pager_quit) {
78             fp = fmt;
79             size = 4;
80             while ((c = *fp++) != 0) {
81                 switch (c) {
82                     case 'b':
83                         size = 1;
84                         break;
85                     case 'h':
86                         size = 2;
87                         break;
88                     case 'l':
89                         size = 4;
90                         break;
91                     case 'g':
92                         size = 8;
93                         break;
94                     case 'a':   /* address */
95                         size = sizeof(void *);
96                         /* always forces a new line */
97                         if (db_print_position() != 0)
98                             db_printf("\n");
99                         db_prev = addr;
100                         db_printsym(addr, DB_STGY_ANY);
101                         db_printf(":\t");
102                         break;
103                     default:
104                         if (db_print_position() == 0) {
105                             /* Print the address. */
106                             db_printsym(addr, DB_STGY_ANY);
107                             db_printf(":\t");
108                             db_prev = addr;
109                         }
110
111                         width = size * 4;
112                         switch (c) {
113                             case 'r':   /* signed, current radix */
114                                 value = db_get_value(addr, size, true);
115                                 addr += size;
116                                 db_printf("%+-*lr", width, (long)value);
117                                 break;
118                             case 'x':   /* unsigned hex */
119                                 value = db_get_value(addr, size, false);
120                                 addr += size;
121                                 db_printf("%-*lx", width, (long)value);
122                                 break;
123                             case 'z':   /* signed hex */
124                                 value = db_get_value(addr, size, true);
125                                 addr += size;
126                                 db_printf("%-*ly", width, (long)value);
127                                 break;
128                             case 'd':   /* signed decimal */
129                                 value = db_get_value(addr, size, true);
130                                 addr += size;
131                                 db_printf("%-*ld", width, (long)value);
132                                 break;
133                             case 'u':   /* unsigned decimal */
134                                 value = db_get_value(addr, size, false);
135                                 addr += size;
136                                 db_printf("%-*lu", width, (long)value);
137                                 break;
138                             case 'o':   /* unsigned octal */
139                                 value = db_get_value(addr, size, false);
140                                 addr += size;
141                                 db_printf("%-*lo", width, (long)value);
142                                 break;
143                             case 'c':   /* character */
144                                 value = db_get_value(addr, 1, false);
145                                 addr += 1;
146                                 if (value >= ' ' && value <= '~')
147                                     db_printf("%c", (int)value);
148                                 else
149                                     db_printf("\\%03o", (int)value);
150                                 break;
151                             case 's':   /* null-terminated string */
152                                 for (;;) {
153                                     value = db_get_value(addr, 1, false);
154                                     addr += 1;
155                                     if (value == 0)
156                                         break;
157                                     if (value >= ' ' && value <= '~')
158                                         db_printf("%c", (int)value);
159                                     else
160                                         db_printf("\\%03o", (int)value);
161                                 }
162                                 break;
163                             case 'S':   /* symbol */
164                                 value = db_get_value(addr, sizeof(void *),
165                                     false);
166                                 addr += sizeof(void *);
167                                 db_printsym(value, DB_STGY_ANY);
168                                 break;
169                             case 'i':   /* instruction */
170                                 addr = db_disasm(addr, false);
171                                 break;
172                             case 'I':   /* instruction, alternate form */
173                                 addr = db_disasm(addr, true);
174                                 break;
175                             default:
176                                 break;
177                         }
178                         if (db_print_position() != 0)
179                             db_end_line(1);
180                         break;
181                 }
182             }
183         }
184         db_next = addr;
185 }
186
187 /*
188  * Print value.
189  */
190 static char     db_print_format = 'x';
191
192 /*ARGSUSED*/
193 void
194 db_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
195 {
196         db_expr_t       value;
197
198         if (modif[0] != '\0')
199             db_print_format = modif[0];
200
201         switch (db_print_format) {
202             case 'a':
203                 db_printsym((db_addr_t)addr, DB_STGY_ANY);
204                 break;
205             case 'r':
206                 db_printf("%+11lr", (long)addr);
207                 break;
208             case 'x':
209                 db_printf("%8lx", (unsigned long)addr);
210                 break;
211             case 'z':
212                 db_printf("%8ly", (long)addr);
213                 break;
214             case 'd':
215                 db_printf("%11ld", (long)addr);
216                 break;
217             case 'u':
218                 db_printf("%11lu", (unsigned long)addr);
219                 break;
220             case 'o':
221                 db_printf("%16lo", (unsigned long)addr);
222                 break;
223             case 'c':
224                 value = addr & 0xFF;
225                 if (value >= ' ' && value <= '~')
226                     db_printf("%c", (int)value);
227                 else
228                     db_printf("\\%03o", (int)value);
229                 break;
230             default:
231                 db_print_format = 'x';
232                 db_error("Syntax error: unsupported print modifier\n");
233                 /*NOTREACHED*/
234         }
235         db_printf("\n");
236 }
237
238 void
239 db_print_loc_and_inst(db_addr_t loc)
240 {
241         db_expr_t off;
242
243         db_printsym(loc, DB_STGY_PROC);
244         if (db_search_symbol(loc, DB_STGY_PROC, &off) != C_DB_SYM_NULL) {
245                 db_printf(":\t");
246                 (void)db_disasm(loc, false);
247         }
248 }
249
250 /*
251  * Search for a value in memory.
252  * Syntax: search [/bhl] addr value [mask] [,count]
253  */
254 void
255 db_search_cmd(db_expr_t dummy1, bool dummy2, db_expr_t dummy3, char *dummy4)
256 {
257         int             t;
258         db_addr_t       addr;
259         int             size;
260         db_expr_t       value;
261         db_expr_t       mask;
262         db_expr_t       count;
263
264         t = db_read_token();
265         if (t == tSLASH) {
266             t = db_read_token();
267             if (t != tIDENT) {
268               bad_modifier:
269                 db_printf("Bad modifier\n");
270                 db_flush_lex();
271                 return;
272             }
273
274             if (!strcmp(db_tok_string, "b"))
275                 size = 1;
276             else if (!strcmp(db_tok_string, "h"))
277                 size = 2;
278             else if (!strcmp(db_tok_string, "l"))
279                 size = 4;
280             else
281                 goto bad_modifier;
282         } else {
283             db_unread_token(t);
284             size = 4;
285         }
286
287         if (!db_expression((db_expr_t *)&addr)) {
288             db_printf("Address missing\n");
289             db_flush_lex();
290             return;
291         }
292
293         if (!db_expression(&value)) {
294             db_printf("Value missing\n");
295             db_flush_lex();
296             return;
297         }
298
299         if (!db_expression(&mask))
300             mask = 0xffffffffUL;
301
302         t = db_read_token();
303         if (t == tCOMMA) {
304             if (!db_expression(&count)) {
305                 db_printf("Count missing\n");
306                 db_flush_lex();
307                 return;
308             }
309         } else {
310             db_unread_token(t);
311             count = -1;         /* effectively forever */
312         }
313         db_skip_to_eol();
314
315         db_search(addr, size, value, mask, count);
316 }
317
318 static void
319 db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask,
320     unsigned int count)
321 {
322         while (count-- != 0) {
323                 db_prev = addr;
324                 if ((db_get_value(addr, size, false) & mask) == value)
325                         break;
326                 addr += size;
327         }
328         db_next = addr;
329 }