Linux stuff

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@951 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-11-23 22:26:33 +00:00
commit 344fa26627
12 changed files with 217 additions and 39 deletions

View file

@ -172,6 +172,10 @@ extern WadReturnFunc *wad_check_return(const char *name);
#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
extern int wad_debug_mode;

View file

@ -1,23 +1,24 @@
SRCS = return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
OBJS = return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o main.o
OBJS = return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
INCLUDE = -I../Include -I.
OPT = -DWAD_SOLARIS
LIBS =
PYINCLUDE = -I/usr/local/include/python2.0
#PYINCLUDE = -I/usr/local/include/python2.0
PYINCLUDE = -I/usr/local/include/python1.5
TCLINCLUDE = -I/usr/local/include
all::
CC -Kpic -c $(OPT) $(INCLUDE) main.cxx
cc -c $(OPT) $(INCLUDE) $(SRCS)
CC -G $(OBJS) -o libwad.so $(LIBS)
CC -G $(OBJS) main.o -o libwad.so $(LIBS)
cp libwad.so ..
python::
cc -c $(OPT) $(INCLUDE) $(SRCS)
CC -Kpic -c $(INCLUDE) $(PYINCLUDE) wadpy.cxx
CC -G $(OBJS) wadpy.o -o libwadpy.so $(LIBS)
CC -G $(OBJS) main.o wadpy.o -o libwadpy.so $(LIBS)
cp libwadpy.so ..
tcl::
@ -28,7 +29,19 @@ tcl::
cp libwadtcl.so ..
linux::
cc -DWAD_LINUX $(INCLUDE) segment.c init.c debug.c
g++ -fpic -c -DWAD_LINUX $(INCLUDE) main.cxx
gcc -g -c -DWAD_LINUX $(INCLUDE) $(SRCS)
g++ -shared $(OBJS) main.o -o libwad.so $(LIBS)
cp libwad.so ..
linux-python::
gcc -c -DWAD_LINUX $(INCLUDE) $(SRCS)
g++ -fpic -c -DWAD_LINUX $(INCLUDE) $(PYINCLUDE) wadpy.cxx
g++ -shared $(OBJS) wadpy.o -o libwadpy.so $(LIBS)
cp libwadpy.so ..
linux2::
cc -DWAD_LINUX $(INCLUDE) signal.c stack.c default.c demangle.c return.c stab.c elf.c object.c segment.c init.c debug.c
debug::
cc -g debug.c $(INCLUDE) -L. -R. -lwad

View file

@ -27,6 +27,11 @@ char *wad_arg_string(WadFrame *frame) {
int i;
WadFrame *nf;
#ifdef WAD_LINUX
strcat(str,"");
return str;
#endif
if (frame->size)
nf = (WadFrame *) (((char *) frame) + frame->size);
else
@ -97,6 +102,7 @@ char *wad_arg_string(WadFrame *frame) {
char *wad_strip_dir(char *name) {
char *c;
/* printf("strip: '%s'\n", name); */
c = name + strlen(name);
while (c != name) {
if (*c == '/') {
@ -202,7 +208,14 @@ void wad_default_callback(int signo, WadFrame *framedata, char *ret) {
printf(" in '%s'", wad_strip_dir(fd+f->src_off));
if (f->line_number > 0) {
printf(", line %d", f->line_number);
fline = f;
{
int fd;
fd = open(SRCFILE(f), O_RDONLY);
if (fd > 0) {
fline = f;
}
close(fd);
}
}
} else {
if (strlen(fd+f->obj_off)) {

View file

@ -224,9 +224,9 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
vaddr = (unsigned long) ptr;
nsymtab = wad_elf_section_byname(wo,".symtab");
if (nsymtab < 0) return 0;
if (nsymtab < 0) goto dynsym;
nstrtab = wad_elf_section_byname(wo,".strtab");
if (nstrtab < 0) return 0;
if (nstrtab < 0) goto dynsym;
symtab_size = wad_elf_section_size(wo,nsymtab);
sym = (Elf32_Sym *) wad_elf_section_data(wo,nsymtab);
@ -239,7 +239,15 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
localfile = name;
}
if (((base + sym[i].st_value) <= vaddr) && (vaddr < (base+sym[i].st_value + sym[i].st_size))) {
if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
}
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
#ifdef WAD_LINUX
/* If the section index is 0, the symbol is undefined */
if (sym[i].st_shndx == 0) continue;
#endif
ws->value = sym[i].st_value;
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
ws->file = localfile;
@ -250,9 +258,10 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
ws->name = name;
return name;
}
}
dynsym:
/* If we didn't find it in the .symtab section. Maybe it's in the .dynsym, .dynstr section */
nsymtab = wad_elf_section_byname(wo,".dynsym");
@ -271,8 +280,14 @@ wad_elf_find_symbol(WadObjectFile *wo, void *ptr, unsigned long base, WadSymbol
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 (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
}
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
#ifdef WAD_LINUX
/* If the section index is 0, the symbol is undefined */
if (sym[i].st_shndx == 0) continue;
#endif
ws->value = sym[i].st_value;
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
ws->file = localfile;

View file

@ -46,11 +46,29 @@ void wad_init() {
wad_debug_mode |= DEBUG_RETURN;
}
#ifndef WAD_LINUX
if (getenv("WAD_DEBUG_SYMBOL_SEARCH")) {
wad_debug_mode |= DEBUG_SYMBOL_SEARCH;
}
if (getenv("WAD_DEBUG_INIT")) {
wad_debug_mode |= DEBUG_INIT;
}
if (getenv("WAD_NOSTACK")) {
wad_debug_mode |= DEBUG_NOSTACK;
}
if (getenv("WAD_ONESHOT")) {
wad_debug_mode |= DEBUG_ONESHOT;
}
if (wad_debug_mode & DEBUG_INIT) {
printf("WAD: initializing\n");
}
if (!init) {
wad_signal_init();
wad_object_init();
}
#endif
init = 1;
}

View file

@ -11,10 +11,14 @@
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
static char linux_firstsegment[1024];
static int linux_first = 1;
static FILE *
segment_open() {
FILE *f;
f = fopen("/proc/self/maps", "r");
linux_first =1;
return f;
}
@ -38,7 +42,7 @@ segment_read(FILE *fs, WadSegment *s)
21 : p
23-31 : Offset
49- : Filename */
len = strlen(pbuffer);
pbuffer[8] = 0;
pbuffer[17] = 0;
@ -49,10 +53,18 @@ segment_read(FILE *fs, WadSegment *s)
strcpy(s->mapname, pbuffer+49);
strcpy(s->mappath, pbuffer+49);
}
if (linux_first) {
strcpy(linux_firstsegment, s->mappath);
linux_first = 0;
}
s->vaddr = (char *) strtoul(pbuffer,NULL,16);
s->size = strtoul(pbuffer+9,NULL,16) - (long) (s->vaddr);
s->offset = strtoul(pbuffer+23,NULL,16);
s->base = s->vaddr;
if (strcmp(linux_firstsegment, s->mappath) == 0) {
s->base = 0;
} else {
s->base = s->vaddr;
}
s++;
return 1;
}

View file

@ -29,7 +29,7 @@ void wad_set_return(const char *name, long value) {
}
void wad_set_returns(WadReturnFunc *rf) {
int i;
int i = 0;
while (strlen(rf[i].name)) {
wad_set_return(rf[i].name, rf[i].value);
i++;

View file

@ -99,7 +99,7 @@ wad_segment_read() {
s->size = ws.size;
s->offset = ws.offset;
if (wad_debug_mode & DEBUG_SEGMENT) {
printf("wad_segment: read : %08x-%08x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->mappath);
printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
}
s++;
}

View file

@ -29,7 +29,7 @@ void wad_set_callback(void (*s)(int,WadFrame *,char *ret)) {
normally. */
static int nlr_levels = 0;
static int *volatile nlr_p = &nlr_levels;
static volatile int *volatile nlr_p = &nlr_levels;
static long nlr_value = 0;
/* Set the return value from another module */
@ -37,6 +37,7 @@ void wad_set_return_value(long value) {
nlr_value = value;
}
#ifdef WAD_SOLARIS
static void nonlocalret() {
long a;
@ -65,15 +66,32 @@ static void nonlocalret() {
asm("restore");
asm(".size _returnsignal,(.-_returnsignal)");
}
#endif
#ifdef WAD_LINUX
static void nonlocalret() {
asm("_returnsignal:");
while (*nlr_p > 0) {
(*nlr_p)--;
asm("leave");
}
asm("movl nlr_value, %eax");
asm("leave");
asm("ret");
}
#endif
void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
greg_t *pc;
greg_t *npc;
greg_t *sp;
greg_t *fp;
unsigned long addr;
ucontext_t *context;
unsigned long p_sp; /* process stack pointer */
unsigned long p_pc; /* Process program counter */
unsigned long p_fp; /* Process frame pointer */
int nlevels = 0;
int found = 0;
void _returnsignal();
@ -86,15 +104,30 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
context = (ucontext_t *) vcontext;
/* Get some information about the current context */
#ifdef WAD_SOLARIS
pc = &((context->uc_mcontext).gregs[REG_PC]);
npc = &((context->uc_mcontext).gregs[REG_nPC]);
sp = &((context->uc_mcontext).gregs[REG_SP]);
#endif
#ifdef WAD_LINUX
sp = &((context->uc_mcontext).gregs[ESP]); /* Top of stack */
fp = &((context->uc_mcontext).gregs[EBP]); /* Stack base - frame pointer */
pc = &((context->uc_mcontext).gregs[EIP]); /* Current instruction */
/* printf("&sp = %x, &pc = %x\n", sp, pc); */
#endif
/* Get some information out of the signal handler stack */
addr = (unsigned long) si->si_addr;
p_pc = (unsigned long) (*pc);
p_sp = (unsigned long) (*sp);
frame = wad_stack_trace(p_pc, p_sp, 0);
#ifdef WAD_LINUX
p_fp = (unsigned long) (*fp);
/* printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp); */
#endif
frame = wad_stack_trace(p_pc, p_sp, p_fp);
origframe =frame;
if (!frame) {
/* We're really hosed here */
@ -144,7 +177,9 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
if (nlr_levels > 0) {
*(pc) = (greg_t) _returnsignal;
#ifdef WAD_SOLARIS
*(npc) = *(pc) + 4;
#endif
return;
}
exit(1);
@ -160,12 +195,19 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
void wad_signal_init() {
struct sigaction newvec;
static stack_t sigstk;
if (wad_debug_mode & DEBUG_INIT) {
printf("WAD: Initializing signal handler.\n");
}
/* 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");
if (!(wad_debug_mode & DEBUG_NOSTACK)) {
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
perror("sigaltstack");
}
}
sigemptyset(&newvec.sa_mask);
sigaddset(&newvec.sa_mask, SIGSEGV);
@ -173,11 +215,24 @@ void wad_signal_init() {
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_flags = SA_SIGINFO;
if (wad_debug_mode & DEBUG_ONESHOT) {
newvec.sa_flags |= SA_RESETHAND;
}
if (!(wad_debug_mode & DEBUG_NOSTACK)) {
newvec.sa_flags |= SA_ONSTACK;
}
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);
if (sigaction(SIGSEGV, &newvec, NULL) < 0) goto werror;
if (sigaction(SIGBUS, &newvec, NULL) < 0) goto werror;
if (sigaction(SIGABRT, &newvec, NULL) < 0) goto werror;
if (sigaction(SIGFPE, &newvec, NULL) < 0) goto werror;
if (sigaction(SIGILL, &newvec, NULL) < 0) goto werror;
return;
werror:
printf("WAD: Couldn't install signal handler!\n");
}

View file

@ -19,7 +19,7 @@ typedef struct Stab {
unsigned n_strx; /* index into file string table */
unsigned char n_type; /* type flag (N_TEXT,..) */
char n_other; /* used by N_SLINE stab */
short n_desc; /* see stabs documentation */
unsigned short n_desc; /* see stabs documentation */
unsigned n_value; /* value of symbol (or sdb offset) */
} Stab;
@ -62,6 +62,7 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
s = (Stab *) sp; /* Stabs data */
ns = size/sizeof(Stab); /* number of stabs */
slen = strlen(wsym->name);
/* Reset the debug information section */
@ -72,27 +73,39 @@ wad_search_stab(void *sp, int size, char *stabstr, WadSymbol *wsym, unsigned lon
debug->nargs = 0;
for (i = 0; i < ns; i++, s++) {
/*#define DEBUG_DEBUG */
if (wad_debug_mode & DEBUG_STABS)
if (wad_debug_mode & DEBUG_STABS) {
/* 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); */
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) {
stabstr+s->n_strx);
}
if ((s->n_type == 0)) { /* && (s->n_desc >= 0)) { */
/* New stabs section. We need to be a little careful here. Do a recursive
search of the subsection. */
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, wsym, offset,debug)) return 1;
/* On solaris, each stabs section seem to increment the stab string pointer. On Linux,
the linker seems to do a certain amount of optimization that results in a single
string table. */
#ifdef WAD_SOLARIS
stabstr += s->n_value; /* Update the string table location*/
#endif
i += s->n_desc;
s += s->n_desc;
debug->objfile[0] = 0;
debug->srcfile[0] = 0;
debug->line_number = -1;
debug->found = 0;
continue;
} else if (s->n_type == 0x64) {
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)] == '/') {
if (strlen(file) && (file[strlen(file)-1] == '/')) {
strcpy(debug->srcfile,file);
} else {
strcat(debug->srcfile,file);

View file

@ -18,9 +18,25 @@
unwinding */
static void
stack_unwind(unsigned long *sp, unsigned long *pc) {
stack_unwind(unsigned long *sp, unsigned long *pc, unsigned long *fp) {
#ifdef WAD_SOLARIS
*pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
*sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
#endif
#ifdef WAD_LINUX
*pc = *((unsigned long *) *fp+1);
*sp = *fp;
*fp = *((unsigned long *) *fp);
/* If we get a frame pointer of zero, we've gone off the end of the stack. Set the
stack pointer to zero to signal the stack unwinder. */
if (*fp == 0) {
*sp = 0;
}
#endif
}
static void *trace_addr = 0;
@ -42,6 +58,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
int ffile;
unsigned long p_pc;
unsigned long p_sp;
unsigned long p_fp;
unsigned long p_lastsp;
int n = 0;
@ -64,10 +81,12 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
nlevels = 0;
p_pc = pc;
p_sp = sp;
p_fp = fp;
while (p_sp) {
/* Add check for stack validity here */
ws = wad_segment_find(segments, (void *) p_sp);
if (!ws) {
/* If the stack is bad, we are really hosed here */
break;
@ -101,6 +120,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
symname = 0;
}
/* if (symname) symname = wad_cplus_demangle(&wsym); */
value = wsym.value;
@ -142,6 +162,8 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
}
}
#ifdef WAD_SOLARIS
/* Before unwinding the stack, copy the locals and %o registers from previous frame */
if (!firstframe) {
int i;
@ -151,18 +173,22 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
frame.regs[i] = lsp[i];
}
}
#endif
firstframe = 0;
/* Determine stack frame size */
p_lastsp = p_sp;
stack_unwind(&p_sp, &p_pc);
stack_unwind(&p_sp, &p_pc, &p_fp);
if (p_sp) {
stacksize = p_sp - p_lastsp;
} else {
#ifdef WAD_SOLARIS
stacksize = 0xffbf0000 - p_lastsp; /* Sick hack alert. Need to get stack top from somewhere */
#endif
#ifdef WAD_LINUX
stacksize = 0xc0000000 - p_lastsp;
#endif
}
/* Set the frame pointer and stack size */
frame.fp = p_sp;
frame.stack_size = stacksize;

View file

@ -155,7 +155,14 @@ static void handler(int signo, WadFrame *frame, char *ret) {
if (f->line_number > 0) {
sprintf(temp,", line %d", f->line_number);
strcat(message,temp);
fline = f;
{
int fd;
fd = open(SRCFILE(f), O_RDONLY);
if (fd > 0) {
fline = f;
}
close(fd);
}
}
} else {
if (strlen(fd+f->obj_off)) {
@ -251,3 +258,5 @@ extern "C"
void initlibwadpy() {
Py_InitModule((char *)"libwadpy",wadmethods);
}