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