Initial revision
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@931 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
d97eab2c7f
commit
41c6156e1d
14 changed files with 1556 additions and 0 deletions
104
SWIG/Tools/WAD/Include/wad.h
Normal file
104
SWIG/Tools/WAD/Include/wad.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wad.h
|
||||
*
|
||||
* WAD header file (obviously)
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
/* Typedef's for various addresses and sizes */
|
||||
typedef char * wadaddr_t;
|
||||
typedef unsigned long wadlen_t;
|
||||
|
||||
/* Memory management */
|
||||
extern void *wadmalloc(unsigned int);
|
||||
extern void wadfree(void *ptr);
|
||||
|
||||
typedef struct WadSegment {
|
||||
wadaddr_t vaddr; /* Virtual address start */
|
||||
wadlen_t size; /* Size of the segment (bytes) */
|
||||
int flags; /* Memory access permissions */
|
||||
wadlen_t offset; /* Offset into mapped object */
|
||||
char mapname[MAX_PATH]; /* Filename mapped to this region */
|
||||
char mappath[MAX_PATH]; /* Full path to mapname */
|
||||
int identifier; /* identifier (if SysV shmem) */
|
||||
long wad; /* Private wad data (if any) */
|
||||
} WadSegment;
|
||||
|
||||
extern void wad_segment_print(WadSegment *s);
|
||||
extern WadSegment *wad_segment_find(wadaddr_t addr);
|
||||
extern WadSegment *wad_segment_first();
|
||||
extern WadSegment *wad_segment_next();
|
||||
|
||||
/* Structure for managing object files */
|
||||
typedef struct WadObject {
|
||||
void *mptr; /* mmap'd pointer */
|
||||
int mlen; /* mmap'd length */
|
||||
void *ptr; /* Pointer to real data */
|
||||
int len; /* Length of real data */
|
||||
int refcnt; /* Reference count */
|
||||
int type; /* Type of the object file */
|
||||
char path[MAX_PATH]; /* Path name of this object */
|
||||
} WadObject;
|
||||
|
||||
extern char *wad_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value);
|
||||
|
||||
/* Maximum number of object files that can be simultaneously loaded into memory */
|
||||
#define WAD_MAX_OBJECT 32
|
||||
|
||||
extern WadObject *wad_object_load(const char *path);
|
||||
extern WadObject *wad_arobject_load(const char *path, const char *name);
|
||||
extern void wad_object_release(WadObject *);
|
||||
|
||||
extern void wad_init();
|
||||
extern void wad_signalhandler(int, siginfo_t *, void *);
|
||||
extern void wad_set_return(char *name, long value);
|
||||
extern int wad_elf_check(WadObject *wo);
|
||||
extern void wad_elf_debug(WadObject *wo);
|
||||
|
||||
/* Debugging information */
|
||||
typedef struct WadDebug {
|
||||
int found; /* Whether or not debugging information was found */
|
||||
char srcfile[1024]; /* Source file */
|
||||
char objfile[1024]; /* Object file */
|
||||
int line_number; /* Line number */
|
||||
int nargs; /* Number of function arguments */
|
||||
} WadDebug;
|
||||
|
||||
extern WadDebug *wad_search_stab(void *stab, int size, char *stabstr, char *symbol, unsigned long offset);
|
||||
extern WadDebug *wad_debug_info(WadObject *wo, char *symbol, unsigned long offset);
|
||||
|
||||
/* This data structure is used to report exception data back to handler functions
|
||||
The offset fields contain offsets from the start of the frame to a location in
|
||||
the data segment */
|
||||
|
||||
typedef struct WadFrame {
|
||||
long size; /* Frame size */
|
||||
long frameno; /* Frame number */
|
||||
long pc; /* Program counter */
|
||||
long sp; /* Stack pointer */
|
||||
long fp; /* Frame pointer */
|
||||
long line_number; /* Source line number */
|
||||
long sym_base; /* Symbol base address */
|
||||
long sym_off; /* Symbol name offset */
|
||||
long src_off; /* Source filename offset */
|
||||
long obj_off; /* Object filename offset */
|
||||
char data[8]; /* Frame data */
|
||||
} WadFrame;
|
||||
|
||||
|
||||
26
SWIG/Tools/WAD/Makefile
Normal file
26
SWIG/Tools/WAD/Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
SRCS = stab.c elf.c object.c init.c segment.c signal.c
|
||||
OBJS = stab.o elf.o object.o signal.o segment.o init.o main.o
|
||||
|
||||
all::
|
||||
CC -Kpic -c main.cxx
|
||||
cc -c $(SRCS)
|
||||
CC -G $(OBJS) -o libwad.so
|
||||
|
||||
swig::
|
||||
swig -python wad.i
|
||||
CC -Kpic -c main.cxx
|
||||
cc -c $(SRCS) wad_wrap.c -I/usr/local/include/python1.6
|
||||
CC -G $(OBJS) wad_wrap.o -o wadmodule.so
|
||||
|
||||
|
||||
some::
|
||||
cc -g bar.c blah.c -L. -lwad -R /u0/beazley/Projects/WAD -lelf
|
||||
|
||||
wc::
|
||||
wc $(SRCS)
|
||||
|
||||
semi::
|
||||
egrep ";" $(SRCS) | wc
|
||||
|
||||
|
||||
13
SWIG/Tools/WAD/Misc/fileheader
Normal file
13
SWIG/Tools/WAD/Misc/fileheader
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* segment.c
|
||||
*
|
||||
* This file provides access to the virtual memory map of a process
|
||||
* including the location of the executable, data segments, shared
|
||||
* libraries, and memory mapped regions. This information is
|
||||
* obtained through /proc.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
58
SWIG/Tools/WAD/Python/wad.i
Normal file
58
SWIG/Tools/WAD/Python/wad.i
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
%module wad
|
||||
%{
|
||||
#include "wad.h"
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
extern jmp_buf Py_cerror;
|
||||
extern PyObject *Py_cerror_obj;
|
||||
|
||||
static PyObject *segfault_exc = 0;
|
||||
static PyObject *buserror_exc = 0;
|
||||
static PyObject *abort_exc = 0;
|
||||
|
||||
/* Handler function */
|
||||
static void handler(int signo, void *clientdata) {
|
||||
static char message[65536];
|
||||
int len = 0;
|
||||
PyObject *type;
|
||||
char *name;
|
||||
|
||||
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;
|
||||
default:
|
||||
type = PyExc_RuntimeError;
|
||||
break;
|
||||
}
|
||||
PyErr_SetString(type, message);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
%init %{
|
||||
wad_set_callback(handler);
|
||||
|
||||
wad_set_return("call_builtin", 0);
|
||||
|
||||
segfault_exc = PyErr_NewException("exceptions.SegFault", NULL, NULL);
|
||||
PyDict_SetItemString(d,"SegFault",segfault_exc);
|
||||
|
||||
buserror_exc = PyErr_NewException("exceptions.BusError", NULL, NULL);
|
||||
PyDict_SetItemString(d,"BusError",buserror_exc);
|
||||
|
||||
abort_exc = PyErr_NewException("exceptions.AbortError", NULL, NULL);
|
||||
PyDict_SetItemString(d,"AbortError",abort_exc);
|
||||
|
||||
%}
|
||||
|
||||
|
||||
11
SWIG/Tools/WAD/README
Normal file
11
SWIG/Tools/WAD/README
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
WAD (Wrapped Application Debugger)
|
||||
|
||||
David M. Beazley
|
||||
Department of Computer Science
|
||||
University of Chicago
|
||||
Chicago, IL 60637
|
||||
beazley@cs.uchicago.edu
|
||||
|
||||
Copyright (C) 2000
|
||||
University of Chicago
|
||||
All Rights Reserved
|
||||
21
SWIG/Tools/WAD/Wad/Makefile
Normal file
21
SWIG/Tools/WAD/Wad/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
SRCS = stab.c elf.c object.c init.c segment.c signal.c
|
||||
OBJS = stab.o elf.o object.o signal.o segment.o init.o main.o
|
||||
INCLUDE = -I../Include
|
||||
|
||||
all::
|
||||
CC -Kpic -c $(INCLUDE) main.cxx
|
||||
cc -c $(INCLUDE) $(SRCS)
|
||||
CC -G $(OBJS) -o libwad.so
|
||||
cp libwad.so ..
|
||||
|
||||
wc::
|
||||
wc $(SRCS)
|
||||
|
||||
semi::
|
||||
egrep ";" $(SRCS) | wc
|
||||
|
||||
|
||||
clean::
|
||||
rm -f *.o *.so *~
|
||||
|
||||
355
SWIG/Tools/WAD/Wad/elf.c
Normal file
355
SWIG/Tools/WAD/Wad/elf.c
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* elf.c
|
||||
*
|
||||
* ELF file management. This file contains functions for accessing ELF
|
||||
* file data from a raw memory mapped ELF file (as performed by the
|
||||
* functions in object.c).
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
#include <sys/elf.h>
|
||||
|
||||
/* --- What's needed here (high level interface) :
|
||||
|
||||
- Mapping of addresses to symbols
|
||||
- Mapping of symbols to file+line
|
||||
- Parameter passing information?
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_check()
|
||||
*
|
||||
* Checks to see if an object file is an ELF file. Returns 1 on success and
|
||||
* changes the type flag of wo to indicate the type of ELF file.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_check(WadObject *wo) {
|
||||
int t;
|
||||
|
||||
if (strncmp((char *)wo->ptr,ELFMAG, SELFMAG) != 0)
|
||||
return 0;
|
||||
|
||||
/* Probably need to put some kind of 32/64 bit check here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_phdrcnt()
|
||||
*
|
||||
* Return number of entries in the ELF program header section
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_phdrcnt(WadObject *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
return eh->e_phnum;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_phdrpos()
|
||||
*
|
||||
* Return the location of the ELF program header.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *
|
||||
wad_elf_phdrpos(WadObject *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *c;
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
c = (char *) wo->ptr;
|
||||
return (void *) (c+eh->e_phoff);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_shdrcnt()
|
||||
*
|
||||
* Return number of entries in the ELF section header
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_shdrcnt(WadObject *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
return eh->e_shnum;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_shdrpos()
|
||||
*
|
||||
* Return the location of the section headers
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *
|
||||
wad_elf_shdrpos(WadObject *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *c;
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
c = (char *) wo->ptr;
|
||||
return (void *) (c+eh->e_shoff);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_header()
|
||||
*
|
||||
* Get a specific section number
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_elf_section_header(WadObject *wo, int sn) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *r;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
if ((sn < 0) || (sn >= eh->e_shnum)) return 0;
|
||||
|
||||
r = (char *) wad_elf_shdrpos(wo) + (sn*eh->e_shentsize);
|
||||
return (void *) r;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_data()
|
||||
*
|
||||
* Get section data
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_elf_section_data(WadObject *wo, int sn) {
|
||||
Elf32_Shdr *sh;
|
||||
char *r;
|
||||
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return 0;
|
||||
|
||||
r = ((char *) wo->ptr) + sh->sh_offset;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_size()
|
||||
* Return section size
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int wad_elf_section_size(WadObject *wo, int sn) {
|
||||
Elf32_Shdr *sh;
|
||||
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return -1;
|
||||
return sh->sh_size;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_name()
|
||||
*
|
||||
* Returns the name of an ELF section
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *wad_elf_section_name(WadObject *wo, int sn) {
|
||||
Elf32_Ehdr *eh;
|
||||
Elf32_Shdr *sh;
|
||||
char *sectionstr;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
|
||||
/* Get the string table */
|
||||
sectionstr = (char *) wad_elf_section_data(wo,eh->e_shstrndx);
|
||||
if (!sectionstr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the section header for the section */
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return 0;
|
||||
return sectionstr + sh->sh_name;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_byname()
|
||||
*
|
||||
* Get section data given a section name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_section_byname(WadObject *wo, char *name) {
|
||||
int i;
|
||||
char *sn;
|
||||
int n;
|
||||
|
||||
n = wad_elf_shdrcnt(wo);
|
||||
for (i = 0; i <n; i++) {
|
||||
sn = wad_elf_section_name(wo,i);
|
||||
if (strcmp(sn,name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_find_symbol()
|
||||
*
|
||||
* Tries to find the symbol associated with a given address. base is the
|
||||
* base address of the object file.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
char *
|
||||
wad_elf_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value) {
|
||||
int nsymtab;
|
||||
int nstrtab;
|
||||
int symtab_size;
|
||||
Elf32_Sym *sym;
|
||||
int nsym;
|
||||
char *str;
|
||||
int i;
|
||||
unsigned long vaddr;
|
||||
char *name;
|
||||
|
||||
vaddr = (unsigned long) ptr;
|
||||
|
||||
nsymtab = wad_elf_section_byname(wo,".symtab");
|
||||
if (nsymtab < 0) return 0;
|
||||
nstrtab = wad_elf_section_byname(wo,".strtab");
|
||||
if (nstrtab < 0) return 0;
|
||||
|
||||
symtab_size = wad_elf_section_size(wo,nsymtab);
|
||||
sym = (Elf32_Sym *) wad_elf_section_data(wo,nsymtab);
|
||||
str = (char *) wad_elf_section_data(wo,nstrtab);
|
||||
|
||||
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||
for (i = 0; i < nsym; i++) {
|
||||
name = str + sym[i].st_name;
|
||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr < (base+sym[i].st_value + sym[i].st_size))) {
|
||||
if (value)
|
||||
*value = sym[i].st_value;
|
||||
return name;
|
||||
}
|
||||
/* printf("%s %x\n", name, sym[i].st_value); */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_debug_info()
|
||||
*
|
||||
* Gather debugging information about a function (if possible)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadDebug *
|
||||
wad_elf_debug_info(WadObject *wo, char *symbol, unsigned long offset) {
|
||||
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
||||
|
||||
void *stab;
|
||||
char *stabstr;
|
||||
int stabsize;
|
||||
WadDebug *wd;
|
||||
|
||||
nstab = wad_elf_section_byname(wo,".stab");
|
||||
nstabstr = wad_elf_section_byname(wo,".stabstr");
|
||||
nstabindex = wad_elf_section_byname(wo,".stab.index");
|
||||
nstabindexstr = wad_elf_section_byname(wo,".stab.indexstr");
|
||||
nstabexcl = wad_elf_section_byname(wo,".stab.excl");
|
||||
nstabexclstr = wad_elf_section_byname(wo,".stab.exclstr");
|
||||
|
||||
#ifdef DEBUG_DEBUG
|
||||
printf("nstab = %d\n", nstab);
|
||||
printf("nstabstr = %d\n", nstabstr);
|
||||
printf("nstabindex = %d\n", nstabindex);
|
||||
printf("nstabindexstr = %d\n", nstabindexstr);
|
||||
printf("nstabexcl = %d\n", nstabexcl);
|
||||
printf("nstabexclstr = %d\n", nstabexclstr);
|
||||
#endif
|
||||
|
||||
/* Now start searching stabs */
|
||||
|
||||
/* Look in the .stab section */
|
||||
if (nstab > 0) {
|
||||
stab = wad_elf_section_data(wo,nstab);
|
||||
stabsize = wad_elf_section_size(wo,nstab);
|
||||
stabstr = (char *) wad_elf_section_data(wo,nstabstr);
|
||||
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
}
|
||||
|
||||
/* Look in the .stab.excl section. A solaris oddity? */
|
||||
|
||||
if (nstabexcl > 0) {
|
||||
stab = wad_elf_section_data(wo,nstabexcl);
|
||||
stabsize = wad_elf_section_size(wo, nstabexcl);
|
||||
stabstr = (char *) wad_elf_section_data(wo, nstabexclstr);
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
}
|
||||
|
||||
/* Look in the .stab.index section. Another solaris oddity? */
|
||||
if (nstabindex > 0) {
|
||||
stab = wad_elf_section_data(wo,nstabindex);
|
||||
stabsize = wad_elf_section_size(wo, nstabindex);
|
||||
stabstr = (char *) wad_elf_section_data(wo, nstabindexstr);
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) {
|
||||
WadObject *wo1;
|
||||
/* Hmmm. Might be in a different file */
|
||||
char objfile[MAX_PATH];
|
||||
strcpy(objfile, wd->objfile);
|
||||
wo1 = wad_object_load(objfile);
|
||||
if (wo1) {
|
||||
wd = wad_debug_info(wo1,symbol,offset);
|
||||
wad_object_release(wo1);
|
||||
} else {
|
||||
printf("couldn't load %s\n", objfile);
|
||||
}
|
||||
if (!wd) return wad_search_stab(stab,stabsize,stabstr,symbol,offset);
|
||||
return wd;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_debug()
|
||||
*
|
||||
* Print some debugging information about an object
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_elf_debug(WadObject *wo) {
|
||||
int i;
|
||||
printf("ELF Debug : obj = %x (%s)\n", wo, wo->path);
|
||||
printf(" phdrcnt = %d\n", wad_elf_phdrcnt(wo));
|
||||
printf(" phdrpos = %x\n", wad_elf_phdrpos(wo));
|
||||
printf(" shdrcnt = %d\n", wad_elf_shdrcnt(wo));
|
||||
printf(" shdrpos = %x\n", wad_elf_shdrpos(wo));
|
||||
for (i = 0; i < wad_elf_shdrcnt(wo); i++) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/* general purpose functions exposed to the outside world */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_find_symbol()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
wad_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value) {
|
||||
return wad_elf_find_symbol(wo,ptr,base,value);
|
||||
}
|
||||
|
||||
WadDebug *
|
||||
wad_debug_info(WadObject *wo, char *symbol, unsigned long offset) {
|
||||
return wad_elf_debug_info(wo,symbol,offset);
|
||||
}
|
||||
48
SWIG/Tools/WAD/Wad/init.c
Normal file
48
SWIG/Tools/WAD/Wad/init.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* init.c
|
||||
*
|
||||
* Initialize the wad system. This sets up a signal handler for catching
|
||||
* SIGSEGV, SIGBUS, and SIGABRT.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
/* Size of signal stack */
|
||||
#define STACK_SIZE 4*SIGSTKSZ
|
||||
|
||||
/* Make the alternate signal stack part of the wad data segment as
|
||||
opposed to putting it on the process heap */
|
||||
|
||||
char wad_sig_stack[STACK_SIZE];
|
||||
|
||||
/* Set up signal handler function for events we care about */
|
||||
void wad_init() {
|
||||
struct sigaction newvec;
|
||||
static int init = 0;
|
||||
static stack_t sigstk;
|
||||
|
||||
if (!init) {
|
||||
/* Set up an alternative stack */
|
||||
sigstk.ss_sp = (char *) wad_sig_stack;
|
||||
sigstk.ss_size = STACK_SIZE;
|
||||
sigstk.ss_flags = 0;
|
||||
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
|
||||
perror("sigaltstack");
|
||||
}
|
||||
sigemptyset(&newvec.sa_mask);
|
||||
sigaddset(&newvec.sa_mask, SIGSEGV);
|
||||
sigaddset(&newvec.sa_mask, SIGBUS);
|
||||
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESETHAND;
|
||||
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||
sigaction(SIGSEGV, &newvec, NULL);
|
||||
sigaction(SIGBUS, &newvec, NULL);
|
||||
sigaction(SIGABRT, &newvec, NULL);
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
14
SWIG/Tools/WAD/Wad/main.cxx
Normal file
14
SWIG/Tools/WAD/Wad/main.cxx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
extern "C" {
|
||||
#include "wad.h"
|
||||
}
|
||||
|
||||
/* This is a sick hack to force initialization upon loading */
|
||||
|
||||
class StartDebug {
|
||||
public:
|
||||
StartDebug() {
|
||||
wad_init();
|
||||
}
|
||||
};
|
||||
|
||||
static StartDebug s;
|
||||
270
SWIG/Tools/WAD/Wad/object.c
Normal file
270
SWIG/Tools/WAD/Wad/object.c
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* object.c
|
||||
*
|
||||
* This file provides access to raw object files and executables.
|
||||
* All memory management is done through mmap() to avoid the
|
||||
* use of malloc()/free()
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
#include <sys/mman.h>
|
||||
#include <ar.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static WadObject wad_objects[WAD_MAX_OBJECT]; /* Object file descriptor table */
|
||||
static int wad_obj_free[WAD_MAX_OBJECT]; /* Free object stack */
|
||||
static int wad_obj_nfree = 0; /* Num free object descriptors */
|
||||
static int wad_obj_init = 0; /* Initialized? */
|
||||
|
||||
/* Initialize internal memory management */
|
||||
static void
|
||||
init_object() {
|
||||
int i;
|
||||
if (wad_obj_init) return;
|
||||
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||
wad_objects[i].mptr = 0;
|
||||
wad_objects[i].mlen = 0;
|
||||
wad_objects[i].ptr = 0;
|
||||
wad_objects[i].len = 0;
|
||||
wad_objects[i].refcnt = 0;
|
||||
wad_objects[i].path[0] = 0;
|
||||
wad_obj_free[i] = i;
|
||||
wad_obj_nfree++;
|
||||
}
|
||||
wad_obj_init = 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_release()
|
||||
*
|
||||
* Done with the object.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_object_release(WadObject *wo) {
|
||||
int n;
|
||||
if (!wo) return;
|
||||
wo->refcnt--;
|
||||
if (wo->refcnt > 0) return;
|
||||
if (wo->mptr) {
|
||||
munmap(wo->mptr, wo->mlen);
|
||||
}
|
||||
wo->mptr = 0;
|
||||
wo->mlen = 0;
|
||||
wo->ptr = 0;
|
||||
wo->len = 0;
|
||||
wo->path[0] = 0;
|
||||
n = wo - wad_objects;
|
||||
wad_obj_free[wad_obj_nfree++] = n;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_load()
|
||||
*
|
||||
* Load an object file into memory using mmap. Returns 0 if the object does
|
||||
* not exist or if there are no more object descriptor slots
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadObject *
|
||||
wad_object_load(const char *path) {
|
||||
WadObject *wo;
|
||||
int nf;
|
||||
int fd;
|
||||
int i;
|
||||
if (!wad_obj_init) init_object();
|
||||
|
||||
/* printf("loading '%s'\n", path); */
|
||||
|
||||
/* See if the path has already been loaded */
|
||||
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||
if (strcmp(wad_objects[i].path,path) == 0) {
|
||||
wo = &wad_objects[i];
|
||||
wo->refcnt++;
|
||||
return wo;
|
||||
}
|
||||
}
|
||||
if (wad_obj_nfree == 0) {
|
||||
printf("wad_object_load: No more space!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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) {
|
||||
strncpy(wo->path, path, MAX_PATH);
|
||||
return wo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to open the requested pathname */
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) return 0; /* Doesn't exist */
|
||||
|
||||
nf = wad_obj_free[wad_obj_nfree-1];
|
||||
wo = wad_objects + nf;
|
||||
wad_obj_nfree--;
|
||||
|
||||
wo->refcnt = 1;
|
||||
strncpy(wo->path,path, MAX_PATH);
|
||||
wo->mlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
wo->mptr = mmap(NULL,wo->mlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
if (wo->mptr == MAP_FAILED) {
|
||||
perror("Whoa. Can't mmap.");
|
||||
wo->mptr = 0;
|
||||
wad_object_release(wo);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
wo->ptr = wo->mptr;
|
||||
wo->len = wo->mlen;
|
||||
return wo;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_arobject_load()
|
||||
*
|
||||
* Load an archive file object into memory using mmap.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadObject *
|
||||
wad_arobject_load(const char *arpath, const char *robjname) {
|
||||
WadObject *wo;
|
||||
int nf;
|
||||
int fd;
|
||||
int i;
|
||||
int arlen;
|
||||
char *arptr;
|
||||
struct ar_hdr *ah;
|
||||
int offset;
|
||||
int msize;
|
||||
char *strtab = 0;
|
||||
int sobjname;
|
||||
char objname[MAX_PATH];
|
||||
|
||||
strcpy(objname,robjname);
|
||||
strcat(objname,"/");
|
||||
sobjname = strlen(objname);
|
||||
if (!wad_obj_init) init_object();
|
||||
|
||||
if (wad_obj_nfree == 0) {
|
||||
printf("wad_object_load: No more space!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to open the requested archive name */
|
||||
fd = open(arpath, O_RDONLY);
|
||||
if (fd < 0) return 0; /* Doesn't exist */
|
||||
|
||||
nf = wad_obj_free[wad_obj_nfree-1];
|
||||
wo = wad_objects + nf;
|
||||
wad_obj_nfree--;
|
||||
wo->refcnt = 1;
|
||||
wo->ptr = 0;
|
||||
|
||||
arlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
arptr = (char *) mmap(NULL,arlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
if (arptr == MAP_FAILED) {
|
||||
perror("Whoa. Can't mmap.");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now take a look at the archive */
|
||||
if (strncmp(arptr,ARMAG,SARMAG) == 0) {
|
||||
/* printf("Got an archive\n"); */
|
||||
} else {
|
||||
printf("Not an archive file\n");
|
||||
goto fatal_error;
|
||||
}
|
||||
|
||||
/* Search the archive for the request member */
|
||||
strtab = 0;
|
||||
|
||||
offset = SARMAG;
|
||||
while (offset < arlen) {
|
||||
char mname[MAX_PATH];
|
||||
ah = (struct ar_hdr *) (arptr + offset);
|
||||
if (strncmp(ah->ar_name,"// ", 3) == 0) {
|
||||
strtab = arptr + offset + sizeof(struct ar_hdr);
|
||||
}
|
||||
msize = atoi(ah->ar_size);
|
||||
|
||||
offset += sizeof(struct ar_hdr);
|
||||
/* Try to figure out the filename */
|
||||
if ((ah->ar_name[0] == '/') && (isdigit(ah->ar_name[1]))) {
|
||||
int soff;
|
||||
char *e;
|
||||
/* Must be in the string offset table */
|
||||
soff = atoi(ah->ar_name+1);
|
||||
if (!strtab) {
|
||||
printf("Whoa. No string offset table\n");
|
||||
goto fatal_error;
|
||||
}
|
||||
e = strchr(strtab+soff,'\n');
|
||||
if (e) {
|
||||
strncpy(mname, strtab+soff, (e - (strtab+soff)));
|
||||
mname[e-(strtab+soff)] = 0;
|
||||
} else {
|
||||
mname[0] = 0;
|
||||
}
|
||||
} else {
|
||||
/* Name must be in the name field */
|
||||
strncpy(mname,ah->ar_name,16);
|
||||
mname[16] = 0;
|
||||
}
|
||||
|
||||
/* printf("ar_name = '%s', ar_size = '%0.10s'\n", mname, ah->ar_size); */
|
||||
/* Compare the names */
|
||||
if (strncmp(mname,objname,sobjname) == 0) {
|
||||
/* Leave the archive mapped in memory, but set a pointer to the member
|
||||
name */
|
||||
|
||||
wo->mptr = (void *) arptr;
|
||||
wo->mlen = arlen;
|
||||
wo->ptr = (void *) (arptr + offset);
|
||||
wo->len = msize;
|
||||
close(fd);
|
||||
return wo;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += msize;
|
||||
}
|
||||
|
||||
fatal_error:
|
||||
munmap(arptr,arlen);
|
||||
close(fd);
|
||||
wad_object_release(wo);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
163
SWIG/Tools/WAD/Wad/segment.c
Normal file
163
SWIG/Tools/WAD/Wad/segment.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* segment.c
|
||||
*
|
||||
* This file provides access to the virtual memory map of a process
|
||||
* including the location of the executable, data segments, shared
|
||||
* libraries, and memory mapped regions. This information is
|
||||
* obtained through /proc.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
#include <procfs.h>
|
||||
|
||||
|
||||
|
||||
/* The current segment is stored in statically allocated memory to avoid
|
||||
the use of malloc()/free(). If a caller wants to make a copy, that is
|
||||
their problem */
|
||||
|
||||
static WadSegment segment; /* Currently loaded segment */
|
||||
static int read_segment = 0;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_print()
|
||||
*
|
||||
* Print the contents of a memory segment. (Debugging)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_segment_print(WadSegment *s) {
|
||||
printf("Segment %x:::\n",s);
|
||||
printf(" mapname = %s\n", s->mapname);
|
||||
printf(" mappath = %s\n", s->mappath);
|
||||
printf(" vaddr = 0x%x\n", s->vaddr);
|
||||
printf(" size = %d\n", s->size);
|
||||
printf(" offset = %d\n", s->offset);
|
||||
printf(" flags = 0x%x\n", s->flags);
|
||||
printf(" identifier = %d\n", s->identifier);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_find()
|
||||
*
|
||||
* Try to find the virtual memory segment corresponding to a virtual address.
|
||||
* This overwrites the previously returned segment data.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadSegment *
|
||||
wad_segment_find(wadaddr_t addr) {
|
||||
char dirname[MAX_PATH];
|
||||
char filename[MAX_PATH];
|
||||
int fd;
|
||||
prmap_t pmap;
|
||||
int offset = 0;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
if (read_segment) {
|
||||
if ((addr >= segment.vaddr) && (addr < (segment.vaddr+segment.size))) return &segment;
|
||||
}
|
||||
|
||||
/* Set location in /proc */
|
||||
sprintf(dirname,"/proc/%d",getpid());
|
||||
|
||||
/* Try to load the virtual address map */
|
||||
sprintf(filename,"%s/map",dirname);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_segment = 0;
|
||||
while (1) {
|
||||
n = read(fd,&pmap,sizeof(prmap_t));
|
||||
if (n < 0) break;
|
||||
offset += n;
|
||||
if ((addr >= (wadaddr_t) pmap.pr_vaddr) && (addr <= (wadaddr_t) (pmap.pr_vaddr + pmap.pr_size))) {
|
||||
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
||||
strcpy(segment.mappath,dirname);
|
||||
strcat(segment.mappath,"/object/");
|
||||
strcat(segment.mappath,pmap.pr_mapname);
|
||||
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
||||
segment.size = pmap.pr_size;
|
||||
segment.offset = pmap.pr_offset;
|
||||
segment.flags = pmap.pr_mflags;
|
||||
segment.identifier = pmap.pr_shmid;
|
||||
segment.wad = offset;
|
||||
read_segment = 1;
|
||||
close(fd);
|
||||
return &segment;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_next()
|
||||
*
|
||||
* Read the next segment
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadSegment *wad_segment_next() {
|
||||
|
||||
char dirname[MAX_PATH];
|
||||
char filename[MAX_PATH];
|
||||
int fd;
|
||||
prmap_t pmap;
|
||||
int offset = 0;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
if (!read_segment) {
|
||||
segment.wad = 0;
|
||||
}
|
||||
|
||||
/* Set location in /proc */
|
||||
sprintf(dirname,"/proc/%d",getpid());
|
||||
|
||||
/* Try to load the virtual address map */
|
||||
sprintf(filename,"%s/map",dirname);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
||||
return 0;
|
||||
}
|
||||
if (lseek(fd, segment.wad, SEEK_SET) < 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
n = read(fd,&pmap,sizeof(prmap_t));
|
||||
if (n <= 0) {
|
||||
read_segment = 0;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
||||
strcpy(segment.mappath,dirname);
|
||||
strcat(segment.mappath,"/object/");
|
||||
strcat(segment.mappath,pmap.pr_mapname);
|
||||
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
||||
segment.size = pmap.pr_size;
|
||||
segment.offset = pmap.pr_offset;
|
||||
segment.flags = pmap.pr_mflags;
|
||||
segment.identifier = pmap.pr_shmid;
|
||||
segment.wad += n;
|
||||
read_segment = 1;
|
||||
close(fd);
|
||||
return &segment;
|
||||
}
|
||||
|
||||
WadSegment *
|
||||
wad_segment_first() {
|
||||
segment.wad = 0;
|
||||
read_segment = 0;
|
||||
return wad_segment_next();
|
||||
}
|
||||
332
SWIG/Tools/WAD/Wad/signal.c
Normal file
332
SWIG/Tools/WAD/Wad/signal.c
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* signal.c
|
||||
*
|
||||
* WAD signal handler.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "wad.h"
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
static char *strip_dir(char *name) {
|
||||
char *c;
|
||||
c = name + strlen(name);
|
||||
while (c != name) {
|
||||
if (*c == '/') {
|
||||
c++;
|
||||
return c;
|
||||
}
|
||||
c--;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Default callback
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_default_callback(int signo, void *framedata) {
|
||||
char *fd;
|
||||
WadFrame *f;
|
||||
switch(signo) {
|
||||
case SIGSEGV:
|
||||
printf("Segmentation fault.\n");
|
||||
break;
|
||||
case SIGBUS:
|
||||
printf("Bus error.\n");
|
||||
break;
|
||||
case SIGABRT:
|
||||
printf("Abort.\n");
|
||||
break;
|
||||
default:
|
||||
printf("Signal %d\n", signo);
|
||||
break;
|
||||
}
|
||||
fd = (char *) framedata;
|
||||
f = (WadFrame *) fd;
|
||||
while (f->size) {
|
||||
printf("#%-3d 0x%08x in %s()", f->frameno, f->pc, *(fd + f->sym_off) ? fd+f->sym_off : "?");
|
||||
if (strlen(fd+f->src_off)) {
|
||||
printf(" in '%s'", strip_dir(fd+f->src_off));
|
||||
if (f->line_number >= 0) {
|
||||
printf(", line %d", f->line_number);
|
||||
}
|
||||
} else {
|
||||
if (strlen(fd+f->obj_off)) {
|
||||
printf(" from '%s'", fd+f->obj_off);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
fd = fd + f->size;
|
||||
f = (WadFrame *) fd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform one level of stack unwinding */
|
||||
unsigned long *stack_unwind(unsigned long *sp) {
|
||||
unsigned long *new_sp;
|
||||
unsigned long ret_addr;
|
||||
int i;
|
||||
new_sp = (unsigned long *) *(sp+14);
|
||||
ret_addr = *(sp+15);
|
||||
return (unsigned long *) new_sp;
|
||||
}
|
||||
|
||||
/* Data structures for containing information about non-local returns */
|
||||
|
||||
typedef struct nonlocal {
|
||||
char symname[256];
|
||||
long value;
|
||||
struct nonlocal *next;
|
||||
} nonlocal;
|
||||
|
||||
static nonlocal *return_points = 0;
|
||||
|
||||
void wad_set_return(char *name, long value) {
|
||||
nonlocal *nl;
|
||||
nl = (nonlocal *) malloc(sizeof(nonlocal));
|
||||
strcpy(nl->symname,name);
|
||||
nl->value = value;
|
||||
nl->next = return_points;
|
||||
return_points = nl;
|
||||
}
|
||||
|
||||
static void (*sig_callback)(int signo, void *data) = 0;
|
||||
|
||||
void wad_set_callback(void (*s)(int,void *)) {
|
||||
sig_callback = s;
|
||||
}
|
||||
|
||||
/* This bit of nastiness is used to make a non-local return from the
|
||||
signal handler to a configurable location on the call stack. In a nutshell,
|
||||
this works by repeatedly calling "restore" to roll back the
|
||||
register windows and stack pointer. Then we fake a return value and
|
||||
return to the caller as if the function had actually completed
|
||||
normally. */
|
||||
|
||||
static int nlr_levels = 0;
|
||||
static int *volatile nlr_p = &nlr_levels;
|
||||
static long nlr_value = 0;
|
||||
|
||||
static void nonlocalret() {
|
||||
long a;
|
||||
|
||||
a = nlr_value;
|
||||
/* We never call this procedure as a function. This code
|
||||
causes an immediate return if someone does this */
|
||||
|
||||
asm("jmp %i7 + 8");
|
||||
asm("restore");
|
||||
|
||||
/* This is the real entry point */
|
||||
/* asm(".globl _returnsignal");*/
|
||||
asm(".type _returnsignal,2");
|
||||
asm("_returnsignal:");
|
||||
|
||||
while (*nlr_p > 0) {
|
||||
(*nlr_p)--;
|
||||
asm("restore");
|
||||
}
|
||||
|
||||
asm("sethi %hi(nlr_value), %o0");
|
||||
asm("or %o0, %lo(nlr_value), %o0");
|
||||
asm("ld [%o0], %i0");
|
||||
|
||||
asm("jmp %i7 + 8");
|
||||
asm("restore");
|
||||
asm(".size _returnsignal,(.-_returnsignal)");
|
||||
}
|
||||
|
||||
void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||
int current;
|
||||
greg_t *pc;
|
||||
greg_t *npc;
|
||||
greg_t *ret;
|
||||
greg_t *sp;
|
||||
int i;
|
||||
unsigned long *user_fp;
|
||||
unsigned long *addr;
|
||||
ucontext_t *context;
|
||||
unsigned long *p_sp; /* process stack pointer */
|
||||
unsigned long *p_pc; /* Process program counter */
|
||||
WadSegment *ws;
|
||||
WadObject *wo;
|
||||
int nlevels;
|
||||
int found = 0;
|
||||
void _returnsignal();
|
||||
int n = 0;
|
||||
char framefile[256];
|
||||
int ffile;
|
||||
WadFrame frame;
|
||||
void *framedata;
|
||||
int fsize = 0; /* Total frame size */
|
||||
sprintf(framefile,"/tmp/wad.%d", getpid());
|
||||
|
||||
/* Open the output file for the traceback */
|
||||
|
||||
ffile = open(framefile, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
|
||||
if (ffile < 0) {
|
||||
printf("can't open %s\n", framefile);
|
||||
}
|
||||
|
||||
context = (ucontext_t *) vcontext;
|
||||
|
||||
/* Get some information about the current context */
|
||||
pc = &((context->uc_mcontext).gregs[REG_PC]);
|
||||
npc = &((context->uc_mcontext).gregs[REG_nPC]);
|
||||
sp = &((context->uc_mcontext).gregs[REG_SP]);
|
||||
ret = &((context->uc_mcontext).gregs[REG_O7]);
|
||||
|
||||
/* Get some information out of the signal handler stack */
|
||||
user_fp = (unsigned long *) _get_fp(); /* Current frame pointer */
|
||||
addr = (unsigned long *) si->si_addr;
|
||||
|
||||
/* Try to do a stack traceback */
|
||||
nlevels = 0;
|
||||
p_pc = (unsigned long *) (*pc);
|
||||
p_sp = (unsigned long *) (*sp);
|
||||
|
||||
while (p_pc) {
|
||||
ws = wad_segment_find((wadaddr_t) p_pc);
|
||||
if (!ws) {
|
||||
printf("No segment found for %x\n", p_pc);
|
||||
} else {
|
||||
WadObject *wo;
|
||||
char *name;
|
||||
|
||||
int symsize = 0; /* Symbol size */
|
||||
int srcsize = 0;
|
||||
int objsize = 0;
|
||||
char *srcname = 0;
|
||||
char *objname = 0;
|
||||
char *symname = 0;
|
||||
int pad = 0;
|
||||
|
||||
unsigned long value;
|
||||
wo = wad_object_load(ws->mappath);
|
||||
if (strcmp(ws->mapname,"a.out") == 0) ws->vaddr= 0;
|
||||
name = wad_find_symbol(wo,(void *) p_pc, (unsigned long) ws->vaddr, &value);
|
||||
|
||||
/* Build up some information about the exception frame */
|
||||
frame.frameno = n;
|
||||
frame.pc = (long) p_pc;
|
||||
frame.sp = (long) p_sp;
|
||||
n++;
|
||||
if (name) {
|
||||
nonlocal *nl;
|
||||
symsize = strlen(name)+1;
|
||||
symname = name;
|
||||
nl = return_points;
|
||||
while (nl) {
|
||||
if (strcmp(name,nl->symname) == 0) {
|
||||
found = 1;
|
||||
nlr_value = nl->value;
|
||||
}
|
||||
nl = nl->next;
|
||||
}
|
||||
{
|
||||
WadDebug *wd;
|
||||
wd = wad_debug_info(wo,name, (unsigned long) p_pc - (unsigned long) ws->vaddr - value);
|
||||
if (wd) {
|
||||
srcname = wd->srcfile;
|
||||
srcsize = strlen(srcname)+1;
|
||||
objname = wd->objfile;
|
||||
objsize = strlen(objname)+1;
|
||||
frame.line_number = wd->line_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Build up the exception frame object */
|
||||
frame.size = sizeof(WadFrame) + symsize + srcsize + objsize;
|
||||
pad = 8 - (frame.size % 8);
|
||||
frame.size += pad;
|
||||
|
||||
frame.data[0] = 0;
|
||||
frame.data[1] = 0;
|
||||
|
||||
/* Build up the offsets */
|
||||
if (!name) {
|
||||
frame.sym_off = sizeof(WadFrame) - 8;
|
||||
frame.src_off = sizeof(WadFrame) - 8;
|
||||
frame.obj_off = sizeof(WadFrame) - 8;
|
||||
} else {
|
||||
frame.sym_off = sizeof(WadFrame);
|
||||
frame.src_off = sizeof(WadFrame)+symsize;
|
||||
frame.obj_off = sizeof(WadFrame)+symsize+srcsize;
|
||||
}
|
||||
write(ffile,&frame,sizeof(WadFrame));
|
||||
if (symname) {
|
||||
write(ffile,symname,symsize);
|
||||
write(ffile,srcname,srcsize);
|
||||
write(ffile,objname,objsize);
|
||||
}
|
||||
write(ffile,frame.data, pad);
|
||||
wad_object_release(wo);
|
||||
}
|
||||
if (!found) nlevels++;
|
||||
p_pc = (unsigned long *) *(p_sp+15);
|
||||
p_sp = stack_unwind(p_sp);
|
||||
if (found) break;
|
||||
}
|
||||
/* Write terminator */
|
||||
frame.size = 0;
|
||||
write(ffile,&frame,sizeof(WadFrame));
|
||||
close(ffile);
|
||||
|
||||
if (found) {
|
||||
nlr_levels = nlevels - 1;
|
||||
} else {
|
||||
nlr_levels = 0;
|
||||
}
|
||||
|
||||
/* Go mmap the debug file */
|
||||
ffile = open(framefile, O_RDONLY, 0644);
|
||||
fsize = lseek(ffile,0,SEEK_END);
|
||||
lseek(ffile,0,SEEK_SET);
|
||||
|
||||
framedata = mmap(NULL, fsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
||||
|
||||
if (sig_callback) {
|
||||
(*sig_callback)(sig,framedata);
|
||||
} else {
|
||||
/* No signal handler defined. Go invoke the default */
|
||||
wad_default_callback(sig, framedata);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
munmap(framedata,fsize);
|
||||
close(ffile);
|
||||
unlink(framefile);
|
||||
if (nlr_levels > 0) {
|
||||
*(pc) = (greg_t) _returnsignal;
|
||||
*(npc) = *(pc) + 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
asm_stuff()
|
||||
{
|
||||
asm(" .globl _get_sp");
|
||||
asm("_get_sp:");
|
||||
asm(" retl");
|
||||
asm(" mov %sp, %o0");
|
||||
asm(" .globl _get_fp");
|
||||
asm("_get_fp:");
|
||||
asm(" retl");
|
||||
asm(" mov %fp, %o0");
|
||||
}
|
||||
|
||||
127
SWIG/Tools/WAD/Wad/stab.c
Normal file
127
SWIG/Tools/WAD/Wad/stab.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* stab.c
|
||||
*
|
||||
* This file reads stabs data and looks for various properties of a
|
||||
* given symbol.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
|
||||
/* stabs data structure. This appears to be somewhat universal. I ripped
|
||||
it out of the Sun C compiler include directory */
|
||||
|
||||
typedef struct Stab {
|
||||
unsigned n_strx; /* index into file string table */
|
||||
unsigned char n_type; /* type flag (N_TEXT,..) */
|
||||
char n_other; /* used by N_SLINE stab */
|
||||
short n_desc; /* see stabs documentation */
|
||||
unsigned n_value; /* value of symbol (or sdb offset) */
|
||||
} Stab;
|
||||
|
||||
/* Match a stabs symbol name against a stab string (which may contain
|
||||
extra information delimetered by a colon */
|
||||
|
||||
int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||
/* printf("matching: %s -> %s\n", symbol, stabtext); */
|
||||
if (strcmp(symbol,stabtext) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((strncmp(symbol, stabtext, slen) == 0) && (*(stabtext+slen) == ':')) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given a stabs data segment (obtained somehow), this function tries to
|
||||
collect as much information as it can about a given symbol.
|
||||
|
||||
s points to the stab data. stabstr points to the stab string section,
|
||||
ns is the size of the stab section, symbol is the item of interest,
|
||||
and offset is the offset in the object file of the symbol
|
||||
|
||||
Note: this function may recurse upon itself if there are multiple
|
||||
stabs sections
|
||||
*/
|
||||
|
||||
static WadDebug debug;
|
||||
|
||||
WadDebug *
|
||||
wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long offset) {
|
||||
Stab *s;
|
||||
int ns;
|
||||
int infunc;
|
||||
int slen;
|
||||
int i;
|
||||
char *file;
|
||||
int chk = 0;
|
||||
|
||||
s = (Stab *) sp; /* Stabs data */
|
||||
ns = size/sizeof(Stab); /* number of stabs */
|
||||
slen = strlen(symbol);
|
||||
|
||||
/* Reset the debug information section */
|
||||
debug.found = 0;
|
||||
debug.srcfile[0] = 0;
|
||||
debug.objfile[0] = 0;
|
||||
debug.line_number = -1;
|
||||
debug.nargs = 0;
|
||||
for (i = 0; i < ns; i++, s++) {
|
||||
/*#define DEBUG_DEBUG */
|
||||
#ifdef DEBUG_DEBUG
|
||||
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);
|
||||
#endif
|
||||
#undef DEBUG_DEBUG
|
||||
if (s->n_type == 0) {
|
||||
/* New stabs section. We need to be a little careful here. Do a recursive
|
||||
search of the subsection. */
|
||||
WadDebug *wd;
|
||||
#ifdef DEBUG_DEBUG
|
||||
printf("Section: %d stabs.\n", s->n_desc);
|
||||
#endif
|
||||
wd = wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
stabstr += s->n_value; /* Update the string table location*/
|
||||
i += s->n_desc;
|
||||
s += s->n_desc;
|
||||
debug.objfile[0] = 0;
|
||||
debug.srcfile[0] = 0;
|
||||
debug.line_number = -1;
|
||||
debug.found = 0;
|
||||
} else if (s->n_type == 0x64) {
|
||||
if (debug.found) return &debug; /* New file and we already found what we wanted */
|
||||
/* Source file specification */
|
||||
/* Look for directory */
|
||||
file = stabstr+s->n_strx;
|
||||
if (file[strlen(file)] == '/') {
|
||||
strcpy(debug.srcfile,file);
|
||||
} else {
|
||||
strcat(debug.srcfile,file);
|
||||
}
|
||||
debug.objfile[0] = 0;
|
||||
} else if (s->n_type == 0x38) {
|
||||
/* Object file specifier */
|
||||
if (debug.objfile[0]) {
|
||||
strcat(debug.objfile,"/");
|
||||
}
|
||||
strcat(debug.objfile,stabstr+s->n_strx);
|
||||
} else if (s->n_type == 0x24) {
|
||||
if (match_stab_symbol(symbol, stabstr+s->n_strx, slen)) {
|
||||
infunc = 1;
|
||||
debug.found = 1;
|
||||
} else {
|
||||
infunc = 0;
|
||||
}
|
||||
} else if (debug.found && (s->n_type == 0x44) && (infunc)) {
|
||||
if (s->n_value <= offset) {
|
||||
debug.line_number = s->n_desc;
|
||||
} else return &debug;
|
||||
}
|
||||
}
|
||||
if (debug.found) return &debug;
|
||||
return 0;
|
||||
}
|
||||
14
SWIG/Tools/WAD/main.cxx
Normal file
14
SWIG/Tools/WAD/main.cxx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
extern "C" {
|
||||
#include "wad.h"
|
||||
}
|
||||
|
||||
/* This is a sick hack to force initialization upon loading */
|
||||
|
||||
class StartDebug {
|
||||
public:
|
||||
StartDebug() {
|
||||
wad_init();
|
||||
}
|
||||
};
|
||||
|
||||
static StartDebug s;
|
||||
Loading…
Add table
Add a link
Reference in a new issue