1 /* $NetBSD: db_run.c,v 1.16 1998/11/25 06:38:03 mycroft Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1993-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 * Author: David B. Golub, Carnegie Mellon University 29 * Date: 7/90 30 */ 31 32 /* 33 * Commands to run process. 34 */ 35 36 #include "opt_ddb.h" 37 38 #include <sys/param.h> 39 #include <sys/proc.h> 40 41 #include <machine/db_machdep.h> 42 43 #include <ddb/db_run.h> 44 #include <ddb/db_access.h> 45 #include <ddb/db_break.h> 46 47 #ifdef SOFTWARE_SSTEP 48 static void db_set_temp_breakpoint __P((db_breakpoint_t, db_addr_t)); 49 static void db_delete_temp_breakpoint __P((db_breakpoint_t)); 50 static struct db_breakpoint db_not_taken_bkpt; 51 static struct db_breakpoint db_taken_bkpt; 52 #endif 53 54 #if defined(DDB) 55 #include <ddb/db_lex.h> 56 #include <ddb/db_watch.h> 57 #include <ddb/db_output.h> 58 #include <ddb/db_sym.h> 59 #include <ddb/db_extern.h> 60 61 int db_run_mode; 62 #define STEP_NONE 0 63 #define STEP_ONCE 1 64 #define STEP_RETURN 2 65 #define STEP_CALLT 3 66 #define STEP_CONTINUE 4 67 #define STEP_INVISIBLE 5 68 #define STEP_COUNT 6 69 70 boolean_t db_sstep_print; 71 int db_loop_count; 72 int db_call_depth; 73 74 boolean_t 75 db_stop_at_pc(regs, is_breakpoint) 76 db_regs_t *regs; 77 boolean_t *is_breakpoint; 78 { 79 register db_addr_t pc; 80 register db_breakpoint_t bkpt; 81 82 pc = PC_REGS(regs); 83 84 #ifdef SOFTWARE_SSTEP 85 /* 86 * If we stopped at one of the single-step breakpoints, 87 * say it's not really a breakpoint so that 88 * we don't skip over the real instruction. 89 */ 90 if (db_taken_bkpt.address == pc || db_not_taken_bkpt.address == pc) 91 *is_breakpoint = FALSE; 92 #endif 93 94 db_clear_single_step(regs); 95 db_clear_breakpoints(); 96 db_clear_watchpoints(); 97 98 #ifdef FIXUP_PC_AFTER_BREAK 99 if (*is_breakpoint) { 100 /* 101 * Breakpoint trap. Fix up the PC if the 102 * machine requires it. 103 */ 104 FIXUP_PC_AFTER_BREAK(regs); 105 pc = PC_REGS(regs); 106 } 107 #endif 108 109 /* 110 * Now check for a breakpoint at this address. 111 */ 112 bkpt = db_find_breakpoint_here(pc); 113 if (bkpt) { 114 if (--bkpt->count == 0) { 115 bkpt->count = bkpt->init_count; 116 *is_breakpoint = TRUE; 117 return (TRUE); /* stop here */ 118 } 119 } else if (*is_breakpoint) { 120 #ifdef PC_ADVANCE 121 PC_ADVANCE(regs); 122 #else 123 PC_REGS(regs) += BKPT_SIZE; 124 #endif 125 } 126 127 *is_breakpoint = FALSE; 128 129 if (db_run_mode == STEP_INVISIBLE) { 130 db_run_mode = STEP_CONTINUE; 131 return (FALSE); /* continue */ 132 } 133 if (db_run_mode == STEP_COUNT) { 134 return (FALSE); /* continue */ 135 } 136 if (db_run_mode == STEP_ONCE) { 137 if (--db_loop_count > 0) { 138 if (db_sstep_print) { 139 db_printf("\t\t"); 140 db_print_loc_and_inst(pc); 141 db_printf("\n"); 142 } 143 return (FALSE); /* continue */ 144 } 145 } 146 if (db_run_mode == STEP_RETURN) { 147 db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); 148 149 /* continue until matching return */ 150 151 if (!inst_trap_return(ins) && 152 (!inst_return(ins) || --db_call_depth != 0)) { 153 if (db_sstep_print) { 154 if (inst_call(ins) || inst_return(ins)) { 155 register int i; 156 157 db_printf("[after %6d] ", db_inst_count); 158 for (i = db_call_depth; --i > 0; ) 159 db_printf(" "); 160 db_print_loc_and_inst(pc); 161 db_printf("\n"); 162 } 163 } 164 if (inst_call(ins)) 165 db_call_depth++; 166 return (FALSE); /* continue */ 167 } 168 } 169 if (db_run_mode == STEP_CALLT) { 170 db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); 171 172 /* continue until call or return */ 173 174 if (!inst_call(ins) && 175 !inst_return(ins) && 176 !inst_trap_return(ins)) { 177 return (FALSE); /* continue */ 178 } 179 } 180 db_run_mode = STEP_NONE; 181 return (TRUE); 182 } 183 184 void 185 db_restart_at_pc(regs, watchpt) 186 db_regs_t *regs; 187 boolean_t watchpt; 188 { 189 register db_addr_t pc = PC_REGS(regs); 190 191 if ((db_run_mode == STEP_COUNT) || 192 (db_run_mode == STEP_RETURN) || 193 (db_run_mode == STEP_CALLT)) { 194 db_expr_t ins; 195 196 /* 197 * We are about to execute this instruction, 198 * so count it now. 199 */ 200 ins = db_get_value(pc, sizeof(int), FALSE); 201 db_inst_count++; 202 db_load_count += inst_load(ins); 203 db_store_count += inst_store(ins); 204 205 #ifdef SOFTWARE_SSTEP 206 /* 207 * Account for instructions in delay slots. 208 */ 209 { 210 db_addr_t brpc; 211 212 brpc = next_instr_address(pc, TRUE); 213 if ((brpc != pc) && 214 (inst_branch(ins) || inst_call(ins) || inst_return(ins))) { 215 ins = db_get_value(brpc, sizeof(int), FALSE); 216 db_inst_count++; 217 db_load_count += inst_load(ins); 218 db_store_count += inst_store(ins); 219 } 220 } 221 #endif 222 } 223 224 if (db_run_mode == STEP_CONTINUE) { 225 if (watchpt || db_find_breakpoint_here(pc)) { 226 /* 227 * Step over breakpoint/watchpoint. 228 */ 229 db_run_mode = STEP_INVISIBLE; 230 db_set_single_step(regs); 231 } else { 232 db_set_breakpoints(); 233 db_set_watchpoints(); 234 } 235 } else { 236 db_set_single_step(regs); 237 } 238 } 239 240 void 241 db_single_step(regs) 242 db_regs_t *regs; 243 { 244 if (db_run_mode == STEP_CONTINUE) { 245 db_run_mode = STEP_INVISIBLE; 246 db_set_single_step(regs); 247 } 248 } 249 250 251 extern int db_cmd_loop_done; 252 253 /* single-step */ 254 /*ARGSUSED*/ 255 void 256 db_single_step_cmd(addr, have_addr, count, modif) 257 db_expr_t addr; 258 int have_addr; 259 db_expr_t count; 260 char * modif; 261 { 262 boolean_t print = FALSE; 263 264 if (count == -1) 265 count = 1; 266 267 if (modif[0] == 'p') 268 print = TRUE; 269 270 db_run_mode = STEP_ONCE; 271 db_loop_count = count; 272 db_sstep_print = print; 273 db_inst_count = 0; 274 db_load_count = 0; 275 db_store_count = 0; 276 277 db_cmd_loop_done = 1; 278 } 279 280 /* trace and print until call/return */ 281 /*ARGSUSED*/ 282 void 283 db_trace_until_call_cmd(addr, have_addr, count, modif) 284 db_expr_t addr; 285 int have_addr; 286 db_expr_t count; 287 char * modif; 288 { 289 boolean_t print = FALSE; 290 291 if (modif[0] == 'p') 292 print = TRUE; 293 294 db_run_mode = STEP_CALLT; 295 db_sstep_print = print; 296 db_inst_count = 0; 297 db_load_count = 0; 298 db_store_count = 0; 299 300 db_cmd_loop_done = 1; 301 } 302 303 /*ARGSUSED*/ 304 void 305 db_trace_until_matching_cmd(addr, have_addr, count, modif) 306 db_expr_t addr; 307 int have_addr; 308 db_expr_t count; 309 char * modif; 310 { 311 boolean_t print = FALSE; 312 313 if (modif[0] == 'p') 314 print = TRUE; 315 316 db_run_mode = STEP_RETURN; 317 db_call_depth = 1; 318 db_sstep_print = print; 319 db_inst_count = 0; 320 db_load_count = 0; 321 db_store_count = 0; 322 323 db_cmd_loop_done = 1; 324 } 325 326 /* continue */ 327 /*ARGSUSED*/ 328 void 329 db_continue_cmd(addr, have_addr, count, modif) 330 db_expr_t addr; 331 int have_addr; 332 db_expr_t count; 333 char * modif; 334 { 335 if (modif[0] == 'c') 336 db_run_mode = STEP_COUNT; 337 else 338 db_run_mode = STEP_CONTINUE; 339 db_inst_count = 0; 340 db_load_count = 0; 341 db_store_count = 0; 342 343 db_cmd_loop_done = 1; 344 } 345 #endif /* DDB */ 346 347 #ifdef SOFTWARE_SSTEP 348 /* 349 * Software implementation of single-stepping. 350 * If your machine does not have a trace mode 351 * similar to the vax or sun ones you can use 352 * this implementation, done for the mips. 353 * Just define the above conditional and provide 354 * the functions/macros defined below. 355 * 356 * boolean_t inst_branch(int inst) 357 * boolean_t inst_call(int inst) 358 * returns TRUE if the instruction might branch 359 * 360 * boolean_t inst_unconditional_flow_transfer(int inst) 361 * returns TRUE if the instruction is an unconditional 362 * transter of flow (i.e. unconditional branch) 363 * 364 * db_addr_t branch_taken(int inst, db_addr_t pc, db_regs_t *regs) 365 * returns the target address of the branch 366 * 367 * db_addr_t next_instr_address(db_addr_t pc, boolean_t bd) 368 * returns the address of the first instruction following the 369 * one at "pc", which is either in the taken path of the branch 370 * (bd == TRUE) or not. This is for machines (e.g. mips) with 371 * branch delays. 372 * 373 * A single-step may involve at most 2 breakpoints - 374 * one for branch-not-taken and one for branch taken. 375 * If one of these addresses does not already have a breakpoint, 376 * we allocate a breakpoint and save it here. 377 * These breakpoints are deleted on return. 378 */ 379 380 #if !defined(DDB) 381 /* XXX - don't check for existing breakpoints in KGDB-only case */ 382 #define db_find_breakpoint_here(pc) (0) 383 #endif 384 385 void 386 db_set_single_step(regs) 387 register db_regs_t *regs; 388 { 389 db_addr_t pc = PC_REGS(regs), brpc = pc; 390 boolean_t unconditional; 391 unsigned int inst; 392 393 /* 394 * User was stopped at pc, e.g. the instruction 395 * at pc was not executed. 396 */ 397 inst = db_get_value(pc, sizeof(int), FALSE); 398 if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) { 399 brpc = branch_taken(inst, pc, regs); 400 if (brpc != pc) { /* self-branches are hopeless */ 401 db_set_temp_breakpoint(&db_taken_bkpt, brpc); 402 } else 403 db_taken_bkpt.address = 0; 404 pc = next_instr_address(pc, TRUE); 405 } 406 407 /* 408 * Check if this control flow instruction is an 409 * unconditional transfer. 410 */ 411 unconditional = inst_unconditional_flow_transfer(inst); 412 413 pc = next_instr_address(pc, FALSE); 414 415 /* 416 * We only set the sequential breakpoint if previous 417 * instruction was not an unconditional change of flow 418 * control. If the previous instruction is an 419 * unconditional change of flow control, setting a 420 * breakpoint in the next sequential location may set 421 * a breakpoint in data or in another routine, which 422 * could screw up in either the program or the debugger. 423 * (Consider, for instance, that the next sequential 424 * instruction is the start of a routine needed by the 425 * debugger.) 426 * 427 * Also, don't set both the taken and not-taken breakpoints 428 * in the same place even if the MD code would otherwise 429 * have us do so. 430 */ 431 if (unconditional == FALSE && 432 db_find_breakpoint_here(pc) == 0 && 433 pc != brpc) 434 db_set_temp_breakpoint(&db_not_taken_bkpt, pc); 435 else 436 db_not_taken_bkpt.address = 0; 437 } 438 439 void 440 db_clear_single_step(regs) 441 db_regs_t *regs; 442 { 443 444 if (db_taken_bkpt.address != 0) 445 db_delete_temp_breakpoint(&db_taken_bkpt); 446 447 if (db_not_taken_bkpt.address != 0) 448 db_delete_temp_breakpoint(&db_not_taken_bkpt); 449 } 450 451 void 452 db_set_temp_breakpoint(bkpt, addr) 453 db_breakpoint_t bkpt; 454 db_addr_t addr; 455 { 456 457 bkpt->map = NULL; 458 bkpt->address = addr; 459 /* bkpt->flags = BKPT_TEMP; - this is not used */ 460 bkpt->init_count = 1; 461 bkpt->count = 1; 462 463 bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE); 464 db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst)); 465 } 466 467 void 468 db_delete_temp_breakpoint(bkpt) 469 db_breakpoint_t bkpt; 470 { 471 db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); 472 bkpt->address = 0; 473 } 474 475 #endif /* SOFTWARE_SSTEP */ 476