예제 #1
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_rt_sigprocmask(struct tcb *tcp)
{
	sigset_t sigset;

	/* Note: arg[3] is the length of the sigset. */
	if (entering(tcp)) {
		printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
		tprints(", ");
		if (!tcp->u_arg[1])
			tprints("NULL, ");
		else if (copy_sigset_len(tcp, tcp->u_arg[1], &sigset, tcp->u_arg[3]) < 0)
			tprintf("%#lx, ", tcp->u_arg[1]);
		else {
			printsigmask(&sigset, 1);
			tprints(", ");
		}
	}
	else {
		if (!tcp->u_arg[2])
			tprints("NULL");
		else if (syserror(tcp))
			tprintf("%#lx", tcp->u_arg[2]);
		else if (copy_sigset_len(tcp, tcp->u_arg[2], &sigset, tcp->u_arg[3]) < 0)
			tprints("[?]");
		else
			printsigmask(&sigset, 1);
		tprintf(", %lu", tcp->u_arg[3]);
	}
	return 0;
}
예제 #2
0
파일: signal.c 프로젝트: GeoffGats/strace
int sys_rt_sigtimedwait(struct tcb *tcp)
{
	if (entering(tcp)) {
		sigset_t sigset;

		if (copy_sigset_len(tcp, tcp->u_arg[0],
				    &sigset, tcp->u_arg[3]) < 0)
			tprints("[?]");
		else
			printsigmask(&sigset, 1);
		tprints(", ");
		/* This is the only "return" parameter, */
		if (tcp->u_arg[1] != 0)
			return 0;
		/* ... if it's NULL, can decode all on entry */
		tprints("NULL, ");
	}
	else if (tcp->u_arg[1] != 0) {
		/* syscall exit, and u_arg[1] wasn't NULL */
		printsiginfo_at(tcp, tcp->u_arg[1]);
		tprints(", ");
	}
	else {
		/* syscall exit, and u_arg[1] was NULL */
		return 0;
	}
	print_timespec(tcp, tcp->u_arg[2]);
	tprintf(", %d", (int) tcp->u_arg[3]);
	return 0;
};
예제 #3
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_sigsuspend(struct tcb *tcp)
{
	if (entering(tcp)) {
		sigset_t sigm;
		long_to_sigset(tcp->u_arg[2], &sigm);
		printsigmask(&sigm, 0);
	}
	return 0;
}
예제 #4
0
파일: signal.c 프로젝트: GeoffGats/strace
void
print_sigset(struct tcb *tcp, long addr, int rt)
{
	sigset_t ss;

	if (!addr)
		tprints("NULL");
	else if (copy_sigset(tcp, addr, &ss) < 0)
		tprintf("%#lx", addr);
	else
		printsigmask(&ss, rt);
}
예제 #5
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_rt_sigsuspend(struct tcb *tcp)
{
	if (entering(tcp)) {
		sigset_t sigm;
		if (copy_sigset_len(tcp, tcp->u_arg[0], &sigm, tcp->u_arg[1]) < 0)
			tprints("[?]");
		else
			printsigmask(&sigm, 1);
	}
	return 0;
}
예제 #6
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_sigaction(struct tcb *tcp)
{
	long addr;
	sigset_t sigset;
	struct old_sigaction sa;

	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		addr = tcp->u_arg[1];
	} else
		addr = tcp->u_arg[2];
	if (addr == 0)
		tprints("NULL");
	else if (!verbose(tcp))
		tprintf("%#lx", addr);
	else if (umove(tcp, addr, &sa) < 0)
		tprints("{...}");
	else {
		/* Architectures using function pointers, like
		 * hppa, may need to manipulate the function pointer
		 * to compute the result of a comparison. However,
		 * the __sa_handler function pointer exists only in
		 * the address space of the traced process, and can't
		 * be manipulated by strace. In order to prevent the
		 * compiler from generating code to manipulate
		 * __sa_handler we cast the function pointers to long. */
		if ((long)sa.__sa_handler == (long)SIG_ERR)
			tprints("{SIG_ERR, ");
		else if ((long)sa.__sa_handler == (long)SIG_DFL)
			tprints("{SIG_DFL, ");
		else if ((long)sa.__sa_handler == (long)SIG_IGN)
			tprints("{SIG_IGN, ");
		else
			tprintf("{%#lx, ", (long) sa.__sa_handler);
		long_to_sigset(sa.sa_mask, &sigset);
		printsigmask(&sigset, 0);
		tprints(", ");
		printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
		if (sa.sa_flags & SA_RESTORER)
			tprintf(", %p", sa.sa_restorer);
#endif
		tprints("}");
	}
	if (entering(tcp))
		tprints(", ");
	else
		tprintf(", %#lx", (unsigned long) sa.sa_restorer);
	return 0;
}
예제 #7
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_sigpending(struct tcb *tcp)
{
	sigset_t sigset;

	if (exiting(tcp)) {
		if (syserror(tcp))
			tprintf("%#lx", tcp->u_arg[0]);
		else if (copy_sigset(tcp, tcp->u_arg[0], &sigset) < 0)
			tprints("[?]");
		else
			printsigmask(&sigset, 0);
	}
	return 0;
}
예제 #8
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_sigsetmask(struct tcb *tcp)
{
	if (entering(tcp)) {
		sigset_t sigm;
		long_to_sigset(tcp->u_arg[0], &sigm);
		printsigmask(&sigm, 0);
	}
	else if (!syserror(tcp)) {
		sigset_t sigm;
		long_to_sigset(tcp->u_rval, &sigm);
		tcp->auxstr = sprintsigmask("old mask ", &sigm, 0);

		return RVAL_HEX | RVAL_STR;
	}
	return 0;
}
예제 #9
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_sigprocmask(struct tcb *tcp)
{
#ifdef ALPHA
	sigset_t ss;
	if (entering(tcp)) {
		/*
		 * Alpha/OSF is different: it doesn't pass in two pointers,
		 * but rather passes in the new bitmask as an argument and
		 * then returns the old bitmask.  This "works" because we
		 * only have 64 signals to worry about.  If you want more,
		 * use of the rt_sigprocmask syscall is required.
		 * Alpha:
		 *	old = osf_sigprocmask(how, new);
		 * Everyone else:
		 *	ret = sigprocmask(how, &new, &old, ...);
		 */
		memcpy(&ss, &tcp->u_arg[1], sizeof(long));
		printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
		tprints(", ");
		printsigmask(&ss, 0);
	}
	else if (!syserror(tcp)) {
		memcpy(&ss, &tcp->u_rval, sizeof(long));
		tcp->auxstr = sprintsigmask("old mask ", &ss, 0);
		return RVAL_HEX | RVAL_STR;
	}
#else /* !ALPHA */
	if (entering(tcp)) {
		printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
		tprints(", ");
		print_sigset(tcp, tcp->u_arg[1], 0);
		tprints(", ");
	}
	else {
		if (!tcp->u_arg[2])
			tprints("NULL");
		else if (syserror(tcp))
			tprintf("%#lx", tcp->u_arg[2]);
		else
			print_sigset(tcp, tcp->u_arg[2], 0);
	}
#endif /* !ALPHA */
	return 0;
}
예제 #10
0
파일: signal.c 프로젝트: lclementi/strace
void
print_sigset_addr_len(struct tcb *tcp, long addr, long len)
{
	sigset_t ss;

	if (!addr) {
		tprints("NULL");
		return;
	}
	/* Here len is usually equals NSIG / 8 or current_wordsize.
	 * But we code this defensively:
	 */
	if (len < 0) {
 bad:
		tprintf("%#lx", addr);
		return;
	}
	if (len > NSIG / 8)
		len = NSIG / 8;
	sigemptyset(&ss);
	if (umoven(tcp, addr, len, (char *)&ss) < 0)
		goto bad;
	printsigmask(&ss);
}
예제 #11
0
파일: signal.c 프로젝트: GeoffGats/strace
int
sys_rt_sigaction(struct tcb *tcp)
{
	struct new_sigaction sa;
	sigset_t sigset;
	long addr;
	int r;

	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		addr = tcp->u_arg[1];
	} else
		addr = tcp->u_arg[2];

	if (addr == 0) {
		tprints("NULL");
		goto after_sa;
	}
	if (!verbose(tcp)) {
		tprintf("%#lx", addr);
		goto after_sa;
	}
#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
	if (current_wordsize != sizeof(sa.sa_flags) && current_wordsize == 4) {
		struct new_sigaction32 sa32;
		r = umove(tcp, addr, &sa32);
		if (r >= 0) {
			memset(&sa, 0, sizeof(sa));
			sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler;
			sa.sa_flags     = sa32.sa_flags;
			sa.sa_restorer  = (void*)(unsigned long)sa32.sa_restorer;
			/* Kernel treats sa_mask as an array of longs.
			 * For 32-bit process, "long" is uint32_t, thus, for example,
			 * 32th bit in sa_mask will end up as bit 0 in sa_mask[1].
			 * But for (64-bit) kernel, 32th bit in sa_mask is
			 * 32th bit in 0th (64-bit) long!
			 * For little-endian, it's the same.
			 * For big-endian, we swap 32-bit words.
			 */
			sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32);
		}
	} else
#endif
	{
		r = umove(tcp, addr, &sa);
	}
	if (r < 0) {
		tprints("{...}");
		goto after_sa;
	}
	/* Architectures using function pointers, like
	 * hppa, may need to manipulate the function pointer
	 * to compute the result of a comparison. However,
	 * the __sa_handler function pointer exists only in
	 * the address space of the traced process, and can't
	 * be manipulated by strace. In order to prevent the
	 * compiler from generating code to manipulate
	 * __sa_handler we cast the function pointers to long. */
	if ((long)sa.__sa_handler == (long)SIG_ERR)
		tprints("{SIG_ERR, ");
	else if ((long)sa.__sa_handler == (long)SIG_DFL)
		tprints("{SIG_DFL, ");
	else if ((long)sa.__sa_handler == (long)SIG_IGN)
		tprints("{SIG_IGN, ");
	else
		tprintf("{%#lx, ", (long) sa.__sa_handler);
	/* Questionable code below.
	 * Kernel won't handle sys_rt_sigaction
	 * with wrong sigset size (just returns EINVAL)
	 * therefore tcp->u_arg[3(4)] _must_ be NSIG / 8 here,
	 * and we always use smaller memcpy. */
	sigemptyset(&sigset);
#if defined(SPARC) || defined(SPARC64)
	if (tcp->u_arg[4] <= sizeof(sigset))
		memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]);
#else
	if (tcp->u_arg[3] <= sizeof(sigset))
		memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]);
#endif
	else
		memcpy(&sigset, &sa.sa_mask, sizeof(sigset));
	printsigmask(&sigset, 1);
	tprints(", ");
	printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
	if (sa.sa_flags & SA_RESTORER)
		tprintf(", %p", sa.sa_restorer);
#endif
	tprints("}");

 after_sa:
	if (entering(tcp))
		tprints(", ");
	else
#if defined(SPARC) || defined(SPARC64)
		tprintf(", %#lx, %lu", tcp->u_arg[3], tcp->u_arg[4]);
#elif defined(ALPHA)
		tprintf(", %lu, %#lx", tcp->u_arg[3], tcp->u_arg[4]);
#else
		tprintf(", %lu", tcp->u_arg[3]);
#endif
	return 0;
}
예제 #12
0
파일: signal.c 프로젝트: lclementi/strace
static void
decode_new_sigaction(struct tcb *tcp, long addr)
{
	struct new_sigaction sa;
	sigset_t sigset;
	int r;

	if (!addr) {
		tprints("NULL");
		return;
	}
	if (!verbose(tcp) || (exiting(tcp) && syserror(tcp))) {
		tprintf("%#lx", addr);
		return;
	}
#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
	if (current_wordsize != sizeof(sa.sa_flags) && current_wordsize == 4) {
		struct new_sigaction32 sa32;
		r = umove(tcp, addr, &sa32);
		if (r >= 0) {
			memset(&sa, 0, sizeof(sa));
			sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler;
			sa.sa_flags     = sa32.sa_flags;
			sa.sa_restorer  = (void*)(unsigned long)sa32.sa_restorer;
			/* Kernel treats sa_mask as an array of longs.
			 * For 32-bit process, "long" is uint32_t, thus, for example,
			 * 32th bit in sa_mask will end up as bit 0 in sa_mask[1].
			 * But for (64-bit) kernel, 32th bit in sa_mask is
			 * 32th bit in 0th (64-bit) long!
			 * For little-endian, it's the same.
			 * For big-endian, we swap 32-bit words.
			 */
			sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32);
		}
	} else
#endif
	{
		r = umove(tcp, addr, &sa);
	}
	if (r < 0) {
		tprints("{...}");
		return;
	}
	/* Architectures using function pointers, like
	 * hppa, may need to manipulate the function pointer
	 * to compute the result of a comparison. However,
	 * the __sa_handler function pointer exists only in
	 * the address space of the traced process, and can't
	 * be manipulated by strace. In order to prevent the
	 * compiler from generating code to manipulate
	 * __sa_handler we cast the function pointers to long. */
	if ((long)sa.__sa_handler == (long)SIG_ERR)
		tprints("{SIG_ERR, ");
	else if ((long)sa.__sa_handler == (long)SIG_DFL)
		tprints("{SIG_DFL, ");
	else if ((long)sa.__sa_handler == (long)SIG_IGN)
		tprints("{SIG_IGN, ");
	else
		tprintf("{%#lx, ", (long) sa.__sa_handler);
	/*
	 * Sigset size is in tcp->u_arg[4] (SPARC)
	 * or in tcp->u_arg[3] (all other),
	 * but kernel won't handle sys_rt_sigaction
	 * with wrong sigset size (just returns EINVAL instead).
	 * We just fetch the right size, which is NSIG / 8.
	 */
	sigemptyset(&sigset);
	memcpy(&sigset, &sa.sa_mask, NSIG / 8);
	printsigmask(&sigset);
	tprints(", ");

	printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
	if (sa.sa_flags & SA_RESTORER)
		tprintf(", %p", sa.sa_restorer);
#endif
	tprints("}");
}