Cleanup of segments
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@1008 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
7d993483cb
commit
792c98acef
8 changed files with 211 additions and 112 deletions
|
|
@ -33,19 +33,26 @@ extern "C" {
|
|||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
/* Low level memory management */
|
||||
|
||||
extern int wad_memory_init();
|
||||
extern void *wad_malloc(int nbytes);
|
||||
extern void wad_release_memory();
|
||||
extern char *wad_strdup(const char *c);
|
||||
|
||||
/* Memory segments */
|
||||
typedef struct WadSegment {
|
||||
char *base; /* Base address for symbol lookup */
|
||||
char *vaddr; /* Virtual address start */
|
||||
unsigned long size; /* Size of the segment (bytes) */
|
||||
unsigned long offset; /* Offset into mapped object */
|
||||
char mapname[MAX_PATH]; /* Filename mapped to this region */
|
||||
char mappath[MAX_PATH]; /* Full path to mapname */
|
||||
char *base; /* Base address for symbol lookup */
|
||||
char *vaddr; /* Virtual address start */
|
||||
unsigned long size; /* Size of the segment (bytes) */
|
||||
unsigned long offset; /* Offset into mapped object */
|
||||
char *mapname; /* Filename mapped to this region */
|
||||
char *mappath; /* Full path to mapname */
|
||||
struct WadSegment *next; /* Next segment */
|
||||
} WadSegment;
|
||||
|
||||
extern WadSegment *wad_segment_read();
|
||||
extern WadSegment *wad_segment_find(WadSegment *s, void *vaddr);
|
||||
extern void wad_segment_release(WadSegment *s);
|
||||
extern int wad_segment_read();
|
||||
extern WadSegment *wad_segment_find(void *vaddr);
|
||||
|
||||
/* Object file handling */
|
||||
typedef struct WadObjectFile {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
#######################################################################
|
||||
|
||||
# These are the files that make up the WAD core
|
||||
WADSRCS = return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
||||
WADOBJS = return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
||||
WADSRCS = memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
||||
WADOBJS = memory.o return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||
WADOPT = -DWAD_SOLARIS
|
||||
WADOPT = -DWAD_LINUX
|
||||
|
||||
# Location of your Python installation
|
||||
PYINCLUDE = -I/usr/local/include/python2.0
|
||||
|
|
@ -23,21 +23,21 @@ TCLSRCS = wadtcl.cxx
|
|||
TCLOBJS = wadtcl.o
|
||||
|
||||
# Location of your Perl installation
|
||||
PERLINCLUDE = -I/usr/perl5/5.00503/sun4-solaris/CORE
|
||||
PERLINCLUDE = -I/usr/lib/perl5/5.00503/i386-linux/CORE
|
||||
PERLSRCS = wadpl.cxx
|
||||
PERLOBJS = wadpl.o
|
||||
|
||||
# C Compiler
|
||||
CC = cc
|
||||
CFLAGS = #
|
||||
CC = gcc
|
||||
CFLAGS = #-fpic
|
||||
|
||||
# C++ Compiler
|
||||
CXX = CC
|
||||
CXXFLAGS = #-Kpic
|
||||
CXX = c++
|
||||
CXXFLAGS = #-fpic
|
||||
|
||||
# Linking options
|
||||
CLINK =
|
||||
CXXLINK = CC -G
|
||||
CXXLINK = g++ -shared
|
||||
|
||||
# Rules for creation of a .o file from .cxx
|
||||
.SUFFIXES: .cxx
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ int wad_debug_mode = 0;
|
|||
void wad_init() {
|
||||
static int init = 0;
|
||||
|
||||
wad_memory_init();
|
||||
if (getenv("WAD_DEBUG_SEGMENT")) {
|
||||
wad_debug_mode |= DEBUG_SEGMENT;
|
||||
}
|
||||
|
|
|
|||
140
SWIG/Tools/WAD/Wad/memory.c
Normal file
140
SWIG/Tools/WAD/Wad/memory.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* memory.c
|
||||
*
|
||||
* This file provides simple mmap() based memory management for WAD. Since
|
||||
* the process heap-allocator might be corrupted when WAD is invoked, we
|
||||
* have to do all of our own memory management. However, since WAD mostly
|
||||
* just collects data, we only provide the function wad_malloc(). To
|
||||
* release all allocated memory, the wad_release_memory() function should
|
||||
* be used.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2001. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
typedef struct _WadMemory {
|
||||
int npages; /* Number of pages */
|
||||
int last; /* Last offset in page */
|
||||
struct _WadMemory *next; /* Pointer to next allocation */
|
||||
} WadMemory;
|
||||
|
||||
static WadMemory *current = 0; /* Current memory block */
|
||||
static int pagesize = 0; /* System page size */
|
||||
static int devzero = 0;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_memory_init()
|
||||
*
|
||||
* Initialize the WAD allocator.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int wad_memory_init() {
|
||||
pagesize = getpagesize();
|
||||
devzero = open("/dev/zero", O_RDWR);
|
||||
if (devzero < 0) {
|
||||
printf("WAD: couldn't open /dev/zero.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_page_alloc()
|
||||
*
|
||||
* Allocate pages using mmap
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_page_alloc(int npages) {
|
||||
void *m;
|
||||
m = mmap(NULL, npages*pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, devzero, 0);
|
||||
if (((long) m) == -1) return 0;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_malloc()
|
||||
*
|
||||
* Allocate memory using mmap(). If the allocation is smaller than half a page,
|
||||
* We'll look at current to see if there is enough space. If so, we'll just
|
||||
* use that memory. Otherwise, we'll allocate a new page. If the allocation
|
||||
* request is larger than a page, we'll round up to the nearest page size and
|
||||
* do a special allocation.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_malloc(int nbytes) {
|
||||
void *ptr;
|
||||
WadMemory *wm;
|
||||
char *c;
|
||||
int npages;
|
||||
printf("wad_malloc: %d\n", nbytes);
|
||||
if (nbytes >= (pagesize >> 2)) {
|
||||
/* Large allocation. */
|
||||
npages = ((nbytes + sizeof(WadMemory))/pagesize) + 1;
|
||||
ptr = wad_page_alloc(npages);
|
||||
if (!ptr) return 0;
|
||||
wm = (WadMemory *)ptr;
|
||||
wm->npages = npages;
|
||||
wm->last = sizeof(WadMemory);
|
||||
wm->next = current;
|
||||
current = wm;
|
||||
c = (char *) current + (current->last);
|
||||
current->last += ((nbytes & ~0x7) + 8);
|
||||
return c;
|
||||
}
|
||||
/* Small allocation. See if there are any regions big enough */
|
||||
wm = current;
|
||||
while (wm) {
|
||||
if (((wm->npages*pagesize) - wm->last) > nbytes) {
|
||||
/* Yep. Found a region */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!wm) {
|
||||
wm = (WadMemory *) wad_page_alloc(1);
|
||||
if (!wm) return 0;
|
||||
wm->npages = 1;
|
||||
wm->last = sizeof(WadMemory);
|
||||
wm->next = current;
|
||||
current = wm;
|
||||
}
|
||||
c = ((char *) wm) + (wm->last);
|
||||
wm->last += ((nbytes & ~0x7) + 8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_release_memory()
|
||||
*
|
||||
* Releases all memory previously allocated by wad_malloc()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_release_memory() {
|
||||
WadMemory *wm, *next;
|
||||
|
||||
wm = current;
|
||||
while (wm) {
|
||||
next = wm->next;
|
||||
munmap(wm, wm->npages*pagesize);
|
||||
wm = next;
|
||||
}
|
||||
current = 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_strdup()
|
||||
*
|
||||
* Duplicate a string
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *wad_strdup(const char *c) {
|
||||
char *t;
|
||||
if (!c) c = "";
|
||||
t = (char *) wad_malloc(strlen(c)+1);
|
||||
strcpy(t,c);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
@ -48,12 +48,13 @@ segment_read(int fd, WadSegment *s)
|
|||
pbuffer[8] = 0;
|
||||
pbuffer[17] = 0;
|
||||
pbuffer[31] = 0;
|
||||
s->mapname[0] = 0;
|
||||
s->mappath[0] = 0;
|
||||
if (len >= 49) {
|
||||
strcpy(s->mapname, pbuffer+49);
|
||||
strcpy(s->mappath, pbuffer+49);
|
||||
}
|
||||
s->mapname = wad_strdup(pbuffer+49);
|
||||
s->mappath = s->mapname;
|
||||
} else {
|
||||
s->mapname = "";
|
||||
s->mappath = s->mapname;
|
||||
}
|
||||
if (linux_first) {
|
||||
strcpy(linux_firstsegment, s->mappath);
|
||||
linux_first = 0;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ segment_read(int fs, WadSegment *s) {
|
|||
|
||||
n = read(fs, &pmap, sizeof(prmap_t));
|
||||
if (n <= 0) return 0;
|
||||
strncpy(s->mapname, pmap.pr_mapname, MAX_PATH);
|
||||
s->mapname = wad_strdup(pmap.pr_mapname);
|
||||
s->mappath = (char *) wad_malloc(20+strlen(pmap.pr_mapname));
|
||||
strcpy(s->mappath,"/proc/self/object/");
|
||||
strcat(s->mappath,pmap.pr_mapname);
|
||||
s->vaddr = (char *) pmap.pr_vaddr;
|
||||
|
|
|
|||
|
|
@ -17,18 +17,6 @@
|
|||
|
||||
#include "wad.h"
|
||||
|
||||
/* General comments:
|
||||
|
||||
The segment map gets returned as an array of WadSegment structures.
|
||||
Due to memory constraints, this is usually located in a memory mapped
|
||||
region or similar section of memory.
|
||||
|
||||
The first element of the memory map describes the segment map (address and size)
|
||||
so that it can be cleaned up later on.
|
||||
|
||||
The last element of the memory map is a sentinel where base == 0 and size == 0.
|
||||
*/
|
||||
|
||||
/* Include the proper code for reading the segment map */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
|
|
@ -39,90 +27,44 @@
|
|||
#include "plat/segment_linux.c"
|
||||
#endif
|
||||
|
||||
static WadSegment *segments = 0; /* Linked list of segments */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_read()
|
||||
*
|
||||
* Read all of the memory segments.
|
||||
* Read all of the memory segments into a linked list. Any previous segment
|
||||
* map is simply lost. The only way to reclaim this memory is to call
|
||||
* wad_release_memory().
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadSegment *
|
||||
int
|
||||
wad_segment_read() {
|
||||
int fs;
|
||||
int dz;
|
||||
int offset = 0;
|
||||
int i;
|
||||
int n = 0;
|
||||
int nsegments;
|
||||
WadSegment *segments;
|
||||
WadSegment *s;
|
||||
WadSegment ws;
|
||||
int n;
|
||||
WadSegment *s, *lasts;
|
||||
|
||||
/* Try to load the virtual address map */
|
||||
segments = 0;
|
||||
lasts = 0;
|
||||
fs = segment_open();
|
||||
if (fs < 0) return 0;
|
||||
nsegments = 0;
|
||||
while (1) {
|
||||
n = segment_read(fs,&ws);
|
||||
if (n <= 0) break;
|
||||
nsegments++;
|
||||
}
|
||||
nsegments+=3;
|
||||
close(fs);
|
||||
|
||||
dz = open("/dev/zero", O_RDWR, 0644);
|
||||
if (dz < 0) {
|
||||
puts("Couldn't open /dev/zero\n");
|
||||
return 0;
|
||||
}
|
||||
segments = (WadSegment *) mmap(NULL, nsegments*sizeof(WadSegment), PROT_READ | PROT_WRITE, MAP_PRIVATE, dz, 0);
|
||||
close(dz);
|
||||
|
||||
fs = segment_open();
|
||||
i = 0;
|
||||
s = segments;
|
||||
|
||||
/* First segment is a map to the segment list */
|
||||
s->base = (char *) segments;
|
||||
s->vaddr = (char *) segments;
|
||||
s->size = nsegments*sizeof(WadSegment);
|
||||
s->mapname[0] = 0;
|
||||
s->mappath[0] = 0;
|
||||
s++;
|
||||
|
||||
while (1) {
|
||||
n = segment_read(fs,&ws);
|
||||
s = (WadSegment *) wad_malloc(sizeof(WadSegment));
|
||||
n = segment_read(fs,s);
|
||||
if (n <= 0) break;
|
||||
strcpy(s->mapname, ws.mapname);
|
||||
strcpy(s->mappath, ws.mappath);
|
||||
s->vaddr = ws.vaddr;
|
||||
s->base = ws.base;
|
||||
s->size = ws.size;
|
||||
s->offset = ws.offset;
|
||||
s->next = 0;
|
||||
if (!lasts) {
|
||||
segments = s;
|
||||
lasts = s;
|
||||
} else {
|
||||
lasts->next = s;
|
||||
lasts = s;
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_SEGMENT) {
|
||||
printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
/* Create sentinel */
|
||||
s->base = 0;
|
||||
s->vaddr = 0;
|
||||
s->size = 0;
|
||||
s->offset = 0;
|
||||
s->mapname[0] =0;
|
||||
s->mappath[0] = 0;
|
||||
close(fs);
|
||||
return segments;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_release()
|
||||
*
|
||||
* This function releases all of the segments.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_segment_release(WadSegment *s) {
|
||||
munmap((void *)s, s->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
|
@ -135,13 +77,14 @@ wad_segment_release(WadSegment *s) {
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadSegment *
|
||||
wad_segment_find(WadSegment *s, void *vaddr) {
|
||||
wad_segment_find(void *vaddr) {
|
||||
WadSegment *ls;
|
||||
WadSegment *s;
|
||||
char *addr = (char *)vaddr;
|
||||
|
||||
ls = s;
|
||||
while (s->size || s->base) {
|
||||
/* printf("s = %x, %x(%d) %x\n",s, s->vaddr, s->size,addr); */
|
||||
s = segments;
|
||||
ls = segments;
|
||||
while (s) {
|
||||
if (strcmp(s->mapname,ls->mapname)) {
|
||||
ls = s; /* First segment for a given name */
|
||||
}
|
||||
|
|
@ -151,9 +94,13 @@ wad_segment_find(WadSegment *s, void *vaddr) {
|
|||
}
|
||||
return ls;
|
||||
}
|
||||
s++;
|
||||
s = s->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,10 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
|
||||
/* Read the segments */
|
||||
|
||||
segments = wad_segment_read();
|
||||
if (wad_segment_read() < 0) {
|
||||
printf("WAD: Unable to read segment map\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the frame file for output */
|
||||
tmpnam(framefile);
|
||||
|
|
@ -97,7 +100,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
|
||||
while (p_sp) {
|
||||
/* Add check for stack validity here */
|
||||
ws = wad_segment_find(segments, (void *) p_sp);
|
||||
ws = wad_segment_find((void *) p_sp);
|
||||
|
||||
if (!ws) {
|
||||
/* If the stack is bad, we are really hosed here */
|
||||
|
|
@ -105,7 +108,7 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
exit(1);
|
||||
break;
|
||||
}
|
||||
ws = wad_segment_find(segments, (void *) p_pc);
|
||||
ws = wad_segment_find((void *) p_pc);
|
||||
{
|
||||
int symsize = 0;
|
||||
int srcsize = 0;
|
||||
|
|
@ -272,7 +275,6 @@ wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
|||
lseek(ffile,0,SEEK_SET);
|
||||
trace_addr = mmap(NULL, trace_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
||||
close(ffile);
|
||||
wad_segment_release(segments);
|
||||
return (WadFrame *) trace_addr;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue