delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/05/23/21:29:08

Message-Id: <199605240127.VAA19071@delorie.com>
Date: Thu, 23 May 1996 12:43:52 -0700 (PDT)
From: Jeff Welty <jwelty AT wdni DOT com>
To: Charles Sandmann <sandmann AT clio DOT rice DOT edu>
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

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 <stdio.h>
#include <stdlib.h>
#include <signal.h>

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) ;
}


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019