*** 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:
Dave Beazley 2001-01-30 17:06:16 +00:00
commit bb2b81dc43
9 changed files with 296 additions and 329 deletions

View file

@ -33,18 +33,20 @@ extern "C" {
#define MAX_PATH 1024
#endif
/* Low level memory management */
/* --- Low level memory management --- */
extern int wad_memory_init();
extern void *wad_malloc(int nbytes);
extern void *wad_pmalloc(int nbytes);
extern void wad_release_memory();
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, ...);
/* Memory segments */
/* --- Memory segments --- */
typedef struct WadSegment {
char *base; /* Base address for symbol lookup */
char *vaddr; /* Virtual address start */
@ -58,9 +60,8 @@ typedef struct WadSegment {
extern int wad_segment_read();
extern WadSegment *wad_segment_find(void *vaddr);
/* Object file handling */
/* --- Object file handling --- */
typedef struct WadObjectFile {
struct WadFile *file; /* File data (private) */
void *ptr; /* Pointer to data */
int len; /* Length of data */
int type; /* Type of the object file */
@ -71,7 +72,7 @@ typedef struct WadObjectFile {
extern void wad_object_reset();
extern WadObjectFile *wad_object_load(const char *path);
/* Symbol table information */
/* --- Symbol table information --- */
typedef struct WadSymbol {
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 void wad_elf_debug(WadObjectFile *wo);
typedef struct WadParm {
char name[64];
int loc; /* Location: register or stack */
int type; /* Argument type */
int value; /* Argument position from stabs */
} WadParm;
typedef struct WadLocal {
char *name; /* Name of the local */
int loc; /* Location: register or stack */
int type; /* Argument type */
unsigned long position; /* Position on the stack */
struct WadLocal *next;
} 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 */
WadParm parms[100]; /* Parameters */
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
@ -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_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 {
long size; /* Frame size */
long lastsize; /* Size of previous frame */
long last; /* Last frame ? */
long frameno; /* Frame number */
long pc; /* Program counter */
long sp; /* Stack pointer */
long fp; /* Frame pointer */
long nargs; /* Number of arguments */
long arg_off; /* Argument offset */
long line_number; /* Source line number */
long sym_base; /* Symbol base address */
long sym_off; /* Symbol name offset */
long src_off; /* Source filename offset */
long obj_off; /* Object filename offset */
long stack_off; /* Stack offset */
long stack_size; /* Size of the stack segment */
long regs[16]; /* Integer registers (%on, %ln) */
double fregs[16]; /* Floating point registers */
char data[8]; /* Frame data */
long frameno; /* Frame number */
long pc; /* Real PC */
long sp; /* Real SP */
long fp; /* Real FP */
char *psp; /* Pointer to where the actual stack data is stored */
int stack_size; /* Stack frame size */
char *symbol; /* Symbol name */
long sym_base; /* Symbol base address */
char *objfile; /* Object file */
char *srcfile; /* Source file */
int line_number; /* Source line */
int nargs; /* Number of arguments */
WadLocal *args; /* Function arguments */
WadLocal *lastarg; /* Last argument */
int nlocals; /* Number of locals */
int last; /* Last frame flag */
struct WadFrame *next; /* Next frame up the stack */
struct WadFrame *prev; /* Previous frame down the stack */
} 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 char *wad_strip_dir(char *);
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 --- */
#define DEBUG_SEGMENT 0x1
#define DEBUG_SYMBOL 0x2
#define DEBUG_STABS 0x4
#define DEBUG_OBJECT 0x8
#define DEBUG_FILE 0x10
#define DEBUG_HOLD 0x20
#define DEBUG_RETURN 0x40
#define DEBUG_SEGMENT 0x1
#define DEBUG_SYMBOL 0x2
#define DEBUG_STABS 0x4
#define DEBUG_OBJECT 0x8
#define DEBUG_FILE 0x10
#define DEBUG_HOLD 0x20
#define DEBUG_RETURN 0x40
#define DEBUG_SYMBOL_SEARCH 0x80
#define DEBUG_INIT 0x100
#define DEBUG_NOSTACK 0x200
#define DEBUG_ONESHOT 0x400
#define DEBUG_STACK 0x800
#define DEBUG_UNWIND 0x1000
#define DEBUG_SIGNAL 0x2000
#define DEBUG_INIT 0x100
#define DEBUG_NOSTACK 0x200
#define DEBUG_ONESHOT 0x400
#define DEBUG_STACK 0x800
#define DEBUG_UNWIND 0x1000
#define DEBUG_SIGNAL 0x2000
extern int wad_debug_mode;
extern int wad_heap_overflow;

View file

@ -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
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)
WADOPT = -DWAD_LINUX
WADOPT = -DWAD_SOLARIS
# Location of your Python installation
PYINCLUDE = -I/usr/local/include/python2.0
@ -23,21 +23,21 @@ TCLSRCS = wadtcl.cxx
TCLOBJS = wadtcl.o
# Location of your Perl installation
PERLINCLUDE = -I/usr/lib/perl5/5.00503/i386-linux/CORE
PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE
PERLSRCS = wadpl.cxx
PERLOBJS = wadpl.o
# C Compiler
CC = gcc
CFLAGS = #-fpic
CC = cc
CFLAGS = #
# C++ Compiler
CXX = c++
CXXFLAGS = #-fpic
CXX = CC
CXXFLAGS = #-Kpic
# Linking options
CLINK =
CXXLINK = g++ -shared
CXXLINK = CC -G
# Rules for creation of a .o file from .cxx
.SUFFIXES: .cxx
@ -76,7 +76,7 @@ wc::
wc $(SRCS)
semi::
egrep ";" $(WADSRCS) | wc
egrep ";" $(SRCS) wadpy.cxx | wc
clean::

View file

@ -73,7 +73,7 @@ int main(int argc, char **argv) {
} else if (strcmp(argv[1],"ret") == 0) {
call_func(4,seg_crash);
} else if (strcmp(argv[1],"test") == 0) {
test(-4,seg_crash);
test(-1000,seg_crash);
} else if (strcmp(argv[1],"double") == 0) {
double_crash(3.14159,2.1828);
} else if (strcmp(argv[1],"math") == 0) {

View file

@ -21,25 +21,20 @@
char *wad_arg_string(WadFrame *frame) {
static char str[1024];
static char temp[64];
WadParm *wp;
WadLocal *wp;
long *stack;
long *nextstack;
int i;
WadFrame *nf;
if (frame->size) {
nf = (WadFrame *) (((char *) frame) + frame->size);
if (nf->size == 0) nf = 0;
} else {
nf = 0;
}
nf = frame->next;
if (nf)
nextstack = STACK(nf);
nextstack = (long *) nf->psp;
else
nextstack = 0;
str[0] = 0;
stack = STACK(frame);
stack = (long *) frame->psp;
#ifdef WAD_LINUX
if (!nf) {
@ -62,15 +57,15 @@ char *wad_arg_string(WadFrame *frame) {
#endif
} else {
/* We were able to get some argument information out the debugging table */
wp = ARGUMENTS(frame);
for (i = 0; i < frame->nargs; i++, wp++) {
wp = frame->args;
for (i = 0; i < frame->nargs; i++, wp = wp->next) {
strcat(str,wp->name);
strcat(str,"=");
/* Try to figure out where the value is */
if ((wp->loc == PARM_STACK) && nf) {
/* Parameter is located on the call stack */
unsigned long argloc = wp->value; /* Location relative to frame pointer */
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 */
@ -85,18 +80,19 @@ char *wad_arg_string(WadFrame *frame) {
}
} else if (wp->loc == PARM_REGISTER) {
#ifdef WAD_SOLARIS
if ((wp->value >= 24) && (wp->value < 32)) {
if ((wp->position >= 24) && (wp->position < 32)) {
/* 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);
} else if ((wp->value >= 8) && (wp->value < 16)) {
} 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->value >= 16) && (wp->value < 24)) {
/* 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);
strcat(str,temp); */
}
#endif
#ifdef WAD_LINUX
@ -202,24 +198,24 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
/* Find the last exception frame */
while (!f->last) {
fd = fd + f->size;
f = (WadFrame *) fd;
while (f && !f->last) {
f = f->next;
}
/* Now work backwards */
fd = fd - f->lastsize;
f = (WadFrame *) fd;
while (1) {
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, *(fd + f->sym_off) ? fd+f->sym_off : "?",
if (f) {
f = f->prev;
}
while (f) {
fprintf(stderr,"#%-3d 0x%08x in %s(%s)", f->frameno, f->pc, f->symbol ? f->symbol : "?",
wad_arg_string(f));
if (strlen(fd+f->src_off)) {
fprintf(stderr," in '%s'", wad_strip_dir(fd+f->src_off));
if (f->srcfile && strlen(f->srcfile)) {
fprintf(stderr," in '%s'", wad_strip_dir(f->srcfile));
if (f->line_number > 0) {
fprintf(stderr,", line %d", f->line_number);
{
int fd;
fd = open(SRCFILE(f), O_RDONLY);
fd = open(f->srcfile, O_RDONLY);
if (fd > 0) {
fline = f;
}
@ -227,14 +223,12 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
}
}
} else {
if (strlen(fd+f->obj_off)) {
fprintf(stderr," from '%s'", fd+f->obj_off);
if (f->objfile && strlen(f->objfile)) {
fprintf(stderr," from '%s'", f->objfile);
}
}
fprintf(stderr,"\n");
if (!f->lastsize) break;
fd = fd - f->lastsize;
f = (WadFrame *) fd;
f = f->prev;
}
if (fline) {
@ -246,9 +240,9 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
last = fline->line_number + 2;
if (first < 1) first = 1;
line = wad_load_source(SRCFILE(fline),first);
line = wad_load_source(fline->srcfile,first);
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++) {
if (i == fline->line_number) fprintf(stderr," => ");
else fprintf(stderr," ");

View file

@ -23,6 +23,7 @@ typedef struct _WadMemory {
} WadMemory;
static WadMemory *current = 0; /* Current memory block */
static WadMemory *persistent = 0; /* Persistent memory data */
static int pagesize = 0; /* System page size */
static int devzero = 0;
@ -92,6 +93,7 @@ void *wad_malloc(int nbytes) {
/* Yep. Found a region */
break;
}
wm = wm->next;
}
if (!wm) {
wad_printf("wad_malloc: new page\n", nbytes);
@ -107,6 +109,24 @@ void *wad_malloc(int nbytes) {
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()
*
@ -119,7 +139,7 @@ void wad_release_memory() {
wm = current;
while (wm) {
next = wm->next;
munmap(wm, wm->npages*pagesize);
munmap((char *) wm, wm->npages*pagesize);
wm = next;
}
current = 0;
@ -139,3 +159,11 @@ char *wad_strdup(const char *c) {
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;
}

View file

@ -4,6 +4,14 @@
* This file provides access to raw object files, executables, and
* library files. Memory management is handled through mmap() to
* 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)
*
@ -46,8 +54,8 @@ load_file(const char *path) {
return 0; /* Doesn't exist. Oh well */
}
if (wad_debug_mode & DEBUG_FILE) wad_printf("loaded.\n");
wf = (WadFile *) wad_malloc(sizeof(WadFile));
wf->path = wad_strdup(path);
wf = (WadFile *) wad_pmalloc(sizeof(WadFile));
wf->path = wad_pstrdup(path);
/* Get file length */
wf->size = lseek(fd,0,SEEK_END);
@ -65,14 +73,13 @@ load_file(const char *path) {
return wf;
}
static WadObjectFile *wad_objects = 0; /* Linked list of object files */
/* -----------------------------------------------------------------------------
* 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
@ -98,7 +105,7 @@ wad_object_reset() {
* wad_object_load()
*
* Load an object file into memory using mmap. Returns 0 if the object does
* not exist or if there are no more object descriptor slots
* not exist or if we're out of memory.
* ----------------------------------------------------------------------------- */
WadObjectFile *
@ -135,7 +142,7 @@ wad_object_load(const char *path) {
wo = wad_arobject_load(realfile,objfile);
if (wo) {
/* Reset the path */
wo->path = wad_strdup(path);
wo->path = wad_pstrdup(path);
return wo;
}
}
@ -143,9 +150,8 @@ wad_object_load(const char *path) {
wf = load_file(path);
if (!wf) return 0;
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
wo->file = wf;
wo->path = wad_strdup(path);
wo = (WadObjectFile *) wad_pmalloc(sizeof(WadObjectFile));
wo->path = wad_pstrdup(path);
wo->ptr = wf->addr;
wo->len = wf->size;
return wo;
@ -154,7 +160,9 @@ wad_object_load(const char *path) {
/* -----------------------------------------------------------------------------
* 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 *
@ -227,8 +235,7 @@ wad_arobject_load(const char *arpath, const char *robjname) {
/* Compare the names */
if (strncmp(mname,objname,sobjname) == 0) {
/* Found the archive */
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
wo->file = wf;
wo = (WadObjectFile *) wad_pmalloc(sizeof(WadObjectFile));
wo->ptr = (void *) (arptr + offset);
wo->len = msize;
wo->path = 0;

View file

@ -12,7 +12,7 @@
#include "wad.h"
/* 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
#ifndef ESP
@ -330,45 +330,42 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
if (wad_debug_mode & DEBUG_STACK) {
/* Walk the exception frames and try to find a return point */
framedata = (char *) frame;
while (frame->size) {
while (frame) {
int i;
WadParm *p;
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", SYMBOL(frame));
printf(" srcfile = '%s'\n", SRCFILE(frame));
printf(" objfile = '%s'\n", OBJFILE(frame));
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 = ARGUMENTS(frame);
for (i = 0; i < frame->nargs; i++, p++) {
printf(" arg[%d] : name = '%s', loc = %d, type = %d, value = %d\n", i, p->name, p->loc, p->type, p->value);
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");
framedata = framedata + frame->size;
frame = (WadFrame *) framedata;
frame = frame->next;
}
frame = origframe;
}
/* Walk the exception frames and try to find a return point */
framedata = (char *) frame;
while (frame->size) {
WadReturnFunc *wr = wad_check_return(framedata+frame->sym_off);
while (frame) {
WadReturnFunc *wr = wad_check_return(frame->symbol);
if (wr) {
found = 1;
wad_nlr_value = wr->value;
retname = wr->name;
}
framedata = framedata + frame->size;
frame = (WadFrame *) framedata;
frame = frame->next;
if (found) {
frame->last = 1; /* Cut off top of the stack trace */
break;
@ -376,7 +373,6 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
nlevels++;
}
if (found) {
wad_nlr_levels = nlevels - 1;
#ifdef WAD_LINUX

View file

@ -12,9 +12,7 @@
#include "wad.h"
/* stabs data structure. This appears to be somewhat universal. */
typedef struct Stab {
unsigned n_strx; /* index into file string table */
unsigned char n_type; /* type flag (N_TEXT,..) */
@ -23,11 +21,26 @@ typedef struct Stab {
unsigned n_value; /* value of symbol (or sdb offset) */
} Stab;
/* Match a stabs symbol name against a stab string (which may contain
extra information delimetered by a colon */
/* stabs data types used by this module */
int match_stab_symbol(char *symbol, char *stabtext, int slen) {
/* wad_printf("matching: %s -> %s\n", symbol, stabtext); */
#define N_UNDF 0x0 /* undefined */
#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) {
return 1;
}
@ -35,6 +48,17 @@ int match_stab_symbol(char *symbol, char *stabtext, int slen) {
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
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
that the only stabs data we will find is a file specifier. In this case,
*/
int
@ -59,6 +82,7 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
int i;
char *file, *lastfile = 0;
int chk = 0;
WadLocal *arg;
s = (Stab *) sp; /* Stabs data */
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->line_number = -1;
debug->nargs = 0;
debug->args = 0;
debug->lastarg = 0;
for (i = 0; i < ns; i++, s++) {
/*#define DEBUG_DEBUG */
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,
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
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->found = 0;
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 */
/* Source file specification */
/* Look for directory */
@ -116,13 +140,13 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
debug->found = 1;
}
lastfile = file;
} else if (s->n_type == 0x38) {
} else if (s->n_type == N_OBJ) {
/* Object file specifier */
if (debug->objfile[0]) {
strcat(debug->objfile,"/");
}
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 (!wsym->file || (strcmp(wsym->file,lastfile) == 0)) {
infunc = 1;
@ -134,13 +158,12 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
} else {
infunc = 0;
}
} else if (debug->found && (s->n_type == 0x44) && (infunc)) {
} 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 == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
} else if (debug->found && ((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) && (infunc)) {
/* Parameter counting */
char *pname;
char *c;
@ -153,41 +176,52 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
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
one identifies its location for the debugger */
if (debug->nargs > 0) {
if (debug->args) {
/* Need to do some fix up for linux here */
int i;
for (i = 0; i < debug->nargs; i++) {
if ((strncmp(debug->parms[i].name, pname,len) == 0) && (strlen(debug->parms[i].name) == len)) {
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 (debug->parms[i].loc == PARM_STACK) {
if (a->loc == PARM_STACK) {
break;
}
/* Go ahead and use the new argument */
if (s->n_type == 0x40)
debug->parms[i].loc = PARM_REGISTER;
a->loc = PARM_REGISTER;
else
debug->parms[i].loc = PARM_STACK;
debug->parms[i].value = s->n_value;
a->loc = PARM_STACK;
a->position = s->n_value;
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);
debug->parms[debug->nargs].name[len] = 0;
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)
debug->parms[debug->nargs].loc = PARM_REGISTER;
arg->loc = PARM_REGISTER;
else
debug->parms[debug->nargs].loc = PARM_STACK;
arg->loc = PARM_STACK;
debug->parms[debug->nargs].value = s->n_value;
debug->parms[debug->nargs].type = 0; /* Not used yet */
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++;
}
}

View file

@ -14,6 +14,9 @@
#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. */
#ifdef WAD_SOLARIS
#define STACK_BASE 0xffbf0000
#endif
@ -21,8 +24,12 @@
#define STACK_BASE 0xc0000000
#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
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
}
static void *trace_addr = 0;
static int trace_len = 0;
/* Perform a stack unwinding given the current value of the pc, stack pointer,
and frame pointer. Returns a pointer to a wad exception frame structure
which is actually a large memory mapped file. */
static char framefile[256];
/* -----------------------------------------------------------------------------
* wad_stack_trace()
*
* Create a stack trace of the process. Returns a linked list of stack frames
* with debugging information and other details.
* ----------------------------------------------------------------------------- */
WadFrame *
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
WadSegment *ws, *segments;
WadObjectFile *wo;
WadFrame frame;
WadSegment *ws;
WadObjectFile *wo;
WadFrame *firstframe=0, *lastframe=0, *frame=0;
WadDebug wd;
WadSymbol wsym;
int nlevels;
int ffile;
unsigned long p_pc;
unsigned long p_sp;
unsigned long p_fp;
unsigned long p_lastsp;
int n = 0;
int lastsize = 0;
int firstframe = 1;
/* Read the segments */
if (wad_segment_read() < 0) {
wad_printf("WAD: Unable to read segment map\n");
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 */
nlevels = 0;
p_pc = pc;
p_sp = sp;
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);
{
int symsize = 0;
int srcsize = 0;
int objsize = 0;
int stacksize = 0;
int argsize = 0;
char *srcname = 0;
char *objname = 0;
char *symname = 0;
int pad = 0;
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);
/* Special hack needed for base address */
}
else {
wo = 0;
@ -136,53 +118,51 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
} else {
symname = 0;
}
/* if (symname) symname = wad_cplus_demangle(&wsym); */
value = wsym.value;
/* Build up some information about the exception frame */
frame.frameno = n;
frame.last = 0;
frame.lastsize = lastsize;
frame.pc = p_pc;
frame.sp = p_sp;
frame.nargs = -1;
frame.arg_off = 0;
frame.sym_base = value + (long) ws->base;
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->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++;
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 */
if (wad_debug_info(wo,&wsym, p_pc - (unsigned long) ws->base - value, &wd)) {
srcname = wd.srcfile;
srcsize = strlen(srcname)+1;
objname = wd.objfile;
objsize = strlen(objname)+1;
frame.nargs = wd.nargs;
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;
}
/*
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 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;
@ -193,16 +173,16 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
}
}
#endif
firstframe = 0;
#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; /* Sick hack alert. Need to get stack top from somewhere */
stacksize = STACK_BASE - p_lastsp;
}
/* 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 */
/* frame.fp = p_sp; */
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;
frame->fp = p_sp;
frame->stack_size = stacksize;
/* Build up the offsets */
if (!symname) {
frame.sym_off = sizeof(WadFrame) - 8;
frame.src_off = sizeof(WadFrame) - 8;
frame.obj_off = sizeof(WadFrame) - 8;
frame.stack_off = sizeof(WadFrame) + argsize;
frame.arg_off = 0;
} else {
frame.arg_off = sizeof(WadFrame);
frame.stack_off = sizeof(WadFrame) + argsize;
frame.sym_off = frame.stack_off + stacksize;
frame.src_off = frame.sym_off + symsize;
frame.obj_off = frame.src_off + srcsize;
/* Copy stack data */
frame->psp = (char *) wad_malloc(stacksize);
if (frame->psp) {
memcpy(frame->psp, (void *) p_lastsp, stacksize);
}
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;
}
}
/* Write terminator */
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;
lastframe->last = 1;
return firstframe;
}
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 :-) */
long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
char *fd;
long *regs;
WadFrame *lastf = 0;
fd = (char *) f;
*error = 0;
/* Start searching */
while (f->size) {
if (strcmp(SYMBOL(f),symbol) == 0) {
while (f) {
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
/* Got a match */
if (lastf) {
regs = STACK(f);
regs = (long *) f->psp;
return regs[8+argno];
}
}
lastf = f;
fd = fd + f->size;
f = (WadFrame *) fd;
f = f->next;
}
*error = -1;
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) {
char *fd;
long *regs;
WadFrame *lastf = 0;
fd = (char *) f;
*error = 0;
/* Start searching */
while (f->size) {
if (strcmp(SYMBOL(f),symbol) == 0) {
while (f) {
if (f->symbol && (strcmp(f->symbol,symbol) == 0)) {
/* Got a match */
if (lastf) {
#ifdef WAD_SOLARIS
regs = STACK(lastf);
regs = (long *) lastf->psp;
return regs[8+argno];
#endif
#ifdef WAD_LINUX
regs = STACK(f);
regs = (long *) f->psp;
return regs[argno+2];
#endif
}
}
lastf = f;
fd = fd + f->size;
f = (WadFrame *) fd;
f = f->next;
}
*error = -1;
return 0;