[Bug 250454] PT_GETFPREGS on i386 oversimplifies translating FPU Tag Word

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Mon Oct 19 09:45:48 UTC 2020


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=250454

            Bug ID: 250454
           Summary: PT_GETFPREGS on i386 oversimplifies translating FPU
                    Tag Word
           Product: Base System
           Version: Unspecified
          Hardware: i386
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: mgorny at gentoo.org
                CC: kib at FreeBSD.org

The current code for translating FXSAVE area into FSAVE-alike struct for
PT_GETFPREGS on i386 is oversimplifying the translation of FPU Tag Word
(.en_tw).  The code maps all non-empty registers into 00 (i.e. normalized
value) without distinguishing between normalized values, zeroes and specials
like FSAVE does.


Simple reproducer (works with -m32 on amd64):

#include <assert.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <machine/reg.h>

int main() {
        int ret;
        int pid = fork();
        assert(pid != -1);
        if (pid == 0) {
                int i;
                pthread_t t2, t3;

                ret = ptrace(PT_TRACE_ME, 0, NULL, 0);
                assert(ret != -1);

                __asm__ __volatile__ (
                        "finit\n\t"
                        "fldz\n\t"
                        "fld1\n\t"
                        "fdiv %st(1),%st(0) \n\t"
                        "fld1\n\t"
                        "int3\n\t"
                );

                return 0;
        }

        pid_t waited = waitpid(pid, &ret, 0);
        assert(waited == pid);
        printf("wait: %d\n", ret);

        struct fpreg fpr;

        ret = ptrace(PT_GETFPREGS, pid, &fpr, 0);
        assert (ret == 0);
        printf("ftw = 0x%04x\n", fpr.fpr_env[2]);

        ret = ptrace(PT_CONTINUE, pid, (void*)1, 0);
        assert(ret == 0);

        waited = waitpid(pid, &ret, 0);
        assert(waited == pid);
        printf("wait: %d\n", ret);

        return 0;
}

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list