Ejemplo n.º 1
0
static void
handle_arch_sysret(Event *event) {
	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		if (opt_T || options.summary) {
			calc_time_spent(event->proc);
		}
		if (options.syscalls) {
			output_right(LT_TOF_SYSCALLR, event->proc,
					arch_sysname(event->proc, event->e_un.sysnum));
		}
		callstack_pop(event->proc);
	}
	continue_process(event->proc->pid);
}
Ejemplo n.º 2
0
static void
handle_sysret(Event *event) {
	debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		if (opt_T || options.summary) {
			calc_time_spent(event->proc);
		}
		if (options.syscalls) {
			output_right(LT_TOF_SYSCALLR, event->proc,
					sysname(event->proc, event->e_un.sysnum));
		}
		assert(event->proc->callstack_depth > 0);
		unsigned d = event->proc->callstack_depth - 1;
		assert(event->proc->callstack[d].is_syscall);
		callstack_pop(event->proc);
	}
	continue_after_syscall(event->proc, event->e_un.sysnum, 1);
}
Ejemplo n.º 3
0
static void
private_process_destroy(struct Process *proc, int was_exec)
{
	/* Pop remaining stack elements.  */
	while (proc->callstack_depth > 0) {
		/* When this is called just before a process is
		 * destroyed, the breakpoints should either have been
		 * retracted by now, or were killed by exec.  In any
		 * case, it's safe to pretend that there are no
		 * breakpoints associated with the stack elements, so
		 * that stack_pop doesn't attempt to destroy them.  */
		size_t i = proc->callstack_depth - 1;
		if (!proc->callstack[i].is_syscall)
			proc->callstack[i].return_addr = 0;

		callstack_pop(proc);
	}

	if (!was_exec)
		free(proc->filename);

	/* Libraries and symbols.  This is only relevant in
	 * leader.  */
	struct library *lib;
	for (lib = proc->libraries; lib != NULL; ) {
		struct library *next = lib->next;
		library_destroy(lib);
		free(lib);
		lib = next;
	}
	proc->libraries = NULL;

	/* Breakpoints.  */
	if (proc->breakpoints != NULL) {
		proc_each_breakpoint(proc, NULL, destroy_breakpoint_cb, NULL);
		dict_clear(proc->breakpoints);
		proc->breakpoints = NULL;
	}

	destroy_unwind(proc);
}
Ejemplo n.º 4
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);
}