示例#1
0
文件: event.c 项目: sstefani/mtrace
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;
}
示例#2
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);
}
示例#3
0
文件: throw.c 项目: BillTheBest/k42
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;
}