void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) { greg_t *pc; greg_t *npc; greg_t *sp; greg_t *fp; #ifdef WAD_LINUX greg_t *esi; greg_t *edi; greg_t *ebx; #endif unsigned long addr; ucontext_t *context; unsigned long p_sp; /* process stack pointer */ unsigned long p_pc; /* Process program counter */ unsigned long p_fp; /* Process frame pointer */ int nlevels = 0; int found = 0; void _returnsignal(); WadFrame *frame, *origframe; char *framedata; char *retname = 0; unsigned long current_brk; /* Reset all of the signals while running WAD */ wad_signal_clear(); wad_nlr_func = 0; context = (ucontext_t *) vcontext; wad_printf("WAD: Collecting debugging information...\n"); /* Read the segments */ if (wad_segment_read() < 0) { wad_printf("WAD: Unable to read segment map\n"); return; } if (wad_debug_mode & DEBUG_SIGNAL) { wad_printf("WAD: siginfo = %x, context = %x\n", si, vcontext); } current_brk = (long) sbrk(0); /* Get some information about the current context */ #ifdef WAD_SOLARIS pc = &((context->uc_mcontext).gregs[REG_PC]); npc = &((context->uc_mcontext).gregs[REG_nPC]); sp = &((context->uc_mcontext).gregs[REG_SP]); #endif #ifdef WAD_LINUX sp = &((context->uc_mcontext).gregs[ESP]); /* Top of stack */ fp = &((context->uc_mcontext).gregs[EBP]); /* Stack base - frame pointer */ pc = &((context->uc_mcontext).gregs[EIP]); /* Current instruction */ esi = &((context->uc_mcontext).gregs[ESI]); edi = &((context->uc_mcontext).gregs[EDI]); ebx = &((context->uc_mcontext).gregs[EBX]); wad_saved_esi = (unsigned long) (*esi); wad_saved_edi = (unsigned long) (*edi); wad_saved_ebx = (unsigned long) (*ebx); /* printf("esi = %x, edi = %x, ebx = %x\n", wad_saved_esi, wad_saved_edi, wad_saved_ebx); */ /* printf("&sp = %x, &pc = %x\n", sp, pc); */ #endif /* Get some information out of the signal handler stack */ addr = (unsigned long) si->si_addr; /* See if this might be a stack overflow */ p_pc = (unsigned long) (*pc); p_sp = (unsigned long) (*sp); #ifdef WAD_LINUX p_fp = (unsigned long) (*fp); #endif #ifdef WAD_SOLARIS p_fp = (unsigned long) *(((long *) p_sp) + 14); #endif if (wad_debug_mode & DEBUG_SIGNAL) { wad_printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp); } frame = wad_stack_trace(p_pc, p_sp, p_fp); if (!frame) { /* We're really hosed. Not possible to generate a stack trace */ wad_printf("WAD: Unable to generate stack trace.\n"); wad_printf("WAD: Maybe the call stack has been corrupted by buffer overflow.\n"); wad_signal_clear(); return; } { WadFrame *f = frame; while (f) { wad_find_object(f); wad_find_symbol(f); f = f->next; } f = frame; while (f) { wad_find_debug(f); wad_build_vars(f); f = f->next; } } wad_heap_overflow = 0; if (sig == SIGSEGV) { if (addr >= current_brk) wad_heap_overflow = 1; } wad_stack_debug(frame); /* Generate debugging strings */ wad_debug_make_strings(frame); wad_stab_debug(); /* Walk the exception frames and try to find a return point */ origframe = frame; while (frame) { WadReturnFunc *wr = wad_check_return(frame->sym_name); if (wr) { found = 1; wad_nlr_value = wr->value; retname = wr->name; } if (found) { frame->last = 1; /* Cut off top of the stack trace */ break; } frame = frame->next; nlevels++; } if (found) { wad_nlr_levels = nlevels - 1; #ifdef WAD_LINUX wad_restore_i386_registers(origframe, wad_nlr_levels); #endif } else { wad_nlr_levels = -1; } wad_string_debug(); wad_memory_debug(); /* Before we do anything with callbacks, we are going to attempt to dump a wad-core */ { int fd; static int already = 0; fd = open("wadtrace",O_WRONLY | O_CREAT | (already*O_APPEND) | ((already==0)*O_TRUNC),0666); if (fd > 0) { wad_dump_trace(fd,sig,origframe,retname); close(fd); already=1; } } if (sig_callback) { (*sig_callback)(sig,origframe,retname); } else { /* No signal handler defined. Go invoke the default */ wad_default_callback(sig, origframe,retname); } if (wad_debug_mode & DEBUG_HOLD) while(1); /* If we found a function to which we should return, we jump to an alternative piece of code that unwinds the stack and initiates a non-local return. */ if (wad_nlr_levels >= 0) { *(pc) = (greg_t) _returnsignal; #ifdef WAD_SOLARIS *(npc) = *(pc) + 4; #endif if (!(wad_debug_mode & DEBUG_ONESHOT)) { wad_signal_init(); } return; } exit(1); }
/* Handler function */ static void handler(int signo, WadFrame *frame, char *ret) { static char message[65536]; static char temp[1024]; int len = 0; PyObject *type; char *name; WadFrame *f; WadFrame *fline = 0; char *srcstr = 0; /* printf("python handler.\n"); */ if (!ret) { wad_default_callback(signo, frame, ret); return; } strcpy(message,"[ C stack trace ]\n\n"); switch(signo) { case SIGSEGV: type = segfault_exc; break; case SIGBUS: type = buserror_exc; break; case SIGABRT: type = abort_exc; break; case SIGFPE: type = PyExc_FloatingPointError; break; case SIGILL: type = illegal_exc; break; default: type = PyExc_RuntimeError; break; } #ifdef OLD f = frame; /* Find the last exception frame */ while (!f->last) { f= f->next; } /* Now work backwards */ f = f->prev; while (f) { strcat(message, f->debug_str); if (f->debug_srcstr) srcstr = f->debug_srcstr; f = f->prev; } if (srcstr) { strcat(message,"\n"); strcat(message, srcstr); strcat(message,"\n"); } #endif if (wad_heap_overflow) { write(2, "WAD: Heap overflow detected.\n", 30); wad_default_callback(signo, frame, ret); } /* Note: if the heap is blown, there is a very good chance that this function will not succeed and we'll dump core. However, the check above should dump a stack trace to stderr just in case we don't make it back. */ #ifdef OLD PyErr_SetString(type, message); #endif PyErr_SetObject(type, new_wadobject(frame,0)); }
/* Handler function */ static void handler(int signo, WadFrame *frame, char *ret) { static char message[65536]; static char temp[1024]; int len = 0; char *name; WadFrame *f; WadFrame *fline = 0; char *srcstr= 0; Tcl_Interp *interp; int err; char *type; if (!ret) { wad_default_callback(signo, frame, ret); return; } strcpy(message,"[ C stack trace ]\n\n"); switch(signo) { case SIGSEGV: type = (char*)"Segmentation fault."; break; case SIGBUS: type = (char*)"Bus error."; break; case SIGABRT: type = (char*)"Abort."; break; case SIGFPE: type = (char*)"Floating point exception."; break; default: type = (char*)"Unknown."; break; } f = frame; /* Find the last exception frame */ while (!f->last) { f= f->next; } /* Now work backwards */ f = f->prev; while (f) { strcat(message, f->debug_str); if (f->debug_srcstr) srcstr = f->debug_srcstr; f = f->prev; } if (srcstr) { strcat(message,"\n"); strcat(message, srcstr); strcat(message,"\n"); } if (wad_heap_overflow) { write(2, "WAD: Heap overflow detected.\n", 30); wad_default_callback(signo, frame, ret); } /* Note: if the heap is blown, there is a very good chance that this function will not succeed and we'll dump core. However, the check above should dump a stack trace to stderr just in case we don't make it back. */ /* Try to get the Tcl interpreter through magic */ if (ret) { interp = (Tcl_Interp *) wad_steal_outarg(frame,ret,1,&err); if (err == 0) { Tcl_SetResult(interp,type,TCL_STATIC); Tcl_AddErrorInfo(interp,message); } } }