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 * Author: David B. Golub, Carnegie Mellon University 28 * Date: 7/90 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 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 static void 68 db_examine(db_addr_t addr, char *fmt, int count) 69 { 70 int c; 71 db_expr_t value; 72 int size; 73 int width; 74 char * fp; 75 76 while (--count >= 0 && !db_pager_quit) { 77 fp = fmt; 78 size = 4; 79 while ((c = *fp++) != 0) { 80 switch (c) { 81 case 'b': 82 size = 1; 83 break; 84 case 'h': 85 size = 2; 86 break; 87 case 'l': 88 size = 4; 89 break; 90 case 'g': 91 size = 8; 92 break; 93 case 'a': /* address */ 94 size = sizeof(void *); 95 /* always forces a new line */ 96 if (db_print_position() != 0) 97 db_printf("\n"); 98 db_prev = addr; 99 db_printsym(addr, DB_STGY_ANY); 100 db_printf(":\t"); 101 break; 102 default: 103 if (db_print_position() == 0) { 104 /* Print the address. */ 105 db_printsym(addr, DB_STGY_ANY); 106 db_printf(":\t"); 107 db_prev = addr; 108 } 109 110 width = size * 4; 111 switch (c) { 112 case 'r': /* signed, current radix */ 113 value = db_get_value(addr, size, TRUE); 114 addr += size; 115 db_printf("%+-*lr", width, (long)value); 116 break; 117 case 'x': /* unsigned hex */ 118 value = db_get_value(addr, size, FALSE); 119 addr += size; 120 db_printf("%-*lx", width, (long)value); 121 break; 122 case 'z': /* signed hex */ 123 value = db_get_value(addr, size, TRUE); 124 addr += size; 125 db_printf("%-*ly", width, (long)value); 126 break; 127 case 'd': /* signed decimal */ 128 value = db_get_value(addr, size, TRUE); 129 addr += size; 130 db_printf("%-*ld", width, (long)value); 131 break; 132 case 'u': /* unsigned decimal */ 133 value = db_get_value(addr, size, FALSE); 134 addr += size; 135 db_printf("%-*lu", width, (long)value); 136 break; 137 case 'o': /* unsigned octal */ 138 value = db_get_value(addr, size, FALSE); 139 addr += size; 140 db_printf("%-*lo", width, (long)value); 141 break; 142 case 'c': /* character */ 143 value = db_get_value(addr, 1, FALSE); 144 addr += 1; 145 if (value >= ' ' && value <= '~') 146 db_printf("%c", (int)value); 147 else 148 db_printf("\\%03o", (int)value); 149 break; 150 case 's': /* null-terminated string */ 151 for (;;) { 152 value = db_get_value(addr, 1, FALSE); 153 addr += 1; 154 if (value == 0) 155 break; 156 if (value >= ' ' && value <= '~') 157 db_printf("%c", (int)value); 158 else 159 db_printf("\\%03o", (int)value); 160 } 161 break; 162 case 'S': /* symbol */ 163 value = db_get_value(addr, sizeof(void *), 164 FALSE); 165 addr += sizeof(void *); 166 db_printsym(value, DB_STGY_ANY); 167 break; 168 case 'i': /* instruction */ 169 addr = db_disasm(addr, FALSE); 170 break; 171 case 'I': /* instruction, alternate form */ 172 addr = db_disasm(addr, TRUE); 173 break; 174 default: 175 break; 176 } 177 if (db_print_position() != 0) 178 db_end_line(1); 179 break; 180 } 181 } 182 } 183 db_next = addr; 184 } 185 186 /* 187 * Print value. 188 */ 189 static char db_print_format = 'x'; 190 191 /*ARGSUSED*/ 192 void 193 db_print_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, 194 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 } 231 db_printf("\n"); 232 } 233 234 void 235 db_print_loc_and_inst(db_addr_t loc) 236 { 237 db_printsym(loc, DB_STGY_PROC); 238 db_printf(":\t"); 239 (void) db_disasm(loc, TRUE); 240 } 241 242 /* 243 * Search for a value in memory. 244 * Syntax: search [/bhl] addr value [mask] [,count] 245 */ 246 void 247 db_search_cmd(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, 248 char *dummy4) 249 { 250 int t; 251 db_addr_t addr; 252 int size; 253 db_expr_t value; 254 db_expr_t mask; 255 db_expr_t count; 256 257 t = db_read_token(); 258 if (t == tSLASH) { 259 t = db_read_token(); 260 if (t != tIDENT) { 261 bad_modifier: 262 db_printf("Bad modifier\n"); 263 db_flush_lex(); 264 return; 265 } 266 267 if (!strcmp(db_tok_string, "b")) 268 size = 1; 269 else if (!strcmp(db_tok_string, "h")) 270 size = 2; 271 else if (!strcmp(db_tok_string, "l")) 272 size = 4; 273 else 274 goto bad_modifier; 275 } else { 276 db_unread_token(t); 277 size = 4; 278 } 279 280 if (!db_expression((db_expr_t *)&addr)) { 281 db_printf("Address missing\n"); 282 db_flush_lex(); 283 return; 284 } 285 286 if (!db_expression(&value)) { 287 db_printf("Value missing\n"); 288 db_flush_lex(); 289 return; 290 } 291 292 if (!db_expression(&mask)) 293 mask = 0xffffffffUL; 294 295 t = db_read_token(); 296 if (t == tCOMMA) { 297 if (!db_expression(&count)) { 298 db_printf("Count missing\n"); 299 db_flush_lex(); 300 return; 301 } 302 } else { 303 db_unread_token(t); 304 count = -1; /* effectively forever */ 305 } 306 db_skip_to_eol(); 307 308 db_search(addr, size, value, mask, count); 309 } 310 311 static void 312 db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask, 313 unsigned int count) 314 { 315 while (count-- != 0) { 316 db_prev = addr; 317 if ((db_get_value(addr, size, FALSE) & mask) == value) 318 break; 319 addr += size; 320 } 321 db_next = addr; 322 } 323