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 | / / \ |