Recently a co-worker of mine needed to enable floating point exceptions in
order to track down an obscure math bug somewhere in the large application
we're working on.  His attempts to do this under his development
environment (MS Windows + MS "Developer Studio") not only crashed his
debugger, but also his entire system.  He asked me to try to track down
the bug on my system, which is Linux 2.0.33 + egcs 1.1 + gdb 4.17.0.4.

It took me a while to determine how to do this, and unfortunately it is
highly platform dependant, and not built into gdb at all.  However the few
people I showed it to were very excited (eg, "wow, I've always wanted to
know how to do that!") so I'm going to post it here in case others were
interested.

Anyhow...

As you'd expect any sort of floating point exception thrown by the
processor gets translated by the OS into SIGFPE, aka Arithmatic exception.
(type "info signal SIGFPE" at the gdb prompt)  So it's actually an OS
issue and not a debugger issue.  (It would be nice if someone could
integrate this into gdb so that you could enable or disable it at will
rather than having to recompile your program whenever you wanted to enable
the exception.  Of course, the code would be quite ugly if you wanted to
keep it cross platform - a mass of #ifdef's.)

My main hint was seeing how FreeBSD does it, from this post:

http://www.freebsd.org/cgi/getmsg.cgi?fetch=642373+645610+/usr/local/www/db/text/1998/freebsd-questions/19980816.freebsd-questions

As it turns out, this is one area that FreeBSD kicks Linux's ass.  Their
method is both platform independant and much cleaner.

Digging around in the include directories, I discovered fpu_control.h.
Glancing into it I learned that:

a) I'd need different code to enable exceptions depending on my processor
b) as of my system (which is a bit out of date, being 2.0.33 and libc5)
only i386 and 68000 have fpu_control functions availible.

Anyhow, all you need to do to enable floating point exceptions (causing a
SIGFPE to be thrown) is include fpu_control.h and add the line:

  __setfpucw(0x1372);

There are actually #define's for the various types of exceptions (divide
by zero, NaN (such as sqrt(-1), etc) in the i386/fpu_control.h, although I
didn't have much luck trying to composite them.  The above seems to enable
all of them.

If I get some time, and presuming someone hasn't already done this in the
development kernels, I may steal the FreeBSD interface and slap it in
there so as to make things a little more reasonable to use.  But in the
meantime you can catch your Inf's and NaN's using the simple code change
above.  (gdb already catches SIGFPE by default, so you don't need to do
anything there)

Hope this is useful to someone.

Reply via email to