Exemple #1
0
WadObjectFile *
wad_object_load(const char *path) {
    WadObjectFile *wo;
    WadFile *wf;
    WadObjectFile  *wad_arobject_load(const char *path, const char *name);

    if (wad_debug_mode & DEBUG_OBJECT) {
        wad_printf("wad: Loading object   '%s'", path);
    }
    for (wo = wad_objects; wo; wo=wo->next) {
        if (strcmp(wo->path,path) == 0) {
            if (wad_debug_mode & DEBUG_OBJECT) {
                wad_printf(" (cached)\n");
            }
            return wo;
        }
    }
    if (wad_debug_mode & DEBUG_OBJECT) {
        wad_printf("\n");
    }
    /* Didn't find it.  Now we need to go load some files */

    /* If this is an archive reference like /path/libfoo.a(blah.o), we need to
       split up the name a little bit */
    {
        char realfile[MAX_PATH];
        char *objfile;
        char *c;
        c = strchr(path,'(');
        if (c) {
            wad_strcpy(realfile,path);
            c = strchr(realfile,'(');
            *c = 0;
            objfile = c+1;
            c = strchr(objfile,')');
            *c = 0;

            /* Okay, I'm going to attempt to map this as a library file */
            wo = wad_arobject_load(realfile,objfile);
            if (wo) {
                /* Reset the path */
                wo->path = wad_strdup(path);
                wo->next = wad_objects;
                wad_objects = wo;
                return wo;
            }
        }
    }
    wf = load_file(path);
    if (!wf) return 0;

    wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
    wo->path = wad_strdup(path);
    wo->ptr = wf->addr;
    wo->len = wf->size;
    wo->next = wad_objects;
    wad_objects = wo;
    return wo;
}
Exemple #2
0
void wad_signal_init() {
  struct sigaction newvec;
  static stack_t  sigstk;
  static int      initstack = 0;

  if (wad_debug_mode & DEBUG_INIT) {
    wad_printf("WAD: Initializing signal handler.\n");
  }
  /* This is buggy in Linux and threads.  disabled by default */

#ifndef WAD_LINUX

  if (!initstack) {
    /* Set up an alternative stack */
    
    sigstk.ss_sp = (char *) wad_sig_stack;
    sigstk.ss_size = STACK_SIZE;
    sigstk.ss_flags = 0;
    if (!(wad_debug_mode & DEBUG_NOSTACK)) {
      if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
	perror("sigaltstack");
      }
    }
    initstack=1;
  }
#endif

  sigemptyset(&newvec.sa_mask);
  sigaddset(&newvec.sa_mask, SIGSEGV);
  sigaddset(&newvec.sa_mask, SIGBUS);
  sigaddset(&newvec.sa_mask, SIGABRT);
  sigaddset(&newvec.sa_mask, SIGILL);
  sigaddset(&newvec.sa_mask, SIGFPE);
  newvec.sa_flags = SA_SIGINFO;

  if (wad_debug_mode & DEBUG_ONESHOT) {
    newvec.sa_flags |= SA_RESETHAND;
  }
#ifndef WAD_LINUX
  if (!(wad_debug_mode & DEBUG_NOSTACK)) {
    newvec.sa_flags |= SA_ONSTACK;
  } 
#endif
  newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
  if (sigaction(SIGSEGV, &newvec, NULL) < 0) goto werror;
  if (sigaction(SIGBUS, &newvec, NULL) < 0) goto werror;
  if (sigaction(SIGABRT, &newvec, NULL) < 0) goto werror;
  if (sigaction(SIGFPE, &newvec, NULL) < 0) goto werror;
  if (sigaction(SIGILL, &newvec, NULL) < 0) goto werror;
  
  return;
 werror:
  wad_printf("WAD: Couldn't install signal handler!\n");
}
Exemple #3
0
int
wad_segment_read() {
  int         fs;
  int         n;
  WadSegment *s, *lasts;

  segments = 0;
  lasts = 0;
  fs = segment_open();

  while (1) {
    s = (WadSegment *) wad_malloc(sizeof(WadSegment));    
  skip:
    n = segment_read(fs,s);
    if (n <= 0) break;
    if (wad_file_check(s->vaddr)) goto skip;  /* Skip files we already loaded */
    s->next = 0;
    if (!lasts) {
      segments = s;
      lasts = s;
    } else {
      lasts->next = s;
      lasts = s;
    }
    if (wad_debug_mode & DEBUG_SEGMENT) {
      wad_printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
    }
  }
  close(fs);
  return 0;
}
Exemple #4
0
void
wad_find_symbol(WadFrame *f) {
  if (wad_debug_mode & DEBUG_SYMBOL) {
    wad_printf("wad: Searching for 0x%08x --> ", f->pc);
  }
  if (f->object)
    wad_elf_find_symbol(f);
  if (wad_debug_mode & DEBUG_SYMBOL) {
    if (f->sym_name) {
      wad_printf("%s", f->sym_name);
      if (f->sym_file)
	wad_printf(" in '%s'\n", f->sym_file);
      else
	wad_printf("\n");
    } else {
      wad_printf("?\n");
    }
  }
}
Exemple #5
0
static
int elf_search_section_sym(WadFrame *f, char *secname, char *strname) {
  int         nsymtab;
  int         nstrtab;
  int         symtab_size;
  Elf32_Sym  *sym;
  int         nsym;
  char       *str;
  int         i;
  unsigned long vaddr, base;
  char        *name;
  char        *localfile = 0;

  vaddr = (unsigned long) f->pc;
  base  = (unsigned long) f->segment->base;

  nsymtab = wad_elf_section_byname(f->object,secname);
  if (nsymtab < 0) return 0;
  nstrtab = wad_elf_section_byname(f->object,strname);
  if (nstrtab < 0) return 0;
  
  symtab_size = wad_elf_section_size(f->object,nsymtab);
  sym = (Elf32_Sym *) wad_elf_section_data(f->object,nsymtab);
  str = (char *) wad_elf_section_data(f->object,nstrtab);

  nsym = (symtab_size/sizeof(Elf32_Sym));
  for (i = 0; i < nsym; i++) {
    name = str + sym[i].st_name;
    /* Look for filename in case the symbol maps to a local symbol */
    if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
      localfile = name;
    }
    if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
      wad_printf("%x(%x): %s   %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
    }
    if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
#ifdef WAD_LINUX
      /* If the section index is 0, the symbol is undefined */
      if (sym[i].st_shndx == 0) continue;
#endif
      f->sym_name = name;
      f->sym_nlen = strlen(name);
      f->sym_base = base + sym[i].st_value;
      f->sym_size = sym[i].st_size;
      if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
	f->sym_file = localfile;
	f->sym_bind = SYM_LOCAL;
      } else {
	f->sym_bind = SYM_GLOBAL;
      }
      return 1;
    }
  }
  return 0;
}
Exemple #6
0
static void types_print() {
  stabtype *s;
  int i;
  for (i = 0; i < HASH_SIZE; i++) {
    s = lnames[i];
    while (s) {
      wad_printf("%20s  %s\n", s->name, s->value);
      s = s->next;
    }
  }
}
Exemple #7
0
/* private function to manage the loading of raw files into memory */
static WadFile *
load_file(const char *path) {
    int fd;
    WadFile *wf = wad_files;

    if (wad_debug_mode & DEBUG_FILE) {
        wad_printf("wad: Loading file     '%s' ... ", path);
    }
    while (wf) {
        if (strcmp(wf->path,path) == 0) {
            if (wad_debug_mode & DEBUG_FILE) wad_printf("cached.\n");
            return wf;
        }
        wf = wf->next;
    }
    fd = open(path, O_RDONLY);
    if (fd < 0) {
        if (wad_debug_mode & DEBUG_FILE) wad_printf("not found!\n");
        return 0;       /* Doesn't exist. Oh well */
    }
    if (wad_debug_mode & DEBUG_FILE) wad_printf("loaded.\n");
    wf = (WadFile *) wad_malloc(sizeof(WadFile));
    wf->path = wad_strdup(path);

    /* Get file length */
    wf->size = lseek(fd,0,SEEK_END);
    lseek(fd,0,SEEK_SET);

    /* Try to mmap the file */
    wf->addr = mmap(NULL,wf->size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
    close(fd);
    if (wf->addr == MAP_FAILED) {
        if (wad_debug_mode & DEBUG_FILE) wad_printf("wad: Couldn't mmap '%s'\n", path);
        return 0;
    }
    wf->next = wad_files;
    wad_files = wf;
    return wf;
}
Exemple #8
0
void
wad_object_reset() {
    WadFile *f = wad_files;
    if (wad_debug_mode & DEBUG_OBJECT) {
        wad_printf("wad: Releasing all files.\n");
    }
    /* Unmap all of the loaded files */
    while (f) {
        if (f->addr) {
            munmap(f->addr, f->size);
        }
        f = f->next;
    }
    /* Reset the linked lists */
    wad_files = 0;
    wad_objects = 0;
}
Exemple #9
0
void
wad_elf_debug(WadObjectFile *wo) {
  int i;
  wad_printf("ELF Debug : obj = %x (%s)\n", wo, wo->path);
  wad_printf("   phdrcnt      = %d\n", wad_elf_phdrcnt(wo));
  wad_printf("   phdrpos      = %x\n", wad_elf_phdrpos(wo));
  wad_printf("   shdrcnt      = %d\n", wad_elf_shdrcnt(wo));
  wad_printf("   shdrpos      = %x\n", wad_elf_shdrpos(wo));
  for (i = 0; i < wad_elf_shdrcnt(wo); i++) {
    wad_printf("      section '%s': data = 0x%x, size = %d\n", 
	   wad_elf_section_name(wo,i),
	   wad_elf_section_data(wo,i),
	   wad_elf_section_size(wo,i));
  }
}
Exemple #10
0
WadSegment *
wad_segment_find(void *vaddr) {
  WadSegment *ls;
  WadSegment *s;
  char *addr = (char *)vaddr;

  s = segments;
  ls = segments;
  while (s) {
    if (strcmp(s->mapname,ls->mapname) || (!strlen(ls->mapname))) {
      ls = s;    /* First segment for a given name */
    }
    if ((addr >= s->vaddr) && (addr < (s->vaddr + s->size))) {
      if (wad_debug_mode & DEBUG_SEGMENT) {
	wad_printf("wad_segment: %08x --> %08x-%08x in %s\n", vaddr, s->vaddr, ((char *) s->vaddr) + s->size, s->mappath);
      }
      return ls;
    }
    s = s->next;
  }
  return 0;
}
Exemple #11
0
/* Initialize wad */
void wad_init() {
  static int init = 0;

  wad_memory_init();
  if (getenv("WAD_DEBUG_SEGMENT")) {
    wad_debug_mode |= DEBUG_SEGMENT;
  }
  if (getenv("WAD_DEBUG_SYMBOL")) {
    wad_debug_mode |= DEBUG_SYMBOL;
  }

  if (getenv("WAD_DEBUG_OBJECT")) {
    wad_debug_mode |= DEBUG_OBJECT;
  }

  if (getenv("WAD_DEBUG_FILE")) {
    wad_debug_mode |= DEBUG_FILE;
  }

  if (getenv("WAD_DEBUG_HOLD")) {
    wad_debug_mode |= DEBUG_HOLD;
  }

  if (getenv("WAD_DEBUG_STABS")) {
    wad_debug_mode |= DEBUG_STABS;
  }

  if (getenv("WAD_DEBUG_RETURN")) {
    wad_debug_mode |= DEBUG_RETURN;
  }

  if (getenv("WAD_DEBUG_SYMBOL_SEARCH")) {
    wad_debug_mode |= DEBUG_SYMBOL_SEARCH;
  }

  if (getenv("WAD_DEBUG_INIT")) {
    wad_debug_mode |= DEBUG_INIT;
  }

  if (getenv("WAD_DEBUG_STACK")) {
    wad_debug_mode |= DEBUG_STACK;
  }

  if (getenv("WAD_DEBUG_UNWIND")) {
    wad_debug_mode |= DEBUG_UNWIND;
  }

  if (getenv("WAD_DEBUG_SIGNAL")) {
    wad_debug_mode |= DEBUG_SIGNAL;
  }

  if (getenv("WAD_NOSTACK")) {
    wad_debug_mode |= DEBUG_NOSTACK;
  }

  if (getenv("WAD_ONESHOT")) {
    wad_debug_mode |= DEBUG_ONESHOT;
  }

  if (getenv("WAD_DEBUG_STRING")) {
    wad_debug_mode |= DEBUG_STRING;
  }

  if (getenv("WAD_DEBUG_MEMORY")) {
    wad_debug_mode |= DEBUG_MEMORY;
  }

  if (wad_debug_mode & DEBUG_INIT) {
    wad_printf("WAD: initializing\n");
  }


  if (!init) {
    wad_signal_init();
    wad_object_reset();
  }
  init = 1;
}
Exemple #12
0
static int
scan_function(Stab *s, char *stabstr, int ns, WadFrame *f) {
  int i;
  unsigned long offset;
  int      get_parms = 1;
  int      nbrace = 0;

  offset = f->pc - f->sym_base;
  if (wad_debug_mode & DEBUG_STABS) {
    wad_printf("---[ %s ] --------------\n", f->sym_name);
  }
  
  for (i = 0; i < ns; i++,s++) {
    if (wad_debug_mode & DEBUG_STABS) {
      wad_printf("   %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value, 
	     stabstr+s->n_strx);
      
    }
    
    if ((s->n_type == N_UNDF) || (s->n_type == N_SO) || /* (s->n_type == N_FUN) || */
	(s->n_type == N_OBJ)) return i;

    if ((s->n_type == N_FUN) && !(strlen(stabstr+s->n_strx))) return 1;

    if (s->n_type == N_LBRAC) {
      nbrace++;
      get_parms = 0;
    }
    if (s->n_type == N_RBRAC) {
      nbrace--;
      if (nbrace <= 0) return i;
    }
    /* Local variable declaration */

    if (s->n_type == N_LSYM) {
      /* This might be a local variable definition */
      /*      wad_printf("local: n_value = %d, offset = %d\n", s->n_value, offset);*/
      if (s->n_desc <= f->loc_line)
      {
	/* Okay. We can pay attention to it */
	char *pname;
	char *c;
	int   len;
	WadLocal *arg, *a;
	pname = stabstr+s->n_strx;
	c = strchr(pname,':');
	if (*(c+1) != '(') continue;
	if (c) {
	  len = (c-pname);
	} else {
	  len = strlen(pname);
	}
	/*	printf("local\n"); */
	stab_symbol(s,stabstr);
	a = f->debug_locals;
	while (a) {
	  if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
	    /* We already saw this argument.  Given a choice between a register and a stack
	       argument.  We will choose the stack version */
	    a->loc = PARM_STACK;
	    a->stack = s->n_value;
	    break;
	  }
	  a = a->next;
	}
	if (a) continue; /* We got an argument match.  Just skip to the next stab */
	arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
	{
	  char t = pname[len];
	  pname[len] = 0;
	  arg->name = wad_string_lookup(pname);
	  pname[len] = t;
	}
	arg->loc = PARM_STACK;
	arg->line = s->n_desc;
	arg->stack = s->n_value;
	arg->type = 0;
	arg->next = 0;
	{
	  char tname[128];
	  char *t = tname;
	  
	  c+=1;
	  while ((*c) && (*c != '=')) {
	    *t++ = *c++;
	  }
	  *t = 0;
	  t = type_resolve(tname);
	  arg->type = type_typecode(t);
	  if (wad_debug_mode & DEBUG_STABS) {
	    wad_printf("type_resolve '%s' -> '%s' (%d)\n", tname, t, arg->type);
	  }
	}
	if (f->debug_locals) {
	  f->debug_lastlocal->next = arg;
	  f->debug_lastlocal = arg;
	} else {
	  f->debug_locals = arg;
	  f->debug_lastlocal = arg;
	  f->debug_nlocals= 0;
	}
	f->debug_nlocals++;
      }
    }

    if (s->n_type == N_SLINE) {
      get_parms = 0;
      if (s->n_value <= offset) {
	f->loc_line = s->n_desc;
      }
    } else if (((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) && get_parms) {
      /* Parameter counting */
      char *pname;
      char *c;
      int   len;
      WadLocal *arg;
      pname = stabstr+s->n_strx;
      c = strchr(pname,':');
      if (c) {
	len = (c-pname);
      } else {
	len = strlen(pname);
      }
      /* Get type information */
      
      stab_symbol(s,stabstr);
      
      /* Check if the argument was already used */
      /* In this case, the first stab simply identifies an argument.  The second
	 one identifies its location for the debugger */
      
      {
	/* Need to do some fix up for linux here */
	WadLocal *a = f->debug_args;
	while (a) {
	  if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
	    /* We already saw this argument.  Given a choice between a register and a stack
	       argument.  We will choose the stack version */
	    
	    if (a->loc == PARM_STACK) {
	      break;
	    }
	    /* Go ahead and use the new argument */
	    if (s->n_type == N_RSYM) {
	      a->loc = PARM_REGISTER;
	      a->reg = s->n_value;
	    } else {
	      a->loc = PARM_STACK;
	      a->stack = s->n_value;
	    }
	    break;
	  }
	  a = a->next;
	}
	if (a) continue; /* We got an argument match.  Just skip to the next stab */
      }
	
      arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
      {
	char t = pname[len];
	pname[len] = 0;
	arg->name = wad_string_lookup(pname);
	pname[len] = t;
      }
      if (s->n_type == N_RSYM) {
	arg->loc = PARM_REGISTER;
	arg->reg = s->n_value;
	arg->stack = 0;
      } else {
	arg->loc = PARM_STACK;
	arg->line = s->n_desc;
	arg->stack = s->n_value;
      }
      arg->type = 0;
      arg->next = 0;
      {
	char tname[128];
	char *t = tname;
	
	c+=2;
	while ((*c) && (*c != '=')) {
	  *t++ = *c++;
	}
	*t = 0;
	t = type_resolve(tname);
	arg->type = type_typecode(t);
	if (wad_debug_mode & DEBUG_STABS) {
	  wad_printf("type_resolve '%s' -> '%s' (%d)\n", tname, t, arg->type);
	}
      }
      if (f->debug_args) {
	f->debug_lastarg->next = arg;
	f->debug_lastarg = arg;
      } else {
	f->debug_args = arg;
	f->debug_lastarg = arg;
	f->debug_nargs= 0;
      }
      f->debug_nargs++;
    }
  }
  return i;
}
Exemple #13
0
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;
}
Exemple #14
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);
}