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 * $Id: db_examine.c,v 1.2 1993/05/20 03:39:12 cgd Exp $ 28 * 29 * HISTORY 30 * $Log: db_examine.c,v $ 31 * Revision 1.2 1993/05/20 03:39:12 cgd 32 * add explicit rcs id 33 * 34 * Revision 1.1.1.1 1993/03/21 09:46:26 cgd 35 * initial import of 386bsd-0.1 sources 36 * 37 * Revision 1.1 1992/03/25 21:45:07 pace 38 * Initial revision 39 * 40 * Revision 2.4 91/02/05 17:06:20 mrt 41 * Changed to new Mach copyright 42 * [91/01/31 16:17:37 mrt] 43 * 44 * Revision 2.3 90/11/07 16:49:23 rpd 45 * Added db_search_cmd, db_search. 46 * [90/11/06 rpd] 47 * 48 * Revision 2.2 90/08/27 21:50:38 dbg 49 * Add 'r', 'z' to print and examine formats. 50 * Change calling sequence of db_disasm. 51 * db_examine sets db_prev and db_next instead of explicitly 52 * advancing dot. 53 * [90/08/20 dbg] 54 * Reflected changes in db_printsym()'s calling seq. 55 * [90/08/20 af] 56 * Reduce lint. 57 * [90/08/07 dbg] 58 * Created. 59 * [90/07/25 dbg] 60 * 61 */ 62 /* 63 * Author: David B. Golub, Carnegie Mellon University 64 * Date: 7/90 65 */ 66 #include "param.h" 67 #include "proc.h" 68 #include <machine/db_machdep.h> /* type definitions */ 69 70 #include <ddb/db_lex.h> 71 #include <ddb/db_output.h> 72 #include <ddb/db_command.h> 73 #include <ddb/db_sym.h> 74 75 char db_examine_format[TOK_STRING_SIZE] = "x"; 76 77 extern db_addr_t db_disasm(/* db_addr_t, boolean_t */); 78 /* instruction disassembler */ 79 80 /* 81 * Examine (print) data. 82 */ 83 /*ARGSUSED*/ 84 void 85 db_examine_cmd(addr, have_addr, count, modif) 86 db_expr_t addr; 87 int have_addr; 88 db_expr_t count; 89 char * modif; 90 { 91 if (modif[0] != '\0') 92 db_strcpy(db_examine_format, modif); 93 94 if (count == -1) 95 count = 1; 96 97 db_examine((db_addr_t) addr, db_examine_format, count); 98 } 99 100 db_examine(addr, fmt, count) 101 register 102 db_addr_t addr; 103 char * fmt; /* format string */ 104 int count; /* repeat count */ 105 { 106 int c; 107 db_expr_t value; 108 int size; 109 int width; 110 char * fp; 111 112 while (--count >= 0) { 113 fp = fmt; 114 size = 4; 115 width = 16; 116 while ((c = *fp++) != 0) { 117 switch (c) { 118 case 'b': 119 size = 1; 120 width = 4; 121 break; 122 case 'h': 123 size = 2; 124 width = 8; 125 break; 126 case 'l': 127 size = 4; 128 width = 16; 129 break; 130 case 'a': /* address */ 131 /* always forces a new line */ 132 if (db_print_position() != 0) 133 db_printf("\n"); 134 db_prev = addr; 135 db_printsym(addr, DB_STGY_ANY); 136 db_printf(":\t"); 137 break; 138 default: 139 if (db_print_position() == 0) { 140 /* If we hit a new symbol, print it */ 141 char * name; 142 db_expr_t off; 143 144 db_find_sym_and_offset(addr, &name, &off); 145 if (off == 0) 146 db_printf("%s:\t", name); 147 else 148 db_printf("\t\t"); 149 150 db_prev = addr; 151 } 152 153 switch (c) { 154 case 'r': /* signed, current radix */ 155 value = db_get_value(addr, size, TRUE); 156 addr += size; 157 db_printf("%-*r", width, value); 158 break; 159 case 'x': /* unsigned hex */ 160 value = db_get_value(addr, size, FALSE); 161 addr += size; 162 db_printf("%-*x", width, value); 163 break; 164 case 'z': /* signed hex */ 165 value = db_get_value(addr, size, TRUE); 166 addr += size; 167 db_printf("%-*z", width, value); 168 break; 169 case 'd': /* signed decimal */ 170 value = db_get_value(addr, size, TRUE); 171 addr += size; 172 db_printf("%-*d", width, value); 173 break; 174 case 'u': /* unsigned decimal */ 175 value = db_get_value(addr, size, FALSE); 176 addr += size; 177 db_printf("%-*u", width, value); 178 break; 179 case 'o': /* unsigned octal */ 180 value = db_get_value(addr, size, FALSE); 181 addr += size; 182 db_printf("%-*o", width, value); 183 break; 184 case 'c': /* character */ 185 value = db_get_value(addr, 1, FALSE); 186 addr += 1; 187 if (value >= ' ' && value <= '~') 188 db_printf("%c", value); 189 else 190 db_printf("\\%03o", value); 191 break; 192 case 's': /* null-terminated string */ 193 for (;;) { 194 value = db_get_value(addr, 1, FALSE); 195 addr += 1; 196 if (value == 0) 197 break; 198 if (value >= ' ' && value <= '~') 199 db_printf("%c", value); 200 else 201 db_printf("\\%03o", value); 202 } 203 break; 204 case 'i': /* instruction */ 205 addr = db_disasm(addr, FALSE); 206 break; 207 case 'I': /* instruction, alternate form */ 208 addr = db_disasm(addr, TRUE); 209 break; 210 default: 211 break; 212 } 213 if (db_print_position() != 0) 214 db_end_line(); 215 break; 216 } 217 } 218 } 219 db_next = addr; 220 } 221 222 /* 223 * Print value. 224 */ 225 char db_print_format = 'x'; 226 227 /*ARGSUSED*/ 228 void 229 db_print_cmd(addr, have_addr, count, modif) 230 db_expr_t addr; 231 int have_addr; 232 db_expr_t count; 233 char * modif; 234 { 235 db_expr_t value; 236 237 if (modif[0] != '\0') 238 db_print_format = modif[0]; 239 240 switch (db_print_format) { 241 case 'a': 242 db_printsym((db_addr_t)addr, DB_STGY_ANY); 243 break; 244 case 'r': 245 db_printf("%11r", addr); 246 break; 247 case 'x': 248 db_printf("%8x", addr); 249 break; 250 case 'z': 251 db_printf("%8z", addr); 252 break; 253 case 'd': 254 db_printf("%11d", addr); 255 break; 256 case 'u': 257 db_printf("%11u", addr); 258 break; 259 case 'o': 260 db_printf("%16o", addr); 261 break; 262 case 'c': 263 value = addr & 0xFF; 264 if (value >= ' ' && value <= '~') 265 db_printf("%c", value); 266 else 267 db_printf("\\%03o", value); 268 break; 269 } 270 db_printf("\n"); 271 } 272 273 db_print_loc_and_inst(loc) 274 db_addr_t loc; 275 { 276 db_printsym(loc, DB_STGY_PROC); 277 db_printf(":\t"); 278 (void) db_disasm(loc, TRUE); 279 } 280 281 db_strcpy(dst, src) 282 register char *dst; 283 register char *src; 284 { 285 while (*dst++ = *src++) 286 ; 287 } 288 289 /* 290 * Search for a value in memory. 291 * Syntax: search [/bhl] addr value [mask] [,count] 292 */ 293 void 294 db_search_cmd() 295 { 296 int t; 297 db_addr_t addr; 298 int size; 299 db_expr_t value; 300 db_expr_t mask; 301 unsigned int count; 302 303 t = db_read_token(); 304 if (t == tSLASH) { 305 t = db_read_token(); 306 if (t != tIDENT) { 307 bad_modifier: 308 db_printf("Bad modifier\n"); 309 db_flush_lex(); 310 return; 311 } 312 313 if (!strcmp(db_tok_string, "b")) 314 size = 1; 315 else if (!strcmp(db_tok_string, "h")) 316 size = 2; 317 else if (!strcmp(db_tok_string, "l")) 318 size = 4; 319 else 320 goto bad_modifier; 321 } else { 322 db_unread_token(t); 323 size = 4; 324 } 325 326 if (!db_expression(&addr)) { 327 db_printf("Address missing\n"); 328 db_flush_lex(); 329 return; 330 } 331 332 if (!db_expression(&value)) { 333 db_printf("Value missing\n"); 334 db_flush_lex(); 335 return; 336 } 337 338 if (!db_expression(&mask)) 339 mask = 0xffffffff; 340 341 t = db_read_token(); 342 if (t == tCOMMA) { 343 if (!db_expression(&count)) { 344 db_printf("Count missing\n"); 345 db_flush_lex(); 346 return; 347 } 348 } else { 349 db_unread_token(t); 350 count = -1; /* effectively forever */ 351 } 352 db_skip_to_eol(); 353 354 db_search(addr, size, value, mask, count); 355 } 356 357 db_search(addr, size, value, mask, count) 358 register 359 db_addr_t addr; 360 int size; 361 db_expr_t value; 362 db_expr_t mask; 363 unsigned int count; 364 { 365 while (count-- != 0) { 366 db_prev = addr; 367 if ((db_get_value(addr, size, FALSE) & mask) == value) 368 break; 369 addr += size; 370 } 371 db_next = addr; 372 } 373