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; } } }
int db_xcdump( db_addr_t addr, int size, int count, task_t task) { register int i, n; db_expr_t value; int bcount; db_addr_t off; char *name; char data[DB_XCDUMP_NC]; db_find_task_sym_and_offset(addr, &name, &off, task); for (n = count*size; n > 0; n -= bcount) { db_prev = addr; if (off == 0) { db_printf("%s:\n", name); off = -1; } db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr, (size != 1) ? " " : "" ); bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n); if (trunc_page(addr) != trunc_page(addr+bcount-1)) { db_addr_t next_page_addr = trunc_page(addr+bcount-1); if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task)) bcount = next_page_addr - addr; } db_read_bytes((vm_offset_t)addr, bcount, data, task); for (i = 0; i < bcount && off != 0; i += size) { if (i % 4 == 0) db_printf(" "); value = db_get_task_value(addr, size, FALSE, task); db_printf("%0*x ", size*2, value); addr += size; db_find_task_sym_and_offset(addr, &name, &off, task); } db_printf("%*s", ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4, ""); bcount = i; db_printf("%s*", (size != 1)? " ": ""); for (i = 0; i < bcount; i++) { value = data[i]; db_printf("%c", (value >= ' ' && value <= '~')? value: '.'); } db_printf("*\n"); } return(addr); }
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_set_breakpoints(void) { register db_breakpoint_t bkpt; 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; boolean_t inserted = TRUE; if (!db_breakpoints_inserted) { for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { if (bkpt->flags & BKPT_SET_IN_MEM) continue; task = bkpt->task; if (bkpt->flags & BKPT_USR_GLOBAL) { if ((bkpt->flags & BKPT_1ST_SET) == 0) { if (cur_task == TASK_NULL) continue; task = cur_task; } else bkpt->flags &= ~BKPT_1ST_SET; } if (DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); if (inst == BKPT_SET(inst)) continue; bkpt->bkpt_inst = inst; db_put_task_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst), task); bkpt->flags |= BKPT_SET_IN_MEM; } else { inserted = FALSE; } } db_breakpoints_inserted = inserted; } }
int db_numargs( struct i386_frame *fp, task_t task) { long *argp; long inst; long args; extern char etext[]; argp = (long *)db_get_task_value((long)&fp->f_retaddr, sizeof(long), FALSE, task); if (argp < (long *)VM_MIN_KERNEL_ADDRESS || argp > (long *)etext) args = db_numargs_default; else if (!DB_CHECK_ACCESS((long)argp, sizeof(long), task)) args = db_numargs_default; else { inst = db_get_task_value((long)argp, sizeof(long), FALSE, task); if ((inst & 0xff) == 0x59) /* popl %ecx */ args = 1; else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */ args = ((inst >> 16) & 0xff) / 4; else args = db_numargs_default; }