*** empty log message ***
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@1011 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
cd2f18170d
commit
bb2b81dc43
9 changed files with 296 additions and 329 deletions
|
|
@ -33,18 +33,20 @@ extern "C" {
|
||||||
#define MAX_PATH 1024
|
#define MAX_PATH 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Low level memory management */
|
/* --- Low level memory management --- */
|
||||||
|
|
||||||
extern int wad_memory_init();
|
extern int wad_memory_init();
|
||||||
extern void *wad_malloc(int nbytes);
|
extern void *wad_malloc(int nbytes);
|
||||||
|
extern void *wad_pmalloc(int nbytes);
|
||||||
extern void wad_release_memory();
|
extern void wad_release_memory();
|
||||||
extern char *wad_strdup(const char *c);
|
extern char *wad_strdup(const char *c);
|
||||||
|
extern char *wad_pstrdup(const char *c);
|
||||||
|
|
||||||
/* I/O */
|
/* --- I/O, Debugging --- */
|
||||||
|
|
||||||
extern void wad_printf(const char *fmt, ...);
|
extern void wad_printf(const char *fmt, ...);
|
||||||
|
|
||||||
/* Memory segments */
|
/* --- Memory segments --- */
|
||||||
typedef struct WadSegment {
|
typedef struct WadSegment {
|
||||||
char *base; /* Base address for symbol lookup */
|
char *base; /* Base address for symbol lookup */
|
||||||
char *vaddr; /* Virtual address start */
|
char *vaddr; /* Virtual address start */
|
||||||
|
|
@ -58,9 +60,8 @@ 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);
|
||||||
|
|
||||||
/* Object file handling */
|
/* --- Object file handling --- */
|
||||||
typedef struct WadObjectFile {
|
typedef struct WadObjectFile {
|
||||||
struct WadFile *file; /* File data (private) */
|
|
||||||
void *ptr; /* Pointer to data */
|
void *ptr; /* Pointer to data */
|
||||||
int len; /* Length of data */
|
int len; /* Length of data */
|
||||||
int type; /* Type of the object file */
|
int type; /* Type of the object file */
|
||||||
|
|
@ -71,7 +72,7 @@ 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 */
|
/* --- Symbol table information --- */
|
||||||
|
|
||||||
typedef struct WadSymbol {
|
typedef struct WadSymbol {
|
||||||
char *name; /* Symbol table name */
|
char *name; /* Symbol table name */
|
||||||
|
|
@ -97,21 +98,23 @@ extern void wad_set_return_func(void (*f)(void));
|
||||||
extern int wad_elf_check(WadObjectFile *wo);
|
extern int wad_elf_check(WadObjectFile *wo);
|
||||||
extern void wad_elf_debug(WadObjectFile *wo);
|
extern void wad_elf_debug(WadObjectFile *wo);
|
||||||
|
|
||||||
typedef struct WadParm {
|
typedef struct WadLocal {
|
||||||
char name[64];
|
char *name; /* Name of the local */
|
||||||
int loc; /* Location: register or stack */
|
int loc; /* Location: register or stack */
|
||||||
int type; /* Argument type */
|
int type; /* Argument type */
|
||||||
int value; /* Argument position from stabs */
|
unsigned long position; /* Position on the stack */
|
||||||
} WadParm;
|
struct WadLocal *next;
|
||||||
|
} WadLocal;
|
||||||
|
|
||||||
/* Debugging information */
|
/* Debugging information */
|
||||||
typedef struct WadDebug {
|
typedef struct WadDebug {
|
||||||
int found; /* Whether or not debugging information was found */
|
int found; /* Whether or not debugging information was found */
|
||||||
char srcfile[1024]; /* Source file */
|
char srcfile[1024]; /* Source file */
|
||||||
char objfile[1024]; /* Object file */
|
char objfile[1024]; /* Object file */
|
||||||
int line_number; /* Line number */
|
int line_number; /* Line number */
|
||||||
int nargs; /* Number of function arguments */
|
int nargs; /* Number of function arguments */
|
||||||
WadParm parms[100]; /* Parameters */
|
WadLocal *args; /* Arguments */
|
||||||
|
WadLocal *lastarg;
|
||||||
} WadDebug;
|
} WadDebug;
|
||||||
|
|
||||||
#define PARM_REGISTER 1
|
#define PARM_REGISTER 1
|
||||||
|
|
@ -120,39 +123,29 @@ typedef struct WadDebug {
|
||||||
extern int wad_search_stab(void *stab, int size, char *stabstr, WadSymbol *symbol, unsigned long offset, WadDebug *wd);
|
extern int wad_search_stab(void *stab, int size, char *stabstr, WadSymbol *symbol, unsigned long offset, WadDebug *wd);
|
||||||
extern int wad_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd);
|
extern int wad_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd);
|
||||||
|
|
||||||
|
/* Data structure containing information about each stack frame */
|
||||||
|
|
||||||
/* This data structure is used to report exception data back to handler functions
|
|
||||||
The offset fields contain offsets from the start of the frame to a location in
|
|
||||||
the data segment */
|
|
||||||
|
|
||||||
typedef struct WadFrame {
|
typedef struct WadFrame {
|
||||||
long size; /* Frame size */
|
long frameno; /* Frame number */
|
||||||
long lastsize; /* Size of previous frame */
|
long pc; /* Real PC */
|
||||||
long last; /* Last frame ? */
|
long sp; /* Real SP */
|
||||||
long frameno; /* Frame number */
|
long fp; /* Real FP */
|
||||||
long pc; /* Program counter */
|
char *psp; /* Pointer to where the actual stack data is stored */
|
||||||
long sp; /* Stack pointer */
|
int stack_size; /* Stack frame size */
|
||||||
long fp; /* Frame pointer */
|
char *symbol; /* Symbol name */
|
||||||
long nargs; /* Number of arguments */
|
long sym_base; /* Symbol base address */
|
||||||
long arg_off; /* Argument offset */
|
char *objfile; /* Object file */
|
||||||
long line_number; /* Source line number */
|
char *srcfile; /* Source file */
|
||||||
long sym_base; /* Symbol base address */
|
int line_number; /* Source line */
|
||||||
long sym_off; /* Symbol name offset */
|
int nargs; /* Number of arguments */
|
||||||
long src_off; /* Source filename offset */
|
WadLocal *args; /* Function arguments */
|
||||||
long obj_off; /* Object filename offset */
|
WadLocal *lastarg; /* Last argument */
|
||||||
long stack_off; /* Stack offset */
|
int nlocals; /* Number of locals */
|
||||||
long stack_size; /* Size of the stack segment */
|
int last; /* Last frame flag */
|
||||||
long regs[16]; /* Integer registers (%on, %ln) */
|
struct WadFrame *next; /* Next frame up the stack */
|
||||||
double fregs[16]; /* Floating point registers */
|
struct WadFrame *prev; /* Previous frame down the stack */
|
||||||
char data[8]; /* Frame data */
|
|
||||||
} WadFrame;
|
} WadFrame;
|
||||||
|
|
||||||
#define SRCFILE(x) ((char *) x) + x->src_off
|
|
||||||
#define SYMBOL(x) ((char *) x) + x->sym_off
|
|
||||||
#define OBJFILE(x) ((char *) x) + x->obj_off
|
|
||||||
#define STACK(x) (long *) (((char *) x) + x->stack_off)
|
|
||||||
#define ARGUMENTS(x) (WadParm *) (((char *) x) + x->arg_off)
|
|
||||||
|
|
||||||
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 char *wad_strip_dir(char *);
|
||||||
extern void wad_default_callback(int signo, WadFrame *frame, char *ret);
|
extern void wad_default_callback(int signo, WadFrame *frame, char *ret);
|
||||||
|
|
@ -175,20 +168,20 @@ extern WadReturnFunc *wad_check_return(const char *name);
|
||||||
|
|
||||||
/* --- Debugging Interface --- */
|
/* --- Debugging Interface --- */
|
||||||
|
|
||||||
#define DEBUG_SEGMENT 0x1
|
#define DEBUG_SEGMENT 0x1
|
||||||
#define DEBUG_SYMBOL 0x2
|
#define DEBUG_SYMBOL 0x2
|
||||||
#define DEBUG_STABS 0x4
|
#define DEBUG_STABS 0x4
|
||||||
#define DEBUG_OBJECT 0x8
|
#define DEBUG_OBJECT 0x8
|
||||||
#define DEBUG_FILE 0x10
|
#define DEBUG_FILE 0x10
|
||||||
#define DEBUG_HOLD 0x20
|
#define DEBUG_HOLD 0x20
|
||||||
#define DEBUG_RETURN 0x40
|
#define DEBUG_RETURN 0x40
|
||||||
#define DEBUG_SYMBOL_SEARCH 0x80
|
#define DEBUG_SYMBOL_SEARCH 0x80
|
||||||
#define DEBUG_INIT 0x100
|
#define DEBUG_INIT 0x100
|
||||||
#define DEBUG_NOSTACK 0x200
|
#define DEBUG_NOSTACK 0x200
|
||||||
#define DEBUG_ONESHOT 0x400
|
#define DEBUG_ONESHOT 0x400
|
||||||
#define DEBUG_STACK 0x800
|
#define DEBUG_STACK 0x800
|
||||||
#define DEBUG_UNWIND 0x1000
|
#define DEBUG_UNWIND 0x1000
|
||||||
#define DEBUG_SIGNAL 0x2000
|
#define DEBUG_SIGNAL 0x2000
|
||||||
|
|
||||||
extern int wad_debug_mode;
|
extern int wad_debug_mode;
|
||||||
extern int wad_heap_overflow;
|
extern int wad_heap_overflow;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
WADSRCS = io.c memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
WADSRCS = 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 = 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 = -DWAD_LINUX
|
WADOPT = -DWAD_SOLARIS
|
||||||
|
|
||||||
# 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/lib/perl5/5.00503/i386-linux/CORE
|
PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE
|
||||||
PERLSRCS = wadpl.cxx
|
PERLSRCS = wadpl.cxx
|
||||||
PERLOBJS = wadpl.o
|
PERLOBJS = wadpl.o
|
||||||
|
|
||||||
# C Compiler
|
# C Compiler
|
||||||
CC = gcc
|
CC = cc
|
||||||
CFLAGS = #-fpic
|
CFLAGS = #
|
||||||
|
|
||||||
# C++ Compiler
|
# C++ Compiler
|
||||||
CXX = c++
|
CXX = CC
|
||||||
CXXFLAGS = #-fpic
|
CXXFLAGS = #-Kpic
|
||||||
|
|
||||||
# Linking options
|
# Linking options
|
||||||
CLINK =
|
CLINK =
|
||||||
CXXLINK = g++ -shared
|
CXXLINK = CC -G
|
||||||
|
|
||||||
# Rules for creation of a .o file from .cxx
|
# Rules for creation of a .o file from .cxx
|
||||||
.SUFFIXES: .cxx
|
.SUFFIXES: .cxx
|
||||||
|
|
@ -76,7 +76,7 @@ wc::
|
||||||
wc $(SRCS)
|
wc $(SRCS)
|
||||||
|
|
||||||
semi::
|
semi::
|
||||||
egrep ";" $(WADSRCS) | wc
|
egrep ";" $(SRCS) wadpy.cxx | wc
|
||||||
|
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ int main(int argc, char **argv) {
|
||||||
} else if (strcmp(argv[1],"ret") == 0) {
|
} else if (strcmp(argv[1],"ret") == 0) {
|
||||||
call_func(4,seg_crash);
|
call_func(4,seg_crash);
|
||||||
} else if (strcmp(argv[1],"test") == 0) {
|
} else if (strcmp(argv[1],"test") == 0) {
|
||||||
test(-4,seg_crash);
|
test(-1000,seg_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) {
|
||||||
|
|
|
||||||
|
|
@ -21,25 +21,20 @@
|
||||||
char *wad_arg_string(WadFrame *frame) {
|
char *wad_arg_string(WadFrame *frame) {
|
||||||
static char str[1024];
|
static char str[1024];
|
||||||
static char temp[64];
|
static char temp[64];
|
||||||
WadParm *wp;
|
WadLocal *wp;
|
||||||
long *stack;
|
long *stack;
|
||||||
long *nextstack;
|
long *nextstack;
|
||||||
int i;
|
int i;
|
||||||
WadFrame *nf;
|
WadFrame *nf;
|
||||||
|
|
||||||
if (frame->size) {
|
nf = frame->next;
|
||||||
nf = (WadFrame *) (((char *) frame) + frame->size);
|
|
||||||
if (nf->size == 0) nf = 0;
|
|
||||||
} else {
|
|
||||||
nf = 0;
|
|
||||||
}
|
|
||||||
if (nf)
|
if (nf)
|
||||||
nextstack = STACK(nf);
|
nextstack = (long *) nf->psp;
|
||||||
else
|
else
|
||||||
nextstack = 0;
|
nextstack = 0;
|
||||||
|
|
||||||
str[0] = 0;
|
str[0] = 0;
|
||||||
stack = STACK(frame);
|
stack = (long *) frame->psp;
|
||||||
|
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
if (!nf) {
|
if (!nf) {
|
||||||
|
|
@ -62,15 +57,15 @@ 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 = ARGUMENTS(frame);
|
wp = frame->args;
|
||||||
for (i = 0; i < frame->nargs; i++, wp++) {
|
for (i = 0; i < frame->nargs; i++, wp = wp->next) {
|
||||||
strcat(str,wp->name);
|
strcat(str,wp->name);
|
||||||
strcat(str,"=");
|
strcat(str,"=");
|
||||||
|
|
||||||
/* Try to figure out where the value is */
|
/* Try to figure out where the value is */
|
||||||
if ((wp->loc == PARM_STACK) && nf) {
|
if ((wp->loc == PARM_STACK) && nf) {
|
||||||
/* Parameter is located on the call stack */
|
/* Parameter is located on the call stack */
|
||||||
unsigned long argloc = wp->value; /* Location relative to frame pointer */
|
unsigned long argloc = wp->position; /* Location relative to frame pointer */
|
||||||
if ((argloc & 0x3) == 0) {
|
if ((argloc & 0x3) == 0) {
|
||||||
if (argloc >= 0) {
|
if (argloc >= 0) {
|
||||||
/* Is word aligned, make some kind of attempt to print this out */
|
/* Is word aligned, make some kind of attempt to print this out */
|
||||||
|
|
@ -85,18 +80,19 @@ char *wad_arg_string(WadFrame *frame) {
|
||||||
}
|
}
|
||||||
} else if (wp->loc == PARM_REGISTER) {
|
} else if (wp->loc == PARM_REGISTER) {
|
||||||
#ifdef WAD_SOLARIS
|
#ifdef WAD_SOLARIS
|
||||||
if ((wp->value >= 24) && (wp->value < 32)) {
|
if ((wp->position >= 24) && (wp->position < 32)) {
|
||||||
/* Value is located in the %in registers */
|
/* Value is located in the %in registers */
|
||||||
sprintf(temp,"0x%x", stack[wp->value - 16]);
|
sprintf(temp,"0x%x", stack[wp->position - 16]);
|
||||||
strcat(str,temp);
|
strcat(str,temp);
|
||||||
} else if ((wp->value >= 8) && (wp->value < 16)) {
|
} else if ((wp->position >= 8) && (wp->position < 16)) {
|
||||||
/* Value is located in the %on registers */
|
/* Value is located in the %on registers */
|
||||||
sprintf(temp,"0x%x", frame->regs[wp->value]);
|
/* sprintf(temp,"0x%x", frame->regs[wp->value]);
|
||||||
strcat(str,temp);
|
strcat(str,temp); */
|
||||||
} else if ((wp->value >= 16) && (wp->value < 24)) {
|
} else if ((wp->position >= 16) && (wp->position < 24)) {
|
||||||
/* Value has been placed in the %ln registers */
|
/* Value has been placed in the %ln registers */
|
||||||
|
/*
|
||||||
sprintf(temp,"0x%x", frame->regs[wp->value - 16]);
|
sprintf(temp,"0x%x", frame->regs[wp->value - 16]);
|
||||||
strcat(str,temp);
|
strcat(str,temp); */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
|
|
@ -202,24 +198,24 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
||||||
|
|
||||||
/* Find the last exception frame */
|
/* Find the last exception frame */
|
||||||
|
|
||||||
while (!f->last) {
|
while (f && !f->last) {
|
||||||
fd = fd + f->size;
|
f = f->next;
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now work backwards */
|
/* Now work backwards */
|
||||||
fd = fd - f->lastsize;
|
if (f) {
|
||||||
f = (WadFrame *) fd;
|
f = f->prev;
|
||||||
while (1) {
|
}
|
||||||
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, *(fd + f->sym_off) ? fd+f->sym_off : "?",
|
while (f) {
|
||||||
|
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, f->symbol ? f->symbol : "?",
|
||||||
wad_arg_string(f));
|
wad_arg_string(f));
|
||||||
if (strlen(fd+f->src_off)) {
|
if (f->srcfile && strlen(f->srcfile)) {
|
||||||
fprintf(stderr," in '%s'", wad_strip_dir(fd+f->src_off));
|
fprintf(stderr," in '%s'", wad_strip_dir(f->srcfile));
|
||||||
if (f->line_number > 0) {
|
if (f->line_number > 0) {
|
||||||
fprintf(stderr,", line %d", f->line_number);
|
fprintf(stderr,", line %d", f->line_number);
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
fd = open(SRCFILE(f), O_RDONLY);
|
fd = open(f->srcfile, O_RDONLY);
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
fline = f;
|
fline = f;
|
||||||
}
|
}
|
||||||
|
|
@ -227,14 +223,12 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strlen(fd+f->obj_off)) {
|
if (f->objfile && strlen(f->objfile)) {
|
||||||
fprintf(stderr," from '%s'", fd+f->obj_off);
|
fprintf(stderr," from '%s'", f->objfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr,"\n");
|
fprintf(stderr,"\n");
|
||||||
if (!f->lastsize) break;
|
f = f->prev;
|
||||||
fd = fd - f->lastsize;
|
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fline) {
|
if (fline) {
|
||||||
|
|
@ -246,9 +240,9 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
|
||||||
last = fline->line_number + 2;
|
last = fline->line_number + 2;
|
||||||
if (first < 1) first = 1;
|
if (first < 1) first = 1;
|
||||||
|
|
||||||
line = wad_load_source(SRCFILE(fline),first);
|
line = wad_load_source(fline->srcfile,first);
|
||||||
if (line) {
|
if (line) {
|
||||||
fprintf(stderr,"\n%s, line %d\n\n", SRCFILE(fline),fline->line_number);
|
fprintf(stderr,"\n%s, line %d\n\n", fline->srcfile,fline->line_number);
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++) {
|
||||||
if (i == fline->line_number) fprintf(stderr," => ");
|
if (i == fline->line_number) fprintf(stderr," => ");
|
||||||
else fprintf(stderr," ");
|
else fprintf(stderr," ");
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ typedef struct _WadMemory {
|
||||||
} WadMemory;
|
} WadMemory;
|
||||||
|
|
||||||
static WadMemory *current = 0; /* Current memory block */
|
static WadMemory *current = 0; /* Current memory block */
|
||||||
|
static WadMemory *persistent = 0; /* Persistent memory data */
|
||||||
static int pagesize = 0; /* System page size */
|
static int pagesize = 0; /* System page size */
|
||||||
static int devzero = 0;
|
static int devzero = 0;
|
||||||
|
|
||||||
|
|
@ -92,6 +93,7 @@ void *wad_malloc(int nbytes) {
|
||||||
/* Yep. Found a region */
|
/* Yep. Found a region */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
wm = wm->next;
|
||||||
}
|
}
|
||||||
if (!wm) {
|
if (!wm) {
|
||||||
wad_printf("wad_malloc: new page\n", nbytes);
|
wad_printf("wad_malloc: new page\n", nbytes);
|
||||||
|
|
@ -107,6 +109,24 @@ void *wad_malloc(int nbytes) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_pmalloc()
|
||||||
|
*
|
||||||
|
* Persistent memory allocation. Allocates memory that will never be reclaimed.
|
||||||
|
* This is only really used to store information pertaining to object files.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void *wad_pmalloc(int nbytes) {
|
||||||
|
void *ptr;
|
||||||
|
WadMemory *tmp;
|
||||||
|
tmp = current;
|
||||||
|
current = persistent;
|
||||||
|
ptr = wad_malloc(nbytes);
|
||||||
|
persistent = current;
|
||||||
|
current = tmp;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_release_memory()
|
* wad_release_memory()
|
||||||
*
|
*
|
||||||
|
|
@ -119,7 +139,7 @@ void wad_release_memory() {
|
||||||
wm = current;
|
wm = current;
|
||||||
while (wm) {
|
while (wm) {
|
||||||
next = wm->next;
|
next = wm->next;
|
||||||
munmap(wm, wm->npages*pagesize);
|
munmap((char *) wm, wm->npages*pagesize);
|
||||||
wm = next;
|
wm = next;
|
||||||
}
|
}
|
||||||
current = 0;
|
current = 0;
|
||||||
|
|
@ -139,3 +159,11 @@ char *wad_strdup(const char *c) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *wad_pstrdup(const char *c) {
|
||||||
|
char *t;
|
||||||
|
if (!c) c = "";
|
||||||
|
t = (char *) wad_pmalloc(strlen(c)+1);
|
||||||
|
strcpy(t,c);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,14 @@
|
||||||
* This file provides access to raw object files, executables, and
|
* This file provides access to raw object files, executables, and
|
||||||
* library files. Memory management is handled through mmap() to
|
* library files. Memory management is handled through mmap() to
|
||||||
* avoid the use of heap/stack space.
|
* avoid the use of heap/stack space.
|
||||||
|
*
|
||||||
|
* All of the files and objects created by this module persist
|
||||||
|
* until the process exits. Since WAD may be invoked multiple times
|
||||||
|
* over the course of program execution, it makes little sense to keep
|
||||||
|
* loading and unloading files---subsequent invocations of the handler
|
||||||
|
* can simply used previously loaded copies. Caveat: things probably
|
||||||
|
* won't work right if a program is doing lots of low-level manipulation
|
||||||
|
* of the dynamic loader.
|
||||||
*
|
*
|
||||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||||
*
|
*
|
||||||
|
|
@ -46,8 +54,8 @@ load_file(const char *path) {
|
||||||
return 0; /* Doesn't exist. Oh well */
|
return 0; /* Doesn't exist. Oh well */
|
||||||
}
|
}
|
||||||
if (wad_debug_mode & DEBUG_FILE) wad_printf("loaded.\n");
|
if (wad_debug_mode & DEBUG_FILE) wad_printf("loaded.\n");
|
||||||
wf = (WadFile *) wad_malloc(sizeof(WadFile));
|
wf = (WadFile *) wad_pmalloc(sizeof(WadFile));
|
||||||
wf->path = wad_strdup(path);
|
wf->path = wad_pstrdup(path);
|
||||||
|
|
||||||
/* Get file length */
|
/* Get file length */
|
||||||
wf->size = lseek(fd,0,SEEK_END);
|
wf->size = lseek(fd,0,SEEK_END);
|
||||||
|
|
@ -65,14 +73,13 @@ load_file(const char *path) {
|
||||||
return wf;
|
return wf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static WadObjectFile *wad_objects = 0; /* Linked list of object files */
|
static WadObjectFile *wad_objects = 0; /* Linked list of object files */
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_object_cleanup()
|
* wad_object_cleanup()
|
||||||
*
|
*
|
||||||
* Reset the object file loader
|
* Reset the object file loader. This unmaps the files themselves, but
|
||||||
|
* memory will leak for object files pointers themselves.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -98,7 +105,7 @@ wad_object_reset() {
|
||||||
* wad_object_load()
|
* wad_object_load()
|
||||||
*
|
*
|
||||||
* Load an object file into memory using mmap. Returns 0 if the object does
|
* Load an object file into memory using mmap. Returns 0 if the object does
|
||||||
* not exist or if there are no more object descriptor slots
|
* not exist or if we're out of memory.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
WadObjectFile *
|
WadObjectFile *
|
||||||
|
|
@ -135,7 +142,7 @@ wad_object_load(const char *path) {
|
||||||
wo = wad_arobject_load(realfile,objfile);
|
wo = wad_arobject_load(realfile,objfile);
|
||||||
if (wo) {
|
if (wo) {
|
||||||
/* Reset the path */
|
/* Reset the path */
|
||||||
wo->path = wad_strdup(path);
|
wo->path = wad_pstrdup(path);
|
||||||
return wo;
|
return wo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,9 +150,8 @@ wad_object_load(const char *path) {
|
||||||
wf = load_file(path);
|
wf = load_file(path);
|
||||||
if (!wf) return 0;
|
if (!wf) return 0;
|
||||||
|
|
||||||
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
|
wo = (WadObjectFile *) wad_pmalloc(sizeof(WadObjectFile));
|
||||||
wo->file = wf;
|
wo->path = wad_pstrdup(path);
|
||||||
wo->path = wad_strdup(path);
|
|
||||||
wo->ptr = wf->addr;
|
wo->ptr = wf->addr;
|
||||||
wo->len = wf->size;
|
wo->len = wf->size;
|
||||||
return wo;
|
return wo;
|
||||||
|
|
@ -154,7 +160,9 @@ wad_object_load(const char *path) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_arobject_load()
|
* wad_arobject_load()
|
||||||
*
|
*
|
||||||
* Load an archive file object into memory using mmap.
|
* Load an object file stored in an archive file created with an archive. The
|
||||||
|
* pathname should be the path of the .a file and robjname should be the name
|
||||||
|
* of the object file stored in the object file.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
WadObjectFile *
|
WadObjectFile *
|
||||||
|
|
@ -227,8 +235,7 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
||||||
/* Compare the names */
|
/* Compare the names */
|
||||||
if (strncmp(mname,objname,sobjname) == 0) {
|
if (strncmp(mname,objname,sobjname) == 0) {
|
||||||
/* Found the archive */
|
/* Found the archive */
|
||||||
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
|
wo = (WadObjectFile *) wad_pmalloc(sizeof(WadObjectFile));
|
||||||
wo->file = wf;
|
|
||||||
wo->ptr = (void *) (arptr + offset);
|
wo->ptr = (void *) (arptr + offset);
|
||||||
wo->len = msize;
|
wo->len = msize;
|
||||||
wo->path = 0;
|
wo->path = 0;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
|
|
||||||
/* For some odd reason, certain linux distributions do not seem to define the
|
/* For some odd reason, certain linux distributions do not seem to define the
|
||||||
ESP, EIP, and EBP registers. This is a hack */
|
register constants in a way that is easily accessible to us. This is a hack */
|
||||||
|
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
#ifndef ESP
|
#ifndef ESP
|
||||||
|
|
@ -330,45 +330,42 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
|
|
||||||
if (wad_debug_mode & DEBUG_STACK) {
|
if (wad_debug_mode & DEBUG_STACK) {
|
||||||
/* Walk the exception frames and try to find a return point */
|
/* Walk the exception frames and try to find a return point */
|
||||||
framedata = (char *) frame;
|
while (frame) {
|
||||||
|
|
||||||
while (frame->size) {
|
|
||||||
int i;
|
int i;
|
||||||
WadParm *p;
|
WadLocal *p;
|
||||||
/* Print out detailed stack trace information */
|
/* Print out detailed stack trace information */
|
||||||
printf("::: Stack frame - 0x%08x :::\n", frame);
|
printf("::: Stack frame - 0x%08x :::\n", frame);
|
||||||
printf(" sp = %x\n", frame->sp);
|
printf(" sp = %x\n", frame->sp);
|
||||||
printf(" fp = %x\n", frame->fp);
|
printf(" fp = %x\n", frame->fp);
|
||||||
printf(" size = %x\n", frame->stack_size);
|
printf(" size = %x\n", frame->stack_size);
|
||||||
printf(" pc = %x (base = %x)\n", frame->pc, frame->sym_base);
|
printf(" pc = %x (base = %x)\n", frame->pc, frame->sym_base);
|
||||||
printf(" symbol = '%s'\n", SYMBOL(frame));
|
printf(" symbol = '%s'\n", frame->symbol ? frame->symbol : "?");
|
||||||
printf(" srcfile = '%s'\n", SRCFILE(frame));
|
printf(" srcfile = '%s'\n", frame->srcfile ? frame->srcfile : "");
|
||||||
printf(" objfile = '%s'\n", OBJFILE(frame));
|
printf(" objfile = '%s'\n", frame->objfile ? frame->objfile : "");
|
||||||
printf(" numargs = %d\n", frame->nargs);
|
printf(" numargs = %d\n", frame->nargs);
|
||||||
printf(" arguments [\n");
|
printf(" arguments [\n");
|
||||||
p = ARGUMENTS(frame);
|
p = frame->args;
|
||||||
for (i = 0; i < frame->nargs; i++, p++) {
|
i = 0;
|
||||||
printf(" arg[%d] : name = '%s', loc = %d, type = %d, value = %d\n", i, p->name, p->loc, p->type, p->value);
|
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");
|
printf(" ]\n");
|
||||||
framedata = framedata + frame->size;
|
frame = frame->next;
|
||||||
frame = (WadFrame *) framedata;
|
|
||||||
}
|
}
|
||||||
frame = origframe;
|
frame = origframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk the exception frames and try to find a return point */
|
/* Walk the exception frames and try to find a return point */
|
||||||
framedata = (char *) frame;
|
while (frame) {
|
||||||
|
WadReturnFunc *wr = wad_check_return(frame->symbol);
|
||||||
while (frame->size) {
|
|
||||||
WadReturnFunc *wr = wad_check_return(framedata+frame->sym_off);
|
|
||||||
if (wr) {
|
if (wr) {
|
||||||
found = 1;
|
found = 1;
|
||||||
wad_nlr_value = wr->value;
|
wad_nlr_value = wr->value;
|
||||||
retname = wr->name;
|
retname = wr->name;
|
||||||
}
|
}
|
||||||
framedata = framedata + frame->size;
|
frame = frame->next;
|
||||||
frame = (WadFrame *) framedata;
|
|
||||||
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;
|
||||||
|
|
@ -376,7 +373,6 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
nlevels++;
|
nlevels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
wad_nlr_levels = nlevels - 1;
|
wad_nlr_levels = nlevels - 1;
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@
|
||||||
|
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
|
|
||||||
|
|
||||||
/* stabs data structure. This appears to be somewhat universal. */
|
/* stabs data structure. This appears to be somewhat universal. */
|
||||||
|
|
||||||
typedef struct Stab {
|
typedef struct Stab {
|
||||||
unsigned n_strx; /* index into file string table */
|
unsigned n_strx; /* index into file string table */
|
||||||
unsigned char n_type; /* type flag (N_TEXT,..) */
|
unsigned char n_type; /* type flag (N_TEXT,..) */
|
||||||
|
|
@ -23,11 +21,26 @@ typedef struct Stab {
|
||||||
unsigned n_value; /* value of symbol (or sdb offset) */
|
unsigned n_value; /* value of symbol (or sdb offset) */
|
||||||
} Stab;
|
} Stab;
|
||||||
|
|
||||||
/* Match a stabs symbol name against a stab string (which may contain
|
/* stabs data types used by this module */
|
||||||
extra information delimetered by a colon */
|
|
||||||
|
|
||||||
int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
#define N_UNDF 0x0 /* undefined */
|
||||||
/* wad_printf("matching: %s -> %s\n", symbol, stabtext); */
|
#define N_FUN 0x24 /* function */
|
||||||
|
#define N_OBJ 0x38 /* object file path */
|
||||||
|
#define N_RSYM 0x40 /* Register symbol */
|
||||||
|
#define N_SLINE 0x44 /* Source line */
|
||||||
|
#define N_SO 0x64 /* Source file name */
|
||||||
|
#define N_PSYM 0xa0 /* Parameter */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* match_stab_symbol()
|
||||||
|
*
|
||||||
|
* Match a stabs symbol name against a stab string. The stab string may contain
|
||||||
|
* extra information delimited by a colon which is not used in the comparsion.
|
||||||
|
* Returns 1 on match, 0 on mismatch.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static int
|
||||||
|
match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||||
if (strcmp(symbol,stabtext) == 0) {
|
if (strcmp(symbol,stabtext) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +48,17 @@ int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* scan_function()
|
||||||
|
*
|
||||||
|
* Collect stabs data for a function definition.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void
|
||||||
|
scan_function(Stab *s, int ns, WadDebug *debug) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a stabs data segment (obtained somehow), this function tries to
|
/* Given a stabs data segment (obtained somehow), this function tries to
|
||||||
collect as much information as it can about a given symbol.
|
collect as much information as it can about a given symbol.
|
||||||
|
|
||||||
|
|
@ -47,7 +71,6 @@ int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||||
|
|
||||||
Note: If a symbol corresponds to a local symbol, it's entirely possible
|
Note: If a symbol corresponds to a local symbol, it's entirely possible
|
||||||
that the only stabs data we will find is a file specifier. In this case,
|
that the only stabs data we will find is a file specifier. In this case,
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -59,6 +82,7 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
int i;
|
int i;
|
||||||
char *file, *lastfile = 0;
|
char *file, *lastfile = 0;
|
||||||
int chk = 0;
|
int chk = 0;
|
||||||
|
WadLocal *arg;
|
||||||
|
|
||||||
s = (Stab *) sp; /* Stabs data */
|
s = (Stab *) sp; /* Stabs data */
|
||||||
ns = size/sizeof(Stab); /* number of stabs */
|
ns = size/sizeof(Stab); /* number of stabs */
|
||||||
|
|
@ -71,16 +95,16 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
debug->objfile[0] = 0;
|
debug->objfile[0] = 0;
|
||||||
debug->line_number = -1;
|
debug->line_number = -1;
|
||||||
debug->nargs = 0;
|
debug->nargs = 0;
|
||||||
|
debug->args = 0;
|
||||||
|
debug->lastarg = 0;
|
||||||
|
|
||||||
for (i = 0; i < ns; i++, s++) {
|
for (i = 0; i < ns; i++, s++) {
|
||||||
/*#define DEBUG_DEBUG */
|
|
||||||
if (wad_debug_mode & DEBUG_STABS) {
|
if (wad_debug_mode & DEBUG_STABS) {
|
||||||
/* wad_printf(" %10d %10x %10d %10d %10d: '%x'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
|
||||||
stabstr+s->n_strx); */
|
|
||||||
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 == 0)) { /* && (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. */
|
||||||
|
|
||||||
|
|
@ -100,7 +124,7 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
debug->line_number = -1;
|
debug->line_number = -1;
|
||||||
debug->found = 0;
|
debug->found = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if (s->n_type == 0x64) {
|
} else if (s->n_type == N_SO) {
|
||||||
if (debug->found) return 1; /* New file and we already found what we wanted */
|
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 */
|
||||||
|
|
@ -116,13 +140,13 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
debug->found = 1;
|
debug->found = 1;
|
||||||
}
|
}
|
||||||
lastfile = file;
|
lastfile = file;
|
||||||
} else if (s->n_type == 0x38) {
|
} else if (s->n_type == N_OBJ) {
|
||||||
/* Object file specifier */
|
/* Object file specifier */
|
||||||
if (debug->objfile[0]) {
|
if (debug->objfile[0]) {
|
||||||
strcat(debug->objfile,"/");
|
strcat(debug->objfile,"/");
|
||||||
}
|
}
|
||||||
strcat(debug->objfile,stabstr+s->n_strx);
|
strcat(debug->objfile,stabstr+s->n_strx);
|
||||||
} else if (s->n_type == 0x24) {
|
} else if (s->n_type == N_FUN) {
|
||||||
if (match_stab_symbol(wsym->name, stabstr+s->n_strx, slen)) {
|
if (match_stab_symbol(wsym->name, stabstr+s->n_strx, slen)) {
|
||||||
if (!wsym->file || (strcmp(wsym->file,lastfile) == 0)) {
|
if (!wsym->file || (strcmp(wsym->file,lastfile) == 0)) {
|
||||||
infunc = 1;
|
infunc = 1;
|
||||||
|
|
@ -134,13 +158,12 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
} else {
|
} else {
|
||||||
infunc = 0;
|
infunc = 0;
|
||||||
}
|
}
|
||||||
} else if (debug->found && (s->n_type == 0x44) && (infunc)) {
|
} else if (debug->found && (s->n_type == N_SLINE) && (infunc)) {
|
||||||
|
|
||||||
/* Line number location */
|
/* Line number location */
|
||||||
if (s->n_value < offset) {
|
if (s->n_value < offset) {
|
||||||
debug->line_number = s->n_desc;
|
debug->line_number = s->n_desc;
|
||||||
} else return 1;
|
} else return 1;
|
||||||
} else if (debug->found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
|
} else if (debug->found && ((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) && (infunc)) {
|
||||||
/* Parameter counting */
|
/* Parameter counting */
|
||||||
char *pname;
|
char *pname;
|
||||||
char *c;
|
char *c;
|
||||||
|
|
@ -153,41 +176,52 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
|
||||||
len = strlen(pname);
|
len = strlen(pname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if already used */
|
/* Check if the argument was already used */
|
||||||
/* In this case, the first stab simply identifies an argument. The second
|
/* In this case, the first stab simply identifies an argument. The second
|
||||||
one identifies its location for the debugger */
|
one identifies its location for the debugger */
|
||||||
|
|
||||||
if (debug->nargs > 0) {
|
if (debug->args) {
|
||||||
/* Need to do some fix up for linux here */
|
/* Need to do some fix up for linux here */
|
||||||
int i;
|
WadLocal *a = debug->args;
|
||||||
for (i = 0; i < debug->nargs; i++) {
|
while (a) {
|
||||||
if ((strncmp(debug->parms[i].name, pname,len) == 0) && (strlen(debug->parms[i].name) == len)) {
|
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
|
/* We already saw this argument. Given a choice between a register and a stack
|
||||||
argument. We will choose the stack version */
|
argument. We will choose the stack version */
|
||||||
if (debug->parms[i].loc == PARM_STACK) {
|
if (a->loc == PARM_STACK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Go ahead and use the new argument */
|
/* Go ahead and use the new argument */
|
||||||
if (s->n_type == 0x40)
|
if (s->n_type == 0x40)
|
||||||
debug->parms[i].loc = PARM_REGISTER;
|
a->loc = PARM_REGISTER;
|
||||||
else
|
else
|
||||||
debug->parms[i].loc = PARM_STACK;
|
a->loc = PARM_STACK;
|
||||||
debug->parms[i].value = s->n_value;
|
a->position = s->n_value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
a = a->next;
|
||||||
}
|
}
|
||||||
if (i < debug->nargs) continue; /* We got an argument match. Just skip to next stab */
|
if (a) continue; /* We got an argument match. Just skip to the next stab */
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(debug->parms[debug->nargs].name,pname,len);
|
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
|
||||||
debug->parms[debug->nargs].name[len] = 0;
|
arg->name = (char *) wad_malloc(len+1);
|
||||||
|
strncpy(arg->name, pname, len);
|
||||||
|
arg->name[len] = 0;
|
||||||
if (s->n_type == 0x40)
|
if (s->n_type == 0x40)
|
||||||
debug->parms[debug->nargs].loc = PARM_REGISTER;
|
arg->loc = PARM_REGISTER;
|
||||||
else
|
else
|
||||||
debug->parms[debug->nargs].loc = PARM_STACK;
|
arg->loc = PARM_STACK;
|
||||||
|
|
||||||
debug->parms[debug->nargs].value = s->n_value;
|
arg->position = s->n_value;
|
||||||
debug->parms[debug->nargs].type = 0; /* Not used yet */
|
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++;
|
debug->nargs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <dlfcn.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. */
|
||||||
|
|
||||||
#ifdef WAD_SOLARIS
|
#ifdef WAD_SOLARIS
|
||||||
#define STACK_BASE 0xffbf0000
|
#define STACK_BASE 0xffbf0000
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -21,8 +24,12 @@
|
||||||
#define STACK_BASE 0xc0000000
|
#define STACK_BASE 0xc0000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Given a stack pointer, this function performs a single level of stack
|
/* -----------------------------------------------------------------------------
|
||||||
unwinding */
|
* stack_unwind()
|
||||||
|
*
|
||||||
|
* Perform a single level of stack unwinding given the stack pointer, frame pointer
|
||||||
|
* and program counter.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) {
|
stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) {
|
||||||
|
|
@ -49,51 +56,34 @@ stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *trace_addr = 0;
|
/* -----------------------------------------------------------------------------
|
||||||
static int trace_len = 0;
|
* wad_stack_trace()
|
||||||
|
*
|
||||||
/* Perform a stack unwinding given the current value of the pc, stack pointer,
|
* Create a stack trace of the process. Returns a linked list of stack frames
|
||||||
and frame pointer. Returns a pointer to a wad exception frame structure
|
* with debugging information and other details.
|
||||||
which is actually a large memory mapped file. */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static char framefile[256];
|
|
||||||
|
|
||||||
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, *segments;
|
WadSegment *ws;
|
||||||
WadObjectFile *wo;
|
WadObjectFile *wo;
|
||||||
WadFrame frame;
|
WadFrame *firstframe=0, *lastframe=0, *frame=0;
|
||||||
WadDebug wd;
|
WadDebug wd;
|
||||||
WadSymbol wsym;
|
WadSymbol wsym;
|
||||||
int nlevels;
|
|
||||||
|
|
||||||
int ffile;
|
|
||||||
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;
|
unsigned long p_lastsp;
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
int lastsize = 0;
|
|
||||||
int firstframe = 1;
|
|
||||||
|
|
||||||
/* Read the segments */
|
/* Read the segments */
|
||||||
|
|
||||||
if (wad_segment_read() < 0) {
|
if (wad_segment_read() < 0) {
|
||||||
wad_printf("WAD: Unable to read segment map\n");
|
wad_printf("WAD: Unable to read segment map\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the frame file for output */
|
|
||||||
tmpnam(framefile);
|
|
||||||
ffile = open(framefile, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
|
||||||
if (ffile < 0) {
|
|
||||||
wad_printf("can't open %s\n", framefile);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to do a stack traceback */
|
/* Try to do a stack traceback */
|
||||||
nlevels = 0;
|
|
||||||
p_pc = pc;
|
p_pc = pc;
|
||||||
p_sp = sp;
|
p_sp = sp;
|
||||||
p_fp = fp;
|
p_fp = fp;
|
||||||
|
|
@ -110,21 +100,13 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
}
|
}
|
||||||
ws = wad_segment_find((void *) p_pc);
|
ws = wad_segment_find((void *) p_pc);
|
||||||
{
|
{
|
||||||
int symsize = 0;
|
int stacksize = 0;
|
||||||
int srcsize = 0;
|
char *symname = 0;
|
||||||
int objsize = 0;
|
|
||||||
int stacksize = 0;
|
|
||||||
int argsize = 0;
|
|
||||||
char *srcname = 0;
|
|
||||||
char *objname = 0;
|
|
||||||
char *symname = 0;
|
|
||||||
int pad = 0;
|
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
|
|
||||||
/* Try to load the object file for this address */
|
/* Try to load the object file for this address */
|
||||||
if (ws) {
|
if (ws) {
|
||||||
wo = wad_object_load(ws->mappath);
|
wo = wad_object_load(ws->mappath);
|
||||||
/* Special hack needed for base address */
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wo = 0;
|
wo = 0;
|
||||||
|
|
@ -136,53 +118,51 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
} else {
|
} else {
|
||||||
symname = 0;
|
symname = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* if (symname) symname = wad_cplus_demangle(&wsym); */
|
|
||||||
|
|
||||||
value = wsym.value;
|
value = wsym.value;
|
||||||
|
|
||||||
|
|
||||||
/* Build up some information about the exception frame */
|
frame = (WadFrame *) wad_malloc(sizeof(WadFrame));
|
||||||
frame.frameno = n;
|
frame->frameno = n;
|
||||||
frame.last = 0;
|
frame->pc = p_pc;
|
||||||
frame.lastsize = lastsize;
|
frame->sp = p_sp;
|
||||||
frame.pc = p_pc;
|
frame->nlocals = -1;
|
||||||
frame.sp = p_sp;
|
frame->nargs = -1;
|
||||||
frame.nargs = -1;
|
frame->objfile = 0;
|
||||||
frame.arg_off = 0;
|
frame->srcfile = 0;
|
||||||
frame.sym_base = value + (long) ws->base;
|
frame->psp = 0;
|
||||||
|
frame->next = 0;
|
||||||
|
frame->prev = lastframe;
|
||||||
|
frame->last = 0;
|
||||||
|
if (lastframe) {
|
||||||
|
lastframe->next = frame;
|
||||||
|
lastframe = frame;
|
||||||
|
} else {
|
||||||
|
lastframe = frame;
|
||||||
|
firstframe = frame;
|
||||||
|
}
|
||||||
|
frame->symbol = wad_strdup(symname);
|
||||||
|
frame->sym_base = value + (long) ws->base;
|
||||||
n++;
|
n++;
|
||||||
if (symname) {
|
if (symname) {
|
||||||
symsize = strlen(symname)+1;
|
|
||||||
|
|
||||||
/* wad_printf("C++: '%s' ---> '%s'\n", symname, wad_cplus_demangle(&wsym));*/
|
|
||||||
|
|
||||||
/* Try to gather some debugging information about this symbol */
|
/* Try to gather some debugging information about this symbol */
|
||||||
if (wad_debug_info(wo,&wsym, p_pc - (unsigned long) ws->base - value, &wd)) {
|
if (wad_debug_info(wo,&wsym, p_pc - (unsigned long) ws->base - value, &wd)) {
|
||||||
srcname = wd.srcfile;
|
frame->srcfile = wad_strdup(wd.srcfile);
|
||||||
srcsize = strlen(srcname)+1;
|
frame->objfile = wad_strdup(wd.objfile);
|
||||||
objname = wd.objfile;
|
frame->args = wd.args;
|
||||||
objsize = strlen(objname)+1;
|
frame->lastarg = wd.lastarg;
|
||||||
frame.nargs = wd.nargs;
|
frame->nargs = wd.nargs;
|
||||||
|
|
||||||
|
/*frame.nargs = wd.nargs;
|
||||||
if (wd.nargs > 0) {
|
if (wd.nargs > 0) {
|
||||||
argsize = sizeof(WadParm)*wd.nargs;
|
argsize = sizeof(WadParm)*wd.nargs;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (wd.nargs >=0) {
|
|
||||||
int i;
|
|
||||||
wad_printf("%s\n",symname);
|
|
||||||
for (i = 0; i < wd.nargs; i++) {
|
|
||||||
wad_printf(" [%d] = '%s', %d, %d\n", i, wd.parms[i].name, wd.parms[i].type, wd.parms[i].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
frame.line_number = wd.line_number;
|
frame->line_number = wd.line_number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WAD_SOLARIS
|
#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 */
|
/* Before unwinding the stack, copy the locals and %o registers from previous frame */
|
||||||
if (!firstframe) {
|
if (!firstframe) {
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -193,16 +173,16 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
firstframe = 0;
|
|
||||||
|
#endif
|
||||||
/* Determine stack frame size */
|
/* Determine stack frame size */
|
||||||
p_lastsp = p_sp;
|
p_lastsp = p_sp;
|
||||||
|
|
||||||
stack_unwind(&p_sp, &p_pc, &p_fp);
|
stack_unwind(&p_sp, &p_pc, &p_fp);
|
||||||
|
|
||||||
if (p_sp) {
|
if (p_sp) {
|
||||||
stacksize = p_sp - p_lastsp;
|
stacksize = p_sp - p_lastsp;
|
||||||
} else {
|
} else {
|
||||||
stacksize = STACK_BASE - p_lastsp; /* Sick hack alert. Need to get stack top from somewhere */
|
stacksize = STACK_BASE - p_lastsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
|
@ -211,101 +191,40 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the frame pointer and stack size */
|
/* Set the frame pointer and stack size */
|
||||||
|
frame->fp = p_sp;
|
||||||
/* frame.fp = p_sp; */
|
frame->stack_size = stacksize;
|
||||||
frame.fp = p_sp;
|
|
||||||
frame.stack_size = stacksize;
|
|
||||||
|
|
||||||
/* Build the exception frame object we'll write */
|
|
||||||
frame.size = sizeof(WadFrame) + symsize + srcsize + objsize + stacksize + argsize;
|
|
||||||
pad = 8 - (frame.size % 8);
|
|
||||||
frame.size += pad;
|
|
||||||
|
|
||||||
frame.data[0] = 0;
|
|
||||||
frame.data[1] = 0;
|
|
||||||
|
|
||||||
/* Build up the offsets */
|
/* Copy stack data */
|
||||||
if (!symname) {
|
frame->psp = (char *) wad_malloc(stacksize);
|
||||||
frame.sym_off = sizeof(WadFrame) - 8;
|
if (frame->psp) {
|
||||||
frame.src_off = sizeof(WadFrame) - 8;
|
memcpy(frame->psp, (void *) p_lastsp, stacksize);
|
||||||
frame.obj_off = sizeof(WadFrame) - 8;
|
|
||||||
frame.stack_off = sizeof(WadFrame) + argsize;
|
|
||||||
frame.arg_off = 0;
|
|
||||||
} else {
|
|
||||||
frame.arg_off = sizeof(WadFrame);
|
|
||||||
frame.stack_off = sizeof(WadFrame) + argsize;
|
|
||||||
frame.sym_off = frame.stack_off + stacksize;
|
|
||||||
frame.src_off = frame.sym_off + symsize;
|
|
||||||
frame.obj_off = frame.src_off + srcsize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write(ffile,&frame,sizeof(WadFrame));
|
|
||||||
/* Write the argument data */
|
|
||||||
if (argsize > 0) {
|
|
||||||
write(ffile, (void *) wd.parms, argsize);
|
|
||||||
}
|
|
||||||
/* Write the stack data */
|
|
||||||
if (stacksize > 0) {
|
|
||||||
write(ffile, (void *) p_lastsp, stacksize);
|
|
||||||
}
|
|
||||||
if (symname) {
|
|
||||||
write(ffile,symname,symsize);
|
|
||||||
write(ffile,srcname,srcsize);
|
|
||||||
write(ffile,objname,objsize);
|
|
||||||
}
|
|
||||||
write(ffile,frame.data, pad);
|
|
||||||
lastsize = frame.size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastframe->last = 1;
|
||||||
/* Write terminator */
|
return firstframe;
|
||||||
frame.size = 0;
|
|
||||||
frame.last = 1;
|
|
||||||
frame.lastsize = lastsize;
|
|
||||||
frame.stack_size = 0;
|
|
||||||
write(ffile,&frame,sizeof(WadFrame));
|
|
||||||
close(ffile);
|
|
||||||
|
|
||||||
/* mmap the debug file back into memory */
|
|
||||||
|
|
||||||
ffile = open(framefile, O_RDONLY, 0644);
|
|
||||||
trace_len = lseek(ffile,0,SEEK_END);
|
|
||||||
lseek(ffile,0,SEEK_SET);
|
|
||||||
trace_addr = mmap(NULL, trace_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
|
||||||
close(ffile);
|
|
||||||
return (WadFrame *) trace_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wad_release_trace() {
|
void wad_release_trace() {
|
||||||
char name[256];
|
|
||||||
munmap(trace_addr, trace_len);
|
|
||||||
unlink(framefile);
|
|
||||||
trace_addr = 0;
|
|
||||||
trace_len = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function steals an argument out of a frame further up the call stack :-) */
|
/* This function steals an argument out of a frame further up the call stack :-) */
|
||||||
|
|
||||||
long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
|
long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
|
||||||
char *fd;
|
|
||||||
long *regs;
|
long *regs;
|
||||||
WadFrame *lastf = 0;
|
WadFrame *lastf = 0;
|
||||||
|
|
||||||
fd = (char *) f;
|
|
||||||
|
|
||||||
*error = 0;
|
*error = 0;
|
||||||
/* Start searching */
|
/* Start searching */
|
||||||
while (f->size) {
|
while (f) {
|
||||||
if (strcmp(SYMBOL(f),symbol) == 0) {
|
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
|
||||||
/* Got a match */
|
/* Got a match */
|
||||||
if (lastf) {
|
if (lastf) {
|
||||||
regs = STACK(f);
|
regs = (long *) f->psp;
|
||||||
return regs[8+argno];
|
return regs[8+argno];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastf = f;
|
lastf = f;
|
||||||
fd = fd + f->size;
|
f = f->next;
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
*error = -1;
|
*error = -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -313,31 +232,27 @@ long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
|
||||||
|
|
||||||
|
|
||||||
long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
|
long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
|
||||||
char *fd;
|
|
||||||
long *regs;
|
long *regs;
|
||||||
WadFrame *lastf = 0;
|
WadFrame *lastf = 0;
|
||||||
|
|
||||||
fd = (char *) f;
|
|
||||||
|
|
||||||
*error = 0;
|
*error = 0;
|
||||||
/* Start searching */
|
/* Start searching */
|
||||||
while (f->size) {
|
while (f) {
|
||||||
if (strcmp(SYMBOL(f),symbol) == 0) {
|
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
|
||||||
/* Got a match */
|
/* Got a match */
|
||||||
if (lastf) {
|
if (lastf) {
|
||||||
#ifdef WAD_SOLARIS
|
#ifdef WAD_SOLARIS
|
||||||
regs = STACK(lastf);
|
regs = (long *) lastf->psp;
|
||||||
return regs[8+argno];
|
return regs[8+argno];
|
||||||
#endif
|
#endif
|
||||||
#ifdef WAD_LINUX
|
#ifdef WAD_LINUX
|
||||||
regs = STACK(f);
|
regs = (long *) f->psp;
|
||||||
return regs[argno+2];
|
return regs[argno+2];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastf = f;
|
lastf = f;
|
||||||
fd = fd + f->size;
|
f = f->next;
|
||||||
f = (WadFrame *) fd;
|
|
||||||
}
|
}
|
||||||
*error = -1;
|
*error = -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue