*** empty log message ***

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@936 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-10-29 19:03:46 +00:00
commit 8cd58c6cf1
9 changed files with 956 additions and 216 deletions

View file

@ -1,14 +1,34 @@
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
SRCS = default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
OBJS = default.o stack.o stab.o elf.o object.o signal.o segment.o init.o main.o
INCLUDE = -I../Include
PYINCLUDE = -I/usr/local/include/python2.0
TCLINCLUDE = -I/usr/local/include
all::
CC -Kpic -c $(INCLUDE) main.cxx
cc -c $(INCLUDE) $(SRCS)
CC -G $(OBJS) -o libwad.so
cp libwad.so ..
python::
cc -c $(INCLUDE) $(SRCS)
CC -Kpic -c $(INCLUDE) $(PYINCLUDE) wadpy.cxx
CC -G $(OBJS) wadpy.o -o wadmodule.so
cp wadmodule.so libwadpy.so
cp libwadpy.so ..
tcl::
cc -c $(INCLUDE) $(SRCS)
CC -Kpic -c $(INCLUDE) $(TCLINCLUDE) wadtcl.cxx
CC -G $(OBJS) wadtcl.o -o wad.so
cp wad.so libwadtcl.so
cp libwadtcl.so ..
debug::
cc -g debug.c $(INCLUDE) -L. -R. -lwad
wc::
wc $(SRCS)

View file

@ -0,0 +1,237 @@
/* -----------------------------------------------------------------------------
* default.c
*
* Default signal handler. Just prints a stack trace and returns.
*
* 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>
/* This function tries to produce some kind of sensible argument
string for a stack frame. If no debugging information is available,
we'll just dump the %i0-%i5 registers in hex. If debugging information
is available, we'll try to do something a little more sensible */
char *wad_arg_string(WadFrame *frame) {
static char str[1024];
static char temp[64];
WadParm *wp;
long *stack;
long *nextstack;
int i;
WadFrame *nf;
if (frame->size)
nf = (WadFrame *) (((char *) frame) + frame->size);
else
nf = 0;
if (nf)
nextstack = STACK(nf);
else
nextstack = 0;
str[0] = 0;
stack = STACK(frame);
if (frame->nargs < 0) {
/* No argument information is available. In this case
we will simply dump the %in registers. (assuming we can
find them) */
for (i = 0; i < 6; i++) {
sprintf(temp,"0x%x", stack[8+i]);
strcat(str,temp);
if (i < 5)
strcat(str,",");
}
} else {
/* We were able to get some argument information out the debugging table */
wp = ARGUMENTS(frame);
for (i = 0; i < frame->nargs; i++, wp++) {
strcat(str,wp->name);
strcat(str,"=");
/* Try to figure out where the value is */
if ((wp->loc == PARM_STACK) && nf) {
/* Parameter is located on the call stack */
unsigned long argloc = wp->value; /* Location relative to frame pointer */
if ((argloc & 0x3) == 0) {
/* Is word aligned, make some kind of attempt to print this out */
unsigned long *p = (unsigned long *) (((char *) nextstack) + argloc);
sprintf(temp,"0x%x", *p);
strcat(str,temp);
}
} else if (wp->loc == PARM_REGISTER) {
if ((wp->value >= 24) && (wp->value < 32)) {
/* Value is located in the %in registers */
sprintf(temp,"0x%x", stack[wp->value - 16]);
strcat(str,temp);
} else if ((wp->value >= 8) && (wp->value < 16)) {
/* Value is located in the %on registers */
sprintf(temp,"0x%x", frame->regs[wp->value]);
strcat(str,temp);
} else if ((wp->value >= 16) && (wp->value < 24)) {
/* Value has been placed in the %ln registers */
sprintf(temp,"0x%x", frame->regs[wp->value - 16]);
strcat(str,temp);
}
}
if (i < (frame->nargs-1)) strcat(str,",");
}
}
return str;
}
char *wad_strip_dir(char *name) {
char *c;
c = name + strlen(name);
while (c != name) {
if (*c == '/') {
c++;
return c;
}
c--;
}
return name;
}
static char *src_file = 0;
static int src_len = 0;
/* Opens up a source file and tries to locate a specific line number */
char *wad_load_source(char *path, int line) {
int fd;
char *c;
char *start;
int n;
fd = open(path, O_RDONLY);
if (fd < 0) return 0;
src_len = lseek(fd, 0, SEEK_END);
lseek(fd,0,SEEK_SET);
src_file = (char *)mmap(NULL,src_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (src_file == MAP_FAILED) {
close(fd);
return 0;
}
close(fd);
n = 0;
start = src_file;
c = src_file;
while (n < src_len) {
if (*c == '\n') {
line--;
if (line == 0) {
return start;
}
start = c+1;
}
c++;
n++;
}
munmap(src_file,src_len);
src_file = 0;
return 0;
}
void wad_release_source() {
if (src_file)
munmap(src_file,src_len);
}
/* -----------------------------------------------------------------------------
* Default callback
* ----------------------------------------------------------------------------- */
void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
char *fd;
WadFrame *f;
WadFrame *fline = 0;
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;
/* Find the last exception frame */
while (!f->last) {
fd = fd + f->size;
f = (WadFrame *) fd;
}
/* Now work backwards */
fd = fd - f->lastsize;
f = (WadFrame *) fd;
while (1) {
printf("#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, *(fd + f->sym_off) ? fd+f->sym_off : "?",
wad_arg_string(f));
if (strlen(fd+f->src_off)) {
printf(" in '%s'", wad_strip_dir(fd+f->src_off));
if (f->line_number > 0) {
printf(", line %d", f->line_number);
fline = f;
}
} else {
if (strlen(fd+f->obj_off)) {
printf(" from '%s'", fd+f->obj_off);
}
}
printf("\n");
if (!f->lastsize) break;
fd = fd - f->lastsize;
f = (WadFrame *) fd;
}
if (fline) {
int first;
int last;
char *line, *c;
int i;
first = fline->line_number - 2;
last = fline->line_number + 2;
if (first < 1) first = 1;
line = wad_load_source(SRCFILE(fline),first);
if (line) {
printf("\n%s, line %d\n\n", SRCFILE(fline),fline->line_number);
for (i = first; i <= last; i++) {
if (i == fline->line_number) printf(" => ");
else printf(" ");
c = strchr(line,'\n');
if (c) {
*c = 0;
printf("%s\n",line);
*c = '\n';
} else {
printf("%s\n",line);
break;
}
line = c+1;
}
wad_release_source();
printf("\n");
}
}
wad_release_trace();
}

View file

@ -307,7 +307,7 @@ wad_elf_debug_info(WadObject *wo, char *symbol, unsigned long offset) {
wd = wad_debug_info(wo1,symbol,offset);
wad_object_release(wo1);
} else {
printf("couldn't load %s\n", objfile);
/* printf("couldn't load %s\n", objfile); */
}
if (!wd) return wad_search_stab(stab,stabsize,stabstr,symbol,offset);
return wd;

View file

@ -78,7 +78,7 @@ wad_segment_find(wadaddr_t addr) {
read_segment = 0;
while (1) {
n = read(fd,&pmap,sizeof(prmap_t));
if (n < 0) break;
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);

View file

@ -15,72 +15,6 @@
#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 {
@ -100,9 +34,9 @@ void wad_set_return(char *name, long value) {
return_points = nl;
}
static void (*sig_callback)(int signo, void *data) = 0;
static void (*sig_callback)(int signo, WadFrame *data, char *ret) = 0;
void wad_set_callback(void (*s)(int,void *)) {
void wad_set_callback(void (*s)(int,WadFrame *,char *ret)) {
sig_callback = s;
}
@ -117,6 +51,11 @@ static int nlr_levels = 0;
static int *volatile nlr_p = &nlr_levels;
static long nlr_value = 0;
/* Set the return value from another module */
void wad_set_return_value(long value) {
nlr_value = value;
}
static void nonlocalret() {
long a;
@ -147,37 +86,19 @@ static void nonlocalret() {
}
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;
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;
unsigned long p_sp; /* process stack pointer */
unsigned long p_pc; /* Process program counter */
int nlevels = 0;
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);
}
WadFrame *frame, *origframe;
char *framedata;
char *retname = 0;
context = (ucontext_t *) vcontext;
@ -185,103 +106,44 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
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;
addr = (unsigned long) si->si_addr;
p_pc = (unsigned long) (*pc);
p_sp = (unsigned long) (*sp);
/* 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;
frame = wad_stack_trace(p_pc, p_sp, 0);
origframe =frame;
if (!frame) {
/* We're really hosed here */
return;
}
/* Write terminator */
frame.size = 0;
write(ffile,&frame,sizeof(WadFrame));
close(ffile);
/* Walk the exception frames and try to find a return point */
framedata = (char *) frame;
while (frame->size) {
nonlocal *nl = return_points;
nl = return_points;
while (nl) {
if (strcmp(framedata + frame->sym_off,nl->symname) == 0) {
found = 1;
nlr_value = nl->value;
retname = nl->symname;
break;
}
nl = nl->next;
}
framedata = framedata + frame->size;
frame = (WadFrame *) framedata;
if (found) {
frame->last = 1; /* Cut off top of the stack trace */
break;
}
nlevels++;
}
if (found) {
nlr_levels = nlevels - 1;
@ -289,44 +151,20 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
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);
(*sig_callback)(sig,origframe,retname);
} else {
/* No signal handler defined. Go invoke the default */
wad_default_callback(sig, framedata);
wad_default_callback(sig, origframe,retname);
}
/* 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");
}

View file

@ -113,13 +113,48 @@ wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long o
if (match_stab_symbol(symbol, stabstr+s->n_strx, slen)) {
infunc = 1;
debug.found = 1;
debug.nargs = 0;
} else {
infunc = 0;
}
} else if (debug.found && (s->n_type == 0x44) && (infunc)) {
/* Line number location */
if (s->n_value <= offset) {
debug.line_number = s->n_desc;
} else return &debug;
} else if (debug.found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
/* Parameter counting */
char *pname;
char *c;
int len;
pname = stabstr+s->n_strx;
c = strchr(pname,':');
if (c) {
len = (c-pname);
} else {
len = strlen(pname);
}
/* Check if already used */
/* In this case, the first stab simply identifies an argument. The second
one identifies its location for the debugger */
if (debug.nargs > 0) {
if (strcmp(debug.parms[debug.nargs-1].name, pname) == 0)
debug.nargs--;
}
strncpy(debug.parms[debug.nargs].name,pname,len);
debug.parms[debug.nargs].name[len] = 0;
if (s->n_type == 0x40)
debug.parms[debug.nargs].loc = PARM_REGISTER;
else
debug.parms[debug.nargs].loc = PARM_STACK;
debug.parms[debug.nargs].value = s->n_value;
debug.nargs++;
}
}
if (debug.found) return &debug;

281
SWIG/Tools/WAD/Wad/stack.c Normal file
View file

@ -0,0 +1,281 @@
/* -----------------------------------------------------------------------------
* stack.c
*
* This file is used to unwind the C call stack.
*
* 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/types.h>
#include <sys/mman.h>
/* Given a stack pointer, this function performs a single level of stack
unwinding */
static void
stack_unwind(unsigned long *sp, unsigned long *pc) {
*pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
*sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
}
static void *trace_addr = 0;
static int trace_len = 0;
/* Perform a stack unwinding given the current value of the pc, stack pointer,
and frame pointer. Returns a pointer to a wad exception frame structure
which is actually a large memory mapped file. */
WadFrame *
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
int i;
WadSegment *ws;
WadObject *wo;
WadFrame frame;
WadDebug *wd;
int nlevels;
char framefile[256];
int ffile;
unsigned long p_pc;
unsigned long p_sp;
unsigned long p_lastsp;
int n = 0;
int lastsize = 0;
int firstframe = 1;
/* Open the frame file for output */
sprintf(framefile,"/tmp/wad.%d", getpid());
ffile = open(framefile, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (ffile < 0) {
printf("can't open %s\n", framefile);
return 0;
}
/* Try to do a stack traceback */
nlevels = 0;
p_pc = pc;
p_sp = sp;
while (p_sp) {
/* Add check for stack validity here */
ws = wad_segment_find((wadaddr_t) p_sp);
if (!ws) {
/* If the stack is bad, we are really hosed here */
break;
}
ws = wad_segment_find((wadaddr_t) p_pc);
{
int symsize = 0;
int srcsize = 0;
int objsize = 0;
int stacksize = 0;
int argsize = 0;
char *srcname = 0;
char *objname = 0;
char *symname = 0;
int pad = 0;
unsigned long value;
/* Try to load the object file for this address */
if (ws) {
wo = wad_object_load(ws->mappath);
/* Special hack needed for base address */
if (strcmp(ws->mapname,"a.out") == 0) ws->vaddr= 0;
}
else {
wo = 0;
}
/* Try to find the symbol corresponding to this PC */
if (wo)
symname = wad_find_symbol(wo,(void *) p_pc, (unsigned long) ws->vaddr, &value);
else
symname = 0;
/* Build up some information about the exception frame */
frame.frameno = n;
frame.last = 0;
frame.lastsize = lastsize;
frame.pc = p_pc;
frame.sp = p_sp;
frame.nargs = -1;
frame.arg_off = 0;
n++;
if (symname) {
symsize = strlen(symname)+1;
/* Try to gather some debugging information about this symbol */
wd = wad_debug_info(wo,symname, p_pc - (unsigned long) ws->vaddr - value);
if (wd) {
srcname = wd->srcfile;
srcsize = strlen(srcname)+1;
objname = wd->objfile;
objsize = strlen(objname)+1;
frame.nargs = wd->nargs;
if (wd->nargs > 0) {
argsize = sizeof(WadParm)*wd->nargs;
}
/*
if (wd->nargs >=0) {
int i;
printf("%s\n",symname);
for (i = 0; i < wd->nargs; i++) {
printf(" [%d] = '%s', %d, %d\n", i, wd->parms[i].name, wd->parms[i].type, wd->parms[i].value);
}
}
*/
frame.line_number = wd->line_number;
}
}
/* Before unwinding the stack, copy the locals and %o registers from previous frame */
if (!firstframe) {
int i;
long *lsp = (long *) p_lastsp;
for (i = 0; i < 16; i++) {
/* printf("regs[%d] = 0x%x\n", lsp[i]); */
frame.regs[i] = lsp[i];
}
}
firstframe = 0;
/* Determine stack frame size */
p_lastsp = p_sp;
stack_unwind(&p_sp, &p_pc);
if (p_sp) {
stacksize = p_sp - p_lastsp;
} else {
stacksize = 0xffbf0000 - p_lastsp; /* Sick hack alert. Need to get stack top from somewhere */
}
/* Set the frame pointer and stack size */
frame.fp = p_sp;
frame.stack_size = stacksize;
/* Build the exception frame object we'll write */
frame.size = sizeof(WadFrame) + symsize + srcsize + objsize + stacksize + argsize;
pad = 8 - (frame.size % 8);
frame.size += pad;
frame.data[0] = 0;
frame.data[1] = 0;
/* Build up the offsets */
if (!symname) {
frame.sym_off = sizeof(WadFrame) - 8;
frame.src_off = sizeof(WadFrame) - 8;
frame.obj_off = sizeof(WadFrame) - 8;
frame.stack_off = sizeof(WadFrame) + argsize;
frame.arg_off = 0;
} else {
frame.arg_off = sizeof(WadFrame);
frame.stack_off = sizeof(WadFrame) + argsize;
frame.sym_off = frame.stack_off + stacksize;
frame.src_off = frame.sym_off + symsize;
frame.obj_off = frame.src_off + srcsize;
}
write(ffile,&frame,sizeof(WadFrame));
/* Write the argument data */
if (argsize > 0) {
write(ffile, (void *) wd->parms, argsize);
}
/* Write the stack data */
if (stacksize > 0) {
write(ffile, (void *) p_lastsp, stacksize);
}
if (symname) {
write(ffile,symname,symsize);
write(ffile,srcname,srcsize);
write(ffile,objname,objsize);
}
write(ffile,frame.data, pad);
lastsize = frame.size;
if (wo)
wad_object_release(wo);
}
}
/* Write terminator */
frame.size = 0;
frame.last = 1;
frame.lastsize = lastsize;
write(ffile,&frame,sizeof(WadFrame));
close(ffile);
/* mmap the debug file back into memory */
ffile = open(framefile, O_RDONLY, 0644);
trace_len = lseek(ffile,0,SEEK_END);
lseek(ffile,0,SEEK_SET);
trace_addr = mmap(NULL, trace_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
close(ffile);
return (WadFrame *) trace_addr;
}
void wad_release_trace() {
char name[256];
munmap(trace_addr, trace_len);
sprintf(name,"/tmp/wad.%d", getpid());
unlink(name);
trace_addr = 0;
trace_len = 0;
}
/* This function steals an argument out of a frame further up the call stack :-) */
long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
char *fd;
long *regs;
WadFrame *lastf = 0;
fd = (char *) f;
*error = 0;
/* Start searching */
while (f->size) {
if (strcmp(SYMBOL(f),symbol) == 0) {
/* Got a match */
if (lastf) {
regs = STACK(f);
return regs[8+argno];
}
}
lastf = f;
fd = fd + f->size;
f = (WadFrame *) fd;
}
*error = -1;
return 0;
}
long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
char *fd;
long *regs;
WadFrame *lastf = 0;
fd = (char *) f;
*error = 0;
/* Start searching */
while (f->size) {
if (strcmp(SYMBOL(f),symbol) == 0) {
/* Got a match */
if (lastf) {
regs = STACK(lastf);
return regs[8+argno];
}
}
lastf = f;
fd = fd + f->size;
f = (WadFrame *) fd;
}
*error = -1;
return 0;
}

View file

@ -0,0 +1,174 @@
/* -----------------------------------------------------------------------------
* wadpy.cxx
*
* Dynamically loadable python module for wad.
*
* 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 "Python.h"
#include "wad.h"
#include <signal.h>
/* These are the python exception objects we will add
SegFault, BusError, AbortError */
static PyObject *segfault_exc = 0;
static PyObject *buserror_exc = 0;
static PyObject *abort_exc = 0;
/* Handler function */
static void handler(int signo, WadFrame *frame, char *ret) {
static char message[65536];
static char temp[1024];
int len = 0;
PyObject *type;
char *name;
char *fd;
WadFrame *f;
WadFrame *fline = 0;
if (!ret) {
wad_default_callback(signo, frame, ret);
return;
}
strcpy(message,"[ C stack trace ]\n\n");
switch(signo) {
case SIGSEGV:
type = segfault_exc;
break;
case SIGBUS:
type = buserror_exc;
break;
case SIGABRT:
type = abort_exc;
break;
default:
type = PyExc_RuntimeError;
break;
}
fd = (char *) frame;
f = (WadFrame *) fd;
/* Find the last exception frame */
while (!f->last) {
fd = fd + f->size;
f = (WadFrame *) fd;
}
/* Now work backwards */
fd = fd - f->lastsize;
f = (WadFrame *) fd;
while (1) {
sprintf(temp,"#%-3d 0x%08x in ", f->frameno, f->pc);
strcat(message,temp);
strcat(message,*(fd + f->sym_off) ? fd+f->sym_off : "?");
strcat(message,"(");
strcat(message,wad_arg_string(f));
strcat(message,")");
if (strlen(SRCFILE(f))) {
strcat(message," in '");
strcat(message, wad_strip_dir(SRCFILE(f)));
strcat(message,"'");
if (f->line_number > 0) {
sprintf(temp,", line %d", f->line_number);
strcat(message,temp);
fline = f;
}
} else {
if (strlen(fd+f->obj_off)) {
strcat(message," from '");
strcat(message, wad_strip_dir(OBJFILE(f)));
strcat(message,"'");
}
}
strcat(message,"\n");
if (!f->lastsize) break;
fd = fd - f->lastsize;
f = (WadFrame *) fd;
}
if (fline) {
int first;
int last;
char *line, *c;
int i;
first = fline->line_number - 2;
last = fline->line_number + 2;
if (first < 1) first = 1;
line = wad_load_source(SRCFILE(fline),first);
if (line) {
strcat(message,"\n");
strcat(message, SRCFILE(fline));
sprintf(temp,", line %d\n\n", fline->line_number);
strcat(message, temp);
for (i = first; i <= last; i++) {
if (i == fline->line_number) strcat(message," => ");
else strcat(message," ");
c = strchr(line,'\n');
if (c) {
*c = 0;
strcat(message,line);
strcat(message,"\n");
*c = '\n';
} else {
strcat(message,line);
strcat(message,"\n");
break;
}
line = c+1;
}
wad_release_source();
strcat(message,"\n");
}
}
PyErr_SetString(type, message);
wad_release_trace();
}
static void pywadinit() {
PyObject *d, *m;
m = PyImport_ImportModule((char *)"__builtin__");
d = PyModule_GetDict(m);
printf("WAD Enabled\n");
segfault_exc = PyErr_NewException((char *)"exceptions.SegFault", NULL, NULL);
PyDict_SetItemString(d,(char *)"SegFault",segfault_exc);
buserror_exc = PyErr_NewException((char *)"exceptions.BusError", NULL, NULL);
PyDict_SetItemString(d,(char *)"BusError",buserror_exc);
abort_exc = PyErr_NewException((char*)"exceptions.AbortError", NULL, NULL);
PyDict_SetItemString(d,(char *)"AbortError",abort_exc);
wad_init();
wad_set_callback(handler);
wad_set_return((char *)"call_builtin",0);
wad_set_return((char *)"_PyImport_LoadDynamicModule",0);
wad_set_return((char *)"PyEval_EvalCode",0);
wad_set_return((char *)"PyObject_GetAttr",0);
}
/* This hack is used to auto-initialize wad regardless of whether we are
used as an imported module or as a link-library for another module */
class wadinitializer {
public:
wadinitializer() {
pywadinit();
}
};
static wadinitializer wi;
static PyMethodDef wadmethods[] = {
{0,0},
};
extern "C"
void initwad() {
Py_InitModule((char *)"wad",wadmethods);
}

View file

@ -0,0 +1,155 @@
/* -----------------------------------------------------------------------------
* wadtcl.cxx
*
* Dynamically loadable Tcl module for wad.
*
* 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 <tcl.h>
#include "wad.h"
#include <signal.h>
/* Handler function */
static void handler(int signo, WadFrame *frame, char *ret) {
static char message[65536];
static char temp[1024];
int len = 0;
char *name;
char *fd;
WadFrame *f;
WadFrame *fline = 0;
Tcl_Interp *interp;
int err;
char *type;
if (!ret) {
wad_default_callback(signo, frame, ret);
return;
}
strcpy(message,"[ C stack trace ]\n\n");
switch(signo) {
case SIGSEGV:
type = "Segmentation fault.";
break;
case SIGBUS:
type = "Bus error.";
break;
case SIGABRT:
type = "Abort.";
break;
default:
break;
}
fd = (char *) frame;
f = (WadFrame *) fd;
/* Find the last exception frame */
while (!f->last) {
fd = fd + f->size;
f = (WadFrame *) fd;
}
/* Now work backwards */
fd = fd - f->lastsize;
f = (WadFrame *) fd;
while (1) {
sprintf(temp,"#%-3d 0x%08x in ", f->frameno, f->pc);
strcat(message,temp);
strcat(message,*(fd + f->sym_off) ? fd+f->sym_off : "?");
strcat(message,"()");
if (strlen(SRCFILE(f))) {
strcat(message," in '");
strcat(message, wad_strip_dir(SRCFILE(f)));
strcat(message,"'");
if (f->line_number > 0) {
sprintf(temp,", line %d", f->line_number);
strcat(message,temp);
fline = f;
}
} else {
if (strlen(fd+f->obj_off)) {
strcat(message," from '");
strcat(message, wad_strip_dir(OBJFILE(f)));
strcat(message,"'");
}
}
strcat(message,"\n");
if (!f->lastsize) break;
fd = fd - f->lastsize;
f = (WadFrame *) fd;
}
if (fline) {
int first;
int last;
char *line, *c;
int i;
first = fline->line_number - 2;
last = fline->line_number + 2;
if (first < 1) first = 1;
line = wad_load_source(SRCFILE(fline),first);
if (line) {
strcat(message,"\n");
strcat(message, SRCFILE(fline));
sprintf(temp,", line %d\n\n", fline->line_number);
strcat(message, temp);
for (i = first; i <= last; i++) {
if (i == fline->line_number) strcat(message," => ");
else strcat(message," ");
c = strchr(line,'\n');
if (c) {
*c = 0;
strcat(message,line);
strcat(message,"\n");
*c = '\n';
} else {
strcat(message,line);
strcat(message,"\n");
break;
}
line = c+1;
}
wad_release_source();
strcat(message,"\n");
}
}
/* Try to get the Tcl interpreter through magic */
if (ret) {
interp = (Tcl_Interp *) wad_steal_outarg(frame,ret,1,&err);
if (err == 0) {
Tcl_SetResult(interp,type,TCL_STATIC);
Tcl_AddErrorInfo(interp,message);
}
}
wad_release_trace();
}
static void tclwadinit() {
printf("WAD Enabled\n");
wad_init();
wad_set_callback(handler);
wad_set_return("TclExecuteByteCode", TCL_ERROR);
wad_set_return("EvalObjv", TCL_ERROR);
}
/* This hack is used to auto-initialize wad regardless of whether we are
used as an imported module or as a link-library for another module */
class wadinitializer {
public:
wadinitializer() {
tclwadinit();
}
};
static wadinitializer wi;
extern "C"
int Wad_Init(Tcl_Interp *interp) {
return TCL_OK;
}