*** 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 #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;

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 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::

View file

@ -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) {

View file

@ -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," ");

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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++;
} }
} }

View file

@ -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;