From bb2b81dc431833bece3316cbb06d6b78917e3237 Mon Sep 17 00:00:00 2001 From: Dave Beazley Date: Tue, 30 Jan 2001 17:06:16 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@1011 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Tools/WAD/Include/wad.h | 113 ++++++++++---------- Tools/WAD/Wad/Makefile | 16 +-- Tools/WAD/Wad/debug.c | 2 +- Tools/WAD/Wad/default.c | 66 ++++++------ Tools/WAD/Wad/memory.c | 30 +++++- Tools/WAD/Wad/object.c | 33 +++--- Tools/WAD/Wad/signal.c | 36 +++---- Tools/WAD/Wad/stab.c | 100 ++++++++++++------ Tools/WAD/Wad/stack.c | 229 +++++++++++++--------------------------- 9 files changed, 296 insertions(+), 329 deletions(-) diff --git a/Tools/WAD/Include/wad.h b/Tools/WAD/Include/wad.h index d65421002..0b5513201 100644 --- a/Tools/WAD/Include/wad.h +++ b/Tools/WAD/Include/wad.h @@ -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; diff --git a/Tools/WAD/Wad/Makefile b/Tools/WAD/Wad/Makefile index 7eaa48a72..4e39c5ced 100644 --- a/Tools/WAD/Wad/Makefile +++ b/Tools/WAD/Wad/Makefile @@ -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:: diff --git a/Tools/WAD/Wad/debug.c b/Tools/WAD/Wad/debug.c index cad64b9fe..db6f0147a 100644 --- a/Tools/WAD/Wad/debug.c +++ b/Tools/WAD/Wad/debug.c @@ -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) { diff --git a/Tools/WAD/Wad/default.c b/Tools/WAD/Wad/default.c index cd8a1a5e1..50c38909d 100644 --- a/Tools/WAD/Wad/default.c +++ b/Tools/WAD/Wad/default.c @@ -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," "); diff --git a/Tools/WAD/Wad/memory.c b/Tools/WAD/Wad/memory.c index b83e25477..18852bb81 100644 --- a/Tools/WAD/Wad/memory.c +++ b/Tools/WAD/Wad/memory.c @@ -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; +} + diff --git a/Tools/WAD/Wad/object.c b/Tools/WAD/Wad/object.c index 5bfeec78a..dc7077762 100644 --- a/Tools/WAD/Wad/object.c +++ b/Tools/WAD/Wad/object.c @@ -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; diff --git a/Tools/WAD/Wad/signal.c b/Tools/WAD/Wad/signal.c index 46ad96a19..b376e13b4 100644 --- a/Tools/WAD/Wad/signal.c +++ b/Tools/WAD/Wad/signal.c @@ -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 diff --git a/Tools/WAD/Wad/stab.c b/Tools/WAD/Wad/stab.c index 874c93cbf..6e2e75289 100644 --- a/Tools/WAD/Wad/stab.c +++ b/Tools/WAD/Wad/stab.c @@ -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++; } } diff --git a/Tools/WAD/Wad/stack.c b/Tools/WAD/Wad/stack.c index 36cd14582..bd6598b94 100644 --- a/Tools/WAD/Wad/stack.c +++ b/Tools/WAD/Wad/stack.c @@ -14,6 +14,9 @@ #include #include +/* 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;