Message-Id: <199605240127.VAA19071@delorie.com> Date: Thu, 23 May 1996 12:43:52 -0700 (PDT) From: Jeff Welty To: Charles Sandmann Cc: djgpp AT delorie DOT com Subject: Re: How do I get a stack trace after a SIGFPE? In-Reply-To: <319b31f8.sandmann@clio.rice.edu> Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII On Thu, 16 May 1996, Charles Sandmann wrote: > I can't say for sure, but NT may be delaying you seeing the interrupt, > or maybe there is a bug in the signal code in this case as far as the > saved register information. It certainly doesn't look right. Things > to try: > 1) while in your error catcher routine, look at the values in the > __djgpp_exception_state structure (sys/exceptn.h ?) and look in > the source directory src/libc/go32/dpmiexcp.c for hints. > 2) you might try the assembly level floating point store info routine to > get a copy of the FPU state for examination - I think it contains > the EIP of the faulting instruction. > Good luck, and let us know what you find. > I have a solution now. It was suggestion #2 that turned out to be the vital clue, and having the source code for fsdb. fsdb not only catches an FPE, but knows what instruction caused the error. Purusing the source code showed me how to get the FPU state and find the eip of the offending instruction. While I still can't get the entire stack trace, just knowing which line of code caused the error is of tremendous help. Thanks for the tips! Sample code follows. Jeff #include #include #include typedef unsigned long word32; typedef unsigned short word16; typedef unsigned char word8; typedef signed long int32; typedef signed short int16; typedef signed char int8; typedef struct { word16 sig0; word16 sig1; word16 sig2; word16 sig3; word16 exponent:15; word16 sign:1; } NPXREG; typedef struct { word32 control; word32 status; word32 tag; word32 eip; word32 cs; word32 dataptr; word32 datasel; NPXREG reg[8]; } NPX; static NPX npx ; /* Store the contents of the NPX in the global variable `npx'. */ static inline void save_npx (void) { asm ("inb $0xa0, %%al testb $0x20, %%al jz 1f xorl %%al, %%al outb %%al, $0xf0 movb $0x20, %%al outb %%al, $0xa0 outb %%al, $0x20 1: fnsave %0 fwait" : "=m" (npx) : /* No input */ : "%eax"); } void ErrorCatcher(int *reglist) { save_npx() ; fprintf(stderr, "Floating point error:\n") ; fprintf(stderr, "Call frame traceback EIPs:\n 0x%08lx\n", npx.eip) ; exit(1) ; } void sub1(void) { double x, y ; x = 10. ; y = 0. ; x = x/y ; } #ifdef __cplusplus typedef void (*fptr)(int); #else typedef void (*fptr)(); #endif int main(int argc, char **argv) { double x, y ; /* cast Catcher to appropriate type */ signal(SIGFPE, (fptr)ErrorCatcher); x = 10. ; y = 0. ; printf("Hello, world\n") ; fflush(stdout) ; sub1() ; printf("%lf\n", x) ; }