void db_delete_breakpoint( task_t task, db_addr_t addr, vm_offset_t task_thd) { register db_breakpoint_t bkpt; register db_breakpoint_t *prev; for (prev = &db_breakpoint_list; (bkpt = *prev) != 0; prev = &bkpt->link) { if ((bkpt->task == task || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL))) && bkpt->address == addr) break; } if (bkpt && (bkpt->flags & BKPT_SET_IN_MEM)) { db_printf("cannot delete it now.\n"); return; } if (bkpt == 0 || db_delete_thread_breakpoint(bkpt, task_thd) < 0) { db_printf("Not set.\n"); return; } if (bkpt->threads == 0) { *prev = bkpt->link; db_breakpoint_free(bkpt); } }
/* * Set a temporary breakpoint. * The instruction is changed immediately, * so the breakpoint does not have to be on the breakpoint list. */ db_breakpoint_t db_set_temp_breakpoint( task_t task, db_addr_t addr) { register db_breakpoint_t bkpt; bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return 0; } bkpt->task = task; bkpt->address = addr; bkpt->flags = BKPT_TEMP; bkpt->threads = 0; if (db_add_thread_breakpoint(bkpt, 0, 1, FALSE) < 0) { if (bkpt) db_breakpoint_free(bkpt); db_printf("Too many thread_breakpoints.\n"); return 0; } bkpt->bkpt_inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); db_put_task_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst), task); return bkpt; }
void db_set_breakpoint( task_t task, db_addr_t addr, int count, thread_act_t thr_act, boolean_t task_bpt) { register db_breakpoint_t bkpt; db_breakpoint_t alloc_bkpt = 0; vm_offset_t task_thd; bkpt = db_find_breakpoint(task, addr); if (bkpt) { if (thr_act == THR_ACT_NULL || db_find_thread_breakpoint(bkpt, thr_act)) { db_printf("Already set.\n"); return; } } else { if (!DB_CHECK_ACCESS(addr, BKPT_SIZE, task)) { if (task) { db_printf("Warning: non-resident page for breakpoint at %lX", addr); db_printf(" in task %lX.\n", task); } else { db_printf("Cannot set breakpoint at %lX in kernel space.\n", addr); return; } } alloc_bkpt = bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return; } bkpt->task = task; bkpt->flags = (task && thr_act == THR_ACT_NULL)? (BKPT_USR_GLOBAL|BKPT_1ST_SET): 0; bkpt->address = addr; bkpt->threads = 0; } if (db_breakpoint_list == 0) db_breakpoint_number = 0; task_thd = (task_bpt) ? (vm_offset_t)(thr_act->task) : (vm_offset_t)thr_act; if (db_add_thread_breakpoint(bkpt, task_thd, count, task_bpt) < 0) { if (alloc_bkpt) db_breakpoint_free(alloc_bkpt); db_printf("Too many thread_breakpoints.\n"); } else { db_printf("set breakpoint #%x\n", db_breakpoint_number); if (alloc_bkpt) { bkpt->link = db_breakpoint_list; db_breakpoint_list = bkpt; } } }
void db_delete_temp_breakpoint( task_t task, db_breakpoint_t bkpt) { db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, task); db_delete_thread_breakpoint(bkpt, 0); db_breakpoint_free(bkpt); }
void db_check_breakpoint_valid(void) { register db_thread_breakpoint_t tbp, tbp_next; register db_breakpoint_t bkpt, *bkptp; bkptp = &db_breakpoint_list; for (bkpt = *bkptp; bkpt; bkpt = *bkptp) { if (bkpt->task != TASK_NULL) { if (db_lookup_task(bkpt->task) < 0) { db_force_delete_breakpoint(bkpt, 0, FALSE); *bkptp = bkpt->link; db_breakpoint_free(bkpt); continue; } } else { for (tbp = bkpt->threads; tbp; tbp = tbp_next) { tbp_next = tbp->tb_next; if (tbp->tb_task_thd == 0) continue; if ((tbp->tb_is_task && db_lookup_task((task_t)(tbp->tb_task_thd)) < 0) || (!tbp->tb_is_task && db_lookup_act((thread_act_t)(tbp->tb_task_thd)) < 0)) { db_force_delete_breakpoint(bkpt, tbp->tb_task_thd, tbp->tb_is_task); } } if (bkpt->threads == 0) { db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, bkpt->task); *bkptp = bkpt->link; db_breakpoint_free(bkpt); continue; } } bkptp = &bkpt->link; } }
void db_clear_breakpoints(void) { register db_breakpoint_t bkpt, *bkptp; register task_t task; db_expr_t inst; thread_act_t cur_act = current_act(); task_t cur_task = (cur_act && !cur_act->kernel_loaded) ? cur_act->task: TASK_NULL; if (db_breakpoints_inserted) { bkptp = &db_breakpoint_list; for (bkpt = *bkptp; bkpt; bkpt = *bkptp) { task = bkpt->task; if (bkpt->flags & BKPT_USR_GLOBAL) { if (cur_task == TASK_NULL) { bkptp = &bkpt->link; continue; } task = cur_task; } if ((bkpt->flags & BKPT_SET_IN_MEM) && DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); if (inst != BKPT_SET(inst)) { if (bkpt->flags & BKPT_USR_GLOBAL) { bkptp = &bkpt->link; continue; } db_force_delete_breakpoint(bkpt, 0, FALSE); *bkptp = bkpt->link; db_breakpoint_free(bkpt); continue; } db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, task); bkpt->flags &= ~BKPT_SET_IN_MEM; } bkptp = &bkpt->link; } db_breakpoints_inserted = FALSE; } }
void db_delete_breakpoint(db_addr_t addr) { db_breakpoint_t bkpt; db_breakpoint_t *prev; for (prev = &db_breakpoint_list; (bkpt = *prev) != 0; prev = &bkpt->link) { if (bkpt->address == addr) { *prev = bkpt->link; break; } } if (bkpt == 0) { db_printf("Not set.\n"); return; } db_breakpoint_free(bkpt); }
void db_delete_temp_breakpoint(db_breakpoint_t bkpt) { db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); db_breakpoint_free(bkpt); }