*** empty log message ***
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@938 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
8d6a32bb08
commit
047feee80d
6 changed files with 123 additions and 172 deletions
|
|
@ -25,29 +25,21 @@ extern "C" {
|
||||||
#define MAX_PATH 1024
|
#define MAX_PATH 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Typedef's for various addresses and sizes */
|
/* Memory segment management */
|
||||||
typedef char * wadaddr_t;
|
|
||||||
typedef unsigned long wadlen_t;
|
|
||||||
|
|
||||||
/* Memory management */
|
|
||||||
extern void *wadmalloc(unsigned int);
|
|
||||||
extern void wadfree(void *ptr);
|
|
||||||
|
|
||||||
typedef struct WadSegment {
|
typedef struct WadSegment {
|
||||||
wadaddr_t vaddr; /* Virtual address start */
|
char *base; /* Base address for symbol lookup */
|
||||||
wadlen_t size; /* Size of the segment (bytes) */
|
char *vaddr; /* Virtual address start */
|
||||||
|
unsigned long size; /* Size of the segment (bytes) */
|
||||||
int flags; /* Memory access permissions */
|
int flags; /* Memory access permissions */
|
||||||
wadlen_t offset; /* Offset into mapped object */
|
unsigned long offset; /* Offset into mapped object */
|
||||||
char mapname[MAX_PATH]; /* Filename mapped to this region */
|
char mapname[MAX_PATH]; /* Filename mapped to this region */
|
||||||
char mappath[MAX_PATH]; /* Full path to mapname */
|
char mappath[MAX_PATH]; /* Full path to mapname */
|
||||||
int identifier; /* identifier (if SysV shmem) */
|
|
||||||
long wad; /* Private wad data (if any) */
|
|
||||||
} WadSegment;
|
} WadSegment;
|
||||||
|
|
||||||
extern void wad_segment_print(WadSegment *s);
|
extern void wad_segment_print(WadSegment *s);
|
||||||
extern WadSegment *wad_segment_find(wadaddr_t addr);
|
extern WadSegment *wad_segment_find(char *addr);
|
||||||
extern WadSegment *wad_segment_first();
|
extern void wad_segment_release();
|
||||||
extern WadSegment *wad_segment_next();
|
|
||||||
|
|
||||||
/* Structure for managing object files */
|
/* Structure for managing object files */
|
||||||
typedef struct WadObject {
|
typedef struct WadObject {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ void wad_init() {
|
||||||
sigaddset(&newvec.sa_mask, SIGABRT);
|
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||||
sigaddset(&newvec.sa_mask, SIGILL);
|
sigaddset(&newvec.sa_mask, SIGILL);
|
||||||
sigaddset(&newvec.sa_mask, SIGFPE);
|
sigaddset(&newvec.sa_mask, SIGFPE);
|
||||||
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK /* | SA_RESETHAND */;
|
||||||
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||||
sigaction(SIGSEGV, &newvec, NULL);
|
sigaction(SIGSEGV, &newvec, NULL);
|
||||||
sigaction(SIGBUS, &newvec, NULL);
|
sigaction(SIGBUS, &newvec, NULL);
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,122 @@
|
||||||
|
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
#include <procfs.h>
|
#include <procfs.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
/* The segment map is actually stored in an mmap'd data structure so we
|
||||||
|
can avoid the use of malloc()/free(). */
|
||||||
|
|
||||||
|
static WadSegment *segments = 0; /* mmap data containing segment info */
|
||||||
|
static int segments_size; /* Size of mmap'd region */
|
||||||
|
static int nsegments = 0; /* Number of segments */
|
||||||
|
|
||||||
/* The current segment is stored in statically allocated memory to avoid
|
/* This function reads the segment map into memory */
|
||||||
the use of malloc()/free(). If a caller wants to make a copy, that is
|
static
|
||||||
their problem */
|
void read_segments() {
|
||||||
|
int fd;
|
||||||
|
int dz;
|
||||||
|
prmap_t pmap;
|
||||||
|
int offset = 0;
|
||||||
|
int i;
|
||||||
|
int n = 0;
|
||||||
|
WadSegment *s;
|
||||||
|
|
||||||
static WadSegment segment; /* Currently loaded segment */
|
/* Try to load the virtual address map */
|
||||||
static int read_segment = 0;
|
fd = open("/proc/self/map", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsegments = 0;
|
||||||
|
while (1) {
|
||||||
|
n = read(fd,&pmap,sizeof(prmap_t));
|
||||||
|
if (n <= 0) break;
|
||||||
|
nsegments++;
|
||||||
|
}
|
||||||
|
nsegments++;
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
dz = open("/dev/zero", O_RDWR, 0644);
|
||||||
|
if (fd < 0) {
|
||||||
|
puts("Couldn't open /dev/zero\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
segments = (WadSegment *) mmap(NULL, nsegments*sizeof(WadSegment), PROT_READ | PROT_WRITE, MAP_PRIVATE, dz, 0);
|
||||||
|
close(dz);
|
||||||
|
segments_size = nsegments*sizeof(WadSegment);
|
||||||
|
|
||||||
|
fd = open("/proc/self/map", O_RDONLY);
|
||||||
|
if (fd < 0) return;
|
||||||
|
i = 0;
|
||||||
|
s = segments;
|
||||||
|
while (1) {
|
||||||
|
n = read(fd,&pmap,sizeof(prmap_t));
|
||||||
|
if (n <= 0) break;
|
||||||
|
strncpy(s->mapname, pmap.pr_mapname, MAX_PATH);
|
||||||
|
strcpy(s->mappath,"/proc/self/object/");
|
||||||
|
strcat(s->mappath,pmap.pr_mapname);
|
||||||
|
s->vaddr = (char *) pmap.pr_vaddr;
|
||||||
|
|
||||||
|
/* This is a solaris oddity. a.out section starts 1 page up, but
|
||||||
|
symbols are relative to a base of 0 */
|
||||||
|
|
||||||
|
if (strcmp(s->mapname,"a.out") == 0) s->base = 0;
|
||||||
|
else s->base = s->vaddr;
|
||||||
|
|
||||||
|
s->size = pmap.pr_size;
|
||||||
|
s->offset = pmap.pr_offset;
|
||||||
|
s->flags = pmap.pr_mflags;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_release()
|
||||||
|
*
|
||||||
|
* This function releases all of the segments.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
void wad_segment_release() {
|
||||||
|
munmap((void *)segments, segments_size);
|
||||||
|
segments = 0;
|
||||||
|
segments_size = 0;
|
||||||
|
nsegments = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_find()
|
||||||
|
*
|
||||||
|
* Try to find the virtual memory segment corresponding to a virtual address.
|
||||||
|
* If a segment is mapped to a file, this function actually returns the *first*
|
||||||
|
* segment that is mapped. This is because symbol relocations are always
|
||||||
|
* performed relative to the beginning of the file (so we need the base address)
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadSegment *
|
||||||
|
wad_segment_find(char *addr) {
|
||||||
|
int i;
|
||||||
|
WadSegment *s, *ls;
|
||||||
|
|
||||||
|
if (!segments) read_segments();
|
||||||
|
if (!segments) return 0;
|
||||||
|
|
||||||
|
s = segments;
|
||||||
|
ls = s;
|
||||||
|
for (i = 0; i < nsegments; i++, s++) {
|
||||||
|
if (strcmp(s->mapname,ls->mapname)) {
|
||||||
|
ls = s; /* First segment for a given name */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((addr >= s->vaddr) && (addr < (s->vaddr + s->size))) {
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* wad_segment_print()
|
* wad_segment_print()
|
||||||
*
|
*
|
||||||
* Print the contents of a memory segment. (Debugging)
|
* Print the contents of a memory segment. (For debugging WAD)
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -39,128 +141,4 @@ wad_segment_print(WadSegment *s) {
|
||||||
printf(" size = %d\n", s->size);
|
printf(" size = %d\n", s->size);
|
||||||
printf(" offset = %d\n", s->offset);
|
printf(" offset = %d\n", s->offset);
|
||||||
printf(" flags = 0x%x\n", s->flags);
|
printf(" flags = 0x%x\n", s->flags);
|
||||||
printf(" identifier = %d\n", s->identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
|
||||||
* wad_segment_find()
|
|
||||||
*
|
|
||||||
* Try to find the virtual memory segment corresponding to a virtual address.
|
|
||||||
* This overwrites the previously returned segment data.
|
|
||||||
* ----------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
WadSegment *
|
|
||||||
wad_segment_find(wadaddr_t addr) {
|
|
||||||
char dirname[MAX_PATH];
|
|
||||||
char filename[MAX_PATH];
|
|
||||||
int fd;
|
|
||||||
prmap_t pmap;
|
|
||||||
int offset = 0;
|
|
||||||
int i;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (read_segment) {
|
|
||||||
if ((addr >= segment.vaddr) && (addr < (segment.vaddr+segment.size))) return &segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set location in /proc */
|
|
||||||
sprintf(dirname,"/proc/%d",getpid());
|
|
||||||
|
|
||||||
/* Try to load the virtual address map */
|
|
||||||
sprintf(filename,"%s/map",dirname);
|
|
||||||
fd = open(filename, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
segment.mapname[0] = 0;
|
|
||||||
|
|
||||||
read_segment = 0;
|
|
||||||
while (1) {
|
|
||||||
n = read(fd,&pmap,sizeof(prmap_t));
|
|
||||||
if (n <= 0) break;
|
|
||||||
offset += n;
|
|
||||||
if ((addr >= (wadaddr_t) pmap.pr_vaddr) && (addr <= (wadaddr_t) (pmap.pr_vaddr + pmap.pr_size))) {
|
|
||||||
/* We are in a new segment */
|
|
||||||
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
|
||||||
strcpy(segment.mappath,dirname);
|
|
||||||
strcat(segment.mappath,"/object/");
|
|
||||||
strcat(segment.mappath,pmap.pr_mapname);
|
|
||||||
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
|
||||||
segment.size = pmap.pr_size;
|
|
||||||
segment.offset = pmap.pr_offset;
|
|
||||||
segment.flags = pmap.pr_mflags;
|
|
||||||
segment.identifier = pmap.pr_shmid;
|
|
||||||
segment.wad = offset;
|
|
||||||
read_segment = 1;
|
|
||||||
close(fd);
|
|
||||||
return &segment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
|
||||||
* wad_segment_next()
|
|
||||||
*
|
|
||||||
* Read the next segment
|
|
||||||
* ----------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
WadSegment *wad_segment_next() {
|
|
||||||
|
|
||||||
char dirname[MAX_PATH];
|
|
||||||
char filename[MAX_PATH];
|
|
||||||
int fd;
|
|
||||||
prmap_t pmap;
|
|
||||||
int offset = 0;
|
|
||||||
int i;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!read_segment) {
|
|
||||||
segment.wad = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set location in /proc */
|
|
||||||
sprintf(dirname,"/proc/%d",getpid());
|
|
||||||
|
|
||||||
/* Try to load the virtual address map */
|
|
||||||
sprintf(filename,"%s/map",dirname);
|
|
||||||
fd = open(filename, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (lseek(fd, segment.wad, SEEK_SET) < 0) {
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n = read(fd,&pmap,sizeof(prmap_t));
|
|
||||||
if (n <= 0) {
|
|
||||||
read_segment = 0;
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
|
||||||
strcpy(segment.mappath,dirname);
|
|
||||||
strcat(segment.mappath,"/object/");
|
|
||||||
strcat(segment.mappath,pmap.pr_mapname);
|
|
||||||
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
|
||||||
segment.size = pmap.pr_size;
|
|
||||||
segment.offset = pmap.pr_offset;
|
|
||||||
segment.flags = pmap.pr_mflags;
|
|
||||||
segment.identifier = pmap.pr_shmid;
|
|
||||||
segment.wad += n;
|
|
||||||
read_segment = 1;
|
|
||||||
close(fd);
|
|
||||||
return &segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
WadSegment *
|
|
||||||
wad_segment_first() {
|
|
||||||
segment.wad = 0;
|
|
||||||
read_segment = 0;
|
|
||||||
return wad_segment_next();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,16 +120,6 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
addr = (unsigned long) si->si_addr;
|
addr = (unsigned long) si->si_addr;
|
||||||
p_pc = (unsigned long) (*pc);
|
p_pc = (unsigned long) (*pc);
|
||||||
p_sp = (unsigned long) (*sp);
|
p_sp = (unsigned long) (*sp);
|
||||||
|
|
||||||
|
|
||||||
/* {
|
|
||||||
Dl_info dli;
|
|
||||||
if (dladdr((void *) p_pc, &dli) >= 0) {
|
|
||||||
printf("dli_fname = %s\n", dli.dli_fname);
|
|
||||||
printf("dli_sname = %s\n", dli.dli_sname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
frame = wad_stack_trace(p_pc, p_sp, 0);
|
frame = wad_stack_trace(p_pc, p_sp, 0);
|
||||||
origframe =frame;
|
origframe =frame;
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
|
|
@ -138,7 +128,6 @@ void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
framedata = (char *) frame;
|
||||||
|
|
||||||
while (frame->size) {
|
while (frame->size) {
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,7 @@ wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long o
|
||||||
} else if (debug.found && (s->n_type == 0x44) && (infunc)) {
|
} else if (debug.found && (s->n_type == 0x44) && (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 &debug;
|
} else return &debug;
|
||||||
} else if (debug.found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
|
} else if (debug.found && ((s->n_type == 0xa0) || (s->n_type == 0x40)) && (infunc)) {
|
||||||
|
|
|
||||||
|
|
@ -63,12 +63,12 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
|
|
||||||
while (p_sp) {
|
while (p_sp) {
|
||||||
/* Add check for stack validity here */
|
/* Add check for stack validity here */
|
||||||
ws = wad_segment_find((wadaddr_t) p_sp);
|
ws = wad_segment_find((char *) p_sp);
|
||||||
if (!ws) {
|
if (!ws) {
|
||||||
/* If the stack is bad, we are really hosed here */
|
/* If the stack is bad, we are really hosed here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ws = wad_segment_find((wadaddr_t) p_pc);
|
ws = wad_segment_find((char *) p_pc);
|
||||||
{
|
{
|
||||||
int symsize = 0;
|
int symsize = 0;
|
||||||
int srcsize = 0;
|
int srcsize = 0;
|
||||||
|
|
@ -85,7 +85,6 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
if (ws) {
|
if (ws) {
|
||||||
wo = wad_object_load(ws->mappath);
|
wo = wad_object_load(ws->mappath);
|
||||||
/* Special hack needed for base address */
|
/* Special hack needed for base address */
|
||||||
if (strcmp(ws->mapname,"a.out") == 0) ws->vaddr= 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wo = 0;
|
wo = 0;
|
||||||
|
|
@ -93,13 +92,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
|
|
||||||
/* Try to find the symbol corresponding to this PC */
|
/* Try to find the symbol corresponding to this PC */
|
||||||
if (wo) {
|
if (wo) {
|
||||||
symname = wad_find_symbol(wo, (void *) p_pc, (unsigned long) ws->vaddr, &value);
|
symname = wad_find_symbol(wo, (void *) p_pc, (unsigned long) ws->base, &value);
|
||||||
/* if (!symname) {
|
|
||||||
Dl_info dli;
|
|
||||||
if (dladdr((void *) p_pc, &dli) >= 0) {
|
|
||||||
symname = (char *) dli.dli_sname;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} else {
|
} else {
|
||||||
symname = 0;
|
symname = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +110,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
symsize = strlen(symname)+1;
|
symsize = strlen(symname)+1;
|
||||||
|
|
||||||
/* Try to gather some debugging information about this symbol */
|
/* Try to gather some debugging information about this symbol */
|
||||||
wd = wad_debug_info(wo,symname, p_pc - (unsigned long) ws->vaddr - value);
|
wd = wad_debug_info(wo,symname, p_pc - (unsigned long) ws->base - value);
|
||||||
if (wd) {
|
if (wd) {
|
||||||
srcname = wd->srcfile;
|
srcname = wd->srcfile;
|
||||||
srcsize = strlen(srcname)+1;
|
srcsize = strlen(srcname)+1;
|
||||||
|
|
@ -222,6 +215,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||||
lseek(ffile,0,SEEK_SET);
|
lseek(ffile,0,SEEK_SET);
|
||||||
trace_addr = mmap(NULL, trace_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
trace_addr = mmap(NULL, trace_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
||||||
close(ffile);
|
close(ffile);
|
||||||
|
wad_segment_release();
|
||||||
return (WadFrame *) trace_addr;
|
return (WadFrame *) trace_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +237,6 @@ long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error) {
|
||||||
|
|
||||||
fd = (char *) f;
|
fd = (char *) f;
|
||||||
|
|
||||||
|
|
||||||
*error = 0;
|
*error = 0;
|
||||||
/* Start searching */
|
/* Start searching */
|
||||||
while (f->size) {
|
while (f->size) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue