flds instruction fails on Mac OSX
Pregunta
The flds
instruction should store the value in register st0
. I am debugging a shared library I don't have code for. Sometimes the flds
instruction doesn't have any effect on st0
. Below is gdb
output for a case when it works and a case when it fails. In the broken case the fstat
register is 0x2261 instead of 0x2061. What does the 0x200 flag indicate?
Working version:
0x6d9b4f : flds -0x4(%ebp) 0x6d9b52 : leave 0x6d9b53 : ret (gdb) info registers fstat st0 st1 st2 st3 st4 st5 st6 st7 fstat 0x2061 8289 st0 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st1 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st2 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st3 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st4 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st5 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st6 780250362506194 (raw 0x4030b1688c6c5af48000) st7 1 (raw 0x3fff8000000000000000) (gdb) ni 0x006d9b52 in Startup () 1: x/3i $pc 0x6d9b52 : leave 0x6d9b53 : ret 0x6d9b54 : push %ebp (gdb) info registers fstat st0 st1 st2 st3 st4 st5 st6 st7 fstat 0x1861 6241 st0 -1584 (raw 0xc009c600000000000000) st1 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st2 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st3 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st4 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st5 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st6 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st7 780250362506194 (raw 0x4030b1688c6c5af48000)
Broken version:
0x6d9b4f : flds -0x4(%ebp) 0x6d9b52 : leave 0x6d9b53 : ret (gdb) info registers fstat st0 st1 st2 st3 st4 st5 st6 st7 fstat 0x2261 8801 st0 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st1 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st2 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st3 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st4 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st5 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st6 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st7 -nan(0xc000000000000000) (raw 0xffffc000000000000000) (gdb) ni 0x006d9b52 in Startup () 1: x/3i $pc 0x6d9b52 : leave 0x6d9b53 : ret 0x6d9b54 : push %ebp (gdb) info registers fstat st0 st1 st2 st3 st4 st5 st6 st7 fstat 0x1a61 6753 st0 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st1 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st2 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st3 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st4 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st5 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st6 -nan(0xc000000000000000) (raw 0xffffc000000000000000) st7 -nan(0xc000000000000000) (raw 0xffffc000000000000000)
Solución
Flag 0x200
is known as C1
condition bit, and it provides additional information in case of an FPU stack problem. The intel manual says this:
The C1 condition code flag is used for a variety of functions. When both the IE and SF flags in the x87 FPU status word are set, indicating a stack overflow or underflow exception (#IS), the C1 flag distinguishes between overflow (C1 = 1) and underflow (C1 = 0).
Note that info float
will give you a more verbose dump, including status and control bit names, even with explanations for the latter.
Status Word: 0x1a61 IE PE SF C1
TOP: 3
What all this means is somewhere the code doesn't balance the fpu stack properly. Apparently both the working and the broken version have a stack problem, just one is underflow and the other is overflow, or the C1
flag has been changed in between.
The reason one of them works is probably because the FPU register in question happens to be empty in one case. We can't tell that without the FPU tag word (which info float
would also show).