Subject: single stepping a setcontext
To: None <tech-kern@netbsd.org>
From: Nick Hudson <nick.hudson@dsl.pipex.com>
List: tech-kern
Date: 11/20/2006 22:54:25
--Boundary-00=_hIjYFpov2guGzKa
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Hi,
While looking through the results of a gdb testsuite output on i386 I noticed
that the single stepping through the return from a signal handler (via
__sigtramp_siginfo_2) doesn't work. Everything works until the setcontext
call where the PSL_T bit is restored from the original context and the trap
never occurs. There are two solutions I can see
1) use the PSL_T bit from the trapframe when doing a setcontext instead of
from the mcontext.
2) preserve the PSL_T bit for all syscalls
I've attached patches for both options.
Does anyone see any problems with either? Which is more preferable?
Thanks,
Nick
--Boundary-00=_hIjYFpov2guGzKa
Content-Type: text/x-diff;
charset="us-ascii";
name="sigstep.diffs"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="sigstep.diffs"
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.586
diff -u -p -u -r1.586 machdep.c
--- sys/arch/i386/i386/machdep.c 16 Nov 2006 01:32:38 -0000 1.586
+++ sys/arch/i386/i386/machdep.c 20 Nov 2006 22:50:54 -0000
@@ -2329,8 +2329,13 @@ cpu_setmcontext(struct lwp *l, const mco
tf->tf_fs = gr[_REG_FS];
tf->tf_es = gr[_REG_ES];
tf->tf_ds = gr[_REG_DS];
- /* Only change the user-alterable part of eflags */
- tf->tf_eflags &= ~PSL_USER;
+ /*
+ * Only change the user-alterable part of eflags, but
+ * preserve PSL_T in case we're trying to trace a
+ * setcontext. For example, when returning from a signal
+ * handler.
+ */
+ tf->tf_eflags &= ~(PSL_USER & ~PSL_T);
tf->tf_eflags |= (gr[_REG_EFL] & PSL_USER);
}
tf->tf_edi = gr[_REG_EDI];
Index: sys/arch/i386/i386/syscall.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/syscall.c,v
retrieving revision 1.41
diff -u -p -u -r1.41 syscall.c
--- sys/arch/i386/i386/syscall.c 19 Jul 2006 21:11:42 -0000 1.41
+++ sys/arch/i386/i386/syscall.c 20 Nov 2006 22:50:54 -0000
@@ -92,7 +92,7 @@ syscall_plain(frame)
register struct proc *p;
int error;
size_t argsize;
- register_t code, args[8], rval[2];
+ register_t code, args[8], rval[2], trace;
uvmexp.syscalls++;
l = curlwp;
@@ -100,6 +100,7 @@ syscall_plain(frame)
LWP_CACHE_CREDS(l, p);
code = frame->tf_eax;
+ trace = frame->tf_eflags & PSL_T;
callp = p->p_emul->e_sysent;
params = (caddr_t)frame->tf_esp + sizeof(int);
@@ -174,6 +175,7 @@ syscall_plain(frame)
frame->tf_eflags |= PSL_C; /* carry bit */
break;
}
+ frame->tf_eflags |= trace;
userret(l);
}
@@ -188,7 +190,7 @@ syscall_fancy(frame)
register struct proc *p;
int error;
size_t argsize;
- register_t code, args[8], rval[2];
+ register_t code, args[8], rval[2], trace;
uvmexp.syscalls++;
l = curlwp;
@@ -196,6 +198,7 @@ syscall_fancy(frame)
LWP_CACHE_CREDS(l, p);
code = frame->tf_eax;
+ trace = frame->tf_eflags & PSL_T;
callp = p->p_emul->e_sysent;
params = (caddr_t)frame->tf_esp + sizeof(int);
@@ -276,6 +279,7 @@ out:
frame->tf_eflags |= PSL_C; /* carry bit */
break;
}
+ frame->tf_eflags |= trace;
trace_exit(l, code, args, rval, error);
--Boundary-00=_hIjYFpov2guGzKa--