1

I am trying to read the FPU context in SIGFPE handler.
With GDB, I set a breakpoint in SIGFPE handler, and check the ucontext for the FPU data, I got followings.

(gdb) p/x *ucontext->uc_mcontext.fpregs
$2 = {cwd = 0x37f, swd = 0x0, ftw = 0x0, fop = 0x0, rip = 0x0, rdp = 0x0, mxcsr = 0x1f80, mxcr_mask = 0xffff
....

And,

(gdb) p/x ucontext->__fpregs_mem
$3 = {cwd = 0xe670, swd = 0xffff, ftw = 0x7fff, fop = 0x0, rip = 0x0, rdp = 0x0, mxcsr = 0x37f, mxcr_mask = 0x0, _st = {{significand = {0x0,
        0x0, 0x0, 0x0}, exponent = 0x0, padding = {0x0, 0x0, 0x0}}, {significand = {0x1f80, 0x0, 0xffff, 0x0},

To my surprise, the FP registers have different data, and it seemed that uc_mcontext.fpregs has the data from an offset of __fpregs_mem.

Why is there a difference, should these 2 fields include the same data, no ?

I am using Ubuntu 16.04 X86_64, gcc version 5.4.0 20160609, GLIBC 2.23-0ubuntu10

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
wangt13
  • 959
  • 7
  • 17

1 Answers1

0

It is technically incorrect to call getcontext in a signal handler (read this) though I somewhat doubt that is the cause of your problems. If your goal is to determine which floating point error occurred then you can use this.

It might become easier to help if you post some code snippets.

Roman
  • 36
  • 1
  • I did NOT call getcontext from signal handler. I just used the input parameter pvcontext of my signal handler, like this, static void my_sigaction(int iSignal, siginfo_t *pssiginfo, void *pvcontext). So I think it is the Linux kernel to save the data to ucontext, and they are different. But I don't know why? – wangt13 Nov 13 '19 at 04:33
  • @wangt13 __fpregs_mem starts with two underscores which indicates that it is a private variable. It is possible that it is only used in cases when glibc fills the structure. The kernel might allocate it differently. – Roman Nov 13 '19 at 04:56
  • @Roman: This question is basically asking how it works under the hood, for curiousity's sake. *Not* asking for the best / correct way to actually access the main thread's x87 register state. Details like if (and why) glibc would copy the kernel's state would make a good answer to this question. – Peter Cordes Nov 13 '19 at 05:03
  • @wangt13 I think this could be the reason if I understand the code correctly https://elixir.bootlin.com/linux/latest/source/arch/x86/kernel/fpu/signal.c#L442 – Roman Nov 13 '19 at 05:36
  • @Roman, I got your point on accessing __fpregs_mem, so basically, accessing fpregs is the right way for user space program to get the FPU registers data, right? My first intent is want to know why the difference exists, then as Peter mentioned, knowing how kernel/glibc do with these stuffs is also important and helpful. – wangt13 Nov 13 '19 at 06:30