/* * Copyright (C) 1996-1998 Ilya Ryzhenkov (orangy@inetlab.com) * This file maintains SIGSEGV handling */ #include "helpdefs.h" #include "dlm.h" #include "dlmimage.h" #include "dlm_sym.h" #include #include #include #define SIGSEGV_TOLERANCE 64 extern unsigned long __djgpp_selector_limit; #define excp __djgpp_exception_state static unsigned long max,tmp,base,idx,min,i; static TDlm *dlm; /* typedef void (*terminate_handler)(); terminate_handler set_terminate__FPFv_v(terminate_handler); */ //static void (*old_terminate)(); //extern void (*__terminate_func)(); void print_name(unsigned int eip) { char *crop_dlm; printf(" 0x%08x ",eip); _sym_dlmsearch(); while ((dlm=_sym_dlmnext())) { base=(unsigned long)dlm->Base; if (base<=eip && base+dlm->VSize>=eip) break; } if (dlm) { max=0; idx=0xFFFFFFFF; for (i=0; iNumSym; i++) if (!(dlm->Symbols[i].e_flags&(DLMSYM_IMPORT|DLMSYM_COMMON))) { tmp=dlm->Symbols[i].e_value+base; if (tmp<=eip && tmp>max) { max=tmp; idx=i; } } if (idx!=0xFFFFFFFF) { if (dlm->Symbols[idx].e_name!=DLMSYM_NONAME) printf(" SYM: %s",dlm->Symbols[idx].e_name+dlm->Strings); else printf(" SYM: #%ld ",idx); printf("+0x%lx",eip-dlm->Symbols[idx].e_value-base); } crop_dlm=strrchr(dlm->filename,'/'); printf(" DLM: %s [0x%lx]",crop_dlm?crop_dlm+1:dlm->filename,base); } } void show_call_frame(void) { unsigned *vbp, *vbp_new, *tos; unsigned veip; int max=0; tos = (unsigned *)__djgpp_selector_limit; vbp = (unsigned *)__djgpp_exception_state->__ebp; printf("\nDLM call frame traceback :\n"); while (((unsigned)vbp >= __djgpp_exception_state->__esp) && (vbp < tos)) { vbp_new = (unsigned *)*vbp; if (vbp_new == 0) break; veip = *(vbp + 1); print_name(veip); puts(""); vbp = vbp_new; if (++max == 10) break; } } void _dlm_sigsegv(int sig) { unsigned long eip=excp->__eip; /* Where error occured */ void *symaddr; signal(SIGSEGV,SIG_DFL); printf("\nDLM -> Exiting due to signal SIGSEGV at\n"); print_name(eip); if (dlm) { min=eip+SIGSEGV_TOLERANCE; idx=0xFFFFFFFF; for (i=0; iNumRel; i++) { tmp=dlm->Relocs[i].r_vaddr+base; if (tmp>=eip && tmpStrings+dlm->Symbols[dlm->Relocs[idx].r_symndx].e_name,0); if (!symaddr) printf("\n possibly because of undefined reference to symbol '%s'\n", dlm->Strings+dlm->Symbols[dlm->Relocs[idx].r_symndx].e_name); else printf("\n the reason cannot be detected. try compiling without -O switch.\n"); } } show_call_frame(); exit(-1); } void _dlm_sig_invalid_new(unsigned long eip,char *name) { printf("\nExiting due to invalid creation class `%s'\nError was at ",name); print_name(eip); exit(-1); } void _dlm_terminate() { printf("\nExiting due to unexpected excpetion thrown\n"); show_call_frame(); exit(-1); } void _dlm_init_signal_handlers() { signal(SIGSEGV,_dlm_sigsegv); //old_terminate=set_terminate__FPFv_v(_dlm_terminate); //__terminate_func=_dlm_terminate; } void _dlm_reset_signal_handlers() { signal(SIGSEGV,SIG_DFL); //set_terminate__FPFv_v(old_terminate); // __terminate_func=old_terminate; }