Beispiel #1
0
ATF_TC_BODY(signal_forward, tc)
{
	struct proc_handle *phdl;
	int state, status;

	phdl = start_prog(tc, true);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	/* The process should have been interrupted by a signal. */
	state = proc_wstatus(phdl);
	ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d",
	    state);

	/* Continue execution and allow the signal to be delivered. */
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	/*
	 * Make sure the process exited with status 0. If it didn't receive the
	 * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit
	 * status, causing the test to fail.
	 */
	state = proc_wstatus(phdl);
	ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d",
	    state);

	status = proc_getwstat(phdl);
	ATF_REQUIRE(status >= 0);
	ATF_REQUIRE(WIFEXITED(status));
	ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);

	proc_free(phdl);
}
Beispiel #2
0
/*
 * Step over the breakpoint.
 */
int
proc_bkptexec(struct proc_handle *phdl, unsigned long saved)
{
	unsigned long pc;
	unsigned long samesaved;
	int status;

	if (proc_regget(phdl, REG_PC, &pc) < 0) {
		warn("ERROR: couldn't get PC register");
		return (-1);
	}
	proc_bkptregadj(&pc);
	if (proc_bkptdel(phdl, pc, saved) < 0) {
		warn("ERROR: couldn't delete breakpoint");
		return (-1);
	}
	/*
	 * Go back in time and step over the new instruction just
	 * set up by proc_bkptdel().
	 */
	proc_regset(phdl, REG_PC, pc);
	if (ptrace(PT_STEP, proc_getpid(phdl), (caddr_t)1, 0) < 0) {
		warn("ERROR: ptrace step failed");
		return (-1);
	}
	proc_wstatus(phdl);
	status = proc_getwstat(phdl);
	if (!WIFSTOPPED(status)) {
		warn("ERROR: don't know why process stopped");
		return (-1);
	}
	/*
	 * Restore the breakpoint. The saved instruction should be
	 * the same as the one that we were passed in.
	 */
	if (proc_bkptset(phdl, pc, &samesaved) < 0) {
		warn("ERROR: couldn't restore breakpoint");
		return (-1);
	}
	assert(samesaved == saved);

	return (0);
}
Beispiel #3
0
/*ARGSUSED*/
static void
prochandler(struct ps_prochandle *P, const char *msg, void *arg)
{
#if defined(sun)
	const psinfo_t *prp = Ppsinfo(P);
	int pid = Pstatus(P)->pr_pid;
	char name[SIG2STR_MAX];
#else
	int wstatus = proc_getwstat(P);
	int pid = proc_getpid(P);
#endif

	if (msg != NULL) {
		notice("pid %d: %s\n", pid, msg);
		return;
	}

#if defined(sun)
	switch (Pstate(P)) {
#else
	switch (proc_state(P)) {
#endif
	case PS_UNDEAD:
#if defined(sun)
		/*
		 * Ideally we would like to always report pr_wstat here, but it
		 * isn't possible given current /proc semantics.  If we grabbed
		 * the process, Ppsinfo() will either fail or return a zeroed
		 * psinfo_t depending on how far the parent is in reaping it.
		 * When /proc provides a stable pr_wstat in the status file,
		 * this code can be improved by examining this new pr_wstat.
		 */
		if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) {
			notice("pid %d terminated by %s\n", pid,
			    proc_signame(WTERMSIG(prp->pr_wstat),
			    name, sizeof (name)));
#else
		if (WIFSIGNALED(wstatus)) {
			notice("pid %d terminated by %d\n", pid,
			    WTERMSIG(wstatus));
#endif
#if defined(sun)
		} else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) {
			notice("pid %d exited with status %d\n",
			    pid, WEXITSTATUS(prp->pr_wstat));
#else
		} else if (WEXITSTATUS(wstatus) != 0) {
			notice("pid %d exited with status %d\n",
			    pid, WEXITSTATUS(wstatus));
#endif
		} else {
			notice("pid %d has exited\n", pid);
		}
		g_pslive--;
		break;

	case PS_LOST:
		notice("pid %d exec'd a set-id or unobservable program\n", pid);
		g_pslive--;
		break;
	}
}

/*ARGSUSED*/
static int
errhandler(const dtrace_errdata_t *data, void *arg)
{
	error(data->dteda_msg);
	return (DTRACE_HANDLE_OK);
}

/*ARGSUSED*/
static int
drophandler(const dtrace_dropdata_t *data, void *arg)
{
	error(data->dtdda_msg);
	return (DTRACE_HANDLE_OK);
}