Date: Fri, 26 Sep 2003 16:02:56 +0200 (CEST) From: Mark Kettenis <kettenis@chello.nl> To: freebsd-amd64@freebsd.org Subject: Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS Message-ID: <200309261402.h8QE2u0R055089@elgar.kettenis.dyndns.org>
next in thread | raw e-mail | index | archive | help
Hi folks, The PTRACE_GETFPREGS and PTRACE_SETFPREGS requests are broken on FreeBSD/amd64. In particular, using PTRACE_SETFPREGS is pointless until the program beging traced has executed its first floating-point instruction; that floating-point instruction will reinitialize the precess' floating-point state, overwriting the values set by PTRACE_SETFPREGS. I traced this back to src/sys/amd64/amd64/machdep.c:fill_fpregs() where we read the floating-point state from the pcb, regardless of whether PCB_NPXINITDONE has been set, and set_fpregs() where we don't set PCB_NPXINITDONE, and fail to properly set the floating-point registers if the current process "owns" the FPU. This probably means that /proc is broken too. What puzzles me is that the amd64 code is pretty much identical to the i386, and that everything appears to be working fine there, at least with GDB. The only thing I can think of is that every process executes a floating-point instruction before reaching main(). However, I haven't been able to find such an instruction. Anyway, I think the code is incorrect on the i386 too, and that we just happen not to notice where it matters. The attached patch fixes things for me. The functions fill_fpregs_xmm() and set_fpregs_xmm() can probably be eliminated passing fpregs directly to npxgetregs and npxsetregs. I'll open a bug report with this info. Mark --- src/sys/amd64/amd64/machdep.c.orig Tue Sep 9 21:32:09 2003 +++ src/sys/amd64/amd64/machdep.c Sat Sep 20 11:47:19 2003 @@ -1413,8 +1413,10 @@ set_fpregs_xmm(struct fpreg *fpregs, str int fill_fpregs(struct thread *td, struct fpreg *fpregs) { + struct savefpu sv_xmm; - fill_fpregs_xmm(&td->td_pcb->pcb_save, fpregs); + npxgetregs(td, &sv_xmm); + fill_fpregs_xmm(&sv_xmm, fpregs); return (0); } @@ -1422,8 +1424,10 @@ fill_fpregs(struct thread *td, struct fp int set_fpregs(struct thread *td, struct fpreg *fpregs) { + struct savefpu sv_xmm; - set_fpregs_xmm(fpregs, &td->td_pcb->pcb_save); + set_fpregs_xmm(fpregs, &sv_xmm); + npxsetregs(td, &sv_xmm); return (0); } --- src/sys/amd64/isa/npx.c.orig Fri Jul 25 23:18:52 2003 +++ src/sys/amd64/isa/npx.c Sat Sep 20 11:47:19 2003 @@ -646,7 +646,7 @@ npxsetregs(td, addr) intr_restore(s); bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr)); } - curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE; + td->td_pcb->pcb_flags |= PCB_NPXINITDONE; } static device_method_t npx_methods[] = {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309261402.h8QE2u0R055089>