From 5cd99377b5cbc918ce9894d2f253b2cbdfbd62f7 Mon Sep 17 00:00:00 2001 From: Dave Beazley Date: Tue, 2 Jan 2001 17:43:45 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@978 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/Tools/WAD/Include/wad.h | 2 + SWIG/Tools/WAD/Makefile | 13 +-- SWIG/Tools/WAD/Makefile.in | 9 ++- SWIG/Tools/WAD/README | 4 + SWIG/Tools/WAD/Test/Makefile.in | 19 +++++ SWIG/Tools/WAD/Test/debug.c | 97 +++++++++++++++++++++++ SWIG/Tools/WAD/Wad/Makefile | 16 ++-- SWIG/Tools/WAD/Wad/init.c | 8 ++ SWIG/Tools/WAD/Wad/plat/segment_solaris.c | 10 +-- SWIG/Tools/WAD/Wad/segment.c | 8 +- SWIG/Tools/WAD/Wad/signal.c | 26 ++++-- SWIG/Tools/WAD/Wad/stack.c | 26 ++++-- SWIG/Tools/WAD/Wad/wadpl.cxx | 10 ++- SWIG/Tools/WAD/Wad/wadtcl.cxx | 6 +- SWIG/Tools/WAD/configure.in | 48 ++++------- 15 files changed, 227 insertions(+), 75 deletions(-) create mode 100644 SWIG/Tools/WAD/Test/Makefile.in create mode 100644 SWIG/Tools/WAD/Test/debug.c diff --git a/SWIG/Tools/WAD/Include/wad.h b/SWIG/Tools/WAD/Include/wad.h index 1b8660a80..c321e8626 100644 --- a/SWIG/Tools/WAD/Include/wad.h +++ b/SWIG/Tools/WAD/Include/wad.h @@ -178,6 +178,8 @@ extern WadReturnFunc *wad_check_return(const char *name); #define DEBUG_NOSTACK 0x200 #define DEBUG_ONESHOT 0x400 #define DEBUG_STACK 0x800 +#define DEBUG_UNWIND 0x1000 +#define DEBUG_SIGNAL 0x2000 extern int wad_debug_mode; diff --git a/SWIG/Tools/WAD/Makefile b/SWIG/Tools/WAD/Makefile index e4aed63fb..b927bc1c4 100644 --- a/SWIG/Tools/WAD/Makefile +++ b/SWIG/Tools/WAD/Makefile @@ -3,20 +3,19 @@ # Location of your Python installation -PYINCLUDE = -I/usr/local/include/python1.5 -I/usr/local/lib/python1.5/config +PYINCLUDE = -I/usr/local/include/python2.0 # Location of your Tcl installation TCLINCLUDE = -I/usr/local/include # Location of your Perl installation -PERLINCLUDE = -I/usr/lib/perl5/5.00503/i386-linux/CORE +PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE all: wad python tcl perl - wad: @cd Wad; $(MAKE) wad - + python: @cd Wad; $(MAKE) SINCLUDE='$(PYINCLUDE)' python @@ -26,4 +25,8 @@ tcl: perl: @cd Wad; $(MAKE) SINCLUDE='$(PERLINCLUDE)' perl - + +clean: + @cd Wad; $(MAKE) clean + rm *.so + diff --git a/SWIG/Tools/WAD/Makefile.in b/SWIG/Tools/WAD/Makefile.in index 6fc1e449e..8b3fc49f6 100644 --- a/SWIG/Tools/WAD/Makefile.in +++ b/SWIG/Tools/WAD/Makefile.in @@ -11,11 +11,10 @@ TCLINCLUDE = @TCLINCLUDE@ PERLINCLUDE = @PERL5EXT@ all: wad @MAKEPYTHON@ @MAKETCL@ @MAKEPERL@ - wad: @cd Wad; $(MAKE) wad - + python: @cd Wad; $(MAKE) SINCLUDE='$(PYINCLUDE)' python @@ -25,4 +24,8 @@ tcl: perl: @cd Wad; $(MAKE) SINCLUDE='$(PERLINCLUDE)' perl - + +clean: + @cd Wad; $(MAKE) clean + rm *.so + diff --git a/SWIG/Tools/WAD/README b/SWIG/Tools/WAD/README index 541a1cd02..3c6d18958 100644 --- a/SWIG/Tools/WAD/README +++ b/SWIG/Tools/WAD/README @@ -123,6 +123,10 @@ WAD_DEBUG_RETURN - Display information about WAD return points. WAD_DEBUG_SYMBOL_SEARCH - Display all symbols in the symbol table that are searched. +WAD_DEBUG_UNWIND - Display information about stack unwinding. + +WAD_DEBUG_SIGNAL - Display information about signal handling. + WAD_DEBUG_INIT - Print initialization information. WAD_NOSTACK - Do NOT use an alternative signal handling stack. diff --git a/SWIG/Tools/WAD/Test/Makefile.in b/SWIG/Tools/WAD/Test/Makefile.in new file mode 100644 index 000000000..e71749775 --- /dev/null +++ b/SWIG/Tools/WAD/Test/Makefile.in @@ -0,0 +1,19 @@ +####################################################################### +# WAD Test makefile +# +# Build some WAD test programs. +####################################################################### + +CC= @CC@ +CCSHARED = @CCSHARED@ +LDSHARED = @LDSHARED@ +RPATH = @RPATH@ + +PYINCLUDE = @PYINCLUDE@ +TCLINCLUDE = @TCLINCLUDE@ +PERLINCLUDE = @PERL5EXT@ +INCLUDE = -I../Include + +test: + $(CC) -g -DNEED_MAIN debug.c $(INCLUDE) -L.. $(RPATH).. -lwad -o debug + diff --git a/SWIG/Tools/WAD/Test/debug.c b/SWIG/Tools/WAD/Test/debug.c new file mode 100644 index 000000000..2af77cd37 --- /dev/null +++ b/SWIG/Tools/WAD/Test/debug.c @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------------- + * debug.c + * + * This file contains a variety of different programming errors to test with + * WAD. + * ----------------------------------------------------------------------------- */ + +#include +#include +#include + +/* A simple segmentation fault on an uninitialized pointer */ +int seg_crash() { + int *a = 0; + *a = 3; + return 1; +} + +/* Blow the process heap */ + +int blowheap_crash() { + int i; + int *a = (int *) malloc(sizeof(int)); + + for (i = 0;; i++) { + a[i] = i; + } +} + +/* Buffer overflow crash on the stack */ +int overflow_crash() { + int a[512]; + int i; + + for (i = 0; i < 1024; i++) { + a[i] = i; + } +} + +/* A simple bus error. This might fail silently on certain platforms */ +int bus_crash() { + int b; + int *a = &b; + a = (int *) ((int) a | 0x1); + *a = 3; + return 1; +} + +/* An assertion */ +int abort_crash(int n) { + assert(n > 0); + return 1; +} + +/* A math error (maybe) */ +int math_crash(int x, int y) { + return x/y; +} + + +#ifdef NEED_MAIN + +static const char *usage="\n\ +Usage: debug type\n\ + seg - Fail with an uninitialized pointer.\n\ + bus - Fail with a bus error.\n\ + abort - Fail with an assertion error.\n\ + math - Fail with a math error.\n\ + heap - Blow the process heap.\n\ + overflow - Buffer overflow on the stack.\n\ +"; + +int main(int argc, char **argv) { + int n; + + printf("WAD debug program.\n"); + + if (argc < 2) { + printf("%s\n", usage); + exit(0); + } + if (strcmp(argv[1],"abort") == 0) { + abort_crash(-4); + } else if (strcmp(argv[1],"seg") ==0) { + seg_crash(); + } else if (strcmp(argv[1],"bus") == 0) { + bus_crash(); + } else if (strcmp(argv[1],"math") == 0) { + math_crash(3,0); + } else if (strcmp(argv[1],"heap") == 0) { + blowheap_crash(); + } else if (strcmp(argv[1],"overflow") == 0) { + overflow_crash(); + } +} + +#endif diff --git a/SWIG/Tools/WAD/Wad/Makefile b/SWIG/Tools/WAD/Wad/Makefile index 3cf30e588..6499d4e06 100644 --- a/SWIG/Tools/WAD/Wad/Makefile +++ b/SWIG/Tools/WAD/Wad/Makefile @@ -10,10 +10,10 @@ WADSRCS = return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c WADOBJS = return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o INCLUDE = -I../Include -I. $(SINCLUDE) -WADOPT = -DWAD_LINUX +WADOPT = -DWAD_SOLARIS # Location of your Python installation -PYINCLUDE = -I/usr/local/include/python1.5 -I/usr/local/lib/python1.5/config +PYINCLUDE = -I/usr/local/include/python2.0 PYSRCS = wadpy.cxx PYOBJS = wadpy.o @@ -23,21 +23,21 @@ TCLSRCS = wadtcl.cxx TCLOBJS = wadtcl.o # Location of your Perl installation -PERLINCLUDE = -I/usr/lib/perl5/5.00503/i386-linux/CORE +PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE PERLSRCS = wadpl.cxx PERLOBJS = wadpl.o # C Compiler -CC = gcc -CFLAGS = -fpic +CC = cc -g +CFLAGS = # C++ Compiler -CXX = c++ -CXXFLAGS = -fpic +CXX = CC +CXXFLAGS = -Kpic # Linking options CLINK = -CXXLINK = g++ -shared +CXXLINK = CC -G # Rules for creation of a .o file from .cxx .SUFFIXES: .cxx diff --git a/SWIG/Tools/WAD/Wad/init.c b/SWIG/Tools/WAD/Wad/init.c index 380c20d32..e3c675c0b 100644 --- a/SWIG/Tools/WAD/Wad/init.c +++ b/SWIG/Tools/WAD/Wad/init.c @@ -58,6 +58,14 @@ void wad_init() { wad_debug_mode |= DEBUG_STACK; } + if (getenv("WAD_DEBUG_UNWIND")) { + wad_debug_mode |= DEBUG_UNWIND; + } + + if (getenv("WAD_DEBUG_SIGNAL")) { + wad_debug_mode |= DEBUG_SIGNAL; + } + if (getenv("WAD_NOSTACK")) { wad_debug_mode |= DEBUG_NOSTACK; } diff --git a/SWIG/Tools/WAD/Wad/plat/segment_solaris.c b/SWIG/Tools/WAD/Wad/plat/segment_solaris.c index cca80a3ee..67fd3975a 100644 --- a/SWIG/Tools/WAD/Wad/plat/segment_solaris.c +++ b/SWIG/Tools/WAD/Wad/plat/segment_solaris.c @@ -12,20 +12,20 @@ * ----------------------------------------------------------------------------- */ -static FILE * +static int segment_open() { - FILE *f; - f = fopen("/proc/self/map", "r"); + int f; + f = open("/proc/self/map", O_RDONLY); return f; } static int -segment_read(FILE *fs, WadSegment *s) { +segment_read(int fs, WadSegment *s) { int dz; int n; prmap_t pmap; - n = fread(&pmap, sizeof(prmap_t), 1, fs); + n = read(fs, &pmap, sizeof(prmap_t)); if (n <= 0) return 0; strncpy(s->mapname, pmap.pr_mapname, MAX_PATH); strcpy(s->mappath,"/proc/self/object/"); diff --git a/SWIG/Tools/WAD/Wad/segment.c b/SWIG/Tools/WAD/Wad/segment.c index e298b6c10..5eeab792b 100644 --- a/SWIG/Tools/WAD/Wad/segment.c +++ b/SWIG/Tools/WAD/Wad/segment.c @@ -47,7 +47,7 @@ WadSegment * wad_segment_read() { - FILE *fs; + int fs; int dz; int offset = 0; int i; @@ -59,7 +59,7 @@ wad_segment_read() { /* Try to load the virtual address map */ fs = segment_open(); - if (!fs) return 0; + if (fs < 0) return 0; nsegments = 0; while (1) { n = segment_read(fs,&ws); @@ -67,7 +67,7 @@ wad_segment_read() { nsegments++; } nsegments+=3; - fclose(fs); + close(fs); dz = open("/dev/zero", O_RDWR, 0644); if (dz < 0) { @@ -110,7 +110,7 @@ wad_segment_read() { s->offset = 0; s->mapname[0] =0; s->mappath[0] = 0; - fclose(fs); + close(fs); return segments; } diff --git a/SWIG/Tools/WAD/Wad/signal.c b/SWIG/Tools/WAD/Wad/signal.c index 4ce9566b1..b88e821b7 100644 --- a/SWIG/Tools/WAD/Wad/signal.c +++ b/SWIG/Tools/WAD/Wad/signal.c @@ -15,6 +15,8 @@ #define STACK_SIZE 4*SIGSTKSZ char wad_sig_stack[STACK_SIZE]; +static wad_stacked_signal = 0; + static void (*sig_callback)(int signo, WadFrame *data, char *ret) = 0; void wad_set_callback(void (*s)(int,WadFrame *,char *ret)) { @@ -28,10 +30,10 @@ void wad_set_callback(void (*s)(int,WadFrame *,char *ret)) { return to the caller as if the function had actually completed normally. */ -static int nlr_levels = 0; -static volatile int *volatile nlr_p = &nlr_levels; -static long nlr_value = 0; -static void (*nlr_func)(void) = 0; +int nlr_levels = 0; +volatile int *volatile nlr_p = &nlr_levels; +long nlr_value = 0; +void (*nlr_func)(void) = 0; /* Set the return value from another module */ void wad_set_return_value(long value) { @@ -117,10 +119,15 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) { nlr_func = 0; - wad_object_init(); + if (!wad_stacked_signal) + wad_object_init(); context = (ucontext_t *) vcontext; + if (wad_debug_mode & DEBUG_SIGNAL) { + printf("WAD: siginfo = %x, context = %x\n", si, vcontext); + } + /* Get some information about the current context */ #ifdef WAD_SOLARIS @@ -144,14 +151,22 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) { p_fp = (unsigned long) (*fp); /* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp); */ #endif + /* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp);*/ + if (wad_stacked_signal) { + printf("Fault in wad at pc = %x, sp = %x\n", p_pc, p_sp); + exit(1); + } + wad_stacked_signal++; frame = wad_stack_trace(p_pc, p_sp, p_fp); origframe =frame; if (!frame) { /* We're really hosed here */ + wad_stacked_signal--; return; } + if (wad_debug_mode & DEBUG_STACK) { /* Walk the exception frames and try to find a return point */ framedata = (char *) frame; @@ -227,6 +242,7 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) { #ifdef WAD_SOLARIS *(npc) = *(pc) + 4; #endif + wad_stacked_signal--; return; } exit(1); diff --git a/SWIG/Tools/WAD/Wad/stack.c b/SWIG/Tools/WAD/Wad/stack.c index ea43fa7e0..2d40bf570 100644 --- a/SWIG/Tools/WAD/Wad/stack.c +++ b/SWIG/Tools/WAD/Wad/stack.c @@ -14,12 +14,22 @@ #include #include +#ifdef WAD_SOLARIS +#define STACK_BASE 0xffbf0000 +#endif +#ifdef WAD_LINUX +#define STACK_BASE 0xc0000000 +#endif + /* Given a stack pointer, this function performs a single level of stack unwinding */ static void stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) { + if (wad_debug_mode & DEBUG_UNWIND) { + printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp); + } #ifdef WAD_SOLARIS *pc = *((unsigned long *) *sp+15); /* %i7 - Return address */ *sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */ @@ -89,6 +99,8 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) { if (!ws) { /* If the stack is bad, we are really hosed here */ + write(1,"Whoa. Stack is corrupted. Bailing out.\n", 39); + exit(1); break; } ws = wad_segment_find(segments, (void *) p_pc); @@ -183,13 +195,14 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) { if (p_sp) { stacksize = p_sp - p_lastsp; } else { -#ifdef WAD_SOLARIS - stacksize = 0xffbf0000 - p_lastsp; /* Sick hack alert. Need to get stack top from somewhere */ -#endif -#ifdef WAD_LINUX - stacksize = 0xc0000000 - p_lastsp; -#endif + stacksize = STACK_BASE - p_lastsp; /* Sick hack alert. Need to get stack top from somewhere */ } + + /* Sanity check */ + if ((p_sp + stacksize) > STACK_BASE) { + stacksize = STACK_BASE - p_sp; + } + /* Set the frame pointer and stack size */ /* frame.fp = p_sp; */ @@ -244,6 +257,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) { frame.size = 0; frame.last = 1; frame.lastsize = lastsize; + frame.stack_size = 0; write(ffile,&frame,sizeof(WadFrame)); close(ffile); diff --git a/SWIG/Tools/WAD/Wad/wadpl.cxx b/SWIG/Tools/WAD/Wad/wadpl.cxx index 7b4a29086..25ca5bb74 100644 --- a/SWIG/Tools/WAD/Wad/wadpl.cxx +++ b/SWIG/Tools/WAD/Wad/wadpl.cxx @@ -32,7 +32,7 @@ static int global_signo = 0; static void returnfunc(void) { SV *s; - s = perl_eval_pv("libwadpl::wad_handler_traceback(0)", 0); + s = perl_eval_pv((char*)"libwadpl::wad_handler_traceback(0)", 0); croak("%s\n%s",SvPV(s,PL_na),message); return; } @@ -57,14 +57,16 @@ static void handler(int signo, WadFrame *frame, char *ret) { switch(signo) { case SIGSEGV: - type = "Segmentation fault."; + type = (char*)"Segmentation fault."; break; case SIGBUS: - type = "Bus error."; + type = (char*)"Bus error."; break; case SIGABRT: - type = "Abort."; + type = (char*)"Abort."; break; + case SIGFPE: + type = (char*)"Math."; default: break; } diff --git a/SWIG/Tools/WAD/Wad/wadtcl.cxx b/SWIG/Tools/WAD/Wad/wadtcl.cxx index a4af5baaa..064b2f3b4 100644 --- a/SWIG/Tools/WAD/Wad/wadtcl.cxx +++ b/SWIG/Tools/WAD/Wad/wadtcl.cxx @@ -34,13 +34,13 @@ static void handler(int signo, WadFrame *frame, char *ret) { strcpy(message,"[ C stack trace ]\n\n"); switch(signo) { case SIGSEGV: - type = "Segmentation fault."; + type = (char*)"Segmentation fault."; break; case SIGBUS: - type = "Bus error."; + type = (char*)"Bus error."; break; case SIGABRT: - type = "Abort."; + type = (char*)"Abort."; break; default: break; diff --git a/SWIG/Tools/WAD/configure.in b/SWIG/Tools/WAD/configure.in index 6d2a7978e..1fbfe4712 100644 --- a/SWIG/Tools/WAD/configure.in +++ b/SWIG/Tools/WAD/configure.in @@ -179,6 +179,19 @@ then fi AC_MSG_RESULT($CXXSHARED) +# RPATH is the path used to look for shared library files. +AC_MSG_CHECKING(RPATH) +if test -z "$RPATH" +then + case $ac_sys_system/$ac_sys_release in + SunOS/5*) RPATH="\"-R\"";; + Linux*) RPATH="-Xlinker -rpath ";; + *) RPATH="";; + esac +fi +AC_MSG_RESULT($RPATH) +AC_SUBST(RPATH) + #-------------------------------------------------------------------- # Try to locate the Tcl package #-------------------------------------------------------------------- @@ -264,7 +277,7 @@ fi AC_MSG_CHECKING(for Python header files) -dirs="$PYINCLUDE $PYINCLUDE/python1.6 $PYINCLUDE/python1.5 $PYINCLUDE/python1.4 $PYINCLUDE/Py $prefix=/include/python1.6 $prefix/include/python1.5 $prefix/include/python1.4 /usr/local/include/python1.6 /usr/local/include/python1.5 /usr/include/python1.5 /usr/local/include/python1.4 /usr/include/python1.4 $prefix/include/Py /usr/local/include/Py /usr/include/Py" +dirs="$PYINCLUDE $PYINCLUDE/python2.0 $PYINCLUDE/python1.6 $PYINCLUDE/python1.5 $prefix/include/python2.0 $prefix/include/python1.6 $prefix/include/python1.5 /usr/local/include/python2.0 /usr/local/include/python1.6 /usr/local/include/python1.5 /usr/include/python1.5" for i in $dirs ; do if test -r $i/Python.h; then AC_MSG_RESULT($i) @@ -279,34 +292,7 @@ if test -z "$PYINCLUDE"; then AC_MSG_RESULT(not found) fi -AC_MSG_CHECKING(for Python library) -dirs="$PYLIB $PYLIB/config $PYLIB/lib $PYLIB/python1.6/config $PYLIB/python1.5/config $PYLIB/python1.4/config $PYLIB/python/lib $prefix/lib/python1.6/config $prefix/lib/python1.5/config $prefix/lib/python1.4/config /usr/local/lib/python1.6/config /usr/local/lib/python1.5/config /usr/lib/python1.5 /usr/local/lib/python1.4/config /usr/lib/python1.4 $prefix/lib/python/lib /usr/local/lib/python/lib /usr/lib/python/lib /home/sci/local/lib/python" - -for i in $dirs ; do - if test -r $i/libpython1.6.a; then - AC_MSG_RESULT($i) - PYLIB="$i" - PYINCLUDE="$PYINCLUDE -I$i" - PYLINK="-lpython1.6" - break - fi - if test -r $i/libpython1.5.a; then - AC_MSG_RESULT($i) - PYLIB="$i" - PYINCLUDE="$PYINCLUDE -I$i" - PYLINK="-lpython1.5" - break - fi - if test -r $i/libPython.a; then - AC_MSG_RESULT($i) - PYLIB="$i" - PYINCLUDE="$PYINCLUDE -I$i" - break - fi -done - AC_SUBST(PYINCLUDE) -AC_SUBST(PYLIB) AC_SUBST(PYLINK) AC_SUBST(MAKEPYTHON) @@ -359,13 +345,10 @@ if test -n "$PERL"; then AC_SUBST(PERL5EXT) AC_SUBST(MAKEPERL) -# NOTE: The following ref to `Source' should NOT be prefixed w/ `$srcdir/'. -# We can remove it if `Source' ever has a generated file but not before. -test -d Source || mkdir Source - dnl We use the following in `AC_OUTPUT' and "make distclean". configure_substituted_files=`echo \ Wad/Makefile \ + Test/Makefile \ Makefile \ ` AC_SUBST(configure_substituted_files) @@ -373,3 +356,4 @@ AC_SUBST(configure_substituted_files) AC_OUTPUT([$configure_substituted_files]) dnl configure.in ends here +