int wad_elf_debug_info(WadFrame *f) { int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr; int ret; void *stab; char *stabstr; int stabsize; nstab = wad_elf_section_byname(f->object,".stab"); nstabstr = wad_elf_section_byname(f->object,".stabstr"); nstabindex = wad_elf_section_byname(f->object,".stab.index"); nstabindexstr = wad_elf_section_byname(f->object,".stab.indexstr"); nstabexcl = wad_elf_section_byname(f->object,".stab.excl"); nstabexclstr = wad_elf_section_byname(f->object,".stab.exclstr"); #ifdef DEBUG_DEBUG wad_printf("nstab = %d\n", nstab); wad_printf("nstabstr = %d\n", nstabstr); wad_printf("nstabindex = %d\n", nstabindex); wad_printf("nstabindexstr = %d\n", nstabindexstr); wad_printf("nstabexcl = %d\n", nstabexcl); wad_printf("nstabexclstr = %d\n", nstabexclstr); #endif /* Now start searching stabs */ /* Look in the .stab section */ if (nstab > 0) { stab = wad_elf_section_data(f->object,nstab); stabsize = wad_elf_section_size(f->object,nstab); stabstr = (char *) wad_elf_section_data(f->object,nstabstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.excl section. A solaris oddity? */ if (nstabexcl > 0) { stab = wad_elf_section_data(f->object,nstabexcl); stabsize = wad_elf_section_size(f->object, nstabexcl); stabstr = (char *) wad_elf_section_data(f->object, nstabexclstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.index section. A Solaris oddity? */ if (nstabindex > 0) { stab = wad_elf_section_data(f->object,nstabindex); stabsize = wad_elf_section_size(f->object, nstabindex); stabstr = (char *) wad_elf_section_data(f->object, nstabindexstr); if (wad_search_stab(stab,stabsize,stabstr, f)) { /* Hmmm. Might be in a different file */ WadObjectFile *wo1, *wold; char objfile[MAX_PATH]; /* printf("DEBUG %s\n", f->sym_name); */ wad_strcpy(objfile, f->loc_objfile); wo1 = wad_object_load(objfile); if (wo1) { wold = f->object; f->object = wo1; wad_find_debug(f); f->object = wold; return ret; } else { /* wad_printf("couldn't load %s\n", objfile); */ } /* if (!ret) return wad_search_stab(stab,stabsize,stabstr,f);*/ return ret; } } return 0; }
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); }