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:
Dave Beazley 2001-01-20 17:31:05 +00:00
commit 792c98acef
8 changed files with 211 additions and 112 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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