void db_breakpoint_cmd( db_expr_t addr, int have_addr, db_expr_t count, char * modif) { register int n; thread_act_t thr_act; boolean_t user_global = db_option(modif, 'U'); boolean_t task_bpt = db_option(modif, 'T'); boolean_t user_space; if (count == -1) count = 1; if (task_bpt && user_global) db_error("Cannot specify both 'T' and 'U'\n"); user_space = (user_global)? TRUE: db_option(modif, 'u'); if (user_space && db_access_level < DB_ACCESS_CURRENT) db_error("User space break point is not supported\n"); if ((!task_bpt || !user_space) && !DB_VALID_ADDRESS(addr, user_space)) { /* if the user has explicitly specified user space, do not insert a breakpoint into the kernel */ if (user_space) db_error("Invalid user space address\n"); user_space = TRUE; db_printf("%#X is in user space\n", addr); db_printf("kernel is from %#X to %#x\n", VM_MIN_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS); } if (db_option(modif, 't') || task_bpt) { for (n = 0; db_get_next_act(&thr_act, n); n++) { if (thr_act == THR_ACT_NULL) db_error("No active thr_act\n"); if (task_bpt && thr_act->task == TASK_NULL) db_error("No task\n"); if (db_access_level <= DB_ACCESS_CURRENT && user_space && thr_act->task != db_current_space()) db_error("Cannot set break point in inactive user space\n"); db_set_breakpoint(db_target_space(thr_act, user_space), (db_addr_t)addr, count, (user_global)? THR_ACT_NULL: thr_act, task_bpt); } } else { db_set_breakpoint(db_target_space(THR_ACT_NULL, user_space), (db_addr_t)addr, count, THR_ACT_NULL, FALSE); } }
void db_task_trap( int type, int code, boolean_t user_space) { jmp_buf_t db_jmpbuf; jmp_buf_t *prev; boolean_t bkpt; boolean_t watchpt; task_t task; task_t task_space; task = db_current_task(); task_space = db_target_space(current_act(), user_space); bkpt = IS_BREAKPOINT_TRAP(type, code); watchpt = IS_WATCHPOINT_TRAP(type, code); /* * Note: we look up PC values in an address space (task_space), * but print symbols using a (task-specific) symbol table, found * using task. */ db_init_default_act(); db_check_breakpoint_valid(); if (db_stop_at_pc(&bkpt, task, task_space)) { if (db_inst_count) { db_printf("After %d instructions (%d loads, %d stores),\n", db_inst_count, db_load_count, db_store_count); } if (bkpt) db_printf("Breakpoint at "); else if (watchpt) db_printf("Watchpoint at "); else db_printf("Stopped at "); db_dot = PC_REGS(DDB_REGS); prev = db_recover; if (_setjmp(db_recover = &db_jmpbuf) == 0) { #if defined(__alpha) db_print_loc(db_dot, task_space); db_printf("\n\t"); db_print_inst(db_dot, task_space); #else /* !defined(__alpha) */ #if defined(__powerpc__) db_print_loc_and_inst(db_dot, task_space); #else /* __powerpc__ */ db_print_loc_and_inst(db_dot, task); #endif /* __powerpc__ */ #endif /* defined(__alpha) */ } else db_printf("Trouble printing location %#X.\n", db_dot); db_recover = prev; db_command_loop(); } db_restart_at_pc(watchpt, task_space); }
/* Delete breakpoint */ void db_delete_cmd(void) { register int n; thread_act_t thr_act; vm_offset_t task_thd; boolean_t user_global = FALSE; boolean_t task_bpt = FALSE; boolean_t user_space = FALSE; boolean_t thd_bpt = FALSE; db_expr_t addr; int t; t = db_read_token(); if (t == tSLASH) { t = db_read_token(); if (t != tIDENT) { db_printf("Bad modifier \"%s\"\n", db_tok_string); db_error(0); } user_global = db_option(db_tok_string, 'U'); user_space = (user_global)? TRUE: db_option(db_tok_string, 'u'); task_bpt = db_option(db_tok_string, 'T'); thd_bpt = db_option(db_tok_string, 't'); if (task_bpt && user_global) db_error("Cannot specify both 'T' and 'U' option\n"); t = db_read_token(); } if ( t == tSTAR ) { db_printf("Delete ALL breakpoints\n"); db_delete_all_breakpoints( (task_t)task_bpt ); return; } if (t == tHASH) { db_thread_breakpoint_t tbp; db_breakpoint_t bkpt; if (db_read_token() != tNUMBER) { db_printf("Bad break point number #%s\n", db_tok_string); db_error(0); } if ((tbp = db_find_breakpoint_number(db_tok_number, &bkpt)) == 0) { db_printf("No such break point #%d\n", db_tok_number); db_error(0); } db_delete_breakpoint(bkpt->task, bkpt->address, tbp->tb_task_thd); return; } db_unread_token(t); if (!db_expression(&addr)) { /* * We attempt to pick up the user_space indication from db_dot, * so that a plain "d" always works. */ addr = (db_expr_t)db_dot; if (!user_space && !DB_VALID_ADDRESS(addr, FALSE)) user_space = TRUE; } if (!DB_VALID_ADDRESS(addr, user_space)) { db_printf("Address %#X is not in %s space\n", addr, (user_space)? "user": "******"); db_error(0); } if (thd_bpt || task_bpt) { for (n = 0; db_get_next_act(&thr_act, n); n++) { if (thr_act == THR_ACT_NULL) db_error("No active thr_act\n"); if (task_bpt) { if (thr_act->task == TASK_NULL) db_error("No task\n"); task_thd = (vm_offset_t) (thr_act->task); } else task_thd = (user_global)? 0: (vm_offset_t) thr_act; db_delete_breakpoint(db_target_space(thr_act, user_space), (db_addr_t)addr, task_thd); } } else { db_delete_breakpoint(db_target_space(THR_ACT_NULL, user_space), (db_addr_t)addr, 0); } }
/* * kdb_trap - field a TRACE or BPT trap */ void kdb_trap( int type, struct savearea *regs) { boolean_t trap_from_user; int previous_console_device; int code=0; previous_console_device=switch_to_serial_console(); switch (type) { case T_TRACE: /* single_step */ case T_PROGRAM: /* breakpoint */ #if 0 case T_WATCHPOINT: /* watchpoint */ #endif case -1: /* keyboard interrupt */ break; default: if (db_recover) { ppc_nested_saved_state = *regs; db_printf("Caught "); if (type > TRAP_TYPES) db_printf("type %d", type); else db_printf("%s", trap_type[type]); db_printf(" trap, pc = %x\n", regs->save_srr0); db_error(""); /*NOTREACHED*/ } kdbprinttrap(type, code, (int *)®s->save_srr0, regs->save_r1); } saved_state[cpu_number()] = regs; ppc_last_saved_statep = regs; ppc_last_kdb_sp = (unsigned) &type; if (!IS_USER_TRAP(regs)) { bzero((char *)&ddb_regs, sizeof (ddb_regs)); ddb_regs = *regs; trap_from_user = FALSE; } else { ddb_regs = *regs; trap_from_user = TRUE; } db_task_trap(type, code, trap_from_user); *regs = ddb_regs; if ((type == T_PROGRAM) && (db_get_task_value(regs->save_srr0, BKPT_SIZE, FALSE, db_target_space(current_act(), trap_from_user)) == BKPT_INST)) regs->save_srr0 += BKPT_SIZE; kdb_exit: saved_state[cpu_number()] = 0; switch_to_old_console(previous_console_device); }