*** empty log message ***
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@1012 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
f8c098f917
commit
11790dbca8
14 changed files with 720 additions and 625 deletions
|
|
@ -33,7 +33,7 @@ extern "C" {
|
||||||
#define MAX_PATH 1024
|
#define MAX_PATH 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* --- Low level memory management --- */
|
/* --- Low level memory management functions --- */
|
||||||
|
|
||||||
extern int wad_memory_init();
|
extern int wad_memory_init();
|
||||||
extern void *wad_malloc(int nbytes);
|
extern void *wad_malloc(int nbytes);
|
||||||
|
|
@ -59,8 +59,9 @@ typedef struct WadSegment {
|
||||||
|
|
||||||
extern int wad_segment_read();
|
extern int wad_segment_read();
|
||||||
extern WadSegment *wad_segment_find(void *vaddr);
|
extern WadSegment *wad_segment_find(void *vaddr);
|
||||||
|
extern int wad_segment_valid(void *vaddr);
|
||||||
|
|
||||||
/* --- Object file handling --- */
|
/* --- Object files --- */
|
||||||
typedef struct WadObjectFile {
|
typedef struct WadObjectFile {
|
||||||
void *ptr; /* Pointer to data */
|
void *ptr; /* Pointer to data */
|
||||||
int len; /* Length of data */
|
int len; /* Length of data */
|
||||||
|
|
@ -72,89 +73,101 @@ typedef struct WadObjectFile {
|
||||||
extern void wad_object_reset();
|
extern void wad_object_reset();
|
||||||
extern WadObjectFile *wad_object_load(const char *path);
|
extern WadObjectFile *wad_object_load(const char *path);
|
||||||
|
|
||||||
/* --- Symbol table information --- */
|
#define SYM_LOCAL 1
|
||||||
|
#define SYM_GLOBAL 2
|
||||||
typedef struct WadSymbol {
|
|
||||||
char *name; /* Symbol table name */
|
|
||||||
char *file; /* Source file (if any) */
|
|
||||||
int type; /* Symbol type */
|
|
||||||
int bind; /* Symbol bind */
|
|
||||||
unsigned long value; /* Symbol value */
|
|
||||||
} WadSymbol;
|
|
||||||
|
|
||||||
#define WS_LOCAL 1
|
|
||||||
#define WS_GLOBAL 2
|
|
||||||
|
|
||||||
extern char *wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, WadSymbol *ws);
|
|
||||||
|
|
||||||
/* Signal handling */
|
/* Signal handling */
|
||||||
extern void wad_init();
|
extern void wad_init();
|
||||||
extern void wad_signalhandler(int, siginfo_t *, void *);
|
extern void wad_signalhandler(int, siginfo_t *, void *);
|
||||||
extern void wad_signal_init();
|
extern void wad_signal_init();
|
||||||
|
extern void wad_signal_clear();
|
||||||
extern void wad_set_return(const char *name, long value);
|
extern void wad_set_return(const char *name, long value);
|
||||||
extern void wad_set_return_value(long value);
|
extern void wad_set_return_value(long value);
|
||||||
extern void wad_set_return_func(void (*f)(void));
|
extern void wad_set_return_func(void (*f)(void));
|
||||||
|
|
||||||
extern int wad_elf_check(WadObjectFile *wo);
|
|
||||||
extern void wad_elf_debug(WadObjectFile *wo);
|
|
||||||
|
|
||||||
typedef struct WadLocal {
|
typedef struct WadLocal {
|
||||||
char *name; /* Name of the local */
|
char *name; /* Name of the local */
|
||||||
|
void *ptr; /* Pointer to data */
|
||||||
|
int size; /* Size of the data */
|
||||||
|
int type; /* Data type */
|
||||||
int loc; /* Location: register or stack */
|
int loc; /* Location: register or stack */
|
||||||
int type; /* Argument type */
|
int stack; /* location on the stack */
|
||||||
unsigned long position; /* Position on the stack */
|
int reg; /* Register number */
|
||||||
|
int line; /* Line number where defined */
|
||||||
struct WadLocal *next;
|
struct WadLocal *next;
|
||||||
} WadLocal;
|
} WadLocal;
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
WadLocal *args; /* Arguments */
|
|
||||||
WadLocal *lastarg;
|
|
||||||
} WadDebug;
|
|
||||||
|
|
||||||
#define PARM_REGISTER 1
|
#define PARM_REGISTER 1
|
||||||
#define PARM_STACK 2
|
#define PARM_STACK 2
|
||||||
|
|
||||||
extern int wad_search_stab(void *stab, int size, char *stabstr, WadSymbol *symbol, unsigned long offset, WadDebug *wd);
|
/* Type codes for local variables */
|
||||||
extern int wad_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd);
|
|
||||||
|
#define TYPE_UNKNOWN 0
|
||||||
|
#define TYPE_INT32 1
|
||||||
|
#define TYPE_INT16 2
|
||||||
|
#define TYPE_INT8 3
|
||||||
|
#define TYPE_INT64 4
|
||||||
|
#define TYPE_UINT32 5
|
||||||
|
#define TYPE_UINT16 6
|
||||||
|
#define TYPE_UINT8 7
|
||||||
|
#define TYPE_UINT64 8
|
||||||
|
#define TYPE_FLOAT 9
|
||||||
|
#define TYPE_DOUBLE 10
|
||||||
|
#define TYPE_POINTER 11
|
||||||
|
|
||||||
/* Data structure containing information about each stack frame */
|
/* Data structure containing information about each stack frame */
|
||||||
|
|
||||||
typedef struct WadFrame {
|
typedef struct WadFrame {
|
||||||
long frameno; /* Frame number */
|
long frameno; /* Frame number */
|
||||||
long pc; /* Real PC */
|
struct WadFrame *next; /* Next frame up the stack */
|
||||||
long sp; /* Real SP */
|
struct WadFrame *prev; /* Previous frame down the stack */
|
||||||
long fp; /* Real FP */
|
|
||||||
char *psp; /* Pointer to where the actual stack data is stored */
|
/* Stack context information */
|
||||||
int stack_size; /* Stack frame size */
|
long pc; /* Real PC */
|
||||||
char *symbol; /* Symbol name */
|
long sp; /* Real SP */
|
||||||
long sym_base; /* Symbol base address */
|
long fp; /* Real FP */
|
||||||
char *objfile; /* Object file */
|
char *stack; /* Pointer to where a copy of the stack frame is stored */
|
||||||
char *srcfile; /* Source file */
|
int stack_size; /* Stack frame size (fp-sp) */
|
||||||
int line_number; /* Source line */
|
|
||||||
int nargs; /* Number of arguments */
|
/* Loading information. Contains information from /proc as well as a pointer to
|
||||||
WadLocal *args; /* Function arguments */
|
the executable or shared library in which the PC is located */
|
||||||
WadLocal *lastarg; /* Last argument */
|
|
||||||
int nlocals; /* Number of locals */
|
WadSegment *segment; /* Memory segment corresponding to PC */
|
||||||
|
WadObjectFile *object; /* Object file corresponding to PC */
|
||||||
|
|
||||||
|
/* Symbol table information for PC */
|
||||||
|
|
||||||
|
char *sym_name; /* Symbol name */
|
||||||
|
char *sym_file; /* Source file (if any) */
|
||||||
|
unsigned long sym_base; /* Symbol base address */
|
||||||
|
unsigned long sym_size; /* Symbol size */
|
||||||
|
int sym_type; /* Symbol type */
|
||||||
|
int sym_bind; /* Symbol binding */
|
||||||
|
|
||||||
|
/* Location information */
|
||||||
|
char *loc_objfile; /* Object filename */
|
||||||
|
char *loc_srcfile; /* Source filename */
|
||||||
|
int loc_line; /* Source line */
|
||||||
|
|
||||||
|
/* Debugging information */
|
||||||
|
int debug_nargs; /* Number of arguments */
|
||||||
|
WadLocal *debug_args; /* Arguments */
|
||||||
|
WadLocal *debug_lastarg; /* Last argument */
|
||||||
|
|
||||||
int last; /* Last frame flag */
|
int last; /* Last frame flag */
|
||||||
struct WadFrame *next; /* Next frame up the stack */
|
|
||||||
struct WadFrame *prev; /* Previous frame down the stack */
|
|
||||||
} WadFrame;
|
} WadFrame;
|
||||||
|
|
||||||
extern WadFrame *wad_stack_trace(unsigned long, unsigned long, unsigned long);
|
extern WadFrame *wad_stack_trace(unsigned long, unsigned long, unsigned long);
|
||||||
extern char *wad_strip_dir(char *);
|
extern void wad_stack_debug(WadFrame *f);
|
||||||
extern void wad_default_callback(int signo, WadFrame *frame, char *ret);
|
|
||||||
extern void wad_set_callback(void (*h)(int, WadFrame *, char *));
|
extern char *wad_strip_dir(char *);
|
||||||
extern char *wad_load_source(char *, int line);
|
extern void wad_default_callback(int signo, WadFrame *frame, char *ret);
|
||||||
extern void wad_release_source();
|
extern void wad_set_callback(void (*h)(int, WadFrame *, char *));
|
||||||
extern void wad_release_trace();
|
extern char *wad_load_source(char *, int line);
|
||||||
extern long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error);
|
extern void wad_release_source();
|
||||||
extern long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error);
|
extern void wad_release_trace();
|
||||||
|
extern long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error);
|
||||||
|
extern long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error);
|
||||||
|
|
||||||
extern char *wad_arg_string(WadFrame *f);
|
extern char *wad_arg_string(WadFrame *f);
|
||||||
|
|
||||||
|
|
@ -166,6 +179,14 @@ typedef struct {
|
||||||
extern void wad_set_returns(WadReturnFunc *rf);
|
extern void wad_set_returns(WadReturnFunc *rf);
|
||||||
extern WadReturnFunc *wad_check_return(const char *name);
|
extern WadReturnFunc *wad_check_return(const char *name);
|
||||||
|
|
||||||
|
extern int wad_search_stab(void *stab, int size, char *stabstr, WadFrame *f);
|
||||||
|
|
||||||
|
extern void wad_find_object(WadFrame *f);
|
||||||
|
extern void wad_find_symbol(WadFrame *f);
|
||||||
|
extern void wad_find_debug(WadFrame *f);
|
||||||
|
extern void wad_build_vars(WadFrame *f);
|
||||||
|
extern char *wad_format_var(WadLocal *l);
|
||||||
|
|
||||||
/* --- Debugging Interface --- */
|
/* --- Debugging Interface --- */
|
||||||
|
|
||||||
#define DEBUG_SEGMENT 0x1
|
#define DEBUG_SEGMENT 0x1
|
||||||
|
|
@ -186,7 +207,17 @@ extern WadReturnFunc *wad_check_return(const char *name);
|
||||||
extern int wad_debug_mode;
|
extern int wad_debug_mode;
|
||||||
extern int wad_heap_overflow;
|
extern int wad_heap_overflow;
|
||||||
|
|
||||||
|
#ifdef WAD_LINUX
|
||||||
|
#define WAD_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
#ifdef WAD_SOLARIS
|
||||||
|
#define WAD_BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
# These are the files that make up the WAD core
|
# These are the files that make up the WAD core
|
||||||
WADSRCS = io.c memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
WADSRCS = vars.c default.c io.c memory.c return.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
||||||
WADOBJS = io.o memory.o return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
WADOBJS = vars.o default.o io.o memory.o return.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
||||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||||
WADOPT = -DWAD_SOLARIS
|
WADOPT = -DWAD_LINUX
|
||||||
|
|
||||||
# Location of your Python installation
|
# Location of your Python installation
|
||||||
PYINCLUDE = -I/usr/local/include/python2.0
|
PYINCLUDE = -I/usr/local/include/python2.0
|
||||||
|
|
@ -23,21 +23,21 @@ TCLSRCS = wadtcl.cxx
|
||||||
TCLOBJS = wadtcl.o
|
TCLOBJS = wadtcl.o
|
||||||
|
|
||||||
# Location of your Perl installation
|
# Location of your Perl installation
|
||||||
PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE
|
PERLINCLUDE = -I/usr/lib/perl5/5.00503/i386-linux/CORE
|
||||||
PERLSRCS = wadpl.cxx
|
PERLSRCS = wadpl.cxx
|
||||||
PERLOBJS = wadpl.o
|
PERLOBJS = wadpl.o
|
||||||
|
|
||||||
# C Compiler
|
# C Compiler
|
||||||
CC = cc
|
CC = gcc
|
||||||
CFLAGS = #
|
CFLAGS = #-fpic
|
||||||
|
|
||||||
# C++ Compiler
|
# C++ Compiler
|
||||||
CXX = CC
|
CXX = c++
|
||||||
CXXFLAGS = #-Kpic
|
CXXFLAGS = #-fpic
|
||||||
|
|
||||||
# Linking options
|
# Linking options
|
||||||
CLINK =
|
CLINK =
|
||||||
CXXLINK = CC -G
|
CXXLINK = g++ -shared
|
||||||
|
|
||||||
# Rules for creation of a .o file from .cxx
|
# Rules for creation of a .o file from .cxx
|
||||||
.SUFFIXES: .cxx
|
.SUFFIXES: .cxx
|
||||||
|
|
@ -67,7 +67,7 @@ wad_perl_handler.c:
|
||||||
python makehandler.py
|
python makehandler.py
|
||||||
|
|
||||||
debug::
|
debug::
|
||||||
cc -g debug.c $(INCLUDE) -L. -R. -lwad
|
cc -g debug.c $(INCLUDE) -L. -Xlinker -rpath . -lwad
|
||||||
|
|
||||||
plus::
|
plus::
|
||||||
CC -g debug.cxx $(INCLUDE) -L. -R. -lwad
|
CC -g debug.cxx $(INCLUDE) -L. -R. -lwad
|
||||||
|
|
@ -76,7 +76,7 @@ wc::
|
||||||
wc $(SRCS)
|
wc $(SRCS)
|
||||||
|
|
||||||
semi::
|
semi::
|
||||||
egrep ";" $(SRCS) wadpy.cxx | wc
|
egrep ";" $(WADSRCS) wadpy.cxx | wc
|
||||||
|
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
# These are the files that make up the WAD core
|
# These are the files that make up the WAD core
|
||||||
WADSRCS = io.c memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
WADSRCS = vars.c io.c memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
||||||
WADOBJS = io.o memory.o return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
WADOBJS = vars.o io.o memory.o return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
||||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||||
WADOPT = @WADOPT@
|
WADOPT = @WADOPT@
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,21 @@
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
int seg_crash(int n) {
|
typedef struct Foo {
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
float c;
|
||||||
|
} Foo;
|
||||||
|
|
||||||
|
static int type_crash(int n, short m, char c, double x, float y, Foo f, void *ptr) {
|
||||||
int *a = 0;
|
int *a = 0;
|
||||||
if (n > 0) seg_crash(n-1);
|
*a = 3;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int seg_crash(int n, double x,
|
||||||
|
float y) {
|
||||||
|
int *a = 0;
|
||||||
|
if (n > 0) seg_crash(n-1,x,y);
|
||||||
*a = 3;
|
*a = 3;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -61,23 +73,26 @@ static int test(int x, int (*f)(int)) {
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int n;
|
int n;
|
||||||
int (*f)(int);
|
int (*f)(int);
|
||||||
|
Foo foo = { 3.14, 28.18, 1.0 };
|
||||||
|
|
||||||
printf("starting.\n");
|
printf("starting.\n");
|
||||||
|
|
||||||
if (strcmp(argv[1],"abort") == 0) {
|
if (strcmp(argv[1],"abort") == 0) {
|
||||||
abort_crash(0);
|
abort_crash(0);
|
||||||
} else if (strcmp(argv[1],"seg") ==0) {
|
} else if (strcmp(argv[1],"seg") ==0) {
|
||||||
seg_crash(0);
|
seg_crash(0,1,2);
|
||||||
} else if (strcmp(argv[1],"bus") == 0) {
|
} else if (strcmp(argv[1],"bus") == 0) {
|
||||||
bus_crash(0);
|
bus_crash(0);
|
||||||
} else if (strcmp(argv[1],"ret") == 0) {
|
} else if (strcmp(argv[1],"ret") == 0) {
|
||||||
call_func(4,seg_crash);
|
call_func(4,abort_crash);
|
||||||
} else if (strcmp(argv[1],"test") == 0) {
|
} else if (strcmp(argv[1],"test") == 0) {
|
||||||
test(-1000,seg_crash);
|
test(-1000,abort_crash);
|
||||||
} else if (strcmp(argv[1],"double") == 0) {
|
} else if (strcmp(argv[1],"double") == 0) {
|
||||||
double_crash(3.14159,2.1828);
|
double_crash(3.14159,2.1828);
|
||||||
} else if (strcmp(argv[1],"math") == 0) {
|
} else if (strcmp(argv[1],"math") == 0) {
|
||||||
math_crash(3,0);
|
math_crash(3,0);
|
||||||
|
} else if (strcmp(argv[1],"type") == 0) {
|
||||||
|
type_crash(34,42,17, 3.14159, 2.1828, foo, &foo);
|
||||||
}
|
}
|
||||||
multi(3,5,10,3.14);
|
multi(3,5,10,3.14);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,15 @@ char *wad_arg_string(WadFrame *frame) {
|
||||||
long *nextstack;
|
long *nextstack;
|
||||||
int i;
|
int i;
|
||||||
WadFrame *nf;
|
WadFrame *nf;
|
||||||
|
|
||||||
nf = frame->next;
|
nf = frame->next;
|
||||||
if (nf)
|
if (nf)
|
||||||
nextstack = (long *) nf->psp;
|
nextstack = (long *) nf->stack;
|
||||||
else
|
else
|
||||||
nextstack = 0;
|
nextstack = 0;
|
||||||
|
|
||||||
str[0] = 0;
|
str[0] = 0;
|
||||||
stack = (long *) frame->psp;
|
stack = (long *) frame->stack;
|
||||||
|
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
if (!nf) {
|
if (!nf) {
|
||||||
|
|
@ -42,7 +42,7 @@ char *wad_arg_string(WadFrame *frame) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (frame->nargs < 0) {
|
if (frame->debug_nargs < 0) {
|
||||||
/* No argument information is available. If we are on SPARC, we'll dump
|
/* No argument information is available. If we are on SPARC, we'll dump
|
||||||
the %in registers since these usually hold input parameters. On
|
the %in registers since these usually hold input parameters. On
|
||||||
Linux, we do nothing */
|
Linux, we do nothing */
|
||||||
|
|
@ -57,52 +57,16 @@ char *wad_arg_string(WadFrame *frame) {
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* We were able to get some argument information out the debugging table */
|
/* We were able to get some argument information out the debugging table */
|
||||||
wp = frame->args;
|
wp = frame->debug_args;
|
||||||
for (i = 0; i < frame->nargs; i++, wp = wp->next) {
|
for (i = 0; i < frame->debug_nargs; i++, wp = wp->next) {
|
||||||
strcat(str,wp->name);
|
strcat(str,wp->name);
|
||||||
strcat(str,"=");
|
strcat(str,"=");
|
||||||
|
strcat(str,wad_format_var(wp));
|
||||||
/* Try to figure out where the value is */
|
if (i < (frame->debug_nargs-1)) strcat(str,",");
|
||||||
if ((wp->loc == PARM_STACK) && nf) {
|
|
||||||
/* Parameter is located on the call stack */
|
|
||||||
unsigned long argloc = wp->position; /* Location relative to frame pointer */
|
|
||||||
if ((argloc & 0x3) == 0) {
|
|
||||||
if (argloc >= 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 {
|
|
||||||
unsigned long *p = (unsigned long *) (((char *) stack) + frame->stack_size + argloc);
|
|
||||||
sprintf(temp,"0x%x", *p);
|
|
||||||
strcat(str,temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (wp->loc == PARM_REGISTER) {
|
|
||||||
#ifdef WAD_SOLARIS
|
|
||||||
if ((wp->position >= 24) && (wp->position < 32)) {
|
|
||||||
/* Value is located in the %in registers */
|
|
||||||
sprintf(temp,"0x%x", stack[wp->position - 16]);
|
|
||||||
strcat(str,temp);
|
|
||||||
} else if ((wp->position >= 8) && (wp->position < 16)) {
|
|
||||||
/* Value is located in the %on registers */
|
|
||||||
/* sprintf(temp,"0x%x", frame->regs[wp->value]);
|
|
||||||
strcat(str,temp); */
|
|
||||||
} else if ((wp->position >= 16) && (wp->position < 24)) {
|
|
||||||
/* Value has been placed in the %ln registers */
|
|
||||||
/*
|
|
||||||
sprintf(temp,"0x%x", frame->regs[wp->value - 16]);
|
|
||||||
strcat(str,temp); */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef WAD_LINUX
|
|
||||||
strcat(str,"?");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (i < (frame->nargs-1)) strcat(str,",");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *wad_strip_dir(char *name) {
|
char *wad_strip_dir(char *name) {
|
||||||
|
|
@ -168,54 +132,45 @@ void wad_release_source() {
|
||||||
* Default callback
|
* Default callback
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
void wad_default_callback(int signo, WadFrame *f, char *ret) {
|
||||||
char *fd;
|
char *fd;
|
||||||
WadFrame *f;
|
|
||||||
WadFrame *fline = 0;
|
WadFrame *fline = 0;
|
||||||
|
|
||||||
switch(signo) {
|
switch(signo) {
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
fprintf(stderr,"Segmentation fault.\n");
|
fprintf(stderr,"WAD: Segmentation fault.\n");
|
||||||
break;
|
break;
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
fprintf(stderr,"Bus error.\n");
|
fprintf(stderr,"WAD: Bus error.\n");
|
||||||
break;
|
break;
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
fprintf(stderr,"Abort.\n");
|
fprintf(stderr,"WAD: Abort.\n");
|
||||||
break;
|
break;
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
fprintf(stderr,"Floating point exception.\n");
|
fprintf(stderr,"WAD: Floating point exception.\n");
|
||||||
break;
|
break;
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
fprintf(stderr,"Illegal instruction.\n");
|
fprintf(stderr,"WAD: Illegal instruction.\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"Signal %d\n", signo);
|
fprintf(stderr,"WAD: Signal %d\n", signo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fd = (char *) framedata;
|
|
||||||
f = (WadFrame *) fd;
|
|
||||||
|
|
||||||
/* Find the last exception frame */
|
/* Find the last exception frame */
|
||||||
|
|
||||||
while (f && !f->last) {
|
while (f && !(f->last)) {
|
||||||
f = f->next;
|
f = f->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now work backwards */
|
|
||||||
if (f) {
|
|
||||||
f = f->prev;
|
|
||||||
}
|
|
||||||
while (f) {
|
while (f) {
|
||||||
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, f->symbol ? f->symbol : "?",
|
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, f->sym_name ? f->sym_name : "?",
|
||||||
wad_arg_string(f));
|
wad_arg_string(f));
|
||||||
if (f->srcfile && strlen(f->srcfile)) {
|
if (f->loc_srcfile && strlen(f->loc_srcfile)) {
|
||||||
fprintf(stderr," in '%s'", wad_strip_dir(f->srcfile));
|
fprintf(stderr," in '%s'", wad_strip_dir(f->loc_srcfile));
|
||||||
if (f->line_number > 0) {
|
if (f->loc_line > 0) {
|
||||||
fprintf(stderr,", line %d", f->line_number);
|
fprintf(stderr,", line %d", f->loc_line);
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
fd = open(f->srcfile, O_RDONLY);
|
fd = open(f->loc_srcfile, O_RDONLY);
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
fline = f;
|
fline = f;
|
||||||
}
|
}
|
||||||
|
|
@ -223,8 +178,8 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (f->objfile && strlen(f->objfile)) {
|
if (f->loc_objfile && strlen(f->loc_objfile)) {
|
||||||
fprintf(stderr," from '%s'", f->objfile);
|
fprintf(stderr," from '%s'", f->loc_objfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr,"\n");
|
fprintf(stderr,"\n");
|
||||||
|
|
@ -236,15 +191,15 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
||||||
int last;
|
int last;
|
||||||
char *line, *c;
|
char *line, *c;
|
||||||
int i;
|
int i;
|
||||||
first = fline->line_number - 2;
|
first = fline->loc_line - 2;
|
||||||
last = fline->line_number + 2;
|
last = fline->loc_line + 2;
|
||||||
if (first < 1) first = 1;
|
if (first < 1) first = 1;
|
||||||
|
|
||||||
line = wad_load_source(fline->srcfile,first);
|
line = wad_load_source(fline->loc_srcfile,first);
|
||||||
if (line) {
|
if (line) {
|
||||||
fprintf(stderr,"\n%s, line %d\n\n", fline->srcfile,fline->line_number);
|
fprintf(stderr,"\n%s, line %d\n\n", fline->loc_srcfile,fline->loc_line);
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++) {
|
||||||
if (i == fline->line_number) fprintf(stderr," => ");
|
if (i == fline->loc_line) fprintf(stderr," => ");
|
||||||
else fprintf(stderr," ");
|
else fprintf(stderr," ");
|
||||||
c = strchr(line,'\n');
|
c = strchr(line,'\n');
|
||||||
if (c) {
|
if (c) {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* --- What's needed here (high level interface) :
|
/* --- What's needed here (high level interface) :
|
||||||
|
|
||||||
- Mapping of addresses to symbols
|
- Mapping of addresses to symbols
|
||||||
|
|
@ -207,30 +206,30 @@ wad_elf_section_byname(WadObjectFile *wo, char *name) {
|
||||||
* base address of the object file.
|
* base address of the object file.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static
|
||||||
char *
|
int elf_search_section_sym(WadFrame *f, char *secname, char *strname) {
|
||||||
wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol *ws) {
|
int nsymtab;
|
||||||
int nsymtab;
|
int nstrtab;
|
||||||
int nstrtab;
|
int symtab_size;
|
||||||
int symtab_size;
|
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
int nsym;
|
int nsym;
|
||||||
char *str;
|
char *str;
|
||||||
int i;
|
int i;
|
||||||
unsigned long vaddr;
|
unsigned long vaddr, base;
|
||||||
char *name;
|
char *name;
|
||||||
char *localfile = 0;
|
char *localfile = 0;
|
||||||
|
|
||||||
vaddr = (unsigned long) ptr;
|
vaddr = (unsigned long) f->pc;
|
||||||
|
base = (unsigned long) f->segment->base;
|
||||||
|
|
||||||
nsymtab = wad_elf_section_byname(wo,".symtab");
|
nsymtab = wad_elf_section_byname(f->object,secname);
|
||||||
if (nsymtab < 0) goto dynsym;
|
if (nsymtab < 0) return 0;
|
||||||
nstrtab = wad_elf_section_byname(wo,".strtab");
|
nstrtab = wad_elf_section_byname(f->object,strname);
|
||||||
if (nstrtab < 0) goto dynsym;
|
if (nstrtab < 0) return 0;
|
||||||
|
|
||||||
symtab_size = wad_elf_section_size(wo,nsymtab);
|
symtab_size = wad_elf_section_size(f->object,nsymtab);
|
||||||
sym = (Elf32_Sym *) wad_elf_section_data(wo,nsymtab);
|
sym = (Elf32_Sym *) wad_elf_section_data(f->object,nsymtab);
|
||||||
str = (char *) wad_elf_section_data(wo,nstrtab);
|
str = (char *) wad_elf_section_data(f->object,nstrtab);
|
||||||
|
|
||||||
nsym = (symtab_size/sizeof(Elf32_Sym));
|
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||||
for (i = 0; i < nsym; i++) {
|
for (i = 0; i < nsym; i++) {
|
||||||
|
|
@ -242,66 +241,36 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
|
||||||
if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
|
if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
|
||||||
wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
|
wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
|
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
/* If the section index is 0, the symbol is undefined */
|
/* If the section index is 0, the symbol is undefined */
|
||||||
if (sym[i].st_shndx == 0) continue;
|
if (sym[i].st_shndx == 0) continue;
|
||||||
#endif
|
#endif
|
||||||
ws->value = sym[i].st_value;
|
f->sym_name = name;
|
||||||
|
f->sym_base = base + sym[i].st_value;
|
||||||
|
f->sym_size = sym[i].st_size;
|
||||||
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
||||||
ws->file = localfile;
|
f->sym_file = localfile;
|
||||||
ws->bind = WS_LOCAL;
|
f->sym_bind = SYM_LOCAL;
|
||||||
} else {
|
} else {
|
||||||
ws->bind = WS_GLOBAL;
|
f->sym_bind = SYM_GLOBAL;
|
||||||
}
|
}
|
||||||
ws->name = name;
|
return 1;
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dynsym:
|
|
||||||
|
|
||||||
/* If we didn't find it in the .symtab section. Maybe it's in the .dynsym, .dynstr section */
|
|
||||||
|
|
||||||
nsymtab = wad_elf_section_byname(wo,".dynsym");
|
|
||||||
if (nsymtab < 0) return 0;
|
|
||||||
nstrtab = wad_elf_section_byname(wo,".dynstr");
|
|
||||||
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));
|
|
||||||
localfile = 0;
|
|
||||||
for (i = 0; i < nsym; i++) {
|
|
||||||
name = str + sym[i].st_name;
|
|
||||||
if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
|
|
||||||
localfile = name;
|
|
||||||
}
|
|
||||||
if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
|
|
||||||
wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
|
|
||||||
}
|
|
||||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
|
|
||||||
#ifdef WAD_LINUX
|
|
||||||
/* If the section index is 0, the symbol is undefined */
|
|
||||||
if (sym[i].st_shndx == 0) continue;
|
|
||||||
#endif
|
|
||||||
ws->value = sym[i].st_value;
|
|
||||||
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
|
||||||
ws->file = localfile;
|
|
||||||
ws->bind = WS_LOCAL;
|
|
||||||
} else {
|
|
||||||
ws->bind = WS_GLOBAL;
|
|
||||||
}
|
|
||||||
ws->name = name;
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wad_elf_find_symbol(WadFrame *f) {
|
||||||
|
/* We simply try a few possible sections */
|
||||||
|
if (elf_search_section_sym(f,".symtab",".strtab")) return;
|
||||||
|
if (elf_search_section_sym(f,".dynsym",".dynstr")) return;
|
||||||
|
|
||||||
|
/* Hmmm. No match found. Oh well */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_elf_debug_info()
|
* wad_elf_debug_info()
|
||||||
*
|
*
|
||||||
|
|
@ -309,19 +278,19 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int
|
int
|
||||||
wad_elf_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd) {
|
wad_elf_debug_info(WadFrame *f) {
|
||||||
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
||||||
int ret;
|
int ret;
|
||||||
void *stab;
|
void *stab;
|
||||||
char *stabstr;
|
char *stabstr;
|
||||||
int stabsize;
|
int stabsize;
|
||||||
|
|
||||||
nstab = wad_elf_section_byname(wo,".stab");
|
nstab = wad_elf_section_byname(f->object,".stab");
|
||||||
nstabstr = wad_elf_section_byname(wo,".stabstr");
|
nstabstr = wad_elf_section_byname(f->object,".stabstr");
|
||||||
nstabindex = wad_elf_section_byname(wo,".stab.index");
|
nstabindex = wad_elf_section_byname(f->object,".stab.index");
|
||||||
nstabindexstr = wad_elf_section_byname(wo,".stab.indexstr");
|
nstabindexstr = wad_elf_section_byname(f->object,".stab.indexstr");
|
||||||
nstabexcl = wad_elf_section_byname(wo,".stab.excl");
|
nstabexcl = wad_elf_section_byname(f->object,".stab.excl");
|
||||||
nstabexclstr = wad_elf_section_byname(wo,".stab.exclstr");
|
nstabexclstr = wad_elf_section_byname(f->object,".stab.exclstr");
|
||||||
|
|
||||||
#ifdef DEBUG_DEBUG
|
#ifdef DEBUG_DEBUG
|
||||||
wad_printf("nstab = %d\n", nstab);
|
wad_printf("nstab = %d\n", nstab);
|
||||||
|
|
@ -336,39 +305,43 @@ wad_elf_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, Wad
|
||||||
|
|
||||||
/* Look in the .stab section */
|
/* Look in the .stab section */
|
||||||
if (nstab > 0) {
|
if (nstab > 0) {
|
||||||
stab = wad_elf_section_data(wo,nstab);
|
stab = wad_elf_section_data(f->object,nstab);
|
||||||
stabsize = wad_elf_section_size(wo,nstab);
|
stabsize = wad_elf_section_size(f->object,nstab);
|
||||||
stabstr = (char *) wad_elf_section_data(wo,nstabstr);
|
stabstr = (char *) wad_elf_section_data(f->object,nstabstr);
|
||||||
|
|
||||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset,wd)) return 1;
|
if (wad_search_stab(stab,stabsize,stabstr, f)) return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look in the .stab.excl section. A solaris oddity? */
|
/* Look in the .stab.excl section. A solaris oddity? */
|
||||||
|
|
||||||
if (nstabexcl > 0) {
|
if (nstabexcl > 0) {
|
||||||
stab = wad_elf_section_data(wo,nstabexcl);
|
stab = wad_elf_section_data(f->object,nstabexcl);
|
||||||
stabsize = wad_elf_section_size(wo, nstabexcl);
|
stabsize = wad_elf_section_size(f->object, nstabexcl);
|
||||||
stabstr = (char *) wad_elf_section_data(wo, nstabexclstr);
|
stabstr = (char *) wad_elf_section_data(f->object, nstabexclstr);
|
||||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset,wd)) return 1;
|
if (wad_search_stab(stab,stabsize,stabstr, f)) return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look in the .stab.index section. A Solaris oddity? */
|
/* Look in the .stab.index section. A Solaris oddity? */
|
||||||
if (nstabindex > 0) {
|
if (nstabindex > 0) {
|
||||||
stab = wad_elf_section_data(wo,nstabindex);
|
stab = wad_elf_section_data(f->object,nstabindex);
|
||||||
stabsize = wad_elf_section_size(wo, nstabindex);
|
stabsize = wad_elf_section_size(f->object, nstabindex);
|
||||||
stabstr = (char *) wad_elf_section_data(wo, nstabindexstr);
|
stabstr = (char *) wad_elf_section_data(f->object, nstabindexstr);
|
||||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset, wd)) {
|
if (wad_search_stab(stab,stabsize,stabstr, f)) {
|
||||||
WadObjectFile *wo1;
|
WadObjectFile *wo1, *wold;
|
||||||
/* Hmmm. Might be in a different file */
|
/* Hmmm. Might be in a different file */
|
||||||
char objfile[MAX_PATH];
|
char objfile[MAX_PATH];
|
||||||
strcpy(objfile, wd->objfile);
|
strcpy(objfile, f->loc_objfile);
|
||||||
wo1 = wad_object_load(objfile);
|
wo1 = wad_object_load(objfile);
|
||||||
if (wo1) {
|
if (wo1) {
|
||||||
ret = wad_debug_info(wo1,wsym,offset,wd);
|
wold = f->object;
|
||||||
|
f->object = wo1;
|
||||||
|
wad_find_debug(f);
|
||||||
|
f->object = wold;
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
/* wad_printf("couldn't load %s\n", objfile); */
|
/* wad_printf("couldn't load %s\n", objfile); */
|
||||||
}
|
}
|
||||||
if (!ret) return wad_search_stab(stab,stabsize,stabstr,wsym, offset,wd);
|
/* if (!ret) return wad_search_stab(stab,stabsize,stabstr,f);*/
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -402,36 +375,32 @@ wad_elf_debug(WadObjectFile *wo) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_find_symbol()
|
* wad_find_symbol()
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
char *
|
void
|
||||||
wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, WadSymbol *ws) {
|
wad_find_symbol(WadFrame *f) {
|
||||||
char *r;
|
|
||||||
ws->name = 0;
|
|
||||||
ws->file = 0;
|
|
||||||
ws->type = 0;
|
|
||||||
ws->bind = 0;
|
|
||||||
ws->value = 0;
|
|
||||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||||
wad_printf("wad: Searching for 0x%08x --> ", ptr);
|
wad_printf("wad: Searching for 0x%08x --> ", f->pc);
|
||||||
}
|
}
|
||||||
r = wad_elf_find_symbol(wo,ptr,base,ws);
|
if (f->object)
|
||||||
if (r) {
|
wad_elf_find_symbol(f);
|
||||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||||
wad_printf("%s", ws->name);
|
if (f->sym_name) {
|
||||||
if (ws->file)
|
wad_printf("%s", f->sym_name);
|
||||||
wad_printf(" in '%s'\n", ws->file);
|
if (f->sym_file)
|
||||||
|
wad_printf(" in '%s'\n", f->sym_file);
|
||||||
else
|
else
|
||||||
wad_printf("\n");
|
wad_printf("\n");
|
||||||
}
|
} else {
|
||||||
} else {
|
|
||||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
|
||||||
wad_printf("?\n");
|
wad_printf("?\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
wad_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd) {
|
wad_find_debug(WadFrame *f) {
|
||||||
return wad_elf_debug_info(wo,wsym, offset,wd);
|
if (f->object)
|
||||||
|
wad_elf_debug_info(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,3 +246,14 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_find_object(WadFrame *f)
|
||||||
|
*
|
||||||
|
* Given a stack frame. Try to locate the object file
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void wad_find_object(WadFrame *f) {
|
||||||
|
if (f->segment) {
|
||||||
|
f->object = wad_object_load(f->segment->mappath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ void wad_set_returns(WadReturnFunc *rf) {
|
||||||
|
|
||||||
WadReturnFunc *wad_check_return(const char *name) {
|
WadReturnFunc *wad_check_return(const char *name) {
|
||||||
int i;
|
int i;
|
||||||
|
if (!name) return 0;
|
||||||
for (i = 0; i < num_return; i++) {
|
for (i = 0; i < num_return; i++) {
|
||||||
if (strcmp(name,return_points[i].name) == 0) {
|
if (strcmp(name,return_points[i].name) == 0) {
|
||||||
if (wad_debug_mode & DEBUG_RETURN) {
|
if (wad_debug_mode & DEBUG_RETURN) {
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,16 @@ wad_segment_find(void *vaddr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_valid()
|
||||||
|
*
|
||||||
|
* Checks to see if a memory address is valid or not based on data in the
|
||||||
|
* segment map
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int wad_segment_valid(void *vaddr) {
|
||||||
|
return wad_segment_find ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,6 @@ static void nonlocalret() {
|
||||||
|
|
||||||
void wad_restore_i386_registers(WadFrame *f, int nlevels) {
|
void wad_restore_i386_registers(WadFrame *f, int nlevels) {
|
||||||
WadFrame *lastf = f;
|
WadFrame *lastf = f;
|
||||||
char *fd = (char *) f;
|
|
||||||
int localsize = 0;
|
int localsize = 0;
|
||||||
unsigned char *pc;
|
unsigned char *pc;
|
||||||
unsigned long *saved;
|
unsigned long *saved;
|
||||||
|
|
@ -226,8 +225,7 @@ void wad_restore_i386_registers(WadFrame *f, int nlevels) {
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd += f->size;
|
f = f->next;
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,6 +258,12 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
wad_nlr_func = 0;
|
wad_nlr_func = 0;
|
||||||
|
|
||||||
context = (ucontext_t *) vcontext;
|
context = (ucontext_t *) vcontext;
|
||||||
|
|
||||||
|
/* Read the segments */
|
||||||
|
if (wad_segment_read() < 0) {
|
||||||
|
wad_printf("WAD: Unable to read segment map\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (wad_debug_mode & DEBUG_SIGNAL) {
|
if (wad_debug_mode & DEBUG_SIGNAL) {
|
||||||
printf("WAD: siginfo = %x, context = %x\n", si, vcontext);
|
printf("WAD: siginfo = %x, context = %x\n", si, vcontext);
|
||||||
|
|
@ -302,6 +306,9 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
p_fp = (unsigned long) (*fp);
|
p_fp = (unsigned long) (*fp);
|
||||||
/* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp); */
|
/* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp); */
|
||||||
|
#endif
|
||||||
|
#ifdef WAD_SOLARIS
|
||||||
|
p_fp = (unsigned long) *(((long *) p_sp) + 14);
|
||||||
#endif
|
#endif
|
||||||
/* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp);*/
|
/* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp);*/
|
||||||
|
|
||||||
|
|
@ -316,62 +323,50 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
}
|
}
|
||||||
wad_stacked_signal++;
|
wad_stacked_signal++;
|
||||||
frame = wad_stack_trace(p_pc, p_sp, p_fp);
|
frame = wad_stack_trace(p_pc, p_sp, p_fp);
|
||||||
origframe =frame;
|
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
/* We're really hosed here */
|
/* We're really hosed. Not possible to generate a stack trace */
|
||||||
wad_stacked_signal--;
|
printf("WAD: Unable to generate stack trace.\n");
|
||||||
|
printf("WAD: Maybe the call stack has been corrupted by buffer overflow.\n");
|
||||||
|
wad_signal_clear();
|
||||||
return;
|
return;
|
||||||
|
/* exit(1); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
WadFrame *f = frame;
|
||||||
|
while (f) {
|
||||||
|
wad_find_object(f);
|
||||||
|
wad_find_symbol(f);
|
||||||
|
wad_find_debug(f);
|
||||||
|
wad_build_vars(f);
|
||||||
|
f = f->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wad_heap_overflow = 0;
|
wad_heap_overflow = 0;
|
||||||
if (sig == SIGSEGV) {
|
if (sig == SIGSEGV) {
|
||||||
if (addr >= current_brk) wad_heap_overflow = 1;
|
if (addr >= current_brk) wad_heap_overflow = 1;
|
||||||
}
|
}
|
||||||
|
wad_stack_debug(frame);
|
||||||
|
|
||||||
if (wad_debug_mode & DEBUG_STACK) {
|
|
||||||
/* Walk the exception frames and try to find a return point */
|
|
||||||
while (frame) {
|
|
||||||
int i;
|
|
||||||
WadLocal *p;
|
|
||||||
/* Print out detailed stack trace information */
|
|
||||||
printf("::: Stack frame - 0x%08x :::\n", frame);
|
|
||||||
printf(" sp = %x\n", frame->sp);
|
|
||||||
printf(" fp = %x\n", frame->fp);
|
|
||||||
printf(" size = %x\n", frame->stack_size);
|
|
||||||
printf(" pc = %x (base = %x)\n", frame->pc, frame->sym_base);
|
|
||||||
printf(" symbol = '%s'\n", frame->symbol ? frame->symbol : "?");
|
|
||||||
printf(" srcfile = '%s'\n", frame->srcfile ? frame->srcfile : "");
|
|
||||||
printf(" objfile = '%s'\n", frame->objfile ? frame->objfile : "");
|
|
||||||
printf(" numargs = %d\n", frame->nargs);
|
|
||||||
printf(" arguments [\n");
|
|
||||||
p = frame->args;
|
|
||||||
i = 0;
|
|
||||||
while (p) {
|
|
||||||
printf(" arg[%d] : name = '%s', loc = %d, type = %d, value = %d\n", i, p->name, p->loc, p->type, p->position);
|
|
||||||
p = p->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
printf(" ]\n");
|
|
||||||
frame = frame->next;
|
|
||||||
}
|
|
||||||
frame = origframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk the exception frames and try to find a return point */
|
/* Walk the exception frames and try to find a return point */
|
||||||
|
origframe = frame;
|
||||||
while (frame) {
|
while (frame) {
|
||||||
WadReturnFunc *wr = wad_check_return(frame->symbol);
|
WadReturnFunc *wr = wad_check_return(frame->sym_name);
|
||||||
if (wr) {
|
if (wr) {
|
||||||
found = 1;
|
found = 1;
|
||||||
wad_nlr_value = wr->value;
|
wad_nlr_value = wr->value;
|
||||||
retname = wr->name;
|
retname = wr->name;
|
||||||
}
|
}
|
||||||
frame = frame->next;
|
|
||||||
if (found) {
|
if (found) {
|
||||||
frame->last = 1; /* Cut off top of the stack trace */
|
frame->last = 1; /* Cut off top of the stack trace */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
frame = frame->next;
|
||||||
nlevels++;
|
nlevels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
wad_nlr_levels = nlevels - 1;
|
wad_nlr_levels = nlevels - 1;
|
||||||
|
|
@ -382,12 +377,13 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
wad_nlr_levels = 0;
|
wad_nlr_levels = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (sig_callback) {
|
if (sig_callback) {
|
||||||
(*sig_callback)(sig,origframe,retname);
|
(*sig_callback)(sig,origframe,retname);
|
||||||
} else {
|
} else {
|
||||||
/* No signal handler defined. Go invoke the default */
|
/* No signal handler defined. Go invoke the default */
|
||||||
|
|
||||||
wad_default_callback(sig, origframe,retname);
|
wad_default_callback(sig, origframe,retname);
|
||||||
wad_release_trace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wad_debug_mode & DEBUG_HOLD) while(1);
|
if (wad_debug_mode & DEBUG_HOLD) while(1);
|
||||||
|
|
@ -464,4 +460,14 @@ void wad_signal_init() {
|
||||||
printf("WAD: Couldn't install signal handler!\n");
|
printf("WAD: Couldn't install signal handler!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* clear signals
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void wad_signal_clear() {
|
||||||
|
signal(SIGSEGV, SIG_DFL);
|
||||||
|
signal(SIGBUS, SIG_DFL);
|
||||||
|
signal(SIGILL, SIG_DFL);
|
||||||
|
signal(SIGFPE, SIG_DFL);
|
||||||
|
signal(SIGABRT, SIG_DFL);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,95 @@ match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scan_function(Stab *s, int ns, WadDebug *debug) {
|
scan_function(Stab *s, char *stabstr, int ns, WadFrame *f) {
|
||||||
|
int i;
|
||||||
|
unsigned long offset;
|
||||||
|
offset = f->pc - f->sym_base;
|
||||||
|
|
||||||
|
for (i = 0; i < ns; i++,s++) {
|
||||||
|
if (wad_debug_mode & DEBUG_STABS) {
|
||||||
|
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
||||||
|
stabstr+s->n_strx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((s->n_type == N_UNDF) || (s->n_type == N_SO) || (s->n_type == N_FUN) ||
|
||||||
|
(s->n_type == N_OBJ)) return;
|
||||||
|
|
||||||
|
if (s->n_type == N_SLINE) {
|
||||||
|
if (s->n_value < offset) {
|
||||||
|
f->loc_line = s->n_desc;
|
||||||
|
}
|
||||||
|
} else if ((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) {
|
||||||
|
/* Parameter counting */
|
||||||
|
char *pname;
|
||||||
|
char *c;
|
||||||
|
int len;
|
||||||
|
WadLocal *arg;
|
||||||
|
pname = stabstr+s->n_strx;
|
||||||
|
c = strchr(pname,':');
|
||||||
|
if (c) {
|
||||||
|
len = (c-pname);
|
||||||
|
} else {
|
||||||
|
len = strlen(pname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the argument was already used */
|
||||||
|
/* In this case, the first stab simply identifies an argument. The second
|
||||||
|
one identifies its location for the debugger */
|
||||||
|
|
||||||
|
if (f->debug_args) {
|
||||||
|
/* Need to do some fix up for linux here */
|
||||||
|
WadLocal *a = f->debug_args;
|
||||||
|
while (a) {
|
||||||
|
if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
|
||||||
|
/* We already saw this argument. Given a choice between a register and a stack
|
||||||
|
argument. We will choose the stack version */
|
||||||
|
|
||||||
|
if (a->loc == PARM_STACK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Go ahead and use the new argument */
|
||||||
|
if (s->n_type == N_RSYM) {
|
||||||
|
a->loc = PARM_REGISTER;
|
||||||
|
a->reg = s->n_value;
|
||||||
|
} else {
|
||||||
|
a->loc = PARM_STACK;
|
||||||
|
a->stack = s->n_value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
a = a->next;
|
||||||
|
}
|
||||||
|
if (a) continue; /* We got an argument match. Just skip to the next stab */
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
|
||||||
|
arg->name = (char *) wad_malloc(len+1);
|
||||||
|
strncpy(arg->name, pname, len);
|
||||||
|
arg->name[len] = 0;
|
||||||
|
if (s->n_type == N_RSYM) {
|
||||||
|
arg->loc = PARM_REGISTER;
|
||||||
|
arg->reg = s->n_value;
|
||||||
|
arg->stack = 0;
|
||||||
|
} else {
|
||||||
|
arg->loc = PARM_STACK;
|
||||||
|
arg->line = s->n_desc;
|
||||||
|
arg->stack = s->n_value;
|
||||||
|
}
|
||||||
|
arg->type = 0;
|
||||||
|
arg->next = 0;
|
||||||
|
if (f->debug_args) {
|
||||||
|
f->debug_lastarg->next = arg;
|
||||||
|
f->debug_lastarg = arg;
|
||||||
|
} else {
|
||||||
|
f->debug_args = arg;
|
||||||
|
f->debug_lastarg = arg;
|
||||||
|
f->debug_nargs= 0;
|
||||||
|
}
|
||||||
|
f->debug_nargs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a stabs data segment (obtained somehow), this function tries to
|
/* Given a stabs data segment (obtained somehow), this function tries to
|
||||||
|
|
@ -74,43 +161,44 @@ scan_function(Stab *s, int ns, WadDebug *debug) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned long offset, WadDebug *debug) {
|
wad_search_stab(void *sp, int size, char *stabstr, WadFrame *f) {
|
||||||
Stab *s;
|
Stab *s;
|
||||||
int ns;
|
int ns;
|
||||||
int infunc;
|
int infunc;
|
||||||
int slen;
|
int slen;
|
||||||
int i;
|
int i;
|
||||||
|
int found = 0;
|
||||||
char *file, *lastfile = 0;
|
char *file, *lastfile = 0;
|
||||||
int chk = 0;
|
int chk = 0;
|
||||||
WadLocal *arg;
|
WadLocal *arg;
|
||||||
|
|
||||||
|
char srcfile[MAX_PATH];
|
||||||
|
char objfile[MAX_PATH];
|
||||||
|
|
||||||
|
if (!f->sym_name) return 0;
|
||||||
|
|
||||||
s = (Stab *) sp; /* Stabs data */
|
s = (Stab *) sp; /* Stabs data */
|
||||||
ns = size/sizeof(Stab); /* number of stabs */
|
ns = size/sizeof(Stab); /* number of stabs */
|
||||||
|
|
||||||
slen = strlen(wsym->name);
|
slen = strlen(f->sym_name);
|
||||||
|
srcfile[0] = 0;
|
||||||
/* Reset the debug information section */
|
objfile[0] = 0;
|
||||||
debug->found = 0;
|
|
||||||
debug->srcfile[0] = 0;
|
|
||||||
debug->objfile[0] = 0;
|
|
||||||
debug->line_number = -1;
|
|
||||||
debug->nargs = 0;
|
|
||||||
debug->args = 0;
|
|
||||||
debug->lastarg = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ns; i++, s++) {
|
for (i = 0; i < ns; i++, s++) {
|
||||||
|
/*
|
||||||
if (wad_debug_mode & DEBUG_STABS) {
|
if (wad_debug_mode & DEBUG_STABS) {
|
||||||
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
||||||
stabstr+s->n_strx);
|
stabstr+s->n_strx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if ((s->n_type == N_UNDF)) { /* && (s->n_desc >= 0)) { */
|
if ((s->n_type == N_UNDF)) { /* && (s->n_desc >= 0)) { */
|
||||||
/* New stabs section. We need to be a little careful here. Do a recursive
|
/* New stabs section. We need to be a little careful here. Do a recursive
|
||||||
search of the subsection. */
|
search of the subsection. */
|
||||||
|
|
||||||
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, wsym, offset,debug)) return 1;
|
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, f)) return 1;
|
||||||
|
|
||||||
/* On solaris, each stabs section seem to increment the stab string pointer. On Linux,
|
/* On solaris, each stabs section seems to increment the stab string pointer. On Linux,
|
||||||
the linker seems to do a certain amount of optimization that results in a single
|
the linker seems to do a certain amount of optimization that results in a single
|
||||||
string table. */
|
string table. */
|
||||||
|
|
||||||
|
|
@ -119,112 +207,48 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
#endif
|
#endif
|
||||||
i += s->n_desc;
|
i += s->n_desc;
|
||||||
s += s->n_desc;
|
s += s->n_desc;
|
||||||
debug->objfile[0] = 0;
|
objfile[0] = 0;
|
||||||
debug->srcfile[0] = 0;
|
srcfile[0] = 0;
|
||||||
debug->line_number = -1;
|
|
||||||
debug->found = 0;
|
|
||||||
continue;
|
continue;
|
||||||
} else if (s->n_type == N_SO) {
|
} else if (s->n_type == N_SO) {
|
||||||
if (debug->found) return 1; /* New file and we already found what we wanted */
|
|
||||||
/* Source file specification */
|
/* Source file specification */
|
||||||
/* Look for directory */
|
/* Look for directory */
|
||||||
file = stabstr+s->n_strx;
|
file = stabstr+s->n_strx;
|
||||||
if (strlen(file) && (file[strlen(file)-1] == '/')) {
|
if (strlen(file) && (file[strlen(file)-1] == '/')) {
|
||||||
strcpy(debug->srcfile,file);
|
strcpy(srcfile,file);
|
||||||
} else {
|
} else {
|
||||||
strcat(debug->srcfile,file);
|
strcat(srcfile,file);
|
||||||
}
|
}
|
||||||
debug->objfile[0] = 0;
|
objfile[0] = 0;
|
||||||
|
/* If we have a file match, we might be looking for a local symbol. If so,
|
||||||
|
we'll go ahead and set the srcfile field of the frame */
|
||||||
|
|
||||||
/* We're going to check for a file match. Maybe we're looking for a local symbol */
|
/* We're going to check for a file match. Maybe we're looking for a local symbol */
|
||||||
if (wsym->file && strcmp(wsym->file,file) == 0) {
|
if (f->sym_file && strcmp(f->sym_file,file) == 0) {
|
||||||
debug->found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
lastfile = file;
|
lastfile = file;
|
||||||
} else if (s->n_type == N_OBJ) {
|
} else if (s->n_type == N_OBJ) {
|
||||||
/* Object file specifier */
|
/* Object file specifier */
|
||||||
if (debug->objfile[0]) {
|
if (objfile[0]) {
|
||||||
strcat(debug->objfile,"/");
|
strcat(objfile,"/");
|
||||||
}
|
}
|
||||||
strcat(debug->objfile,stabstr+s->n_strx);
|
strcat(objfile,stabstr+s->n_strx);
|
||||||
} else if (s->n_type == N_FUN) {
|
} else if (s->n_type == N_FUN) {
|
||||||
if (match_stab_symbol(wsym->name, stabstr+s->n_strx, slen)) {
|
if (match_stab_symbol(f->sym_name, stabstr+s->n_strx, slen)) {
|
||||||
if (!wsym->file || (strcmp(wsym->file,lastfile) == 0)) {
|
if (!f->sym_file || (strcmp(f->sym_file,lastfile) == 0)) {
|
||||||
infunc = 1;
|
/* Go find debugging information for the function */
|
||||||
debug->found = 1;
|
scan_function(s+1, stabstr, ns -i - 1, f);
|
||||||
debug->nargs = 0;
|
f->loc_srcfile = wad_strdup(srcfile);
|
||||||
} else {
|
f->loc_objfile = wad_strdup(objfile);
|
||||||
infunc = 0;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
infunc = 0;
|
|
||||||
}
|
}
|
||||||
} else if (debug->found && (s->n_type == N_SLINE) && (infunc)) {
|
|
||||||
/* Line number location */
|
|
||||||
if (s->n_value < offset) {
|
|
||||||
debug->line_number = s->n_desc;
|
|
||||||
} else return 1;
|
|
||||||
} else if (debug->found && ((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) && (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 the argument was already used */
|
|
||||||
/* In this case, the first stab simply identifies an argument. The second
|
|
||||||
one identifies its location for the debugger */
|
|
||||||
|
|
||||||
if (debug->args) {
|
|
||||||
/* Need to do some fix up for linux here */
|
|
||||||
WadLocal *a = debug->args;
|
|
||||||
while (a) {
|
|
||||||
if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
|
|
||||||
/* We already saw this argument. Given a choice between a register and a stack
|
|
||||||
argument. We will choose the stack version */
|
|
||||||
if (a->loc == PARM_STACK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Go ahead and use the new argument */
|
|
||||||
if (s->n_type == 0x40)
|
|
||||||
a->loc = PARM_REGISTER;
|
|
||||||
else
|
|
||||||
a->loc = PARM_STACK;
|
|
||||||
a->position = s->n_value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
a = a->next;
|
|
||||||
}
|
|
||||||
if (a) continue; /* We got an argument match. Just skip to the next stab */
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
|
|
||||||
arg->name = (char *) wad_malloc(len+1);
|
|
||||||
strncpy(arg->name, pname, len);
|
|
||||||
arg->name[len] = 0;
|
|
||||||
if (s->n_type == 0x40)
|
|
||||||
arg->loc = PARM_REGISTER;
|
|
||||||
else
|
|
||||||
arg->loc = PARM_STACK;
|
|
||||||
|
|
||||||
arg->position = s->n_value;
|
|
||||||
arg->type = 0;
|
|
||||||
arg->next = 0;
|
|
||||||
if (debug->args) {
|
|
||||||
debug->lastarg->next = arg;
|
|
||||||
debug->lastarg = arg;
|
|
||||||
} else {
|
|
||||||
debug->args = arg;
|
|
||||||
debug->lastarg = arg;
|
|
||||||
}
|
|
||||||
debug->nargs++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug->found) return 1;
|
if (found) {
|
||||||
return 0;
|
f->loc_srcfile = wad_strdup(srcfile);
|
||||||
|
f->loc_objfile = wad_strdup(objfile);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* stack.c
|
* stack.c
|
||||||
*
|
*
|
||||||
* This file is used to unwind the C call stack.
|
* This file unwinds the C call stack and creates a list of stack frames.
|
||||||
*
|
*
|
||||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||||
*
|
*
|
||||||
|
|
@ -10,252 +10,211 @@
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
/* This needs to be changed so that the value is dynamically determined
|
/* -----------------------------------------------------------------------------
|
||||||
Might also get weird problems with stacks located in different regions. */
|
* new_frame()
|
||||||
|
*
|
||||||
|
* Create a new stack frame object and initialize all of the fields.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifdef WAD_SOLARIS
|
static WadFrame *
|
||||||
#define STACK_BASE 0xffbf0000
|
new_frame() {
|
||||||
#endif
|
WadFrame *f;
|
||||||
#ifdef WAD_LINUX
|
f = (WadFrame *) wad_malloc(sizeof(WadFrame));
|
||||||
#define STACK_BASE 0xc0000000
|
f->frameno = 0;
|
||||||
#endif
|
f->segment = 0;
|
||||||
|
f->object = 0;
|
||||||
|
f->pc = 0;
|
||||||
|
f->sp = 0;
|
||||||
|
f->sp = 0;
|
||||||
|
f->stack = 0;
|
||||||
|
f->stack_size = 0;
|
||||||
|
|
||||||
|
f->sym_name = 0;
|
||||||
|
f->sym_file = 0;
|
||||||
|
f->sym_base = 0;
|
||||||
|
f->sym_size = 0;
|
||||||
|
f->sym_type = 0;
|
||||||
|
f->sym_bind = 0;
|
||||||
|
|
||||||
|
f->loc_objfile = 0;
|
||||||
|
f->loc_srcfile = 0;
|
||||||
|
f->loc_line = 0;
|
||||||
|
|
||||||
|
f->debug_nargs = -1;
|
||||||
|
f->debug_args = 0;
|
||||||
|
f->debug_lastarg = 0;
|
||||||
|
|
||||||
|
f->last = 0;
|
||||||
|
f->next = 0;
|
||||||
|
f->prev = 0;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* stack_unwind()
|
* stack_unwind()
|
||||||
*
|
*
|
||||||
* Perform a single level of stack unwinding given the stack pointer, frame pointer
|
* This function performs a single level of stack unwinding given the stack pointer
|
||||||
* and program counter.
|
* frame pointer and program counter. Validations are made to make sure the stack
|
||||||
|
* and frame pointers are in valid memory. Updates the values of the sp, pc, and fp
|
||||||
|
* in-place. Returns a stack frame object on success, 0 if memory is invalid
|
||||||
|
* or the end of the stack has been reached.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static WadFrame *
|
||||||
stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) {
|
stack_unwind(unsigned long *pc, unsigned long *sp, unsigned long *fp) {
|
||||||
|
WadSegment *sp_seg, *fp_seg;
|
||||||
|
WadFrame *f;
|
||||||
if (wad_debug_mode & DEBUG_UNWIND) {
|
if (wad_debug_mode & DEBUG_UNWIND) {
|
||||||
wad_printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
|
wad_printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify that the sp and fp are in mapped memory */
|
||||||
|
sp_seg = wad_segment_find((void *) *sp);
|
||||||
|
fp_seg = wad_segment_find((void *) *fp);
|
||||||
|
|
||||||
|
if (!(sp_seg && fp_seg && (sp_seg == fp_seg))) {
|
||||||
|
/* Either the stack pointer or frame pointer is invalid. Or, the stack pointer
|
||||||
|
and frame pointer are in different memory regions. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check to see if the PC is valid */
|
||||||
|
if (!wad_segment_valid((void *) *pc)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = new_frame();
|
||||||
|
f->pc = *pc;
|
||||||
|
f->sp = *sp;
|
||||||
|
f->fp = *fp;
|
||||||
|
f->segment = wad_segment_find((void *) *pc);
|
||||||
|
f->stack_size = *fp - *sp;
|
||||||
|
|
||||||
|
/* Make a copy of the call stack */
|
||||||
|
f->stack = (char *) wad_malloc(f->stack_size);
|
||||||
|
memcpy(f->stack,(void *) *sp, f->stack_size);
|
||||||
|
|
||||||
|
/* Update the sp, fp, and pc */
|
||||||
|
|
||||||
#ifdef WAD_SOLARIS
|
#ifdef WAD_SOLARIS
|
||||||
*pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
|
*pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
|
||||||
*sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
|
*sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
|
||||||
|
if (wad_segment_valid((void *) *sp)) {
|
||||||
|
*fp = *((unsigned long *) *sp+14);
|
||||||
|
} else {
|
||||||
|
*fp = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
*pc = *((unsigned long *) *fp+1);
|
if (wad_segment_valid((void *) ((unsigned long *) *fp+1))) {
|
||||||
*sp = *fp;
|
*pc = *((unsigned long *) *fp+1);
|
||||||
*fp = *((unsigned long *) *fp);
|
*sp = *fp;
|
||||||
|
} else {
|
||||||
/* If we get a frame pointer of zero, we've gone off the end of the stack. Set the
|
|
||||||
stack pointer to zero to signal the stack unwinder. */
|
|
||||||
|
|
||||||
if (*fp == 0) {
|
|
||||||
*sp = 0;
|
*sp = 0;
|
||||||
}
|
}
|
||||||
|
if (wad_segment_valid((void *) ((unsigned long *) *fp))) {
|
||||||
|
*fp = *((unsigned long *) *fp);
|
||||||
|
} else {
|
||||||
|
*fp = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_stack_trace()
|
* wad_stack_trace()
|
||||||
*
|
*
|
||||||
* Create a stack trace of the process. Returns a linked list of stack frames
|
* Create a stack trace of the process. Returns a linked list of stack frames
|
||||||
* with debugging information and other details.
|
* with a limited about debugging information and other details.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
WadFrame *
|
WadFrame *
|
||||||
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
WadSegment *ws;
|
|
||||||
WadObjectFile *wo;
|
|
||||||
WadFrame *firstframe=0, *lastframe=0, *frame=0;
|
WadFrame *firstframe=0, *lastframe=0, *frame=0;
|
||||||
WadDebug wd;
|
|
||||||
WadSymbol wsym;
|
|
||||||
|
|
||||||
unsigned long p_pc;
|
unsigned long p_pc;
|
||||||
unsigned long p_sp;
|
unsigned long p_sp;
|
||||||
unsigned long p_fp;
|
unsigned long p_fp;
|
||||||
unsigned long p_lastsp;
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
/* Read the segments */
|
|
||||||
if (wad_segment_read() < 0) {
|
|
||||||
wad_printf("WAD: Unable to read segment map\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Try to do a stack traceback */
|
/* Try to do a stack traceback */
|
||||||
|
|
||||||
p_pc = pc;
|
p_pc = pc;
|
||||||
p_sp = sp;
|
p_sp = sp;
|
||||||
p_fp = fp;
|
p_fp = fp;
|
||||||
|
|
||||||
while (p_sp) {
|
while ((frame = stack_unwind(&p_pc, &p_sp, &p_fp))) {
|
||||||
/* Add check for stack validity here */
|
/* Got a frame successfully */
|
||||||
ws = wad_segment_find((void *) p_sp);
|
frame->frameno = n;
|
||||||
|
if (lastframe) {
|
||||||
if (!ws) {
|
lastframe->next = frame;
|
||||||
/* 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((void *) p_pc);
|
|
||||||
{
|
|
||||||
int stacksize = 0;
|
|
||||||
char *symname = 0;
|
|
||||||
unsigned long value;
|
|
||||||
|
|
||||||
/* Try to load the object file for this address */
|
|
||||||
if (ws) {
|
|
||||||
wo = wad_object_load(ws->mappath);
|
|
||||||
}
|
|
||||||
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->base, &wsym);
|
|
||||||
} else {
|
|
||||||
symname = 0;
|
|
||||||
}
|
|
||||||
value = wsym.value;
|
|
||||||
|
|
||||||
frame = (WadFrame *) wad_malloc(sizeof(WadFrame));
|
|
||||||
frame->frameno = n;
|
|
||||||
frame->pc = p_pc;
|
|
||||||
frame->sp = p_sp;
|
|
||||||
frame->nlocals = -1;
|
|
||||||
frame->nargs = -1;
|
|
||||||
frame->objfile = 0;
|
|
||||||
frame->srcfile = 0;
|
|
||||||
frame->psp = 0;
|
|
||||||
frame->next = 0;
|
|
||||||
frame->prev = lastframe;
|
frame->prev = lastframe;
|
||||||
frame->last = 0;
|
lastframe = frame;
|
||||||
if (lastframe) {
|
} else {
|
||||||
lastframe->next = frame;
|
firstframe = frame;
|
||||||
lastframe = frame;
|
lastframe = frame;
|
||||||
} else {
|
|
||||||
lastframe = frame;
|
|
||||||
firstframe = frame;
|
|
||||||
}
|
|
||||||
frame->symbol = wad_strdup(symname);
|
|
||||||
frame->sym_base = value + (long) ws->base;
|
|
||||||
n++;
|
|
||||||
if (symname) {
|
|
||||||
/* Try to gather some debugging information about this symbol */
|
|
||||||
if (wad_debug_info(wo,&wsym, p_pc - (unsigned long) ws->base - value, &wd)) {
|
|
||||||
frame->srcfile = wad_strdup(wd.srcfile);
|
|
||||||
frame->objfile = wad_strdup(wd.objfile);
|
|
||||||
frame->args = wd.args;
|
|
||||||
frame->lastarg = wd.lastarg;
|
|
||||||
frame->nargs = wd.nargs;
|
|
||||||
|
|
||||||
/*frame.nargs = wd.nargs;
|
|
||||||
if (wd.nargs > 0) {
|
|
||||||
argsize = sizeof(WadParm)*wd.nargs;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
frame->line_number = wd.line_number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WAD_SOLARIS
|
|
||||||
|
|
||||||
#ifdef OLD /* Might not be necessary. Registers stored on stack already */
|
|
||||||
/* 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++) {
|
|
||||||
/* wad_printf("regs[%d] = 0x%x\n", lsp[i]); */
|
|
||||||
frame.regs[i] = lsp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* Determine stack frame size */
|
|
||||||
p_lastsp = p_sp;
|
|
||||||
stack_unwind(&p_sp, &p_pc, &p_fp);
|
|
||||||
|
|
||||||
if (p_sp) {
|
|
||||||
stacksize = p_sp - p_lastsp;
|
|
||||||
} else {
|
|
||||||
stacksize = STACK_BASE - p_lastsp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
if ((p_sp + stacksize) > STACK_BASE) {
|
|
||||||
stacksize = STACK_BASE - p_sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the frame pointer and stack size */
|
|
||||||
frame->fp = p_sp;
|
|
||||||
frame->stack_size = stacksize;
|
|
||||||
|
|
||||||
/* Copy stack data */
|
|
||||||
frame->psp = (char *) wad_malloc(stacksize);
|
|
||||||
if (frame->psp) {
|
|
||||||
memcpy(frame->psp, (void *) p_lastsp, stacksize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
n++;
|
||||||
}
|
}
|
||||||
lastframe->last = 1;
|
if (lastframe)
|
||||||
|
lastframe->last = 1;
|
||||||
return firstframe;
|
return firstframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wad_release_trace() {
|
/* -----------------------------------------------------------------------------
|
||||||
}
|
* wad_stack_debug()
|
||||||
|
*
|
||||||
|
* Make a dump of a stack trace
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* This function steals an argument out of a frame further up the call stack :-) */
|
void wad_stack_debug(WadFrame *frame) {
|
||||||
long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
|
if (wad_debug_mode & DEBUG_STACK) {
|
||||||
long *regs;
|
/* Walk the exception frames and try to find a return point */
|
||||||
WadFrame *lastf = 0;
|
while (frame) {
|
||||||
|
/* Print out detailed stack trace information */
|
||||||
|
printf("::: Stack frame - 0x%08x :::\n", frame);
|
||||||
|
printf(" pc = %x\n", frame->pc);
|
||||||
|
printf(" sp = %x\n", frame->sp);
|
||||||
|
printf(" fp = %x\n", frame->fp);
|
||||||
|
printf(" stack = %x\n", frame->stack);
|
||||||
|
printf(" size = %x\n", frame->stack_size);
|
||||||
|
printf(" segment = %x (%s)\n", frame->segment, frame->segment ? frame->segment->mappath : "?");
|
||||||
|
printf(" object = %x (%s)\n", frame->object, frame->object ? frame->object->path : "?");
|
||||||
|
|
||||||
*error = 0;
|
if (frame->sym_name) {
|
||||||
/* Start searching */
|
printf(" sym_name = %s\n", frame->sym_name);
|
||||||
while (f) {
|
printf(" sym_base = %x\n", frame->sym_base);
|
||||||
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
|
printf(" sym_size = %x\n", frame->sym_size);
|
||||||
/* Got a match */
|
printf(" sym_bind = %x\n", frame->sym_bind);
|
||||||
if (lastf) {
|
printf(" sym_file = %s\n", frame->sym_file ? frame->sym_file : "");
|
||||||
regs = (long *) f->psp;
|
|
||||||
return regs[8+argno];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
lastf = f;
|
|
||||||
f = f->next;
|
|
||||||
}
|
|
||||||
*error = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (frame->loc_srcfile) {
|
||||||
long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
|
printf(" loc_srcfile = %s\n", frame->loc_srcfile);
|
||||||
long *regs;
|
|
||||||
WadFrame *lastf = 0;
|
|
||||||
|
|
||||||
*error = 0;
|
|
||||||
/* Start searching */
|
|
||||||
while (f) {
|
|
||||||
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
|
|
||||||
/* Got a match */
|
|
||||||
if (lastf) {
|
|
||||||
#ifdef WAD_SOLARIS
|
|
||||||
regs = (long *) lastf->psp;
|
|
||||||
return regs[8+argno];
|
|
||||||
#endif
|
|
||||||
#ifdef WAD_LINUX
|
|
||||||
regs = (long *) f->psp;
|
|
||||||
return regs[argno+2];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frame->loc_objfile) {
|
||||||
|
printf(" loc_objfile = %s\n", frame->loc_objfile);
|
||||||
|
}
|
||||||
|
printf(" loc_line = %d\n", frame->loc_line);
|
||||||
|
|
||||||
|
|
||||||
|
printf(" debug_nargs = %d\n", frame->debug_nargs);
|
||||||
|
if (frame->debug_args) {
|
||||||
|
int i = 0;
|
||||||
|
WadLocal *p = frame->debug_args;
|
||||||
|
printf(" debug_args = [ \n");
|
||||||
|
while (p) {
|
||||||
|
printf(" arg[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" ]\n");
|
||||||
|
|
||||||
|
frame = frame->next;
|
||||||
}
|
}
|
||||||
lastf = f;
|
|
||||||
f = f->next;
|
|
||||||
}
|
}
|
||||||
*error = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
119
SWIG/Tools/WAD/Wad/vars.c
Normal file
119
SWIG/Tools/WAD/Wad/vars.c
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* vars.c
|
||||||
|
*
|
||||||
|
* This file examines the stack trace and tries to make some sense out of
|
||||||
|
* collected debugging information. This includes locating the data on
|
||||||
|
* the stack and/or registers.
|
||||||
|
*
|
||||||
|
* This feature is detached from the debugging info collector to make
|
||||||
|
* it independent of debugging formats.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_build_vars()
|
||||||
|
*
|
||||||
|
* Build variable information for a single stack frame
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void wad_build_vars(WadFrame *f) {
|
||||||
|
char *stack = 0;
|
||||||
|
char *nstack = 0;
|
||||||
|
char *pstack = 0;
|
||||||
|
WadLocal *loc;
|
||||||
|
int laststack = 0;
|
||||||
|
WadLocal *lastloc = 0;
|
||||||
|
|
||||||
|
stack = (char *) f->stack;
|
||||||
|
if (f->next) {
|
||||||
|
nstack = (char *) f->next->stack;
|
||||||
|
}
|
||||||
|
if (f->prev) {
|
||||||
|
pstack = (char *) f->prev->stack;
|
||||||
|
}
|
||||||
|
loc = f->debug_args;
|
||||||
|
|
||||||
|
while (loc) {
|
||||||
|
loc->ptr = 0;
|
||||||
|
if (loc->loc == PARM_STACK) {
|
||||||
|
if ((loc->stack >= 0) && (nstack)) {
|
||||||
|
loc->ptr = (void *) (nstack + loc->stack);
|
||||||
|
} else if (loc->stack < 0) {
|
||||||
|
loc->ptr = (void *) (stack + f->stack_size + loc->stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastloc) {
|
||||||
|
/* Figure out the size */
|
||||||
|
if (!lastloc->size)
|
||||||
|
lastloc->size = abs(loc->stack - lastloc->stack);
|
||||||
|
}
|
||||||
|
lastloc = loc;
|
||||||
|
loc = loc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If last size is not set. Assume that it is a word */
|
||||||
|
if (lastloc && (!lastloc->size)) {
|
||||||
|
lastloc->size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to make a formatted version of a local */
|
||||||
|
char *wad_format_var(WadLocal *l) {
|
||||||
|
static char hexdigits[] = "0123456789abcdef";
|
||||||
|
static char buffer[1024];
|
||||||
|
|
||||||
|
buffer[0] = 0;
|
||||||
|
|
||||||
|
switch(l->type) {
|
||||||
|
case TYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
/* Hmmm. Unknown data type. We'll just dump out digits */
|
||||||
|
if (l->ptr) {
|
||||||
|
if (l->size <= 8) {
|
||||||
|
int incr,i;
|
||||||
|
int b;
|
||||||
|
int leading = 1;
|
||||||
|
char *c;
|
||||||
|
char *ptr;
|
||||||
|
#ifdef WAD_LITTLE_ENDIAN
|
||||||
|
ptr = ((char *) l->ptr) + l->size - 1;
|
||||||
|
incr = -1;
|
||||||
|
#else
|
||||||
|
ptr = (char *) l->ptr;
|
||||||
|
incr =1 ;
|
||||||
|
#endif
|
||||||
|
strcat(buffer,"0x");
|
||||||
|
c = buffer+2;
|
||||||
|
for (i = 0; i < l->size; i++) {
|
||||||
|
b = (int) *ptr;
|
||||||
|
if (!leading || (b)) {
|
||||||
|
if (!leading || (b & 0xf0))
|
||||||
|
*(c++) = hexdigits[(b & 0xf0) >> 4];
|
||||||
|
*(c++) = hexdigits[(b & 0xf)];
|
||||||
|
leading = 0;
|
||||||
|
}
|
||||||
|
ptr += incr;
|
||||||
|
}
|
||||||
|
if (leading)
|
||||||
|
*(c++) = '0';
|
||||||
|
|
||||||
|
*c = 0;
|
||||||
|
} else {
|
||||||
|
sprintf(buffer,"unknown(%d bytes)", l->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -100,10 +100,11 @@ static void handler(int signo, WadFrame *frame, char *ret) {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
PyObject *type;
|
PyObject *type;
|
||||||
char *name;
|
char *name;
|
||||||
char *fd;
|
|
||||||
WadFrame *f;
|
WadFrame *f;
|
||||||
WadFrame *fline = 0;
|
WadFrame *fline = 0;
|
||||||
|
|
||||||
|
|
||||||
|
printf("python handler.\n");
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
wad_default_callback(signo, frame, ret);
|
wad_default_callback(signo, frame, ret);
|
||||||
return;
|
return;
|
||||||
|
|
@ -130,34 +131,32 @@ static void handler(int signo, WadFrame *frame, char *ret) {
|
||||||
type = PyExc_RuntimeError;
|
type = PyExc_RuntimeError;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fd = (char *) frame;
|
|
||||||
f = (WadFrame *) fd;
|
|
||||||
|
|
||||||
|
f = frame;
|
||||||
/* Find the last exception frame */
|
/* Find the last exception frame */
|
||||||
while (!f->last) {
|
while (!f->last) {
|
||||||
fd = fd + f->size;
|
f= f->next;
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
|
printf("f = %x\n", f);
|
||||||
/* Now work backwards */
|
/* Now work backwards */
|
||||||
fd = fd - f->lastsize;
|
f = f->prev;
|
||||||
f = (WadFrame *) fd;
|
while (f) {
|
||||||
while (1) {
|
|
||||||
sprintf(temp,"#%-3d 0x%08x in ", f->frameno, f->pc);
|
sprintf(temp,"#%-3d 0x%08x in ", f->frameno, f->pc);
|
||||||
strcat(message,temp);
|
strcat(message,temp);
|
||||||
strcat(message,*(fd + f->sym_off) ? fd+f->sym_off : "?");
|
strcat(message, f->sym_name ? f->sym_name : "?");
|
||||||
strcat(message,"(");
|
strcat(message,"(");
|
||||||
strcat(message,wad_arg_string(f));
|
strcat(message,wad_arg_string(f));
|
||||||
strcat(message,")");
|
strcat(message,")");
|
||||||
if (strlen(SRCFILE(f))) {
|
if (f->loc_srcfile && strlen(f->loc_srcfile)) {
|
||||||
strcat(message," in '");
|
strcat(message," in '");
|
||||||
strcat(message, wad_strip_dir(SRCFILE(f)));
|
strcat(message, wad_strip_dir(f->loc_srcfile));
|
||||||
strcat(message,"'");
|
strcat(message,"'");
|
||||||
if (f->line_number > 0) {
|
if (f->loc_line > 0) {
|
||||||
sprintf(temp,", line %d", f->line_number);
|
sprintf(temp,", line %d", f->loc_line);
|
||||||
strcat(message,temp);
|
strcat(message,temp);
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
fd = open(SRCFILE(f), O_RDONLY);
|
fd = open(f->loc_srcfile, O_RDONLY);
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
fline = f;
|
fline = f;
|
||||||
}
|
}
|
||||||
|
|
@ -165,34 +164,32 @@ static void handler(int signo, WadFrame *frame, char *ret) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strlen(fd+f->obj_off)) {
|
if (f->loc_objfile && strlen(f->loc_objfile)) {
|
||||||
strcat(message," from '");
|
strcat(message," from '");
|
||||||
strcat(message, wad_strip_dir(OBJFILE(f)));
|
strcat(message, wad_strip_dir(f->loc_objfile));
|
||||||
strcat(message,"'");
|
strcat(message,"'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strcat(message,"\n");
|
strcat(message,"\n");
|
||||||
if (!f->lastsize) break;
|
f = f->prev;
|
||||||
fd = fd - f->lastsize;
|
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
if (fline) {
|
if (fline) {
|
||||||
int first;
|
int first;
|
||||||
int last;
|
int last;
|
||||||
char *line, *c;
|
char *line, *c;
|
||||||
int i;
|
int i;
|
||||||
first = fline->line_number - 2;
|
first = fline->loc_line - 2;
|
||||||
last = fline->line_number + 2;
|
last = fline->loc_line + 2;
|
||||||
if (first < 1) first = 1;
|
if (first < 1) first = 1;
|
||||||
|
|
||||||
line = wad_load_source(SRCFILE(fline),first);
|
line = wad_load_source(fline->loc_srcfile,first);
|
||||||
if (line) {
|
if (line) {
|
||||||
strcat(message,"\n");
|
strcat(message,"\n");
|
||||||
strcat(message, SRCFILE(fline));
|
strcat(message, fline->loc_srcfile);
|
||||||
sprintf(temp,", line %d\n\n", fline->line_number);
|
sprintf(temp,", line %d\n\n", fline->loc_line);
|
||||||
strcat(message, temp);
|
strcat(message, temp);
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++) {
|
||||||
if (i == fline->line_number) strcat(message," => ");
|
if (i == fline->loc_line) strcat(message," => ");
|
||||||
else strcat(message," ");
|
else strcat(message," ");
|
||||||
c = strchr(line,'\n');
|
c = strchr(line,'\n');
|
||||||
if (c) {
|
if (c) {
|
||||||
|
|
@ -222,7 +219,6 @@ static void handler(int signo, WadFrame *frame, char *ret) {
|
||||||
back. */
|
back. */
|
||||||
|
|
||||||
PyErr_SetString(type, message);
|
PyErr_SetString(type, message);
|
||||||
wad_release_trace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pywadinit() {
|
static void pywadinit() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue