[PATCH] display mask on enter to sigreturn, not exit

Denys Vlasenko dvlasenk at redhat.com
Mon Jan 9 12:49:10 UTC 2012


sys_sigreturn() performs ugly manipulations in order to show
the signal mask which is restored by this syscall: on syscall entry,
fetches it from the stack, saves it in tcp->u_arg[]
(where it used to overflow this array - fixed sometime ago),
then retrieves the mask and displays it on syscall exit.

Apparently, the motivation is to make it slightly more obvious
to user that signal mask is restored only when this syscall returns.
IMO, this hardly justifies the necessary hacks. It is much easier
to display the mask at the point when we fetch it - on syscall entry.

While at it, I made it so that we do display returned value/errno.
I see no point in hiding it and showing uninformative "= ?" instead.

Example of pause() being interrupted by ALRM which has installed handler
which re-arms ALRM:
Before the patch:

rt_sigsuspend([INT])                    = ? ERESTARTNOHAND (To be restarted)
--- {si_signo=SIGALRM, si_code=SI_KERNEL} (Alarm clock) ---
rt_sigaction(SIGALRM, {0x807b18a, [ALRM], SA_RESTORER|SA_RESTART, 0x80486e3}, {0x807b18a, [ALRM], SA_RESTORER|SA_RESTART, 0x80486e3}, 8) = 0
alarm(1)                                = 0
sigreturn()                             = ? (mask now [INT])

After:

rt_sigsuspend([INT])                    = ? ERESTARTNOHAND (To be restarted)
--- {si_signo=SIGALRM, si_code=SI_KERNEL, si_value={int=134513920, ptr=0x8048500}} (Alarm clock) ---
rt_sigaction(SIGALRM, {0x807b18a, [ALRM], SA_RESTORER|SA_RESTART, 0x80486e3}, {0x807b18a, [ALRM], SA_RESTORER|SA_RESTART, 0x80486e3}, 8) = 0
alarm(1)                                = 0
sigreturn() (mask now [INT])            = -1 EINTR (Interrupted system call)

An open question is how exactly to display the mask.
"mask now"? "[sig]mask on stack?" Other ideas?

-- 
vda

diff -d -urpN strace.3/defs.h strace.4/defs.h
--- strace.3/defs.h	2012-01-04 15:09:05.000000000 +0100
+++ strace.4/defs.h	2012-01-09 13:25:17.314779225 +0100
@@ -391,6 +391,14 @@ extern int mp_ioctl(int f, int c, void *

  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

+#ifdef LINUX
+# if defined(I386)
+struct pt_regs i386_regs;
+# elif defined(X86_64)
+struct pt_regs x86_64_regs;
+# endif
+#endif /* LINUX */
+
  /* Trace Control Block */
  struct tcb {
  	int flags;		/* See below for TCB_ values */
diff -d -urpN strace.3/signal.c strace.4/signal.c
--- strace.3/signal.c	2012-01-04 15:09:05.000000000 +0100
+++ strace.4/signal.c	2012-01-09 13:16:26.126233162 +0100
@@ -1117,95 +1117,58 @@ sys_sigreturn(struct tcb *tcp)
  	if (entering(tcp)) {
  		struct pt_regs regs;
  		struct sigcontext_struct sc;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
  			return 0;
  		if (umove(tcp, regs.ARM_sp, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.oldmask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.oldmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(S390) || defined(S390X)
  	if (entering(tcp)) {
  		long usp;
  		struct sigcontext_struct sc;
-		tcp->u_arg[0] = 0;
  		if (upeek(tcp, PT_GPR15, &usp) < 0)
  			return 0;
-		if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
-			return 0;
-		tcp->u_arg[0] = 1;
-		memcpy(&tcp->u_arg[1], &sc.oldmask[0], NSIG / 8);
-	} else {
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
+		if (umove(tcp, usp + __SIGNAL_FRAMESIZE, &sc) < 0)
  			return 0;
-		tcp->auxstr = sprintsigmask("mask now ", (sigset_t *)&tcp->u_arg[1], 0);
-		return RVAL_NONE | RVAL_STR;
+		tprints(sprintsigmask(") (mask now ", (sigset_t *)&sc.oldmask[0], 0);
  	}
  	return 0;
  #elif defined(I386)
  	if (entering(tcp)) {
-		long esp;
  		struct sigcontext_struct sc;
-		tcp->u_arg[0] = 0;
-		if (upeek(tcp, 4*UESP, &esp) < 0)
-			return 0;
-		if (umove(tcp, esp, &sc) < 0)
-			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.oldmask;
-	}
-	else {
  		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
+		if (umove(tcp, i386_regs.esp, &sc) < 0)
  			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.oldmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0));
  	}
  	return 0;
  #elif defined(IA64)
  	if (entering(tcp)) {
  		struct sigcontext sc;
  		long sp;
+		sigset_t sigm;
  		/* offset of sigcontext in the kernel's sigframe structure: */
  #		define SIGFRAME_SC_OFFSET	0x90
-		tcp->u_arg[0] = 0;
  		if (upeek(tcp, PT_R12, &sp) < 0)
  			return 0;
  		if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		memcpy(tcp->u_arg + 1, &sc.sc_mask, NSIG / 8);
-	}
-	else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
  		sigemptyset(&sigm);
-		memcpy(&sigm, tcp->u_arg + 1, NSIG / 8);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		memcpy(&sigm, &sc.sc_mask, NSIG / 8);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(POWERPC)
  	if (entering(tcp)) {
  		long esp;
  		struct sigcontext_struct sc;
-		tcp->u_arg[0] = 0;
-		if (upeek(tcp, sizeof(unsigned long)*PT_R1, &esp) < 0)
+		sigset_t sigm;
+		if (upeek(tcp, sizeof(unsigned long) * PT_R1, &esp) < 0)
  			return 0;
  		/* Skip dummy stack frame. */
  #ifdef POWERPC64
@@ -1218,61 +1181,34 @@ sys_sigreturn(struct tcb *tcp)
  #endif
  		if (umove(tcp, esp, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.oldmask;
-	}
-	else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.oldmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(M68K)
  	if (entering(tcp)) {
  		long usp;
  		struct sigcontext sc;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (upeek(tcp, 4*PT_USP, &usp) < 0)
  			return 0;
  		if (umove(tcp, usp, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.sc_mask;
-	}
-	else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.sc_mask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(ALPHA)
  	if (entering(tcp)) {
  		long fp;
  		struct sigcontext_struct sc;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (upeek(tcp, REG_FP, &fp) < 0)
  			return 0;
  		if (umove(tcp, fp, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.sc_mask;
-	}
-	else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.sc_mask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined (SPARC) || defined (SPARC64)
@@ -1280,7 +1216,7 @@ sys_sigreturn(struct tcb *tcp)
  		long i1;
  		struct pt_regs regs;
  		m_siginfo_t si;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
  			perror("sigreturn: PTRACE_GETREGS");
  			return 0;
@@ -1290,16 +1226,8 @@ sys_sigreturn(struct tcb *tcp)
  			perror("sigreturn: umove");
  			return 0;
  		}
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = si.si_mask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(si.si_mask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
@@ -1308,23 +1236,15 @@ sys_sigreturn(struct tcb *tcp)
  	if (entering(tcp)) {
  		long sp;
  		struct ucontext uc;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (upeek(tcp, REG_SP, &sp) < 0)
  			return 0;
  		/* There are six words followed by a 128-byte siginfo.  */
  		sp = sp + 6 * 4 + 128;
  		if (umove(tcp, sp, &uc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = *(long *) &uc.uc_sigmask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(*(long *) &uc.uc_sigmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(MIPS)
@@ -1332,7 +1252,7 @@ sys_sigreturn(struct tcb *tcp)
  		long sp;
  		struct pt_regs regs;
  		m_siginfo_t si;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
  			perror("sigreturn: PTRACE_GETREGS");
  			return 0;
@@ -1340,65 +1260,40 @@ sys_sigreturn(struct tcb *tcp)
  		sp = regs.regs[29];
  		if (umove(tcp, sp, &si) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = si.si_mask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(si.si_mask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(CRISV10) || defined(CRISV32)
  	if (entering(tcp)) {
  		struct sigcontext sc;
  		long regs[PT_MAX+1];
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
  			perror("sigreturn: PTRACE_GETREGS");
  			return 0;
  		}
  		if (umove(tcp, regs[PT_USP], &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.oldmask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.oldmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(TILE)
  	if (entering(tcp)) {
  		struct ucontext uc;
  		long sp;
+		sigset_t sigm;

  		/* offset of ucontext in the kernel's sigframe structure */
  #		define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(struct siginfo)
-		tcp->u_arg[0] = 0;
  		if (upeek(tcp, PTREGS_OFFSET_SP, &sp) < 0)
  			return 0;
  		if (umove(tcp, sp + SIGFRAME_UC_OFFSET, &uc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		memcpy(tcp->u_arg + 1, &uc.uc_sigmask, NSIG / 8);
-	}
-	else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
  		sigemptyset(&sigm);
-		memcpy(&sigm, tcp->u_arg + 1, NSIG / 8);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		memcpy(&sigm, &uc.uc_sigmask, NSIG / 8);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #elif defined(MICROBLAZE)
@@ -1406,22 +1301,14 @@ sys_sigreturn(struct tcb *tcp)
  	if (entering(tcp)) {
  		struct sigcontext sc;
  		long sp;
-		tcp->u_arg[0] = 0;
+		sigset_t sigm;
  		/* Read r1, the stack pointer.  */
  		if (upeek(tcp, 1 * 4, &sp) < 0)
  			return 0;
  		if (umove(tcp, sp, &sc) < 0)
  			return 0;
-		tcp->u_arg[0] = 1;
-		tcp->u_arg[1] = sc.oldmask;
-	} else {
-		sigset_t sigm;
-		tcp->u_rval = tcp->u_error = 0;
-		if (tcp->u_arg[0] == 0)
-			return 0;
-		long_to_sigset(tcp->u_arg[1], &sigm);
-		tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-		return RVAL_NONE | RVAL_STR;
+		long_to_sigset(sc.oldmask, &sigm);
+		tprints(sprintsigmask(") (mask now ", &sigm, 0);
  	}
  	return 0;
  #else
diff -d -urpN strace.3/syscall.c strace.4/syscall.c
--- strace.3/syscall.c	2012-01-04 15:09:05.000000000 +0100
+++ strace.4/syscall.c	2012-01-09 13:24:57.122811923 +0100
@@ -734,10 +734,10 @@ is_restart_error(struct tcb *tcp)
  struct tcb *tcp_last = NULL;

  #ifdef LINUX
-# if defined (I386)
-static struct pt_regs i386_regs;
+# if defined(I386)
+struct pt_regs i386_regs;
  # elif defined(X86_64)
-static struct pt_regs x86_64_regs;
+struct pt_regs x86_64_regs;
  # elif defined (IA64)
  long r8, r10, psr; /* TODO: make static? */
  long ia32 = 0; /* not static */




More information about the Strace-devel mailing list