Cleanup
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@942 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
f4eb15b8d0
commit
f5d2474195
7 changed files with 406 additions and 233 deletions
|
|
@ -18,9 +18,11 @@
|
|||
#include <limits.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
#include <procfs.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -45,28 +47,40 @@ extern WadSegment *wad_segment_read();
|
|||
extern WadSegment *wad_segment_find(WadSegment *s, void *vaddr);
|
||||
extern void wad_segment_release(WadSegment *s);
|
||||
|
||||
/* Structure for managing object files */
|
||||
/* Object file handling */
|
||||
typedef struct WadObjectFile {
|
||||
void *mptr; /* mmap'd pointer to file */
|
||||
int mlen; /* mmap'd length */
|
||||
void *ptr; /* Pointer to real data */
|
||||
int len; /* Length of real data */
|
||||
int refcnt; /* Reference count */
|
||||
int type; /* Type of the object file */
|
||||
char path[MAX_PATH]; /* Path name of this object */
|
||||
struct WadFile *file; /* File data (private) */
|
||||
int refcnt; /* Reference count */
|
||||
void *ptr; /* Pointer to data */
|
||||
int len; /* Length of data */
|
||||
int type; /* Type of the object file */
|
||||
char path[MAX_PATH]; /* Path name of this object */
|
||||
} WadObjectFile;
|
||||
|
||||
extern char *wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, unsigned long *value);
|
||||
|
||||
/* Maximum number of object files that can be simultaneously loaded into memory */
|
||||
#define WAD_MAX_OBJECT 32
|
||||
|
||||
extern void wad_object_init();
|
||||
extern WadObjectFile *wad_object_load(const char *path);
|
||||
extern WadObjectFile *wad_arobject_load(const char *path, const char *name);
|
||||
extern void wad_object_release(WadObjectFile *);
|
||||
extern void wad_object_release(WadObjectFile *);
|
||||
extern void wad_object_cleanup();
|
||||
|
||||
/* Symbol table information */
|
||||
|
||||
typedef struct WadSymbol {
|
||||
char *name; /* Symbol table name */
|
||||
char *file; /* Source file (if any) */
|
||||
int type; /* Symbol type */
|
||||
int bind; /* Symbol bind */
|
||||
unsigned long value; /* Symbol value */
|
||||
} WadSymbol;
|
||||
|
||||
#define WS_LOCAL 1
|
||||
#define WS_GLOBAL 2
|
||||
|
||||
extern char *wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, WadSymbol *ws);
|
||||
|
||||
/* Signal handling */
|
||||
extern void wad_init();
|
||||
extern void wad_signalhandler(int, siginfo_t *, void *);
|
||||
extern void wad_signal_init();
|
||||
extern void wad_set_return(const char *name, long value);
|
||||
extern void wad_set_return_value(long value);
|
||||
|
||||
|
|
@ -93,8 +107,9 @@ typedef struct WadDebug {
|
|||
#define PARM_REGISTER 1
|
||||
#define PARM_STACK 2
|
||||
|
||||
extern WadDebug *wad_search_stab(void *stab, int size, char *stabstr, char *symbol, unsigned long offset);
|
||||
extern WadDebug *wad_debug_info(WadObjectFile *wo, char *symbol, unsigned long offset);
|
||||
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);
|
||||
|
||||
|
||||
/* 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
|
||||
|
|
@ -152,6 +167,9 @@ extern void wad_set_returns(WadReturnFunc *rf);
|
|||
#define DEBUG_SEGMENT 0x1
|
||||
#define DEBUG_SYMBOL 0x2
|
||||
#define DEBUG_STABS 0x4
|
||||
#define DEBUG_OBJECT 0x8
|
||||
#define DEBUG_FILE 0x10
|
||||
#define DEBUG_HOLD 0x20
|
||||
|
||||
extern int wad_debug_mode;
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ wad_elf_section_byname(WadObjectFile *wo, char *name) {
|
|||
|
||||
|
||||
char *
|
||||
wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, unsigned long *value) {
|
||||
wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol *ws) {
|
||||
int nsymtab;
|
||||
int nstrtab;
|
||||
int symtab_size;
|
||||
|
|
@ -213,6 +213,7 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, unsigned l
|
|||
int i;
|
||||
unsigned long vaddr;
|
||||
char *name;
|
||||
char *localfile = 0;
|
||||
|
||||
vaddr = (unsigned long) ptr;
|
||||
|
||||
|
|
@ -228,10 +229,20 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, unsigned l
|
|||
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||
for (i = 0; i < nsym; i++) {
|
||||
name = str + sym[i].st_name;
|
||||
/* Look for filename in case the symbol maps to a local symbol */
|
||||
if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
|
||||
localfile = name;
|
||||
}
|
||||
/* printf("%s %x\n", name, sym[i].st_value); */
|
||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr < (base+sym[i].st_value + sym[i].st_size))) {
|
||||
if (value)
|
||||
*value = sym[i].st_value;
|
||||
ws->value = sym[i].st_value;
|
||||
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
||||
ws->file = localfile;
|
||||
ws->bind = WS_LOCAL;
|
||||
} else {
|
||||
ws->bind = WS_GLOBAL;
|
||||
}
|
||||
ws->name = name;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
@ -249,17 +260,25 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, unsigned l
|
|||
str = (char *) wad_elf_section_data(wo,nstrtab);
|
||||
|
||||
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||
localfile = 0;
|
||||
for (i = 0; i < nsym; i++) {
|
||||
name = str + sym[i].st_name;
|
||||
if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
|
||||
localfile = name;
|
||||
}
|
||||
/* printf("%x(%x): %s %x + %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size); */
|
||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr < (base+sym[i].st_value + sym[i].st_size))) {
|
||||
if (value)
|
||||
*value = sym[i].st_value;
|
||||
ws->value = sym[i].st_value;
|
||||
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
||||
ws->file = localfile;
|
||||
ws->bind = WS_LOCAL;
|
||||
} else {
|
||||
ws->bind = WS_GLOBAL;
|
||||
}
|
||||
ws->name = name;
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -269,14 +288,13 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, unsigned l
|
|||
* Gather debugging information about a function (if possible)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadDebug *
|
||||
wad_elf_debug_info(WadObjectFile *wo, char *symbol, unsigned long offset) {
|
||||
int
|
||||
wad_elf_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd) {
|
||||
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
||||
|
||||
int ret;
|
||||
void *stab;
|
||||
char *stabstr;
|
||||
int stabsize;
|
||||
WadDebug *wd;
|
||||
|
||||
nstab = wad_elf_section_byname(wo,".stab");
|
||||
nstabstr = wad_elf_section_byname(wo,".stabstr");
|
||||
|
|
@ -302,8 +320,7 @@ wad_elf_debug_info(WadObjectFile *wo, char *symbol, unsigned long offset) {
|
|||
stabsize = wad_elf_section_size(wo,nstab);
|
||||
stabstr = (char *) wad_elf_section_data(wo,nstabstr);
|
||||
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset,wd)) return 1;
|
||||
}
|
||||
|
||||
/* Look in the .stab.excl section. A solaris oddity? */
|
||||
|
|
@ -312,30 +329,28 @@ wad_elf_debug_info(WadObjectFile *wo, char *symbol, unsigned long offset) {
|
|||
stab = wad_elf_section_data(wo,nstabexcl);
|
||||
stabsize = wad_elf_section_size(wo, nstabexcl);
|
||||
stabstr = (char *) wad_elf_section_data(wo, nstabexclstr);
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset,wd)) return 1;
|
||||
}
|
||||
|
||||
/* Look in the .stab.index section. Another solaris oddity? */
|
||||
/* Look in the .stab.index section. A Solaris oddity? */
|
||||
if (nstabindex > 0) {
|
||||
stab = wad_elf_section_data(wo,nstabindex);
|
||||
stabsize = wad_elf_section_size(wo, nstabindex);
|
||||
stabstr = (char *) wad_elf_section_data(wo, nstabindexstr);
|
||||
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||
if (wd) {
|
||||
if (wad_search_stab(stab,stabsize,stabstr, wsym, offset, wd)) {
|
||||
WadObjectFile *wo1;
|
||||
/* Hmmm. Might be in a different file */
|
||||
char objfile[MAX_PATH];
|
||||
strcpy(objfile, wd->objfile);
|
||||
wo1 = wad_object_load(objfile);
|
||||
if (wo1) {
|
||||
wd = wad_debug_info(wo1,symbol,offset);
|
||||
ret = wad_debug_info(wo1,wsym,offset,wd);
|
||||
wad_object_release(wo1);
|
||||
} else {
|
||||
/* printf("couldn't load %s\n", objfile); */
|
||||
}
|
||||
if (!wd) return wad_search_stab(stab,stabsize,stabstr,symbol,offset);
|
||||
return wd;
|
||||
if (!ret) return wad_search_stab(stab,stabsize,stabstr,wsym, offset,wd);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -370,11 +385,34 @@ wad_elf_debug(WadObjectFile *wo) {
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, unsigned long *value) {
|
||||
return wad_elf_find_symbol(wo,ptr,base,value);
|
||||
wad_find_symbol(WadObjectFile *wo, void *ptr, unsigned base, WadSymbol *ws) {
|
||||
char *r;
|
||||
ws->name = 0;
|
||||
ws->file = 0;
|
||||
ws->type = 0;
|
||||
ws->bind = 0;
|
||||
ws->value = 0;
|
||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||
printf("wad: Searching for 0x%08x --> ", ptr);
|
||||
}
|
||||
r = wad_elf_find_symbol(wo,ptr,base,ws);
|
||||
if (r) {
|
||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||
printf("%s", ws->name);
|
||||
if (ws->file)
|
||||
printf(" in '%s'\n", ws->file);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||
printf("?\n");
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
WadDebug *
|
||||
wad_debug_info(WadObjectFile *wo, char *symbol, unsigned long offset) {
|
||||
return wad_elf_debug_info(wo,symbol,offset);
|
||||
int
|
||||
wad_debug_info(WadObjectFile *wo, WadSymbol *wsym, unsigned long offset, WadDebug *wd) {
|
||||
return wad_elf_debug_info(wo,wsym, offset,wd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,22 +12,12 @@
|
|||
|
||||
#include "wad.h"
|
||||
|
||||
/* Size of signal stack */
|
||||
#define STACK_SIZE 4*SIGSTKSZ
|
||||
|
||||
/* Debugging flag */
|
||||
int wad_debug_mode = 0;
|
||||
|
||||
/* Make the alternate signal stack part of the wad data segment as
|
||||
opposed to putting it on the process heap */
|
||||
|
||||
char wad_sig_stack[STACK_SIZE];
|
||||
|
||||
/* Set up signal handler function for events we care about */
|
||||
/* Initialize wad */
|
||||
void wad_init() {
|
||||
struct sigaction newvec;
|
||||
static int init = 0;
|
||||
static stack_t sigstk;
|
||||
|
||||
if (getenv("WAD_DEBUG_SEGMENT")) {
|
||||
wad_debug_mode |= DEBUG_SEGMENT;
|
||||
|
|
@ -36,27 +26,25 @@ void wad_init() {
|
|||
wad_debug_mode |= DEBUG_SYMBOL;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_OBJECT")) {
|
||||
wad_debug_mode |= DEBUG_OBJECT;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_FILE")) {
|
||||
wad_debug_mode |= DEBUG_FILE;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_HOLD")) {
|
||||
wad_debug_mode |= DEBUG_HOLD;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_STABS")) {
|
||||
wad_debug_mode |= DEBUG_STABS;
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
/* Set up an alternative stack */
|
||||
sigstk.ss_sp = (char *) wad_sig_stack;
|
||||
sigstk.ss_size = STACK_SIZE;
|
||||
sigstk.ss_flags = 0;
|
||||
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
|
||||
perror("sigaltstack");
|
||||
}
|
||||
sigemptyset(&newvec.sa_mask);
|
||||
sigaddset(&newvec.sa_mask, SIGSEGV);
|
||||
sigaddset(&newvec.sa_mask, SIGBUS);
|
||||
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||
sigaddset(&newvec.sa_mask, SIGILL);
|
||||
sigaddset(&newvec.sa_mask, SIGFPE);
|
||||
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK /* | SA_RESETHAND */;
|
||||
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||
sigaction(SIGSEGV, &newvec, NULL);
|
||||
sigaction(SIGBUS, &newvec, NULL);
|
||||
sigaction(SIGABRT, &newvec, NULL);
|
||||
sigaction(SIGFPE, &newvec, NULL);
|
||||
sigaction(SIGILL, &newvec, NULL);
|
||||
wad_signal_init();
|
||||
wad_object_init();
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* object.c
|
||||
*
|
||||
* This file provides access to raw object files and executables.
|
||||
* All memory management is done through mmap() to avoid the
|
||||
* use of malloc()/free()
|
||||
* 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.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
|
|
@ -12,24 +12,122 @@
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
#include <sys/mman.h>
|
||||
#include <ar.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/* Maximum number of files that can be loaded at once */
|
||||
|
||||
#define WAD_MAX_FILE 32
|
||||
|
||||
typedef struct WadFile {
|
||||
int refcnt;
|
||||
void *addr;
|
||||
int size;
|
||||
char path[MAX_PATH];
|
||||
} WadFile;
|
||||
|
||||
static WadFile wad_files[WAD_MAX_FILE]; /* Array of file objects */
|
||||
|
||||
/* private function to manage the loading of raw files into memory */
|
||||
|
||||
static WadFile *
|
||||
load_file(const char *path) {
|
||||
int i;
|
||||
int fd;
|
||||
WadFile *firstfree = 0;
|
||||
WadFile *firstreplace = 0;
|
||||
WadFile *wf = wad_files;
|
||||
|
||||
if (wad_debug_mode & DEBUG_FILE) {
|
||||
printf("wad: Loading file '%s' ... ", path);
|
||||
}
|
||||
/* Walk through the file list to see if we already know about the file */
|
||||
for (i = 0; i < WAD_MAX_FILE; i++, wf++) {
|
||||
if (strcmp(wf->path, path) == 0) {
|
||||
wf->refcnt++;
|
||||
if (wad_debug_mode & DEBUG_FILE) {
|
||||
printf("cached.\n");
|
||||
}
|
||||
return wf;
|
||||
}
|
||||
if (wf->refcnt <= 0) {
|
||||
if (wf->path[0] == 0) firstfree = wf;
|
||||
else firstreplace = wf;
|
||||
}
|
||||
}
|
||||
|
||||
if (!firstfree && !firstreplace) {
|
||||
if (wad_debug_mode & DEBUG_FILE) printf("out of memory!\n");
|
||||
return 0; /* Out of space */
|
||||
}
|
||||
|
||||
if (!firstfree) firstfree = firstreplace;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (wad_debug_mode & DEBUG_FILE) printf("not found!\n");
|
||||
return 0; /* Doesn't exist. Oh well */
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_FILE) printf("loaded.\n");
|
||||
/* If already mapped, unmap the file */
|
||||
if (firstfree->addr) {
|
||||
if (wad_debug_mode & DEBUG_FILE)
|
||||
printf("wad: Unloading file '%s'\n", firstfree->path);
|
||||
munmap(firstfree->addr,firstfree->size);
|
||||
}
|
||||
|
||||
firstfree->refcnt = 1;
|
||||
strncpy(firstfree->path,path,MAX_PATH);
|
||||
|
||||
/* Get file length */
|
||||
firstfree->size = lseek(fd,0,SEEK_END);
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
firstfree->addr = mmap(NULL,firstfree->size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
if (firstfree->addr == MAP_FAILED) {
|
||||
if (wad_debug_mode & DEBUG_FILE) printf("wad: Couldn't mmap '%s'\n", path);
|
||||
firstfree->refcnt = 0;
|
||||
firstfree->path[0] = 0;
|
||||
firstfree->addr = 0;
|
||||
firstfree->size = 0;
|
||||
return 0;
|
||||
}
|
||||
return firstfree;
|
||||
}
|
||||
|
||||
static void
|
||||
release_file(WadFile *f) {
|
||||
if (wad_debug_mode & DEBUG_FILE) printf("wad: Releasing file '%s'\n", f->path);
|
||||
f->refcnt--;
|
||||
}
|
||||
|
||||
#define WAD_MAX_OBJECT 32
|
||||
|
||||
static WadObjectFile wad_objects[WAD_MAX_OBJECT]; /* Object file descriptor table */
|
||||
static int wad_obj_free[WAD_MAX_OBJECT]; /* Free object stack */
|
||||
static int wad_obj_nfree = 0; /* Num free object descriptors */
|
||||
static int wad_obj_init = 0; /* Initialized? */
|
||||
static int wad_obj_free[WAD_MAX_OBJECT]; /* Free object stack */
|
||||
static int wad_obj_nfree = 0; /* Num free object descriptors */
|
||||
|
||||
/* Initialize internal memory management */
|
||||
static void
|
||||
init_object() {
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_init()
|
||||
*
|
||||
* Initialize the object file system
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_object_init() {
|
||||
int i;
|
||||
if (wad_obj_init) return;
|
||||
|
||||
for (i = 0; i < WAD_MAX_FILE; i++) {
|
||||
wad_files[i].refcnt = 0;
|
||||
wad_files[i].addr = 0;
|
||||
wad_files[i].size = 0;
|
||||
wad_files[i].path[0] = 0;
|
||||
}
|
||||
|
||||
wad_obj_nfree = 0;
|
||||
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||
wad_objects[i].mptr = 0;
|
||||
wad_objects[i].mlen = 0;
|
||||
wad_objects[i].ptr = 0;
|
||||
wad_objects[i].len = 0;
|
||||
wad_objects[i].refcnt = 0;
|
||||
|
|
@ -37,9 +135,32 @@ init_object() {
|
|||
wad_obj_free[i] = i;
|
||||
wad_obj_nfree++;
|
||||
}
|
||||
wad_obj_init = 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_cleanup()
|
||||
*
|
||||
* Release all files loaded during the debugging
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_object_cleanup() {
|
||||
int i;
|
||||
WadFile *f = wad_files;
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
printf("wad: Releasing all files.\n");
|
||||
}
|
||||
for (i = 0; i < WAD_MAX_FILE; i++, f++) {
|
||||
if (f->addr) {
|
||||
munmap(f->addr, f->size);
|
||||
}
|
||||
f->addr = 0;
|
||||
f->size = 0;
|
||||
f->path[0] = 0;
|
||||
f->refcnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_release()
|
||||
*
|
||||
|
|
@ -50,13 +171,14 @@ void
|
|||
wad_object_release(WadObjectFile *wo) {
|
||||
int n;
|
||||
if (!wo) return;
|
||||
|
||||
wo->refcnt--;
|
||||
if (wo->refcnt > 0) return;
|
||||
if (wo->mptr) {
|
||||
munmap(wo->mptr, wo->mlen);
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
printf("wad: Releasing object '%s'\n", wo->path);
|
||||
}
|
||||
wo->mptr = 0;
|
||||
wo->mlen = 0;
|
||||
release_file(wo->file);
|
||||
wo->file = 0;
|
||||
wo->ptr = 0;
|
||||
wo->len = 0;
|
||||
wo->path[0] = 0;
|
||||
|
|
@ -74,13 +196,13 @@ wad_object_release(WadObjectFile *wo) {
|
|||
WadObjectFile *
|
||||
wad_object_load(const char *path) {
|
||||
WadObjectFile *wo;
|
||||
int nf;
|
||||
int fd;
|
||||
WadFile *wf;
|
||||
int i;
|
||||
if (!wad_obj_init) init_object();
|
||||
|
||||
/* printf("loading '%s'\n", path); */
|
||||
WadObjectFile *wad_arobject_load(const char *path, const char *name);
|
||||
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
printf("wad: Loading object '%s'\n", path);
|
||||
}
|
||||
/* See if the path has already been loaded */
|
||||
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||
if (strcmp(wad_objects[i].path,path) == 0) {
|
||||
|
|
@ -90,7 +212,8 @@ wad_object_load(const char *path) {
|
|||
}
|
||||
}
|
||||
if (wad_obj_nfree == 0) {
|
||||
printf("wad_object_load: No more space!\n");
|
||||
if (wad_debug_mode & DEBUG_OBJECT)
|
||||
printf("wad: No more space in wad_object_load()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -117,32 +240,17 @@ wad_object_load(const char *path) {
|
|||
}
|
||||
}
|
||||
}
|
||||
wf = load_file(path);
|
||||
if (!wf) return 0;
|
||||
|
||||
/* Try to open the requested pathname */
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) return 0; /* Doesn't exist */
|
||||
|
||||
nf = wad_obj_free[wad_obj_nfree-1];
|
||||
wo = wad_objects + nf;
|
||||
wo = wad_objects + wad_obj_free[wad_obj_nfree-1];
|
||||
wad_obj_nfree--;
|
||||
|
||||
wo->file = wf;
|
||||
wo->refcnt = 1;
|
||||
strncpy(wo->path,path, MAX_PATH);
|
||||
wo->mlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
wo->mptr = mmap(NULL,wo->mlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
if (wo->mptr == MAP_FAILED) {
|
||||
perror("Whoa. Can't mmap.");
|
||||
wo->mptr = 0;
|
||||
wad_object_release(wo);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
wo->ptr = wo->mptr;
|
||||
wo->len = wo->mlen;
|
||||
wo->ptr = wf->addr;
|
||||
wo->len = wf->size;
|
||||
return wo;
|
||||
}
|
||||
|
||||
|
|
@ -155,6 +263,7 @@ wad_object_load(const char *path) {
|
|||
WadObjectFile *
|
||||
wad_arobject_load(const char *arpath, const char *robjname) {
|
||||
WadObjectFile *wo;
|
||||
WadFile *wf;
|
||||
int nf;
|
||||
int fd;
|
||||
int i;
|
||||
|
|
@ -170,16 +279,12 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
|||
strcpy(objname,robjname);
|
||||
strcat(objname,"/");
|
||||
sobjname = strlen(objname);
|
||||
if (!wad_obj_init) init_object();
|
||||
|
||||
if (wad_obj_nfree == 0) {
|
||||
printf("wad_object_load: No more space!\n");
|
||||
return 0;
|
||||
}
|
||||
wf = load_file(arpath);
|
||||
if (!wf) return 0; /* Doesn't exit */
|
||||
|
||||
/* Try to open the requested archive name */
|
||||
fd = open(arpath, O_RDONLY);
|
||||
if (fd < 0) return 0; /* Doesn't exist */
|
||||
arptr = (char *) wf->addr;
|
||||
arlen = wf->size;
|
||||
|
||||
nf = wad_obj_free[wad_obj_nfree-1];
|
||||
wo = wad_objects + nf;
|
||||
|
|
@ -187,28 +292,17 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
|||
wo->refcnt = 1;
|
||||
wo->ptr = 0;
|
||||
|
||||
arlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
arptr = (char *) mmap(NULL,arlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
if (arptr == MAP_FAILED) {
|
||||
perror("Whoa. Can't mmap.");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now take a look at the archive */
|
||||
if (strncmp(arptr,ARMAG,SARMAG) == 0) {
|
||||
/* printf("Got an archive\n"); */
|
||||
} else {
|
||||
printf("Not an archive file\n");
|
||||
goto fatal_error;
|
||||
/* Not an archive file */
|
||||
release_file(wf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search the archive for the request member */
|
||||
strtab = 0;
|
||||
|
||||
offset = SARMAG;
|
||||
while (offset < arlen) {
|
||||
char mname[MAX_PATH];
|
||||
|
|
@ -226,8 +320,9 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
|||
/* Must be in the string offset table */
|
||||
soff = atoi(ah->ar_name+1);
|
||||
if (!strtab) {
|
||||
printf("Whoa. No string offset table\n");
|
||||
goto fatal_error;
|
||||
/* No offset table */
|
||||
release_file(wf);
|
||||
return 0;
|
||||
}
|
||||
e = strchr(strtab+soff,'\n');
|
||||
if (e) {
|
||||
|
|
@ -241,30 +336,21 @@ wad_arobject_load(const char *arpath, const char *robjname) {
|
|||
strncpy(mname,ah->ar_name,16);
|
||||
mname[16] = 0;
|
||||
}
|
||||
|
||||
/* printf("ar_name = '%s', ar_size = '%0.10s'\n", mname, ah->ar_size); */
|
||||
/* Compare the names */
|
||||
if (strncmp(mname,objname,sobjname) == 0) {
|
||||
/* Leave the archive mapped in memory, but set a pointer to the member
|
||||
name */
|
||||
|
||||
wo->mptr = (void *) arptr;
|
||||
wo->mlen = arlen;
|
||||
/* Found the archive */
|
||||
|
||||
wo = wad_objects + wad_obj_free[wad_obj_nfree-1];
|
||||
wad_obj_nfree--;
|
||||
wo->file = wf;
|
||||
wo->refcnt = 1;
|
||||
wo->ptr = (void *) (arptr + offset);
|
||||
wo->len = msize;
|
||||
close(fd);
|
||||
return wo;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += msize;
|
||||
}
|
||||
|
||||
fatal_error:
|
||||
munmap(arptr,arlen);
|
||||
close(fd);
|
||||
wad_object_release(wo);
|
||||
release_file(wf);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@
|
|||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "wad.h"
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* Signal handling stack */
|
||||
#define STACK_SIZE 4*SIGSTKSZ
|
||||
char wad_sig_stack[STACK_SIZE];
|
||||
|
||||
/* Data structures for containing information about non-local returns */
|
||||
|
||||
|
|
@ -109,6 +108,8 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
|||
char *framedata;
|
||||
char *retname = 0;
|
||||
|
||||
wad_object_init();
|
||||
|
||||
context = (ucontext_t *) vcontext;
|
||||
|
||||
/* Get some information about the current context */
|
||||
|
|
@ -165,6 +166,10 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
|||
wad_default_callback(sig, origframe,retname);
|
||||
}
|
||||
|
||||
if (wad_debug_mode & DEBUG_HOLD) while(1);
|
||||
|
||||
wad_object_cleanup();
|
||||
|
||||
/* If we found a function to which we should return, we jump to
|
||||
an alternative piece of code that unwinds the stack and
|
||||
initiates a non-local return. */
|
||||
|
|
@ -176,3 +181,35 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
|||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_signal_init()
|
||||
*
|
||||
* Reset the signal handler.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_signal_init() {
|
||||
struct sigaction newvec;
|
||||
static stack_t sigstk;
|
||||
/* Set up an alternative stack */
|
||||
sigstk.ss_sp = (char *) wad_sig_stack;
|
||||
sigstk.ss_size = STACK_SIZE;
|
||||
sigstk.ss_flags = 0;
|
||||
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
|
||||
perror("sigaltstack");
|
||||
}
|
||||
sigemptyset(&newvec.sa_mask);
|
||||
sigaddset(&newvec.sa_mask, SIGSEGV);
|
||||
sigaddset(&newvec.sa_mask, SIGBUS);
|
||||
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||
sigaddset(&newvec.sa_mask, SIGILL);
|
||||
sigaddset(&newvec.sa_mask, SIGFPE);
|
||||
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESETHAND;
|
||||
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||
sigaction(SIGSEGV, &newvec, NULL);
|
||||
sigaction(SIGBUS, &newvec, NULL);
|
||||
sigaction(SIGABRT, &newvec, NULL);
|
||||
sigaction(SIGFPE, &newvec, NULL);
|
||||
sigaction(SIGILL, &newvec, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,86 +44,91 @@ int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
|||
and offset is the offset in the object file of the symbol
|
||||
|
||||
Note: this function may recurse upon itself if there are multiple
|
||||
stabs sections
|
||||
stabs sections.
|
||||
|
||||
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,
|
||||
|
||||
*/
|
||||
|
||||
static WadDebug debug;
|
||||
|
||||
WadDebug *
|
||||
wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long offset) {
|
||||
int
|
||||
wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned long offset, WadDebug *debug) {
|
||||
Stab *s;
|
||||
int ns;
|
||||
int infunc;
|
||||
int slen;
|
||||
int i;
|
||||
char *file;
|
||||
char *file, *lastfile = 0;
|
||||
int chk = 0;
|
||||
|
||||
s = (Stab *) sp; /* Stabs data */
|
||||
ns = size/sizeof(Stab); /* number of stabs */
|
||||
slen = strlen(symbol);
|
||||
slen = strlen(wsym->name);
|
||||
|
||||
/* Reset the debug information section */
|
||||
debug.found = 0;
|
||||
debug.srcfile[0] = 0;
|
||||
debug.objfile[0] = 0;
|
||||
debug.line_number = -1;
|
||||
debug.nargs = 0;
|
||||
debug->found = 0;
|
||||
debug->srcfile[0] = 0;
|
||||
debug->objfile[0] = 0;
|
||||
debug->line_number = -1;
|
||||
debug->nargs = 0;
|
||||
for (i = 0; i < ns; i++, s++) {
|
||||
/*#define DEBUG_DEBUG */
|
||||
#ifdef DEBUG_DEBUG
|
||||
printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
||||
if (wad_debug_mode & DEBUG_STABS)
|
||||
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);
|
||||
#endif
|
||||
#undef DEBUG_DEBUG
|
||||
|
||||
if (s->n_type == 0) {
|
||||
/* New stabs section. We need to be a little careful here. Do a recursive
|
||||
search of the subsection. */
|
||||
WadDebug *wd;
|
||||
#ifdef DEBUG_DEBUG
|
||||
printf("Section: %d stabs.\n", s->n_desc);
|
||||
#endif
|
||||
wd = wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, symbol, offset);
|
||||
if (wd) return wd;
|
||||
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, wsym, offset,debug)) return 1;
|
||||
stabstr += s->n_value; /* Update the string table location*/
|
||||
i += s->n_desc;
|
||||
s += s->n_desc;
|
||||
debug.objfile[0] = 0;
|
||||
debug.srcfile[0] = 0;
|
||||
debug.line_number = -1;
|
||||
debug.found = 0;
|
||||
debug->objfile[0] = 0;
|
||||
debug->srcfile[0] = 0;
|
||||
debug->line_number = -1;
|
||||
debug->found = 0;
|
||||
} else if (s->n_type == 0x64) {
|
||||
if (debug.found) return &debug; /* 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 */
|
||||
/* Look for directory */
|
||||
file = stabstr+s->n_strx;
|
||||
if (file[strlen(file)] == '/') {
|
||||
strcpy(debug.srcfile,file);
|
||||
strcpy(debug->srcfile,file);
|
||||
} else {
|
||||
strcat(debug.srcfile,file);
|
||||
strcat(debug->srcfile,file);
|
||||
}
|
||||
debug.objfile[0] = 0;
|
||||
debug->objfile[0] = 0;
|
||||
/* We're going to check for a file match. Maybe we're looking for a local symbol */
|
||||
if (wsym->file && strcmp(wsym->file,file) == 0) {
|
||||
debug->found = 1;
|
||||
}
|
||||
lastfile = file;
|
||||
} else if (s->n_type == 0x38) {
|
||||
/* Object file specifier */
|
||||
if (debug.objfile[0]) {
|
||||
strcat(debug.objfile,"/");
|
||||
if (debug->objfile[0]) {
|
||||
strcat(debug->objfile,"/");
|
||||
}
|
||||
strcat(debug.objfile,stabstr+s->n_strx);
|
||||
strcat(debug->objfile,stabstr+s->n_strx);
|
||||
} else if (s->n_type == 0x24) {
|
||||
if (match_stab_symbol(symbol, stabstr+s->n_strx, slen)) {
|
||||
infunc = 1;
|
||||
debug.found = 1;
|
||||
debug.nargs = 0;
|
||||
if (match_stab_symbol(wsym->name, stabstr+s->n_strx, slen)) {
|
||||
if (!wsym->file || (strcmp(wsym->file,lastfile) == 0)) {
|
||||
infunc = 1;
|
||||
debug->found = 1;
|
||||
debug->nargs = 0;
|
||||
} else {
|
||||
infunc = 0;
|
||||
}
|
||||
} else {
|
||||
infunc = 0;
|
||||
}
|
||||
} else if (debug.found && (s->n_type == 0x44) && (infunc)) {
|
||||
} else if (debug->found && (s->n_type == 0x44) && (infunc)) {
|
||||
|
||||
/* Line number location */
|
||||
if (s->n_value < offset) {
|
||||
debug.line_number = s->n_desc;
|
||||
} else return &debug;
|
||||
} else if (debug.found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
|
||||
debug->line_number = s->n_desc;
|
||||
} else return 1;
|
||||
} else if (debug->found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
|
||||
/* Parameter counting */
|
||||
char *pname;
|
||||
char *c;
|
||||
|
|
@ -140,24 +145,24 @@ wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long o
|
|||
/* In this case, the first stab simply identifies an argument. The second
|
||||
one identifies its location for the debugger */
|
||||
|
||||
if (debug.nargs > 0) {
|
||||
if (strcmp(debug.parms[debug.nargs-1].name, pname) == 0)
|
||||
debug.nargs--;
|
||||
if (debug->nargs > 0) {
|
||||
if (strcmp(debug->parms[debug->nargs-1].name, pname) == 0)
|
||||
debug->nargs--;
|
||||
}
|
||||
strncpy(debug.parms[debug.nargs].name,pname,len);
|
||||
debug.parms[debug.nargs].name[len] = 0;
|
||||
strncpy(debug->parms[debug->nargs].name,pname,len);
|
||||
debug->parms[debug->nargs].name[len] = 0;
|
||||
|
||||
if (s->n_type == 0x40)
|
||||
debug.parms[debug.nargs].loc = PARM_REGISTER;
|
||||
debug->parms[debug->nargs].loc = PARM_REGISTER;
|
||||
else
|
||||
debug.parms[debug.nargs].loc = PARM_STACK;
|
||||
debug->parms[debug->nargs].loc = PARM_STACK;
|
||||
|
||||
debug.parms[debug.nargs].value = s->n_value;
|
||||
/* printf("%s : %d: %d : %s\n", debug.parms[debug.nargs].name, s->n_type, debug.parms[debug.nargs].value,pname); */
|
||||
debug->parms[debug->nargs].value = s->n_value;
|
||||
/* printf("%s : %d: %d : %s\n", debug->parms[debug->nargs].name, s->n_type, debug->parms[debug->nargs].value,pname); */
|
||||
|
||||
debug.nargs++;
|
||||
debug->nargs++;
|
||||
}
|
||||
}
|
||||
if (debug.found) return &debug;
|
||||
if (debug->found) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
WadSegment *ws, *segments;
|
||||
WadObjectFile *wo;
|
||||
WadFrame frame;
|
||||
WadDebug *wd;
|
||||
WadDebug wd;
|
||||
WadSymbol wsym;
|
||||
int nlevels;
|
||||
char framefile[256];
|
||||
int ffile;
|
||||
|
|
@ -95,11 +96,12 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
|
||||
/* Try to find the symbol corresponding to this PC */
|
||||
if (wo) {
|
||||
symname = wad_find_symbol(wo, (void *) p_pc, (unsigned long) ws->base, &value);
|
||||
symname = wad_find_symbol(wo, (void *) p_pc, (unsigned long) ws->base, &wsym);
|
||||
} else {
|
||||
symname = 0;
|
||||
}
|
||||
|
||||
value = wsym.value;
|
||||
|
||||
/* Build up some information about the exception frame */
|
||||
frame.frameno = n;
|
||||
frame.last = 0;
|
||||
|
|
@ -113,26 +115,25 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
symsize = strlen(symname)+1;
|
||||
|
||||
/* Try to gather some debugging information about this symbol */
|
||||
wd = wad_debug_info(wo,symname, p_pc - (unsigned long) ws->base - value);
|
||||
if (wd) {
|
||||
srcname = wd->srcfile;
|
||||
if (wad_debug_info(wo,&wsym, p_pc - (unsigned long) ws->base - value, &wd)) {
|
||||
srcname = wd.srcfile;
|
||||
srcsize = strlen(srcname)+1;
|
||||
objname = wd->objfile;
|
||||
objname = wd.objfile;
|
||||
objsize = strlen(objname)+1;
|
||||
frame.nargs = wd->nargs;
|
||||
if (wd->nargs > 0) {
|
||||
argsize = sizeof(WadParm)*wd->nargs;
|
||||
frame.nargs = wd.nargs;
|
||||
if (wd.nargs > 0) {
|
||||
argsize = sizeof(WadParm)*wd.nargs;
|
||||
}
|
||||
/*
|
||||
if (wd->nargs >=0) {
|
||||
if (wd.nargs >=0) {
|
||||
int i;
|
||||
printf("%s\n",symname);
|
||||
for (i = 0; i < wd->nargs; i++) {
|
||||
printf(" [%d] = '%s', %d, %d\n", i, wd->parms[i].name, wd->parms[i].type, wd->parms[i].value);
|
||||
for (i = 0; i < wd.nargs; i++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +187,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
write(ffile,&frame,sizeof(WadFrame));
|
||||
/* Write the argument data */
|
||||
if (argsize > 0) {
|
||||
write(ffile, (void *) wd->parms, argsize);
|
||||
write(ffile, (void *) wd.parms, argsize);
|
||||
}
|
||||
/* Write the stack data */
|
||||
if (stacksize > 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue