Initial revision

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@931 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-10-28 14:51:41 +00:00
commit 41c6156e1d
14 changed files with 1556 additions and 0 deletions

View 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
View 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

View 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.
* ----------------------------------------------------------------------------- */

View 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
View 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

View 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
View 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
View 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;
}

View 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
View 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;
}

View 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
View 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
View 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
View 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;