static int handle_breakpoint(struct task *task) { struct breakpoint *bp = task->event.e_un.breakpoint; unsigned int hw = bp->hw; debug(DEBUG_EVENT, "+++ process pid=%d breakpoint addr=%#lx", task->pid, bp->addr); assert(task->stopped); if (unlikely(options.verbose > 1)) set_timer(&task->halt_time, hw ? &hw_bp_time : &sw_bp_time); if (unlikely(options.verbose)) ++bp->count; if (unlikely(task->skip_bp)) { struct breakpoint *skip_bp = task->skip_bp; task->skip_bp = NULL; breakpoint_put(skip_bp); if (likely(skip_bp == bp)) { skip_breakpoint(task, bp); goto end; } if (unlikely(options.verbose)) fprintf(stderr, "!!!unhandled skip breakpoint for pid=%d\n", task->pid); } if (unlikely(bp->deleted)) { continue_task(task, 0); goto end; } #if HW_BREAKPOINTS > 1 if (bp->type >= BP_HW) { if (unlikely(++bp->hwcnt >= (BP_REORDER_THRESHOLD << hw))) { struct timespec start; if (unlikely(options.verbose > 1)) start_time(&start); reorder_hw_bp(task); if (unlikely(options.verbose > 1)) set_timer(&start, &reorder_time); } } #endif if (bp->on_hit && bp->on_hit(task, bp)) { continue_task(task, 0); goto end; } if (likely(bp->libsym && !task->breakpoint)) { struct library_symbol *libsym = bp->libsym; save_param_context(task); if (libsym->func->report_out || !options.nocpp) { task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, BP_HW_SCRATCH); if (likely(task->breakpoint)) { task->libsym = libsym; task->breakpoint->on_hit = handle_call_after; #if HW_BREAKPOINTS > 0 enable_scratch_hw_bp(task, task->breakpoint); #endif } } if (libsym->func->report_in) { struct timespec start; if (unlikely(options.verbose > 1)) start_time(&start); libsym->func->report_in(task, libsym); if (unlikely(options.verbose > 1)) set_timer(&start, &report_in_time); } } if (task->bp_skipped) task->bp_skipped = 0; else skip_breakpoint(task, bp); end: breakpoint_put(bp); return 0; }
static void handle_breakpoint(Event *event) { int i, j; Breakpoint *sbp; Process *leader = event->proc->leader; /* The leader has terminated. */ if (leader == NULL) { continue_process(event->proc->pid); return; } debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr); debug(2, "event: breakpoint (%p)", event->e_un.brk_addr); #ifdef __powerpc__ /* Need to skip following NOP's to prevent a fake function from being stacked. */ long stub_addr = (long) get_count_register(event->proc); Breakpoint *stub_bp = NULL; char nop_instruction[] = PPC_NOP; stub_bp = address2bpstruct(leader, event->e_un.brk_addr); if (stub_bp) { unsigned char *bp_instruction = stub_bp->orig_value; if (memcmp(bp_instruction, nop_instruction, PPC_NOP_LENGTH) == 0) { if (stub_addr != (long) event->e_un.brk_addr) { set_instruction_pointer (event->proc, event->e_un.brk_addr + 4); continue_process(event->proc->pid); return; } } } #endif for (i = event->proc->callstack_depth - 1; i >= 0; i--) { if (event->e_un.brk_addr == event->proc->callstack[i].return_addr) { #ifdef __powerpc__ /* * PPC HACK! (XXX FIXME TODO) * The PLT gets modified during the first call, * so be sure to re-enable the breakpoint. */ unsigned long a; struct library_symbol *libsym = event->proc->callstack[i].c_un.libfunc; void *addr = sym2addr(event->proc, libsym); if (libsym->plt_type != LS_TOPLT_POINT) { unsigned char break_insn[] = BREAKPOINT_VALUE; sbp = address2bpstruct(leader, addr); assert(sbp); a = ptrace(PTRACE_PEEKTEXT, event->proc->pid, addr); if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) { sbp->enabled--; insert_breakpoint(event->proc, addr, libsym, 1); } } else { sbp = dict_find_entry(leader->breakpoints, addr); /* On powerpc, the breakpoint address may end up being actual entry point of the library symbol, not the PLT address we computed. In that case, sbp is NULL. */ if (sbp == NULL || addr != sbp->addr) { insert_breakpoint(event->proc, addr, libsym, 1); } } #elif defined(__mips__) void *addr = NULL; struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc; struct library_symbol *new_sym; assert(sym); addr = sym2addr(event->proc, sym); sbp = dict_find_entry(leader->breakpoints, addr); if (sbp) { if (addr != sbp->addr) { insert_breakpoint(event->proc, addr, sym, 1); } } else { new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); new_sym->next = leader->list_of_symbols; leader->list_of_symbols = new_sym; insert_breakpoint(event->proc, addr, new_sym, 1); } #endif for (j = event->proc->callstack_depth - 1; j > i; j--) { callstack_pop(event->proc); } if (event->proc->state != STATE_IGNORED) { if (opt_T || options.summary) { calc_time_spent(event->proc); } } event->proc->return_addr = event->e_un.brk_addr; if (event->proc->state != STATE_IGNORED) { mock_return(LT_TOF_FUNCTIONR, event->proc, event->proc->callstack[i].c_un.libfunc->name); output_right(LT_TOF_FUNCTIONR, event->proc, event->proc->callstack[i].c_un.libfunc->name); } callstack_pop(event->proc); sbp = address2bpstruct(leader, event->e_un.brk_addr); continue_after_breakpoint(event->proc, sbp); return; } } if ((sbp = address2bpstruct(leader, event->e_un.brk_addr))) { if (sbp->libsym == NULL) { continue_after_breakpoint(event->proc, sbp); return; } if (strcmp(sbp->libsym->name, "") == 0) { debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n"); arch_check_dbg(leader); } if (event->proc->state != STATE_IGNORED) { event->proc->stack_pointer = get_stack_pointer(event->proc); event->proc->return_addr = get_return_addr(event->proc, event->proc->stack_pointer); callstack_push_symfunc(event->proc, sbp->libsym); output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name); } #ifdef PLT_REINITALISATION_BP if (event->proc->need_to_reinitialize_breakpoints && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) == 0)) reinitialize_breakpoints(leader); #endif continue_after_breakpoint(event->proc, sbp); return; } if (event->proc->state != STATE_IGNORED && !options.no_plt) { output_line(event->proc, "unexpected breakpoint at %p", (void *)event->e_un.brk_addr); } continue_process(event->proc->pid); }
static void * throw_helper(struct eh_context *eh, void *pc, frame_state *my_udata, long *offset_p) { frame_state ustruct2, *udata = &ustruct2; frame_state ustruct; frame_state *sub_udata = &ustruct; void *saved_pc = pc; void *handler; void *handler_p = NULL; void *pc_p = NULL; frame_state saved_ustruct; int new_eh_model; int cleanup = 0; int only_cleanup = 0; int rethrow = 0; int saved_state = 0; long args_size; __eh_info *eh_info = (__eh_info *)eh->info; if (eh->table_index != (void *) 0) { rethrow = 1; } memcpy(udata, my_udata, sizeof (*udata)); handler = (void *) 0; for (;;) { frame_state *p = udata; udata = next_stack_level (pc, udata, sub_udata); sub_udata = p; if (! udata) { break; } if (udata->eh_ptr == ((void *)0) ) { new_eh_model = 0; } else { new_eh_model = (((exception_descriptor *)(udata->eh_ptr))-> runtime_id_field == ((void *) -2) ); } if (rethrow) { rethrow = 0; handler = find_exception_handler (eh->table_index, udata->eh_ptr, eh_info, 1, &cleanup); eh->table_index = (void *)0; } else { if (new_eh_model) { handler = find_exception_handler (pc, udata->eh_ptr, eh_info, 0, &cleanup); } else { handler = old_find_exception_handler (pc, udata->eh_ptr); } } if (handler) { if (cleanup) { if (!saved_state) { saved_ustruct = *udata; handler_p = handler; pc_p = pc; saved_state = 1; only_cleanup = 1; } } else { only_cleanup = 0; break; } } pc = get_return_addr (udata, sub_udata) - 1; } if (saved_state) { udata = &saved_ustruct; handler = handler_p; pc = pc_p; if (only_cleanup) { __unwinding_cleanup (); } } if (! handler) { __terminate(); } eh->handler_label = handler; args_size = udata->args_size; if (pc == saved_pc) { udata = my_udata; } else { int i; void *handler_pc = pc; pc = saved_pc; memcpy (udata, my_udata, sizeof (*udata)); while (pc != handler_pc) { frame_state *p = udata; udata = next_stack_level (pc, udata, sub_udata); sub_udata = p; for (i = 0; i < 76 ; ++i) { if (i != udata->retaddr_column && udata->saved[i]) { if (in_reg_window (i, udata) && udata->saved[udata->retaddr_column] == 2 && udata->reg_or_offset[udata->retaddr_column] == i) { continue; } copy_reg (i, udata, my_udata); } } pc = get_return_addr (udata, sub_udata) - 1; } if (udata->saved[udata->retaddr_column] == 2 ) { i = udata->reg_or_offset[udata->retaddr_column]; if (in_reg_window (i, udata)) { copy_reg (i, udata, my_udata); } } } *offset_p = udata->cfa - my_udata->cfa + args_size; return handler; }