Return to BSD News archive
Newsgroups: comp.unix.bsd
Path: sserve!manuel!munnari.oz.au!mips!mips!darwin.sura.net!jvnc.net!yale.edu!yale!gumby!destroyer!sol.ctr.columbia.edu!usc!cs.utexas.edu!lgc.com!usenet
From: adunham@lgc.com (Alan Dunham)
Subject: Crash Tracebacks in 386BSD
Message-ID: <1992Aug27.212418.19185@lgc.com>
Sender: usenet@lgc.com
Nntp-Posting-Host: sparky.lgc.com
Organization: Landmark Graphics Corp., Houston, Tx
Date: Thu, 27 Aug 1992 21:24:18 GMT
Lines: 1650
Howdy:
I have ported my crash traceback to 386BSD. (see Doctor Dobbs
Journal September 1992 page 80). This file includes test.c, a
small test program, and 386bsdcrash.c, the main code file.
The test program calls trb_signalinit() to set things up.
This was a quick port and I haven't tested the hell out of it,
so if you find any bugs, email me at adunham@ita.lgc.com and
I'll summarize fixes to the net.
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* test.c a small program to test the crash traceback */
#define DEBUGPRINT /* we don't want debug info */
#ifdef DEBUGPRINT
# define DBPRINT(s) printf s
#else
# define DBPRINT(s)
#endif
void tst_segv(),tst_bus();
void tst_fltdiv(), tst_intdiv(), tst_intoverflow();
void tst_fltoverflow(), tst_fltunderflow();
void tst_lv4(),tst_lv3(),tst_lv2(),tst_lv1();
/*----------------------------------------*/
void tst_segv()
{
char text[16];
char *ptr;
int ii, jj, arr[16];
strcpy(text,"seg fault");
DBPRINT((" in segv\n"));
jj= 4096;
arr[jj] = ii;
}
void tst_fltdiv()
{
char text[16];
float e,d,f;
/*-------------------------------*/
strcpy(text,"fltdiv");
DBPRINT((" in fltdiv \n"));
f= 127.0;
e= 0.0;
d= 126.0;
f=d/e;
}
void tst_intdiv()
{
int a,b,c;
DBPRINT((" in intdiv \n"));
c=12;
a=1;
b=0;
c=a/b;
}
void tst_intoverflow()
{
int i,aa,bb,cc;
char text[16];
strcpy(text,"intoverflow");
DBPRINT((" in intoverflow \n"));
aa= 0x0000ffff;
for(i=0;i<8;i++)
{aa= aa*16;
printf("i=%d aa=0x%x \n",i,aa);
}
}
void tst_fltoverflow()
{
int i;
float ff;
char text[16];
strcpy(text,"fltoverflow");
DBPRINT((" in fltoverflow \n"));
ff= 6.023e23;
for(i=0;i<30;i++)
{ff= ff* 1.0e2;
printf("i=%d ff=%10.3e \n",i,ff);
}
}
void tst_fltunderflow()
{
int i;
float ff;
char text[16];
strcpy(text,"fltunderflow");
DBPRINT((" in fltunderflow \n"));
ff= 6.023e-23;
for(i=0;i<30;i++)
{ff= ff* 1.0e-2;
printf("i=%d ff=%10.3e \n",i,ff);
}
}
void tst_lv4(paramtext)
char *paramtext;
{
long l4;
char text[16];
l4= 0xcafefade;
strcpy(text,"level4");
tst_bus();
}
void tst_lv3(paramtext)
char *paramtext;
{
long l3;
char text[16];
l3= 0xdeafdead;
strcpy(text,"level3");
tst_lv4("call 4");
}
void tst_lv2(paramtext)
char *paramtext;
{
long l2;
char text[17];
l2= 0xfeedface;
strcpy(text,"level2");
tst_lv3("call 3");
}
void tst_lv1()
{
long l1, *lptr;
char text[16];
l1= 0xdeedfade;
lptr= &l1;
strcpy(text,"level1");
tst_lv2("call 2");
}
void tst_bus()
{
char *ptr;
unsigned long uu;
char text[16];
strcpy(text,"bus error");
ptr= 0x0;
*ptr=0;
}
void tst_param(ii,ss,ff,dd,cc,uc,us,ul,ui)
int ii;
short ss;
float ff;
double dd;
char cc;
unsigned char uc;
unsigned short us;
unsigned long ul;
unsigned int ui;
{
tst_bus();
}
void tst_param2(ii,ss,ff,dd,cc,uc,us,ul,ui,ptr)
int *ii;
short *ss;
float *ff;
double *dd;
char *cc;
unsigned char *uc;
unsigned short *us;
unsigned long *ul;
unsigned int *ui;
char *ptr;
{
tst_bus();
}
main(argc,argv)
int argc;
char *argv[];
{
int ii;
char cc;
long ll;
short ss;
float ff;
double dd;
unsigned char uc;
unsigned short us;
unsigned long ul;
unsigned int ui;
int iarr[12];
float farr[8];
char text[21];
int random;
/*--------------------*/
trb_signalinit(argc,argv);
ll=0xfeeadded;
strcpy(text,"traceback");
for(ii=0;ii<12;ii++) iarr[ii]=ii;
for(ii=0,ff=100;ii<8;ii++,ff++) farr[ii]=ff;
ii=12;
cc='q';
ss=24;
ff=256.0;
dd=512.0;
uc= 65;
us= -4;
ul= -8;
ui= -16;
/* get a random number */
random= time(0);
random= random & 7;
printf("random= %d \n",random);
switch (random)
{case 0: tst_fltoverflow(); /* overflow */
break;
case 1: tst_bus(); /* bus error */
break;
case 2: tst_segv(); /* segmentation fault */
break;
case 3: tst_intdiv(); /* integer divide */
break;
case 4: tst_fltdiv(ll,ss,ff,dd); /* float divide */
break;
case 5: tst_lv1(); /* several call levels */
break;
case 6: tst_param(ii,ss,ff,dd,cc,uc,us,ul,ui); /* show parameters */
break;
case 7: tst_param2(&ii,&ss,&ff,&dd,&cc,&uc,&us,&ul,&ui,text);
break;
default: break;
} /* end of switch */
exit(0);
}
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* 386bsdcrash.c signal handling & stack traceback */
/*
* Copyright 1992, Alan Dunham
*
* This code may be copied as long as this copyright notice remains intact
*
*/
#include <stdio.h>
#include <signal.h> /* for signal definitions */
#include <a.out.h> /* for NSYMOFF etc */
#include <stab.h> /* for N_SLINE etc */
#include <string.h> /* for strtok &strstr */
#include <sys/types.h> /* for ctime */
/*----------------- local defines --------------------*/
#undef PROTOTYPES /* ignore prototype info */
#undef DEBUGPRINT /* we want debug info */
#define STACKDUMP 0 /* set to 1 to get 32bit stack dumps */
#define FRAMEDUMP 0 /* set to 1 to dump each stack frame */
#define PARAMDUMP 0 /* set to 1 to get parameter dumps */
#define SYMBOLDUMP 0 /* set to 1 to get local symbol dumps */
#define JUMPPC 1 /* how to find next program counter */
#define JUMPSP 0 /* how to find next stack pointer */
#define MAXLEVEL 40 /* maximum number of nested subroutine calls */
#define MAXPARAM 40 /* maximum number of subroutine parameters */
#define DUMPSIZE 256 /* size of stack dump in longwords */
#define NSIGNAL 31 /* #signals to describe in text array */
#define STREQ(a,b) (strcmp((a),(b))==0)
#define STRNEQ(a,b) (strcmp((a),(b))!=0)
#define CNULL '\0'
#ifdef PROTOTYPES
# define P_(s) s
#else
# define P_(s) ()
#endif
#ifdef DEBUGPRINT
# define DBPRINT(s) printf s
#else
# define DBPRINT(s)
#endif
/* defines for data dictionary: basic types */
#define D_INT 1
#define D_CHAR 2
#define D_LONG 3
#define D_UINT 4
#define D_ULONG 5
#define D_SHORT 6
#define D_LONGLONG 7
#define D_USHORT 8
#define D_ULONGLONG 9
#define D_SIGNEDCHAR 10
#define D_UCHAR 11
#define D_FLOAT 12
#define D_DOUBLE 13
#define D_LONGDOUBLE 14
#define D_VOID 15
/*----------------- external functions --------------------*/
char *malloc();
char *getenv();
/*----------------- internal functions --------------------*/
static void trb_exefind P_((int argc, char *argv));
static void trb_exeinfo();
static void trb_dictionary P_((int ilevel, FILE fp, FILE fp2));
static void trb_symboldump();
static void trb_stackdump P_((unsigned long start, int nn, FILE **fp));
static void trb_framedump P_((unsigned long sp, unsigned long pc,
unsigned long fremeend, FILE **fp));
static void trb_getline P_((int nlevel));
static void trb_params P_((int ilevel, FILE fp, FILE fp2));
static void trb_symbols P_((int ilevel, FILE fp, FILE fp2));
static void trb_traceback P_((int nlevel));
void trb_userinfo P_((FILE fp));
void trb_handle P_((int sig,int code,struct sigcontext *scp));
static void trb_sigtextinit();
static char *trb_codetext P_((int sig, int code));
static void trb_signal();
void trb_signalinit P_((int argc, char *argv[]));
static void str_getdelimited P_((char *inttext, char *bounds,
char *outtext));
static void str_whiteout P_((char *string, char *chars));
/*----------------- structure definitions -----------------*/
struct levelstr /* info for each function in traceback */
{unsigned long stackpointer; /* start of stack frame */
unsigned long programcounter; /* return address */
unsigned long frameend; /* end of stack frame (+4) */
long fileaddr,funcaddr; /* addresses into string table */
char funcname[256]; /* name of function */
char filename[256]; /* name of source file */
int found; /* 0 if function not found */
int filesymbol; /* symbol # for start of source file */
int funcsymbol; /* symbol # for start of function */
int line; /* line number in source file */
};
struct exestr /* information about the executable file */
{int nsym; /* number of symbols in symbol table */
unsigned long magic; /* the magic number of the file */
long stroffset; /* offset to the string table */
long symoffset; /* offset to the symbol table */
char name[256]; /* path to the file */
};
struct dictstr /* a dictionary of defined variable types */
{char match[8]; /* the defined type */
char basetype[8]; /* what it is defined from */
int code; /* our base identifier ie D_INT */
char fullstring[80]; /* as it was read from COFF */
int ptr; /* 1 if it is a pointer */
int lower,upper; /* array bounds */
};
/*----------------- global variables ----------------------*/
char sigtext[NSIGNAL+1][64]; /* describe signal values */
struct levelstr level[MAXLEVEL]; /* one per stack frame */
struct exestr exe;
struct dictstr dictionary[200]; /* allow 200 per source file */
int ndict; /* number of types per source file */
FILE *fpcrash,*fpstackdump,*fpframedump;
/* pointers to files CRASH, STACKDUMP, FRAMEDUMP */
char description[17][20] = {"???","int","char","long","unsigned int",
"unsigned long","short","longlong","unsigned short",
"unsigned longlong","signed char","unsigned char",
"float","double","longdouble","void","???" };
/****************************************************************/
/* trb_exefind */
/* find the path of the file we are executing */
/****************************************************************/
static void trb_exefind(argc,argv)
int argc;
char *argv[];
{
FILE *fp;
int ll;
char name[256],*path;
char *ptr,trial[256];
/*---------------------------------*/
/* get name of program */
strcpy(name,argv[0]);
/* 1: if name contains a slash, assume it is the direct path */
ptr= strchr(name,'/');
if(ptr!=NULL)
{strcpy(trial,name);
fp= fopen(trial,"r");
if(fp!=NULL)
{fclose(fp);strcpy(exe.name,trial);return;}
}
/* 2: look in the user's path */
ptr= getenv("PATH");
ll= strlen(ptr);
path= malloc(ll+1);
strcpy(path,ptr);
/* separate path string into its components */
ptr= strtok(path,":");
while(ptr!=NULL)
{strcpy(trial,ptr);
strcat(trial,"/");
strcat(trial,name);
DBPRINT(("trial exe is %s \n",trial));
fp= fopen(trial,"r");
if(fp!=NULL) {fclose(fp);strcpy(exe.name,trial);free(path);return;}
ptr= strtok(NULL,":");
}
/* 3: try the local directory in case it is not in the path */
strcpy(trial,"./");
strcat(trial,name);
DBPRINT(("trial exe is %s \n",trial));
fp= fopen(trial,"r");
if(fp!=NULL){fclose(fp);strcpy(exe.name,trial);return;}
} /* end of trb_exefind */
/****************************************************************/
/* trb_exeinfo */
/* get needed info from executable file header */
/****************************************************************/
static void trb_exeinfo()
{
int status;
unsigned long magic;
FILE *fp;
struct exec header; /* exe file header (from a.out.h) */
struct nlist symbol; /* symbol table entry */
/*--------------------*/
/* open exe file */
fp= fopen(exe.name,"r");
if(fp==NULL)
{printf("can't open %s\n",exe.name);
exit(1);}
/* read the file header */
status= fread(&header,sizeof(header),1,fp);
if(status==0) {printf("could not read header\n"); exit(2);}
/* is the magic number okay ? */
magic= header.a_magic;
status= N_BADMAG(header);
if(status!=0)
{printf("bad magic number = %ld 0x%lx 0%lo \n",magic,magic,magic);
exit(3);
}
exe.magic= magic;
/* how big is the symbol table */
exe.nsym= header.a_syms/sizeof(symbol);
if(exe.nsym==0) exit(4);
/* get file offsets for symbol table & string table */
exe.symoffset= N_SYMOFF(header);
exe.stroffset= N_STROFF(header);
fclose(fp);
} /* end of trb_exeinfo */
/****************************************************************/
/* trb_dictionary */
/* make a "data dictionary" for a source file */
/****************************************************************/
static void trb_dictionary(ilevel,fp,fp2)
int ilevel;
FILE *fp, *fp2;
{
int i,j,status,type,off;
int low,high,code,pointer;
int isym;
struct nlist symbol; /* symbol table entry */
long nseek;
char *ptr, *ptr2;
char ttext[1024],tempstring[64];
char symbolname[32],junk1[8],junk2[8],match[8];
/*--------------------*/
dictionary[0].code=D_INT;
dictionary[1].code=D_CHAR;
dictionary[2].code=D_LONG;
dictionary[3].code=D_UINT;
dictionary[4].code=D_ULONG;
dictionary[5].code=D_SHORT;
dictionary[6].code=D_LONGLONG;
dictionary[7].code=D_USHORT;
dictionary[8].code=D_ULONGLONG;
dictionary[9].code=D_SIGNEDCHAR;
dictionary[10].code=D_UCHAR;
dictionary[11].code=D_FLOAT;
dictionary[12].code=D_DOUBLE;
dictionary[13].code=D_LONGDOUBLE;
dictionary[14].code=D_VOID;
strcpy(dictionary[0].match,"1");
strcpy(dictionary[1].match,"2");
strcpy(dictionary[2].match,"3");
strcpy(dictionary[3].match,"4");
strcpy(dictionary[4].match,"5");
strcpy(dictionary[5].match,"6");
strcpy(dictionary[6].match,"7");
strcpy(dictionary[7].match,"8");
strcpy(dictionary[8].match,"9");
strcpy(dictionary[9].match,"10");
strcpy(dictionary[10].match,"11");
strcpy(dictionary[11].match,"12");
strcpy(dictionary[12].match,"13");
strcpy(dictionary[13].match,"14");
strcpy(dictionary[14].match,"15");
for(i=0;i<15;i++)
{dictionary[i].ptr=0;
dictionary[i].lower=0;
dictionary[i].upper=0;
dictionary[i].basetype[0]=CNULL;
}
/* open exe file */
fp= fopen(exe.name,"r");
fp2= fopen(exe.name,"r");
if(fp==NULL)
{printf("can't open %s\n",exe.name);
exit(1);}
ndict=15;
isym= level[ilevel].filesymbol+1; /* seek to source files' symbols */
nseek= exe.symoffset + isym*sizeof(symbol);
fseek(fp,nseek,0);
for(i=isym;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
if(type==N_SO) return; /* we are at the next source file */
if(type!=N_LSYM && type!=N_PSYM) continue; /* local syms & params */
nseek= exe.stroffset+symbol.n_un.n_strx;
fseek(fp2,nseek,0);
ptr= fgets(ttext,sizeof(ttext),fp2); /* text describing symbol */
/* ignore structures for now */
str_getdelimited(ttext,":=",match);
if(match[0]=='\0') continue; /* new defines are surrounded by := */
if(match[0]=='t') continue; /* ignore basic types */
if(match[0]=='p') /* remove the p if it is a parameter */
{strcpy(tempstring,match); strcpy(match,&tempstring[1]);}
/* extract the symbol name */
strcpy(tempstring,ttext);
str_whiteout(tempstring,":=;");
sscanf(tempstring,"%s",symbolname);
/* it is a new type, clear some flags */
dictionary[ndict].ptr= 0;
dictionary[ndict].code= 0;
dictionary[ndict].lower= 0;
dictionary[ndict].upper= 0;
strcpy(dictionary[ndict].match,match);
/* is this new type a pointer */
ptr2=strstr(ptr,"=*");
if(ptr2!=NULL)
{str_getdelimited(ptr2,"*\0",match);
strcpy(dictionary[ndict].basetype,match);
dictionary[ndict].ptr= 1;
for(j=0;j<ndict;j++)
{if(STREQ(match,dictionary[j].match))
{code= dictionary[j].code;
pointer= dictionary[j].ptr+1;
dictionary[ndict].code= code;
dictionary[ndict].ptr= pointer;
break;
}
}
ndict++;
continue;
}
/* is this new type an array */
ptr2=strstr(ptr,"=ar");
if(ptr2!=NULL)
{strcpy(tempstring,ptr);
str_whiteout(tempstring,":;()");
sscanf(tempstring,"%s %s %d %d %s",junk1,junk2,&low,&high,match);
strcpy(dictionary[ndict].basetype,match);
dictionary[ndict].lower= low;
dictionary[ndict].upper= high;
code=0;
for(j=0;j<ndict;j++)
{if(STREQ(match,dictionary[j].match))
{code=dictionary[j].code;
dictionary[ndict].code=code;
break;
}
}
ndict++;
continue;
}
} /* end of loop over all symbols */
printf("ndict extended to %d \n",ndict);
} /* end of trb_dictionary */
/****************************************************************/
/* trb_translate */
/* what kind of variable is a symbol */
/****************************************************************/
static void trb_translate(ttext,code,pointer,array)
char *ttext;
int *code, *pointer, *array;
{
int i,j,status,type,off;
int low,high,size;
int isym;
struct nlist symbol; /* symbol table entry */
long nseek;
char *ptr, *ptr2;
char tempstring[64];
char symbolname[32],junk1[8],junk2[8],match[8];
/*--------------------*/
/* zero the output flags */
*code= 0;
*pointer= 0;
*array= 0;
/* ignore structures for now */
str_getdelimited(ttext,":=",match);
if(match[0]=='\0') str_getdelimited(ttext,":\0",match); /* case of var:17 */
if(match[0]=='p') /* remove the p if it is a parameter */
{strcpy(tempstring,match); strcpy(match,&tempstring[1]);}
/* look in the data dictionary */
{for(j=0;j<ndict;j++)
{if(STREQ(match,dictionary[j].match))
{*code= dictionary[j].code;
*pointer= dictionary[j].ptr;
size= dictionary[j].upper-dictionary[j].lower+1;
if(size>1) *array=size;
return;
}
}
return;
}
} /* end of trb_translate */
/****************************************************************/
/* trb_verbalize */
/* print what kind of variable a symbol is */
/****************************************************************/
static void trb_verbalize(name,code,pointer,array)
char *name;
int code,pointer,array;
{
char ttext[80],size[16];
/*------------------------------------------------------*/
strcpy(ttext,name);
if(pointer>0)
strcat(ttext," is a pointer to type ");
else if(array>1)
strcat(ttext," is an array of type ");
else
strcat(ttext," is a variable of type ");
if(pointer==2) strcat(ttext,"*");
if(pointer==3) strcat(ttext,"*");
strcat(ttext,description[code]);
if(array>1) {sprintf(size," [%d] ",array); strcat(ttext,size); }
printf("%s\n",ttext);
} /* end of trb_verbalize */
/****************************************************************/
/* trb_symboldump */
/* dump text of local symbols */
/****************************************************************/
static void trb_symboldump()
{
int i,j,ll,status,type,off,line;
FILE *fp, *fp2, *fpout;
struct nlist symbol; /* symbol table entry */
long nseek;
char *ptr, *ptr2;
char ttext[1024];
long fileaddr,funcaddr;
unsigned long address;
char filename[256],funcname[256];
/*--------------------*/
/* open exe file */
fp= fopen(exe.name,"r");
fp2= fopen(exe.name,"r");
if(fp==NULL)
{printf("can't open %s\n",exe.name);
exit(1);}
/* open file SYMBOLDUMP */
fpout= fopen("SYMBOLDUMP","w");
if(fpout==NULL)
{printf("can't open file SYMBOLDUMP for output\n");
exit(1);}
trb_userinfo(fpout);
fseek(fp,exe.symoffset,0);
for(i=0;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
if(type==N_SO) /* source file name: name,,0,0,address */
{fileaddr= symbol.n_un.n_strx;
fseek(fp2,exe.stroffset,0);
fseek(fp2,fileaddr,1);
ptr= fgets(filename,sizeof(filename),fp2);
fprintf(fpout,"filename %s \n",filename);
}
else if(type==N_FUN) /* procedure: name,,0,linenumber,address */
{funcaddr= symbol.n_un.n_strx;
fseek(fp2,exe.stroffset,0);
fseek(fp2,funcaddr,1);
ptr= fgets(ttext,sizeof(ttext),fp2);
ptr= strtok(ttext,":");
ll= strlen(ptr);
if(ll>250){strncpy(funcname,ptr,250); funcname[250]= CNULL;}
else strcpy(funcname,ptr);
fprintf(fpout,"procedure %s \n",funcname);
}
else if(type==N_SLINE) /* src line: 0,,0,linenumber,address */
{line= symbol.n_desc;
address= symbol.n_value;
fprintf(fpout,"line=%d address=%x\n",line,address);
}
else if(type==N_LSYM)
{off= symbol.n_value;
nseek= exe.stroffset+symbol.n_un.n_strx;
fseek(fp2,nseek,0);
ptr= fgets(ttext,sizeof(ttext),fp2);
fprintf(fpout,"frame offset=%d symbol text: >%s< \n",off,ttext);
}
else if(type==N_PSYM) /* parameter: name,,0,type,offset */
{off= symbol.n_value;
nseek=exe.stroffset+symbol.n_un.n_strx;
fseek(fp2,nseek,0);
ptr= fgets(ttext,sizeof(ttext),fp2);
fprintf(fpout,"frame offset=%d param text: >%s< \n",off,ttext);
}
} /* end of loop over all symbols */
fclose(fp);
fclose(fp2);
fclose(fpout);
} /* end of trb_symboldump */
/****************************************************************/
/* trb_stackdump */
/* dump the stack */
/****************************************************************/
static void trb_stackdump(start,nn,fp0)
unsigned long start;
int nn;
FILE **fp0;
{
int i,j;
FILE *fp;
/*------------------------------------------------------*/
fp= *fp0;
if(fp==0)
{fp= fopen("STACKDUMP","a"); /* open for append */
if(fp==NULL) fp= stdout; /* if failure, use standard out */
*fp0= fp; /* save it in case we have two crashes */
}
trb_userinfo(fp);
for (i=0; i<nn;i++)
{fprintf(fp,"%08x ", (long)start);
fprintf(fp,"%08x ", *(unsigned long *)(start));
for(j=0;j<4;j++,start++)
fprintf(fp,"%c", isprint(*(unsigned char *)(start))
? *(unsigned char *)(start) : ' ');
fprintf(fp,"\n");
}
fclose(fp);
} /* end of trb_stackdump */
/****************************************************************/
/* trb_framedump */
/* dump a stack frame */
/****************************************************************/
static void trb_framedump(stackpointer,programcounter,frameend,fp0)
unsigned long stackpointer,programcounter,frameend;
FILE **fp0;
{
int j;
unsigned long stackaddress,stackvalue;
FILE *fp;
/*------------------------------------------------------*/
fp= *fp0;
if(fp==0)
{fp= fopen("FRAMEDUMP","a");
if(fp==NULL) fp= stdout;
trb_userinfo(fp);
*fp0= fp;
}
fprintf(fp,"-----------------------------------\n");
fprintf(fp,"sp=%08x pc=%08x\n",stackpointer,programcounter);
j= 0;
stackaddress= stackpointer;
while(stackaddress<frameend)
{stackvalue= *( (long *)stackaddress);
fprintf(fp," %8x",stackvalue);
j++;
if(j==8) {fprintf(fp,"\n");j= 0;}
stackaddress= stackaddress+4;
}
if(j!=0)fprintf(fp,"\n");
fprintf(fp,"-----------------------------------\n");
} /* end of trb_framedump */
/****************************************************************/
/* trb_getline */
/* find file lines matching addresses */
/****************************************************************/
static void trb_getline(nlevel)
int nlevel;
{
FILE *fp,*fp2;
struct nlist symbol; /* symbol table entry */
unsigned long address,match,lastaddress;
int type,line,funcsymbol,filesymbol;
int i,j,ll,status;
long fileaddr,funcaddr,magic;
int iff;
char *ptr,ttext[256];
char funcname[256],filename[256];
/*----------------------*/
/* initialize */
address= 0; funcsymbol= 0; filesymbol=0;
lastaddress= 0xFFFF;
for(i=0;i<MAXLEVEL;i++)level[i].found= 0;
DBPRINT(("trb_getline: nlevel=%d pc[0]=%x\n",nlevel,level[0].programcounter));
/* use first file pointer to read symbol table */
fp= fopen(exe.name,"r");
if(fp==NULL) {printf("can't open %s\n",exe.name);exit(1);}
/* use second file pointer to read the string table */
fp2= fopen(exe.name,"r");
/* read all symbols, look at source lines, file & function names */
fseek(fp,exe.symoffset,0);
for(i=0;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
/* what type of symbol is it */
if(type==N_SLINE) /* src line: 0,,0,linenumber,address */
{line= symbol.n_desc;
address= symbol.n_value;
DBPRINT(("line=%d address=%x\n",line,address));
}
else if(type==N_FUN) /* procedure: name,,0,linenumber,address */
{funcaddr= symbol.n_un.n_strx;
address= symbol.n_value;
funcsymbol= i;
fseek(fp2,exe.stroffset,0);
fseek(fp2,funcaddr,1);
ptr= fgets(ttext,sizeof(ttext),fp2);
ptr= strtok(ttext,":");
ll= strlen(ptr);
if(ll>250){strncpy(funcname,ptr,250); funcname[250]= CNULL;}
else strcpy(funcname,ptr);
DBPRINT(("procedure %s address=%x\n",funcname,address));
for(iff=0;iff<nlevel;iff++) /* we matched address, now fill funcname */
if(strcmp(level[iff].funcname,"nextf")==0)
{strcpy(level[iff].funcname,funcname);
level[iff].funcsymbol= funcsymbol; /* symbol# of function name */
}
}
else if(type==N_SO) /* source file name: name,,0,0,address */
{fileaddr= symbol.n_un.n_strx;
address= symbol.n_value;
filesymbol= i;
fseek(fp2,exe.stroffset,0);
fseek(fp2,fileaddr,1);
ptr= fgets(filename,sizeof(filename),fp2);
DBPRINT(("filename %s address=%x\n",filename,address));
}
/* does this address match one of ours? */
for(iff=0;iff<nlevel;iff++)
{if(level[iff].found==0)
{match= level[iff].programcounter;
if(address==match)
{DBPRINT(("exact match of %x found at line %d\n",match,line));
level[iff].found= 1;
level[iff].filesymbol= filesymbol; /* store symbol# of the file */
strcpy(level[iff].funcname,"nextf");
strcpy(level[iff].filename,filename);
level[iff].line= line;
}
else if(address>match && lastaddress<match && lastaddress>(match-64))
{
DBPRINT(("match of %x before line %d, lastaddress=%x address=%x\n",
match,line,lastaddress,address));
level[iff].found= 1;
level[iff].filesymbol= filesymbol; /* store symbol# of the file */
strcpy(level[iff].funcname,"nextf");
strcpy(level[iff].filename,filename);
level[iff].line= line-1;
}
}
}
lastaddress= address;
} /* end of loop over all nsym */
fclose(fp2);
fclose(fp);
} /* end of trb_getline */
/****************************************************************/
/* trb_params */
/* print one level of parameters */
/****************************************************************/
static void trb_params(ilevel,fp,fp2)
int ilevel;
FILE *fp, *fp2;
{
int i,status,type;
int isym,code,pointer,array;
int size,middle,sum;
long addr,off,address,newaddress,stackbase,nseek,contents;
struct nlist symbol; /* symbol table entry */
char *ptr,ttext[1024],symbolname[80],symboltype[80];
char params[1024],tempstring[1024],outtext[80];
int ii;
char cc;
short ss;
long ll,l2;
unsigned char uc;
unsigned short us;
unsigned long ul;
unsigned int ui;
float ff;
double dd;
long vv;
/*------------------------------------*/
strcpy(params,level[ilevel].funcname);
strcat(params,"(");
isym= level[ilevel].funcsymbol+1;
nseek= exe.symoffset + isym*sizeof(symbol);
/* do a quick loop to get parameter names */
fseek(fp,nseek,0);
for(i=isym;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
if(type==N_FUN) break; /* that is all for this function */
else if(type==N_SO) break; /* that is all for this function */
else if(type==N_PSYM) /* parameter: name,,0,type,offset */
{addr= symbol.n_un.n_strx; /* symbol name in string table */
fseek(fp2,exe.stroffset,0);
fseek(fp2,addr,1);
ptr= fgets(ttext,sizeof(ttext),fp2);
/* extract the symbol's name */
strcpy(tempstring,ttext);
str_whiteout(tempstring,":=;");
sscanf(tempstring,"%s",symbolname);
strcat(params,symbolname); strcat(params,",");
}
}
/* change the last comma to an ) and print the parameters */
ll= strlen(params);
if(params[ll-1]==',') params[ll-1]= ')'; else strcat(params,")");
fprintf(fpcrash,"%s\n",params);
/* do a second loop to get values */
fseek(fp,nseek,0);
for(i=isym;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
if(type==N_FUN) break; /* that is all for this function */
else if(type==N_SO) break; /* that is all for this function */
else if(type!=N_PSYM)continue;
addr= symbol.n_un.n_strx;
off= symbol.n_value; /* offset from stack frame end */
fseek(fp2,exe.stroffset,0);
fseek(fp2,addr,1);
ptr= fgets(ttext,sizeof(ttext),fp2);
/* extract the symbol's name */
strcpy(tempstring,ttext);
str_whiteout(tempstring,":=;");
sscanf(tempstring,"%s",symbolname);
/* extract text we use to get the symbol's type */
ptr= strchr(ttext,':');
strcpy(symboltype,ptr);
stackbase= level[ilevel].frameend;
stackbase= level[ilevel].stackpointer;
address= stackbase+off; /* where the variable's bytes are */
/* find out what kind of symbol it is */
trb_translate(ttext,&code,&pointer,&array);
#if PARAMDUMP
printf("param: >%s< off=%d\n",ttext,off);
trb_verbalize(symbolname,code,pointer,array);
#endif
/* if it is a pointer, print the address & dereference it */
if(pointer==1)
{newaddress= *(unsigned long *) address;
fprintf(fpcrash," %s = 0x%x (pointer to %s) \n",
symbolname, newaddress, description[code]);
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
}
else if(pointer==2) /* it could be a pointer to a pointer */
{newaddress= *(unsigned long *) address;
fprintf(fpcrash," %s = 0x%x (pointer to *%s) \n",
symbolname, newaddress, description[code]);
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
newaddress= *(unsigned long *) address;
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
}
/* treat a ptr to char as an array */
if(pointer>0 && code==D_CHAR) goto arrays; /* written by an ex- */
/* fortran programmer */
/* an array of any type */
if(array>1) goto arrays;
/* int */
else if(code==D_INT)
{ii= *(int *)address;
sprintf(outtext,"%d 0x%x (long)",ii,ii);}
/* char */
else if(code==D_CHAR)
{cc= *(char *)address;
sprintf(outtext,"\'%c\' 0x%x (char)",cc,cc);}
/* long */
else if(code==D_LONG)
{ll= *(long *)address;
sprintf(outtext,"%d 0x%x (long)",ll,ll);}
/* short */
else if(code==D_SHORT)
{ss= *(short *)address;
sprintf(outtext,"%hd 0x%hx (short)",ss,ss);}
/* unsigned char */
else if(code==D_UCHAR)
{uc= *(unsigned char *)address;
sprintf(outtext,"\'%c\' 0x%x (u char)",uc,uc);}
/* unsigned short */
else if(code==D_USHORT)
{us= *(unsigned short *)address;
sprintf(outtext,"%hu 0x%hx (u short)",us,us);}
/* unsigned long */
else if(code==D_ULONG)
{ul= *(unsigned long *)address;
sprintf(outtext,"%u 0x%x (u long)",ul,ul);}
/* unsigned int */
else if(code==D_UINT)
{ui= *(unsigned int *)address;
sprintf(outtext,"%u 0x%x (u int)",ui,ui);}
/* float */
else if(code==D_FLOAT)
{ff= *(float *)address;
ll= *(long *)address;
sprintf(outtext,"%f 0x%08x (float)",ff,ll);}
/* double */
else if(code==D_DOUBLE)
{dd= *(double *)address;
ll= *(long *)address;
l2= *(long *)(address+sizeof(long));
sprintf(outtext,"%f 0x%08x%08x (double)",dd,ll,l2);}
/* void */
else if(code==D_VOID)
{vv= *(long *)address;
sprintf(outtext,"%d 0x%x (void)",vv,vv);}
/* ??? */
else
sprintf(outtext," unknown type ");
if(pointer==0)fprintf(fpcrash," %s = %s \n",symbolname,outtext);
else if(pointer==1)fprintf(fpcrash," *%s = %s \n",symbolname,outtext);
else if(pointer==2)fprintf(fpcrash," **%s = %s \n",symbolname,outtext);
continue;
/*---------*/
arrays:
/*---------*/
size= array-1;
middle= array/2;
/* int or long array */
if(code==D_INT || code==D_LONG)
{fprintf(fpcrash," %s = an array of type %s \n",
symbolname,description[code]);
ii= *(int *)address;
fprintf(fpcrash," %s[0] = %d 0x%x \n", symbolname,ii,ii);
ii= *(int *) (address+middle*sizeof(int));
fprintf(fpcrash," %s[%d] = %d 0x%x \n", symbolname,middle,ii,ii);
ii= *(int *) (address+size*sizeof(int));
fprintf(fpcrash," %s[%d] = %d 0x%x \n", symbolname,size,ii,ii);
}
/* char array */
else if(code==D_CHAR)
{sum=pointer;
if(array>1)sum++;
else if(sum==1)
fprintf(fpcrash," *%s = \"%s\"\n",symbolname,address);
else if(sum==2)
fprintf(fpcrash," *%s = \"%s\"\n",symbolname,address);
}
/* float array */
else if(code==D_FLOAT)
{fprintf(fpcrash," %s = an array of type %s \n",
symbolname,description[code]);
ff= *(float *)address;
fprintf(fpcrash," %s[0] = %f 0x%x \n", symbolname,ff,ff);
ff= *(float *) (address+middle*sizeof(float));
fprintf(fpcrash," %s[%d] = %f 0x%x \n", symbolname,middle,ff,ff);
ff= *(float *) (address+size*sizeof(float));
fprintf(fpcrash," %s[%d] = %f 0x%x \n", symbolname,size,ff,ff);
}
/* need to put in other types of arrays */
} /* end of loop over all nsym */
} /* end of trb_params */
/****************************************************************/
/* trb_symbols */
/* print local symbols in procedure of interest */
/****************************************************************/
static void trb_symbols(ilevel,fp,fp2)
int ilevel;
FILE *fp, *fp2;
{
int i,type,status,isym;
int code,pointer,array,middle,size;
long addr,off,address,newaddress,stackbase;
unsigned long value;
long nseek;
struct nlist symbol; /* symbol table entry */
char *ptr,ttext[1024],tempstring[1024];
char symbolname[80],symboltype[80];
short int jtemp; unsigned short jtemp2;
char outtext[80];
int ii;
char cc;
short ss;
long ll,l2;
unsigned char uc;
unsigned short us;
unsigned long ul;
unsigned int ui;
float ff;
double dd;
long vv;
/*-----------------------------------*/
isym= level[ilevel].funcsymbol+1;
nseek= exe.symoffset + isym*sizeof(symbol);
fseek(fp,nseek,0);
stackbase= level[ilevel].stackpointer;
for(i=isym;i<exe.nsym;i++)
{status= fread(&symbol,sizeof(symbol),1,fp);
if(status==0) printf("could not read symbol\n");
type= symbol.n_type;
if(type==N_FUN) return; /* new function */
else if(type==N_SO) return; /* new source file */
else if(type!=N_LSYM) continue; /* local sym: name,,0,type,offset */
addr= symbol.n_un.n_strx; /* pointer to string table */
off= symbol.n_value; /* offset from stack frame end */
fseek(fp2,exe.stroffset,0);
fseek(fp2,addr,1);
ptr= fgets(ttext,sizeof(ttext),fp2);
/* get the symbol's name */
strcpy(tempstring,ttext);
str_whiteout(tempstring,":=;");
sscanf(tempstring,"%s",symbolname);
/* get text used to find type of symbol */
ptr= strchr(ttext,':');
strcpy(symboltype,ptr);
address= stackbase+off;
/* find out what kind of symbol it is */
trb_translate(ttext,&code,&pointer,&array);
#if SYMBOLDUMP
printf("symbol: >%s< off=%d\n",ttext,off);
trb_verbalize(symbolname,code,pointer,array);
#endif
/* if it is a pointer, print the address & dereference it */
if(pointer==1)
{newaddress= *(unsigned long *) address;
fprintf(fpcrash," %s = 0x%x (pointer to %s) \n",
symbolname, newaddress, description[code]);
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
}
else if(pointer==2) /* could have pointer to pointer */
{newaddress= *(unsigned long *) address;
fprintf(fpcrash," %s = 0x%x (pointer to *%s) \n",
symbolname, newaddress, description[code]);
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
newaddress= *(unsigned long *) address;
if(newaddress>=0 && newaddress<0x1000) continue;
else address= newaddress;
}
/* treat a ptr to char as an array */
if(pointer>0 && code==D_CHAR) goto arrays;
/* an array of any type */
if(array>1) goto arrays;
/* int */
else if(code==D_INT)
{ii= *(int *)address;
sprintf(outtext,"%d 0x%x (long)",ii,ii);}
/* char */
else if(code==D_CHAR)
{cc= *(char *)address;
sprintf(outtext,"\'%c\' 0x%x (char)",cc,cc);}
/* long */
else if(code==D_LONG)
{ll= *(long *)address;
sprintf(outtext,"%ld 0x%x (long)",ll,ll);}
/* short */
else if(code==D_SHORT)
{ss= *(short *)address;
sprintf(outtext,"%hd 0x%hx (short)",ss,ss);}
/* unsigned char */
else if(code==D_UCHAR)
{uc= *(unsigned char *)address;
sprintf(outtext,"\'%c\' 0x%x (u char)",uc,uc);}
/* unsigned short */
else if(code==D_USHORT)
{us= *(unsigned short *)address;
sprintf(outtext,"%hu 0x%hx (u short)",us,us);}
/* unsigned long */
else if(code==D_ULONG)
{ul= *(unsigned long *)address;
sprintf(outtext,"%u 0x%x (u long)",ul,ul);}
/* unsigned int */
else if(code==D_UINT)
{ui= *(unsigned int *)address;
sprintf(outtext,"%u 0x%x (u int)",ui,ui);}
/* float */
else if(code==D_FLOAT)
{ff= *(float *)address;
ll= *(long *)address;
sprintf(outtext,"%f 0x%08x (float)",ff,ll);}
/* double */
else if(code==D_DOUBLE)
{dd= *(double *)address;
ll= *(long *)address;
l2= *(long *)(address+sizeof(long));
sprintf(outtext,"%f 0x%08x%08x (double)",dd,ll,l2);}
/* void */
else if(code==D_VOID)
{vv= *(long *)address;
sprintf(outtext,"%d 0x%x (void)",vv,vv);}
/* ??? */
else
sprintf(outtext," unknown type ");
if(pointer==0)fprintf(fpcrash," %s = %s \n",symbolname,outtext);
else if(pointer==1)fprintf(fpcrash," *%s = %s \n",symbolname,outtext);
continue;
/*---------*/
arrays:
/*---------*/
size= array-1;
middle= array/2;
/* int or long array */
if(code==D_INT || code==D_LONG)
{fprintf(fpcrash," %s = an array of type %s \n",
symbolname,description[code]);
ii= *(int *)address;
fprintf(fpcrash," %s[0] = %d 0x%x \n", symbolname,ii,ii);
ii= *(int *) (address+middle*sizeof(int));
fprintf(fpcrash," %s[%d] = %d 0x%x \n", symbolname,middle,ii,ii);
ii= *(int *) (address+size*sizeof(int));
fprintf(fpcrash," %s[%d] = %d 0x%x \n", symbolname,size,ii,ii);
}
/* char array */
else if(code==D_CHAR)
fprintf(fpcrash," %s = \"%s\" \n",symbolname,address);
/* float array */
else if(code==D_FLOAT)
{fprintf(fpcrash," %s = an array of type %s \n",
symbolname,description[code]);
ff= *(float *)address;
ll= *(long *)address;
fprintf(fpcrash," %s[0] = %f 0x%x \n", symbolname,ff,ll);
ff= *(float *) (address+middle*sizeof(float));
ll= *(long *) (address+middle*sizeof(float));
fprintf(fpcrash," %s[%d] = %f 0x%x \n", symbolname,middle,ff,ll);
ff= *(float *) (address+size*sizeof(float));
ll= *(long *) (address+size*sizeof(float));
fprintf(fpcrash," %s[%d] = %f 0x%x \n", symbolname,size,ff,ll);
}
/* dump other kinds of arrays */
} /* end of loop over all nsym */
} /* end of trb_symbols */
/****************************************************************/
/* trb_traceback */
/* print a traceback */
/****************************************************************/
static void trb_traceback(nlevel)
int nlevel;
{
int i;
FILE *fp,*fp2;
/*---------------------------*/
if(nlevel<1)return;
/* use first file pointer to read the symbol table */
fp= fopen(exe.name,"r");
if(fp==NULL) {printf("can't open %s\n",exe.name);exit(1);}
/* use second file pointer to read the string table */
fp2= fopen(exe.name,"r");
/* print a traceback to the screen */
fprintf(fpcrash,"---------- traceback ----------\n");
for(i=0;i<nlevel;i++)
if(level[i].found!=0)fprintf(fpcrash,"file %s line %d function %s() \n",
level[i].filename, level[i].line, level[i].funcname);
else
fprintf(fpcrash,"address %x \n", level[i].programcounter);
for(i=0;i<nlevel;i++)
{
fprintf(fpcrash,"------------------------------------\n");
if(level[i].found!=0)
{
trb_dictionary(i,fp,fp2);
trb_params(i,fp,fp2);
fprintf(fpcrash," -- local symbols for %s --\n",level[i].funcname);
trb_symbols(i,fp,fp2);
}
}
fclose(fp2);
fclose(fp);
} /* end of trb_traceback */
/****************************************************************/
/* trb_userinfo */
/* put program name, user, etc into a file */
/****************************************************************/
void trb_userinfo(fp)
FILE *fp;
{
int ll;
char *user,host[64],nouser[8];
time_t timeofday;
char fulltime[26];
/* get the user's name */
user= (char *) getlogin();
if(user==NULL)user= (char *)getpwuid(getuid());
if(user==NULL){strcpy(nouser,"????"); user=nouser; }
/* get the time */
timeofday=time((time_t *)0);
strcpy(fulltime,(char *)ctime(&timeofday));
fulltime[24]=CNULL;
/* get the host */
gethostname(host,64);
/* write to a file */
fprintf(fp,"user=%s host=%s date=%s \n", user,host,fulltime);
fprintf(fp,"program=%s \n", exe.name);
} /* end of trb_userinfo */
/****************************************************************/
/* trb_handle */
/* handle all signals */
/****************************************************************/
void trb_handle(sig,code,scp)
int sig, code;
struct sigcontext *scp;
{
int i,j,exitflag;
int nlevel;
unsigned long programcounter,stackpointer,frameend;
unsigned long instruction;
char *ptr;
char *startdump;
/*--------------------*/
/* write to a file called CRASH */
if(fpcrash==0) fpcrash= fopen("CRASH","a"); /* open for append */
if(fpcrash==NULL) fpcrash= stdout; /* if failure, use standard output */
fprintf(fpcrash,"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n");
trb_userinfo(fpcrash);
/* print meaningful message for signal */
fprintf(fpcrash,"%s signal=%d(%d) \n",sigtext[sig],sig,code);
ptr= trb_codetext(sig,code);
if(ptr!=NULL) fprintf(fpcrash,"%s\n",ptr);
/* get stack pointer & program counter */
programcounter= scp->sc_pc;
stackpointer= scp->sc_fp;
frameend= *( (long *)stackpointer +JUMPSP);
DBPRINT((" pc=0x%x sp=0x%x \n", programcounter,stackpointer));
#if STACKDUMP
startdump= (char *)scp->sc_sp;
startdump= startdump-128;
trb_stackdump(startdump,DUMPSIZE,&fpstackdump);
#endif
/* walk the stack, storing stack pointers & program counters */
nlevel= 0;
while(stackpointer!=0)
{level[nlevel].programcounter= programcounter;
level[nlevel].frameend= frameend;
level[nlevel].stackpointer= stackpointer;
if(nlevel<MAXLEVEL)nlevel++;
DBPRINT(("sp=%08x pc=%08x\n",stackpointer,programcounter));
#if FRAMEDUMP
trb_framedump(stackpointer,programcounter,frameend,&fpframedump);
#endif
programcounter= *( (long *)stackpointer +JUMPPC);
stackpointer= *( (long *)stackpointer +JUMPSP);
if(stackpointer!=0) frameend= *( (long *)stackpointer +JUMPSP);
if(frameend==0) stackpointer= 0; /* we are at the end */
}
trb_exeinfo(); /* get info from file header */
trb_getline(nlevel); /* convert addresses to line numbers */
trb_traceback(nlevel); /* print a full traceback */
#if SYMBOLDUMP
trb_symboldump();
#endif
exitflag= 0;
switch(sig)
{case SIGTRAP: exitflag= 1; break;
case SIGSEGV: exitflag= 1; break;
case SIGABRT: exitflag= 1; break;
case SIGBUS: exitflag= 1; break;
case SIGILL: exitflag= 1; break;
case SIGFPE: exitflag= 1; break;
default:
printf("signal %d sent to trb_handle \n",sig);
break;
} /* end of switch on sig */
fprintf(fpcrash,"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
#if FRAMEDUMP
fclose(fpframedump);
#endif
if(exitflag)
{if(fpcrash!=stdout) {fclose(fpcrash); system("ls -l CRASH");}
exit(sig);
}
return;
} /* end of trb_handle */
/****************************************************************/
/* trb_sigtextinit */
/* initialize signal text messages */
/****************************************************************/
static void trb_sigtextinit()
{
strcpy(sigtext[1], "SIGHUP: hangup signal received");
strcpy(sigtext[2], "SIGINT: interrupt signal received");
strcpy(sigtext[3], "SIGQUIT: quit signal received");
strcpy(sigtext[4], "SIGILL: illegal instruction (not reset when caught)");
strcpy(sigtext[5], "SIGTRAP: trace trap (not reset when caught)");
strcpy(sigtext[6], "SIGABRT: abort or IOT instruction");
strcpy(sigtext[7], "SIGEMT: EMT instruction");
strcpy(sigtext[8], "SIGFPE: floating point exception");
strcpy(sigtext[9], "SIGKILL: kill signal received");
strcpy(sigtext[10], "SIGBUS: bus error");
strcpy(sigtext[11], "SIGSEGV: segmentation violation");
strcpy(sigtext[12], "SIGSYS: bad argument to system call");
strcpy(sigtext[13], "SIGPIPE: write on a pipe with no one to read it");
strcpy(sigtext[14], "SIGALRM: alarm clock signal received");
strcpy(sigtext[15], "SIGTERM: received software termination signal");
strcpy(sigtext[16], "SIGURG: urgent condition on IO channel");
strcpy(sigtext[17], "SIGSTOP: sendable stop signal not from tty");
strcpy(sigtext[18], "SIGTSTP: received stop signal from tty");
strcpy(sigtext[19], "SIGCONT: continue a stopped process");
strcpy(sigtext[20], "SIGCHLD: child process has stopped or exited");
strcpy(sigtext[21], "SIGTTIN: to readers pgrp upon background tty read");
strcpy(sigtext[22], "SIGTTOU: like TTIN for output if (tp->t_local<OSTOP)");
strcpy(sigtext[23], "SIGIO: input/output possible signal");
strcpy(sigtext[24], "SIGXCPU: exceeded CPU time limit");
strcpy(sigtext[25], "SIGXFSZ: exceeded file size limit");
strcpy(sigtext[26], "SIGVTALRM: received virtual time alarm");
strcpy(sigtext[27], "SIGPROF: received profiling time alarm");
strcpy(sigtext[28], "SIGWINCH: window changed");
strcpy(sigtext[29], "SIGLOST: resource lost (eg, record-lock lost)");
strcpy(sigtext[30], "SIGUSR1: received user defined signal 1");
strcpy(sigtext[31], "SIGUSR2: received user defined signal 2");
} /* end if trb_sigtextinit */
/****************************************************************/
/* trb_codetext */
/* return text explanation of signal */
/****************************************************************/
static char *trb_codetext(sig,code)
int sig,code;
{
if(sig==SIGILL)
return("illegal instruction fault");
else if(sig==SIGFPE)
{if(code==0)return("float divide by zero or overflow");
else if(code==2)return("integer divide by zero");
else return("misc floating point error");
}
else if(sig==SIGBUS)
return("hardware alignment error");
else if(sig==SIGSEGV)
return("no mapping at the fault address");
else
return(NULL);
} /* end of trb_codetext */
/****************************************************************/
/* trb_signal */
/* initiate trapping of all signals */
/****************************************************************/
static void trb_signal()
{
int status;
/*---------------------------------------*/
trb_sigtextinit();
/* trap the important signals */
/* signal(SIGILL,trb_handle);
signal(SIGTRAP,trb_handle); */
signal(SIGFPE,trb_handle); /* floating point errors */
signal(SIGBUS,trb_handle); /* bus errors */
signal(SIGSEGV,trb_handle); /* segmentation faults */
signal(SIGABRT,trb_handle); /* to get integer divide */
/* don't trap the rest */
#if 0
signal(SIGHUP,trb_handle);
signal(SIGINT,trb_handle);
signal(SIGQUIT,trb_handle);
signal(SIGEMT,trb_handle);
signal(SIGKILL,trb_handle);
signal(SIGSYS,trb_handle);
signal(SIGPIPE,trb_handle);
signal(SIGALRM,trb_handle);
signal(SIGTERM,trb_handle);
signal(SIGURG,trb_handle);
signal(SIGSTOP,trb_handle);
signal(SIGTSTP,trb_handle);
signal(SIGCONT,trb_handle);
signal(SIGCHLD,trb_handle);
signal(SIGTTIN,trb_handle);
signal(SIGTTOU,trb_handle);
signal(SIGIO,trb_handle);
signal(SIGXCPU,trb_handle);
signal(SIGXFSZ,trb_handle);
signal(SIGVTALRM,trb_handle);
signal(SIGPROF,trb_handle);
signal(SIGWINCH,trb_handle);
signal(SIGLOST,trb_handle);
signal(SIGUSR1,trb_handle);
signal(SIGUSR2,trb_handle);
#endif
} /* end of trb_signal */
/****************************************************************/
/* trb_signalinit */
/* initiate trapping of all signals */
/****************************************************************/
void trb_signalinit(argc,argv)
int argc;
char *argv[];
{
FILE *fp;
/*---------------------------------------*/
/* find the executable file */
trb_exefind(argc,argv);
/* remove files CRASH, STACKDUMP, & FRAMEDUMP */
unlink("./CRASH");
unlink("./STACKDUMP");
unlink("./FRAMEDUMP");
fpcrash= 0;
fpstackdump= 0;
fpframedump= 0;
/* set up our signal handler */
trb_signal();
} /* end of ita_signalinit */
/**************************************************************/
/* str_getdelimited */
/* returns substring bounded by 2 characters */
/**************************************************************/
static void str_getdelimited(intext,bounds,outtext)
char *intext,*bounds,*outtext;
{
int ll;
char start, end;
char *ptr, *ptr2;
/*------------------------------------------------------*/
outtext[0]=CNULL;
start= bounds[0];
end= bounds[1];
ptr=strchr(intext,start);
if(ptr==NULL)return;
ptr++;
ptr2=strchr(ptr,end);
if(ptr2==NULL)return;
ll=ptr2-ptr;
strncpy(outtext,ptr,ll);
outtext[ll]=CNULL;
}
/********************************************************/
/* str_whiteout */
/* routine to change certain characters to blanks */
/********************************************************/
static void str_whiteout(string,chars)
char *string,*chars;
{
/*... locals */
int i,j,ls,lc;
char cc;
/*-----------------------------*/
ls=strlen(string);
if(ls<1)return;
lc=strlen(chars);
if(lc<1)return;
for(i=0;i<ls;i++)
{cc=string[i];
for(j=0;j<lc;j++)if(cc==chars[j])cc=' ';
string[i]=cc;
}
} /* end of str_whiteout */
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
Alan Dunham | /\ /\ | Calgary ...
adunham@ita.lgc.com | / \ / \ | home of Big Rock beer
(403) 269 4669 | / \/ \ |
Calgary, Alberta | / / \ |