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