Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://ElectricFence-2.2.2-19.src.rpm:38696/ElectricFence-2.2.2.tar.gz  info  downloads

ElectricFence-2.2.2/ 40755    764    764           0  6704702357  12600 5ustar  brucebruceElectricFence-2.2.2/README100644    764    764        1612  6704253163  13551 0ustar  brucebruceThis is Electric Fence 2.2

Electric Fence is a different kind of malloc() debugger. It uses the virtual
memory hardware of your system to detect when software overruns the boundaries
of a malloc() buffer. It will also detect any accesses of memory that has
been released by free(). Because it uses the VM hardware for detection,
Electric Fence stops your program on the first instruction that causes
a bounds violation. It's then trivial to use a debugger to display the
offending statement.

This version should run on all systems that support POSIX mmap() and
mprotect(). This includes Linux, Unix, and I think even BeOS.

Complete information on the use of Electric Fence is in the manual page
efence.3 .

There is a mailing list to support Electric Fence. You can subscribe to it
using the web form at http://lists.perens.com/mailman/listinfo/electric-fence.

	Thanks

	Bruce Perens
	bruce@perens.com
ElectricFence-2.2.2/Makefile100644    764    764        3455  6704676551  14352 0ustar  brucebrucePIC= -fPIC
CFLAGS= -g -DUSE_SEMAPHORE $(PIC)
LIBS= -lpthread

prefix=/usr
BIN_INSTALL_DIR= $(prefix)/bin
LIB_INSTALL_DIR= $(prefix)/lib
MAN_INSTALL_DIR= $(prefix)/man/man3

CC= cc
AR= ar
INSTALL= install

PACKAGE_SOURCE= README efence.3 Makefile efence.h \
	efence.c page.c print.c eftest.c tstheap.c CHANGES

OBJECTS= efence.o page.o print.o

all:	libefence.a libefence.so.0.0 tstheap eftest
	@ echo
	@ echo "Testing Electric Fence."
	@ echo "After the last test, it should print that the test has PASSED."
	./eftest
	./tstheap 3072
	@ echo
	@ echo "Electric Fence confidence test PASSED." 
	@ echo

install: libefence.a efence.3 libefence.so.0.0
	$(INSTALL) -m 755 ef.sh $(BIN_INSTALL_DIR)/ef
	$(INSTALL) -m 644 libefence.a $(LIB_INSTALL_DIR)
	$(INSTALL) -m 755 libefence.so.0.0 $(LIB_INSTALL_DIR)
	- rm -f $(LIB_INSTALL_DIR)/libefence.so.0
	ln -s libefence.so.0.0 $(LIB_INSTALL_DIR)/libefence.so.0
	- rm -f $(LIB_INSTALL_DIR)/libefence.so
	ln -s libefence.so.0.0 $(LIB_INSTALL_DIR)/libefence.so
	$(INSTALL) -m 644 efence.3 $(MAN_INSTALL_DIR)/efence.3

clean:
	- rm -f $(OBJECTS) tstheap.o eftest.o tstheap eftest \
	 libefence.a libefence.so.0.0 libefence.cat ElectricFence.shar

roff:
	nroff -man < efence.3 > efence.cat


ElectricFence.shar: $(PACKAGE_SOURCE)
	shar $(PACKAGE_SOURCE) > ElectricFence.shar

shar: ElectricFence.shar

libefence.a: $(OBJECTS)
	- rm -f libefence.a
	$(AR) crv libefence.a $(OBJECTS)

libefence.so.0.0: $(OBJECTS)
	gcc -g -shared -Wl,-soname,libefence.so.0 -o libefence.so.0.0 \
		$(OBJECTS) -lpthread -lc 

tstheap: libefence.a tstheap.o
	- rm -f tstheap
	$(CC) $(CFLAGS) tstheap.o libefence.a -o tstheap $(LIBS)

eftest: libefence.a eftest.o
	- rm -f eftest
	$(CC) $(CFLAGS) eftest.o libefence.a -o eftest $(LIBS)

$(OBJECTS) tstheap.o eftest.o: efence.h

.c.o:
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
ElectricFence-2.2.2/efence.h100644    764    764        2234  6704226031  14262 0ustar  brucebruce#include <sys/types.h>
#include <sys/param.h>
#include <stdarg.h>

/*
 * ef_number is the largest unsigned integer we'll need. On systems that
 * support 64-bit pointers, this may be "unsigned long long".
 */
#if defined(USE_LONG_LONG)
typedef unsigned long long	ef_number;
#else
typedef unsigned long		ef_number;
#endif

/*
 * NBBY is the number of bits per byte. Some systems define it in
 * <sys/param.h> .
 */
#ifndef	NBBY
#define	NBBY	8
#endif

/*
 * This is used to declare functions with "C" linkage if we are compiling
 * with C++ .
 */
#ifdef	__cplusplus
#define	C_LINKAGE	"C"
#else
#define	C_LINKAGE
#endif

void			Page_AllowAccess(void * address, size_t size);
void *			Page_Create(size_t size);
void			Page_Delete(void * address, size_t size);
void			Page_DenyAccess(void * address, size_t size);
size_t			Page_Size(void);

void			EF_Abort(const char * message, ...);
void			EF_Abortv(const char * message, va_list args);
void			EF_Exit(const char * message, ...);
void			EF_Exitv(const char * message, va_list args);
void			EF_Print(const char * message, ...);
void			EF_Printv(const char * message, va_list args);
void			EF_InternalError(const char * message, ...);
ElectricFence-2.2.2/efence.c100644    764    764       61554  6704513501  14310 0ustar  brucebruce/*
 * Electric Fence - Red-Zone memory allocator.
 * Bruce Perens, 1988, 1993
 * 
 * This is a special version of malloc() and company for debugging software
 * that is suspected of overrunning or underrunning the boundaries of a
 * malloc buffer, or touching free memory.
 *
 * It arranges for each malloc buffer to be followed (or preceded)
 * in the address space by an inaccessable virtual memory page,
 * and for free memory to be inaccessable. If software touches the
 * inaccessable page, it will get an immediate segmentation
 * fault. It is then trivial to uncover the offending code using a debugger.
 *
 * An advantage of this product over most malloc debuggers is that this one
 * detects reading out of bounds as well as writing, and this one stops on
 * the exact instruction that causes the error, rather than waiting until the
 * next boundary check.
 *
 * There is one product that debugs malloc buffer overruns
 * better than Electric Fence: "Purify" from Purify Systems, and that's only
 * a small part of what Purify does. I'm not affiliated with Purify, I just
 * respect a job well done.
 *
 * This version of malloc() should not be linked into production software,
 * since it tremendously increases the time and memory overhead of malloc().
 * Each malloc buffer will consume a minimum of two virtual memory pages,
 * this is 16 kilobytes on many systems. On some systems it will be necessary
 * to increase the amount of swap space in order to debug large programs that
 * perform lots of allocation, because of the per-buffer overhead.
 */
#include "efence.h"
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#ifdef USE_SEMAPHORE
# include <pthread.h>
# include <semaphore.h>
#endif

#ifdef	malloc
#undef	malloc
#endif

#ifdef	calloc
#undef	calloc
#endif

static const char	version[] = "\n  Electric Fence 2.2.0"
 " Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>\n";

/*
 * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
 * system at one time. We'll break that memory down into smaller pieces for
 * malloc buffers. One megabyte is probably a good value.
 */
#define			MEMORY_CREATION_SIZE	1024 * 1024

/*
 * Enum Mode indicates the status of a malloc buffer.
 */
enum _Mode {
	NOT_IN_USE = 0,	/* Available to represent a malloc buffer. */
	FREE,		/* A free buffer. */
	ALLOCATED,	/* A buffer that is in use. */
	PROTECTED,	/* A freed buffer that can not be allocated again. */
	INTERNAL_USE	/* A buffer used internally by malloc(). */
};
typedef enum _Mode	Mode;

/*
 * Struct Slot contains all of the information about a malloc buffer except
 * for the contents of its memory.
 */
struct _Slot {
	void *		userAddress;
	void *		internalAddress;
	size_t		userSize;
	size_t		internalSize;
	Mode		mode;
};
typedef struct _Slot	Slot;

/*
 * EF_ALIGNMENT is a global variable used to control the default alignment
 * of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
 * so that its name matches the name of the environment variable that is used
 * to set it. This gives the programmer one less name to remember.
 * If the value is -1, it will be set from the environment or sizeof(int)
 * at run time.
 */
int		EF_ALIGNMENT = -1;

/*
 * EF_PROTECT_FREE is a global variable used to control the disposition of
 * memory that is released using free(). It is all-caps so that its name
 * matches the name of the environment variable that is used to set it.
 * If its value is greater non-zero, memory released by free is made
 * inaccessable and never allocated again. Any software that touches free
 * memory will then get a segmentation fault. If its value is zero, freed
 * memory will be available for reallocation, but will still be inaccessable
 * until it is reallocated.
 * If the value is -1, it will be set from the environment or to 0 at run-time.
 */
int		EF_PROTECT_FREE = -1;

/*
 * EF_PROTECT_BELOW is used to modify the behavior of the allocator. When
 * its value is non-zero, the allocator will place an inaccessable page
 * immediately _before_ the malloc buffer in the address space, instead
 * of _after_ it. Use this to detect malloc buffer under-runs, rather than
 * over-runs. It won't detect both at the same time, so you should test your
 * software twice, once with this value clear, and once with it set.
 * If the value is -1, it will be set from the environment or to zero at
 * run-time
 */
int		EF_PROTECT_BELOW = -1;

/*
 * EF_ALLOW_MALLOC_0 is set if Electric Fence is to allow malloc(0). I
 * trap malloc(0) by default because it is a common source of bugs.
 */
int		EF_ALLOW_MALLOC_0 = -1;

/*
 * EF_FILL is set to 0-255 if Electric Fence should fill all new allocated
 * memory with the specified value.
 */
int		EF_FILL = -1;

/*
 * allocationList points to the array of slot structures used to manage the
 * malloc arena.
 */
static Slot *		allocationList = 0;

/*
 * allocationListSize is the size of the allocation list. This will always
 * be a multiple of the page size.
 */
static size_t		allocationListSize = 0;

/*
 * slotCount is the number of Slot structures in allocationList.
 */
static size_t		slotCount = 0;

/*
 * unUsedSlots is the number of Slot structures that are currently available
 * to represent new malloc buffers. When this number gets too low, we will
 * create new slots.
 */
static size_t		unUsedSlots = 0;

/*
 * slotsPerPage is the number of slot structures that fit in a virtual
 * memory page.
 */
static size_t		slotsPerPage = 0;

/*
 * internalUse is set when allocating and freeing the allocatior-internal
 * data structures.
 */
static int		internalUse = 0;

/*
 * noAllocationListProtection is set to tell malloc() and free() not to
 * manipulate the protection of the allocation list. This is only set in
 * realloc(), which does it to save on slow system calls, and in
 * allocateMoreSlots(), which does it because it changes the allocation list.
 */
static int		noAllocationListProtection = 0;

#ifdef USE_SEMAPHORE
/*
 * EF_sem is a semaphore used to allow one thread at a time into
 * these routines.
 * Also, we use semEnabled as a boolean to see if we should be
 * using the semaphore.
 * semThread is set to the thread id of the thread that currently
 * has the semaphore so that when/if it tries to get the semaphore
 * again (realloc calling malloc/free) - nothing will happen to the
 * semaphore.
 * semDepth is used to keep track of how many times the same thread
 * gets the semaphore - so we know when it is actually freed.
 */
static sem_t      EF_sem = { 0 };
static int        semEnabled = 0;
static pthread_t  semThread = (pthread_t) 0;
static int        semDepth = 0;
#endif

/*
 * bytesPerPage is set at run-time to the number of bytes per virtual-memory
 * page, as returned by Page_Size().
 */
static size_t		bytesPerPage = 0;

static void
lock()
{
#ifdef USE_SEMAPHORE
	/* Are we using a semaphore? */
	if (!semEnabled)
		return;

	/* Do we already have the semaphore? */
	if (semThread == pthread_self()) {
		/* Increment semDepth - push one stack level */
		semDepth++;
		return;
	}

	/* Wait for the semaphore. */
	while (sem_wait(&EF_sem) < 0)
		/* try again */;

	/* Let everyone know who has the semaphore. */
	semThread = pthread_self();
	semDepth++;
#endif	/* USE_SEMAPHORE */
}

static void
release()
{
#ifdef	USE_SEMAPHORE
	/* Are we using a semaphore? */
	if (!semEnabled)
		return;

	/* Do we have the semaphore?  Cannot free it if we don't. */
	if (semThread != pthread_self()) {
		if ( semThread == 0 )
			EF_InternalError(
			 "Releasing semaphore that wasn't locked.");

		else
			EF_InternalError(
			 "Semaphore doesn't belong to thread.");
	}

	/* Make sure this is positive as well. */
	if (semDepth <= 0)
		EF_InternalError("Semaphore depth");
	/* Decrement semDepth - popping one stack level */
	semDepth--;

	/* Only actually free the semaphore when we've reached the top */
	/* of our call stack. */
	if (semDepth == 0) {
		/* Zero this before actually free'ing the semaphore. */
		semThread = (pthread_t) 0;
		if (sem_post(&EF_sem) < 0)
			EF_InternalError("Failed to post the semaphore.");
	}
#endif /* USE_SEMAPHORE */
}

/*
 * initialize sets up the memory allocation arena and the run-time
 * configuration information.
 */
static void
initialize(void)
{
	size_t	size = MEMORY_CREATION_SIZE;
	size_t	slack;
	char *	string;
	Slot *	slot;

	EF_Print(version);

#ifdef USE_SEMAPHORE
	if (sem_init(&EF_sem, 0, 1) >= 0) {
		semEnabled = 1;
	}
#endif
	lock();

	/*
	 * Import the user's environment specification of the default
	 * alignment for malloc(). We want that alignment to be under
	 * user control, since smaller alignment lets us catch more bugs,
	 * however some software will break if malloc() returns a buffer
	 * that is not word-aligned.
	 *
	 * I would like
	 * alignment to be zero so that we could catch all one-byte
	 * overruns, however if malloc() is asked to allocate an odd-size
	 * buffer and returns an address that is not word-aligned, or whose
	 * size is not a multiple of the word size, software breaks.
	 * This was the case with the Sun string-handling routines,
	 * which can do word fetches up to three bytes beyond the end of a
	 * string. I handle this problem in part by providing
	 * byte-reference-only versions of the string library functions, but
	 * there are other functions that break, too. Some in X Windows, one
	 * in Sam Leffler's TIFF library, and doubtless many others.
	 */
	if ( EF_ALIGNMENT == -1 ) {
		if ( (string = getenv("EF_ALIGNMENT")) != 0 )
			EF_ALIGNMENT = (size_t)atoi(string);
		else
			EF_ALIGNMENT = sizeof(int);
	}

	/*
	 * See if the user wants to protect the address space below a buffer,
	 * rather than that above a buffer.
	 */
	if ( EF_PROTECT_BELOW == -1 ) {
		if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
			EF_PROTECT_BELOW = (atoi(string) != 0);
		else
			EF_PROTECT_BELOW = 0;
	}

	/*
	 * See if the user wants to protect memory that has been freed until
	 * the program exits, rather than until it is re-allocated.
	 */
	if ( EF_PROTECT_FREE == -1 ) {
		if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
			EF_PROTECT_FREE = (atoi(string) != 0);
		else
			EF_PROTECT_FREE = 0;
	}

	/*
	 * See if the user wants to allow malloc(0).
	 */
	if ( EF_ALLOW_MALLOC_0 == -1 ) {
		if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
			EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
		else
			EF_ALLOW_MALLOC_0 = 0;
	}

	
	/*
	 * Check if we should be filling new memory with a value.
	 */
	if ( EF_FILL == -1 ) {
		if ( (string = getenv("EF_FILL")) != 0)
			EF_FILL = (unsigned char) atoi(string);
	}

	/*
	 * Get the run-time configuration of the virtual memory page size.
 	 */
	bytesPerPage = Page_Size();

	/*
	 * Figure out how many Slot structures to allocate at one time.
	 */
	slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
	allocationListSize = bytesPerPage;

	if ( allocationListSize > size )
		size = allocationListSize;

	if ( (slack = size % bytesPerPage) != 0 )
		size += bytesPerPage - slack;

	/*
	 * Allocate memory, and break it up into two malloc buffers. The
	 * first buffer will be used for Slot structures, the second will
	 * be marked free.
	 */
	slot = allocationList = (Slot *)Page_Create(size);
	memset((char *)allocationList, 0, allocationListSize);

	slot[0].internalSize = slot[0].userSize = allocationListSize;
	slot[0].internalAddress = slot[0].userAddress = allocationList;
	slot[0].mode = INTERNAL_USE;
	if ( size > allocationListSize ) {
		slot[1].internalAddress = slot[1].userAddress
		 = ((char *)slot[0].internalAddress) + slot[0].internalSize;
		slot[1].internalSize
		 = slot[1].userSize = size - slot[0].internalSize;
		slot[1].mode = FREE;
	}

	/*
	 * Deny access to the free page, so that we will detect any software
	 * that treads upon free memory.
	 */
	Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);

	/*
	 * Account for the two slot structures that we've used.
	 */
	unUsedSlots = slotCount - 2;

	release();
}

/*
 * allocateMoreSlots is called when there are only enough slot structures
 * left to support the allocation of a single malloc buffer.
 */
static void
allocateMoreSlots(void)
{
	size_t	newSize = allocationListSize + bytesPerPage;
	void *	newAllocation;
	void *	oldAllocation = allocationList;

	Page_AllowAccess(allocationList, allocationListSize);
	noAllocationListProtection = 1;
	internalUse = 1;

	newAllocation = malloc(newSize);
	memcpy(newAllocation, allocationList, allocationListSize);
	memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);

	allocationList = (Slot *)newAllocation;
	allocationListSize = newSize;
	slotCount += slotsPerPage;
	unUsedSlots += slotsPerPage;

	free(oldAllocation);

	/*
	 * Keep access to the allocation list open at this point, because
	 * I am returning to memalign(), which needs that access.
 	 */
	noAllocationListProtection = 0;
	internalUse = 0;
}

/*
 * This is the memory allocator. When asked to allocate a buffer, allocate
 * it in such a way that the end of the buffer is followed by an inaccessable
 * memory page. If software overruns that buffer, it will touch the bad page
 * and get an immediate segmentation fault. It's then easy to zero in on the
 * offending code with a debugger.
 *
 * There are a few complications. If the user asks for an odd-sized buffer,
 * we would have to have that buffer start on an odd address if the byte after
 * the end of the buffer was to be on the inaccessable page. Unfortunately,
 * there is lots of software that asks for odd-sized buffers and then
 * requires that the returned address be word-aligned, or the size of the
 * buffer be a multiple of the word size. An example are the string-processing
 * functions on Sun systems, which do word references to the string memory
 * and may refer to memory up to three bytes beyond the end of the string.
 * For this reason, I take the alignment requests to memalign() and valloc()
 * seriously, and 
 * 
 * Electric Fence wastes lots of memory. I do a best-fit allocator here
 * so that it won't waste even more. It's slow, but thrashing because your
 * working set is too big for a system's RAM is even slower. 
 */
extern C_LINKAGE void *
memalign(size_t alignment, size_t userSize)
{
	register Slot *	slot;
	register size_t	count;
	Slot *		fullSlot = 0;
	Slot *		emptySlots[2];
	size_t		internalSize;
	size_t		slack;
	char *		address;

	if ( allocationList == 0 )
		initialize();

	lock();

	if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
		EF_Abort("Allocating 0 bytes, probably a bug.");

	/*
	 * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
	 * and company will be page-aligned.
 	 */
	if ( !EF_PROTECT_BELOW && alignment > 1 ) {
		if ( (slack = userSize % alignment) != 0 )
			userSize += alignment - slack;
	}

	/*
	 * The internal size of the buffer is rounded up to the next page-size
	 * boudary, and then we add another page's worth of memory for the
	 * dead page.
	 */
	internalSize = userSize + bytesPerPage;
	if ( (slack = internalSize % bytesPerPage) != 0 )
		internalSize += bytesPerPage - slack;

	/*
	 * These will hold the addresses of two empty Slot structures, that
	 * can be used to hold information for any memory I create, and any
	 * memory that I mark free.
	 */
	emptySlots[0] = 0;
	emptySlots[1] = 0;

	/*
	 * The internal memory used by the allocator is currently
	 * inaccessable, so that errant programs won't scrawl on the
	 * allocator's arena. I'll un-protect it here so that I can make
	 * a new allocation. I'll re-protect it before I return.
 	 */
	if ( !noAllocationListProtection )
		Page_AllowAccess(allocationList, allocationListSize);

	/*
	 * If I'm running out of empty slots, create some more before
	 * I don't have enough slots left to make an allocation.
	 */
	if ( !internalUse && unUsedSlots < 7 ) {
		allocateMoreSlots();
	}
	
	/*
	 * Iterate through all of the slot structures. Attempt to find a slot
	 * containing free memory of the exact right size. Accept a slot with
	 * more memory than we want, if the exact right size is not available.
	 * Find two slot structures that are not in use. We will need one if
	 * we split a buffer into free and allocated parts, and the second if
	 * we have to create new memory and mark it as free.
	 *
	 */
	
	for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
		if ( slot->mode == FREE
		 && slot->internalSize >= internalSize ) {
			if ( !fullSlot
			 ||slot->internalSize < fullSlot->internalSize){
				fullSlot = slot;
				if ( slot->internalSize == internalSize
				 && emptySlots[0] )
					break;	/* All done, */
			}
		}
		else if ( slot->mode == NOT_IN_USE ) {
			if ( !emptySlots[0] )
				emptySlots[0] = slot;
			else if ( !emptySlots[1] )
				emptySlots[1] = slot;
			else if ( fullSlot
			 && fullSlot->internalSize == internalSize )
				break;	/* All done. */
		}
		slot++;
	}
	if ( !emptySlots[0] )
		EF_InternalError("No empty slot 0.");

	if ( !fullSlot ) {
		/*
		 * I get here if I haven't been able to find a free buffer
		 * with all of the memory I need. I'll have to create more
		 * memory. I'll mark it all as free, and then split it into
		 * free and allocated portions later.
		 */
		size_t	chunkSize = MEMORY_CREATION_SIZE;

		if ( !emptySlots[1] )
			EF_InternalError("No empty slot 1.");

		if ( chunkSize < internalSize )
			chunkSize = internalSize;

		if ( (slack = chunkSize % bytesPerPage) != 0 )
			chunkSize += bytesPerPage - slack;

		/* Use up one of the empty slots to make the full slot. */
		fullSlot = emptySlots[0];
		emptySlots[0] = emptySlots[1];
		fullSlot->internalAddress = Page_Create(chunkSize);
		fullSlot->internalSize = chunkSize;
		fullSlot->mode = FREE;
		unUsedSlots--;
		
		/* Fill the slot if it was specified to do so. */
		if ( EF_FILL != -1 )
			memset(
			 (char *)fullSlot->internalAddress
			,EF_FILL
			,chunkSize);
	}
  
	/*
	 * If I'm allocating memory for the allocator's own data structures,
	 * mark it INTERNAL_USE so that no errant software will be able to
	 * free it.
	 */
	if ( internalUse )
		fullSlot->mode = INTERNAL_USE;
	else
		fullSlot->mode = ALLOCATED;

	/*
	 * If the buffer I've found is larger than I need, split it into
	 * an allocated buffer with the exact amount of memory I need, and
	 * a free buffer containing the surplus memory.
	 */
	if ( fullSlot->internalSize > internalSize ) {
		emptySlots[0]->internalSize
		 = fullSlot->internalSize - internalSize;
		emptySlots[0]->internalAddress
		 = ((char *)fullSlot->internalAddress) + internalSize;
		emptySlots[0]->mode = FREE;
		fullSlot->internalSize = internalSize;
		unUsedSlots--;
	}

	if ( !EF_PROTECT_BELOW ) {
		/*
		 * Arrange the buffer so that it is followed by an inaccessable
		 * memory page. A buffer overrun that touches that page will
		 * cause a segmentation fault.
		 */
		address = (char *)fullSlot->internalAddress;

		/* Set up the "live" page. */
		if ( internalSize - bytesPerPage > 0 )
				Page_AllowAccess(
				 fullSlot->internalAddress
				,internalSize - bytesPerPage);
			
		address += internalSize - bytesPerPage;

		/* Set up the "dead" page. */
		if ( EF_PROTECT_FREE )
			Page_Delete(address, bytesPerPage);
		else
			Page_DenyAccess(address, bytesPerPage);

		/* Figure out what address to give the user. */
		address -= userSize;
	}
	else {	/* EF_PROTECT_BELOW != 0 */
		/*
		 * Arrange the buffer so that it is preceded by an inaccessable
		 * memory page. A buffer underrun that touches that page will
		 * cause a segmentation fault.
		 */
		address = (char *)fullSlot->internalAddress;

		/* Set up the "dead" page. */
		if ( EF_PROTECT_FREE )
			Page_Delete(address, bytesPerPage);
		else
			Page_DenyAccess(address, bytesPerPage);
			
		address += bytesPerPage;

		/* Set up the "live" page. */
		if ( internalSize - bytesPerPage > 0 )
			Page_AllowAccess(address, internalSize - bytesPerPage);
	}

	fullSlot->userAddress = address;
	fullSlot->userSize = userSize;

	/*
	 * Make the pool's internal memory inaccessable, so that the program
	 * being debugged can't stomp on it.
	 */
	if ( !internalUse )
		Page_DenyAccess(allocationList, allocationListSize);

	release();

	return address;
}

/*
 * Find the slot structure for a user address.
 */
static Slot *
slotForUserAddress(void * address)
{
	register Slot *	slot = allocationList;
	register size_t	count = slotCount;
	
	for ( ; count > 0; count-- ) {
		if ( slot->userAddress == address )
			return slot;
		slot++;
	}

	return 0;
}

/*
 * Find the slot structure for an internal address.
 */
static Slot *
slotForInternalAddress(void * address)
{
	register Slot *	slot = allocationList;
	register size_t	count = slotCount;
	
	for ( ; count > 0; count-- ) {
		if ( slot->internalAddress == address )
			return slot;
		slot++;
	}
	return 0;
}

/*
 * Given the internal address of a buffer, find the buffer immediately
 * before that buffer in the address space. This is used by free() to
 * coalesce two free buffers into one.
 */
static Slot *
slotForInternalAddressPreviousTo(void * address)
{
	register Slot *	slot = allocationList;
	register size_t	count = slotCount;
	
	for ( ; count > 0; count-- ) {
		if ( ((char *)slot->internalAddress)
		 + slot->internalSize == address )
			return slot;
		slot++;
	}
	return 0;
}

extern C_LINKAGE void
free(void * address)
{
	Slot *	slot;
	Slot *	previousSlot = 0;
	Slot *	nextSlot = 0;

	if ( address == 0 )
		return;

	if ( allocationList == 0 )
		EF_Abort("free() called before first malloc().");

	lock();

	if ( !noAllocationListProtection )
		Page_AllowAccess(allocationList, allocationListSize);

	slot = slotForUserAddress(address);

	if ( !slot )
		EF_Abort("free(%a): address not from malloc().", address);

	if ( slot->mode != ALLOCATED ) {
		if ( internalUse && slot->mode == INTERNAL_USE )
			/* Do nothing. */;
		else {
			EF_Abort(
			 "free(%a): freeing free memory."
			,address);
		}
	}

	if ( EF_PROTECT_FREE )
		slot->mode = PROTECTED;
	else
		slot->mode = FREE;

	/*
	 * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
	 * is true, free memory is never reallocated, so it remains access
	 * denied for the life of the process. When EF_PROTECT_FREE is false, 
	 * the memory may be re-allocated, at which time access to it will be
	 * allowed again.
	 *
	 * Some operating systems allow munmap() with single-page resolution,
	 * and allow you to un-map portions of a region, rather than the
	 * entire region that was mapped with mmap(). On those operating
	 * systems, we can release protected free pages with Page_Delete(),
	 * in the hope that the swap space attached to those pages will be
	 * released as well.
	 */
	if ( EF_PROTECT_FREE )
	    Page_Delete(slot->internalAddress, slot->internalSize);
	else
	    Page_DenyAccess(slot->internalAddress, slot->internalSize);

	previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
	nextSlot = slotForInternalAddress(
	 ((char *)slot->internalAddress) + slot->internalSize);

	if ( previousSlot && previousSlot->mode == slot->mode ) {
		/* Coalesce previous slot with this one. */
		previousSlot->internalSize += slot->internalSize;
		slot->internalAddress = slot->userAddress = 0;
		slot->internalSize = slot->userSize = 0;
		slot->mode = NOT_IN_USE;
		slot = previousSlot;
		unUsedSlots++;
	}
	if ( nextSlot && nextSlot->mode == slot->mode ) {
		/* Coalesce next slot with this one. */
		slot->internalSize += nextSlot->internalSize;
		nextSlot->internalAddress = nextSlot->userAddress = 0;
		nextSlot->internalSize = nextSlot->userSize = 0;
		nextSlot->mode = NOT_IN_USE;
		unUsedSlots++;
	}

	slot->userAddress = slot->internalAddress;
	slot->userSize = slot->internalSize;

	if ( !noAllocationListProtection )
		Page_DenyAccess(allocationList, allocationListSize);

	release();
}

extern C_LINKAGE void *
realloc(void * oldBuffer, size_t newSize)
{
	void *	newBuffer = 0;

	if ( allocationList == 0 )
		initialize();	/* This sets EF_ALIGNMENT */

	lock();

	newBuffer = malloc(newSize);

	if ( oldBuffer ) {
		size_t	size;
		Slot *	slot;


		Page_AllowAccess(allocationList, allocationListSize);
		noAllocationListProtection = 1;
		
		slot = slotForUserAddress(oldBuffer);

		if ( slot == 0 )
			EF_Abort(
			 "realloc(%a, %d): address not from malloc()."
			,oldBuffer
			,newSize);

		if ( newSize < (size = slot->userSize) )
			size = newSize;

		if ( size > 0 )
			memcpy(newBuffer, oldBuffer, size);

		free(oldBuffer);
		noAllocationListProtection = 0;
		Page_DenyAccess(allocationList, allocationListSize);

		if ( size < newSize )
			memset(&(((char *)newBuffer)[size]), 0, newSize - size);
		
		/* Internal memory was re-protected in free() */
	}

	release();

	return newBuffer;
}

extern C_LINKAGE void *
malloc(size_t size)
{
	if ( allocationList == 0 )
		initialize();	/* This sets EF_ALIGNMENT */

	return memalign(EF_ALIGNMENT, size);
}

extern C_LINKAGE void *
calloc(size_t nelem, size_t elsize)
{
	size_t	size = nelem * elsize;
	void *	allocation = malloc(size);

	memset(allocation, 0, size);
	return allocation;
}

/*
 * This will catch more bugs if you remove the page alignment, but it
 * will break some software.
 */
extern C_LINKAGE void *
valloc (size_t size)
{
	return memalign(bytesPerPage, size);
}

#ifdef __hpux
/*
 * HP-UX 8/9.01 strcat reads a word past source when doing unaligned copies!
 * Work around it here. The bug report has been filed with HP.
 */
char *strcat(char *d, const char *s)
{
	strcpy(d+strlen(d), s);
	return d;
}
#endif
ElectricFence-2.2.2/page.c100644    764    764       10047  6704213766  14000 0ustar  brucebruce#include "efence.h"
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

/*
 * Lots of systems are missing the definition of PROT_NONE.
 */
#ifndef	PROT_NONE
#define	PROT_NONE	0
#endif

/*
 * 386 BSD has MAP_ANON instead of MAP_ANONYMOUS.
 */
#if ( !defined(MAP_ANONYMOUS) && defined(MAP_ANON) )
#define	MAP_ANONYMOUS	MAP_ANON
#endif

/*
 * For some reason, I can't find mprotect() in any of the headers on
 * IRIX or SunOS 4.1.2
 */
/* extern C_LINKAGE int mprotect(void * addr, size_t len, int prot); */

static caddr_t	startAddr = (caddr_t) 0;

#if ( !defined(sgi) && !defined(_AIX) &&!defined(__USE_BSD))
extern int	sys_nerr;
extern char *	sys_errlist[];
#endif

static const char *
stringErrorReport(void)
{
#if ( defined(sgi) )
	return strerror(oserror());
#elif ( defined(_AIX) )
	return strerror(errno);
#else
	if ( errno > 0 && errno < sys_nerr )
		return sys_errlist[errno];
	else
		return "Unknown error.\n";
#endif
}

/*
 * Create memory.
 */
#if defined(MAP_ANONYMOUS)
void *
Page_Create(size_t size)
{
	caddr_t		allocation;

	/*
	 * In this version, "startAddr" is a _hint_, not a demand.
	 * When the memory I map here is contiguous with other
	 * mappings, the allocator can coalesce the memory from two
	 * or more mappings into one large contiguous chunk, and thus
	 * might be able to find a fit that would not otherwise have
	 * been possible. I could _force_ it to be contiguous by using
	 * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
	 * generated by other software, etc.
	 */
	allocation = (caddr_t) mmap(
	 startAddr
	,(int)size
	,PROT_READ|PROT_WRITE
	,MAP_PRIVATE|MAP_ANONYMOUS
	,-1
	,0);

#ifndef	__hpux
	/*
	 * Set the "address hint" for the next mmap() so that it will abut
	 * the mapping we just created.
	 *
	 * HP/UX 9.01 has a kernel bug that makes mmap() fail sometimes
	 * when given a non-zero address hint, so we'll leave the hint set
	 * to zero on that system. HP recently told me this is now fixed.
	 * Someone please tell me when it is probable to assume that most
	 * of those systems that were running 9.01 have been upgraded.
	 */
	startAddr = allocation + size;
#endif

	if ( allocation == (caddr_t)-1 )
		EF_Exit("mmap() failed: %s", stringErrorReport());

	return (void *)allocation;
}
#else
void *
Page_Create(size_t size)
{
	static int	devZeroFd = -1;
	caddr_t		allocation;

	if ( devZeroFd == -1 ) {
		devZeroFd = open("/dev/zero", O_RDWR);
		if ( devZeroFd < 0 )
			EF_Exit(
			 "open() on /dev/zero failed: %s"
			,stringErrorReport());
	}

	/*
	 * In this version, "startAddr" is a _hint_, not a demand.
	 * When the memory I map here is contiguous with other
	 * mappings, the allocator can coalesce the memory from two
	 * or more mappings into one large contiguous chunk, and thus
	 * might be able to find a fit that would not otherwise have
	 * been possible. I could _force_ it to be contiguous by using
	 * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
	 * generated by other software, etc.
	 */
	allocation = (caddr_t) mmap(
	 startAddr
	,(int)size
	,PROT_READ|PROT_WRITE
	,MAP_PRIVATE
	,devZeroFd
	,0);

	startAddr = allocation + size;

	if ( allocation == (caddr_t)-1 )
		EF_Exit("mmap() failed: %s", stringErrorReport());

	return (void *)allocation;
}
#endif

static void
mprotectFailed(void)
{
	EF_Exit("mprotect() failed: %s", stringErrorReport());
}

void
Page_AllowAccess(void * address, size_t size)
{
	if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
		mprotectFailed();
}

void
Page_DenyAccess(void * address, size_t size)
{
	if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
		mprotectFailed();
}

void
Page_Delete(void * address, size_t size)
{
	if ( munmap((caddr_t)address, size) < 0 )
		Page_DenyAccess(address, size);
}

#if defined(_SC_PAGESIZE)
size_t
Page_Size(void)
{
	return (size_t)sysconf(_SC_PAGESIZE);
}
#elif defined(_SC_PAGE_SIZE)
size_t
Page_Size(void)
{
	return (size_t)sysconf(_SC_PAGE_SIZE);
}
#else
/* extern int	getpagesize(); */
size_t
Page_Size(void)
{
	return getpagesize();
}
#endif
ElectricFence-2.2.2/print.c100644    764    764        7034  6704230121  14162 0ustar  brucebruce#include "efence.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

/*
 * These routines do their printing without using stdio. Stdio can't
 * be used because it calls malloc(). Internal routines of a malloc()
 * debugger should not re-enter malloc(), so stdio is out.
 */

/*
 * NUMBER_BUFFER_SIZE is the longest character string that could be needed
 * to represent an unsigned integer, assuming we might print in base 2.
 */
#define	NUMBER_BUFFER_SIZE	(sizeof(ef_number) * NBBY)

static void
do_abort()
{
	/*
	 * I use kill(getpid(), SIGILL) instead of abort() because some
	 * mis-guided implementations of abort() flush stdio, which can
	 * cause malloc() or free() to be called.
	 */
	kill(getpid(), SIGILL);
	/* Just in case something handles SIGILL and returns, exit here. */
	_exit(-1);
}

static void
printNumber(ef_number number, ef_number base)
{
	char		buffer[NUMBER_BUFFER_SIZE];
	char *		s = &buffer[NUMBER_BUFFER_SIZE];
	int		size;
	
	do {
		ef_number	digit;

		if ( --s == buffer )
			EF_Abort("Internal error printing number.");

		digit = number % base;

		if ( digit < 10 )
			*s = '0' + digit;
		else
			*s = 'a' + digit - 10;

	} while ( (number /= base) > 0 );

	size = &buffer[NUMBER_BUFFER_SIZE] - s;

	if ( size > 0 )
		write(2, s, size);
}

void
EF_Printv(const char * pattern, va_list args)
{
	static const char	bad_pattern[] =
	 "\nBad pattern specifier %%%c in EF_Print().\n";
	const char *	s = pattern;
	char		c;

	while ( (c = *s++) != '\0' ) {
		if ( c == '%' ) {
			c = *s++;
			switch ( c ) {
			case '%':
				(void) write(2, &c, 1);
				break;
			case 'a':
				/*
				 * Print an address passed as a void pointer.
				 * The type of ef_number must be set so that
				 * it is large enough to contain all of the
				 * bits of a void pointer.
				 */
				printNumber(
				 (ef_number)va_arg(args, void *)
				,0x10);
				break;
			case 's':
				{
					const char *	string;
					size_t		length;

					string = va_arg(args, char *);
					length = strlen(string);

					(void) write(2, string, length);
				}
				break;
			case 'd':
				{
					int	n = va_arg(args, int);

					if ( n < 0 ) {
						char	c = '-';
						write(2, &c, 1);
						n = -n;
					}
					printNumber(n, 10);
				}
				break;
			case 'x':
				printNumber(va_arg(args, u_int), 0x10);
				break;
			case 'c':
				{
					char	c = va_arg(args, char);
					
					(void) write(2, &c, 1);
				}
				break;
			default:
				{
					EF_Print(bad_pattern, c);
				}
		
			}
		}
		else
			(void) write(2, &c, 1);
	}
}

void
EF_Abortv(const char * pattern, va_list args)
{
	EF_Print("\nElectricFence Aborting: ");
	EF_Printv(pattern, args);
	EF_Print("\n");
	do_abort();
}

void
EF_Abort(const char * pattern, ...)
{
	va_list	args;

	va_start(args, pattern);
	EF_Abortv(pattern, args);
	/* Not reached: va_end(args); */
}

void
EF_Exitv(const char * pattern, va_list args)
{
	EF_Print("\nElectricFence Exiting: ");
	EF_Printv(pattern, args);
	EF_Print("\n");

	/*
	 * I use _exit() because the regular exit() flushes stdio,
	 * which may cause malloc() or free() to be called.
	 */
	_exit(-1);
}

void
EF_Exit(const char * pattern, ...)
{
	va_list	args;

	va_start(args, pattern);

	EF_Exitv(pattern, args);

	/* Not reached: va_end(args); */
}

void
EF_Print(const char * pattern, ...)
{
	va_list	args;

	va_start(args, pattern);
	EF_Printv(pattern, args);
	va_end(args);
}

void
EF_InternalError(const char * pattern, ...)
{
	va_list	args;

	EF_Print("\nInternal error in allocator: ");
	va_start(args, pattern);
	EF_Printv(pattern, args);
	EF_Print("\n");
	va_end(args);
	do_abort();
}
ElectricFence-2.2.2/eftest.c100644    764    764        7443  5707641006  14336 0ustar  brucebruce#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>
#include <signal.h>
#include "efence.h"

/*
 * Electric Fence confidence tests.
 * Make sure all of the various functions of Electric Fence work correctly.
 */

#ifndef	PAGE_PROTECTION_VIOLATED_SIGNAL
#define	PAGE_PROTECTION_VIOLATED_SIGNAL	SIGSEGV
#endif

struct diagnostic {
	int		(*test)(void);
	int		expectedStatus;
	const char *	explanation;
};

extern int	EF_PROTECT_BELOW;
extern int	EF_ALIGNMENT;

static jmp_buf	env;

/*
 * There is still too little standardization of the arguments and return
 * type of signal handler functions.
 */
static
void
segmentationFaultHandler(
int signalNumber
#if ( defined(_AIX) )
, ...
#endif
)
 {
	signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
	longjmp(env, 1);
}

static int
gotSegmentationFault(int (*test)(void))
{
	if ( setjmp(env) == 0 ) {
		int			status;

		signal(PAGE_PROTECTION_VIOLATED_SIGNAL
		,segmentationFaultHandler);
		status = (*test)();
		signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
		return status;
	}
	else
		return 1;
}

static char *	allocation;
/* c is global so that assignments to it won't be optimized out. */
char	c;

static int
testSizes(void)
{
	/*
	 * If ef_number can't hold all of the bits of a void *, have the user
	 * add -DUSE_ LONG_LONG to the compiler flags so that ef_number will be
	 * declared as "unsigned long long" instead of "unsigned long".
	 */
	return ( sizeof(ef_number) < sizeof(void *) );
}

static int
allocateMemory(void)
{
	allocation = (char *)malloc(1);

	if ( allocation != 0 )
		return 0;
	else
		return 1;
}

static int
freeMemory(void)
{
	free(allocation);
	return 0;
}

static int
protectBelow(void)
{
	EF_PROTECT_BELOW = 1;
	return 0;
}

static int
read0(void)
{
	c = *allocation;

	return 0;
}

static int
write0(void)
{
	*allocation = 1;

	return 0;
}

static int
read1(void)
{
	c = allocation[1];

	return 0;
}

static int
readMinus1(void)
{
	c = allocation[-1];
	return 0;
}

static struct diagnostic diagnostics[] = {
	{
		testSizes, 0,
		"Please add -DLONG_LONG to the compiler flags and recompile."
	},
	{
		allocateMemory, 0,
		"Allocation 1: This test allocates a single byte of memory."
	},
	{
		read0, 0,
		"Read valid memory 1: This test reads the allocated memory."
	},
	{
		write0, 0,
		"Write valid memory 1: This test writes the allocated memory."
	},
	{
		read1, 1,
		"Read overrun: This test reads beyond the end of the buffer."
	},
	{
		freeMemory, 0,
		"Free memory: This test frees the allocated memory."
	},
	{
		protectBelow, 0,
		"Protect below: This sets Electric Fence to protect\n"
		"the lower boundary of a malloc buffer, rather than the\n"
		"upper boundary."
	},
	{
		allocateMemory, 0,
		"Allocation 2: This allocates memory with the lower boundary"
		" protected."
	},
	{
		read0, 0,
		"Read valid memory 2: This test reads the allocated memory."
	},
	{
		write0, 0,
		"Write valid memory 2: This test writes the allocated memory."
	},
	{
		readMinus1, 1,
		"Read underrun: This test reads before the beginning of the"
		" buffer."
	},
	{
		0, 0, 0
	}
};

static const char	failedTest[]
 = "Electric Fence confidence test failed.\n";

static const char	newline = '\n';

int
main(int argc, char * * argv)
{
	static const struct diagnostic *	diag = diagnostics;
	

	EF_PROTECT_BELOW = 0;
	EF_ALIGNMENT = 0;

	while ( diag->explanation != 0 ) {
		int	status = gotSegmentationFault(diag->test);

		if ( status != diag->expectedStatus ) {
			/*
			 * Don't use stdio to print here, because stdio
			 * uses malloc() and we've just proven that malloc()
			 * is broken. Also, use _exit() instead of exit(),
			 * because _exit() doesn't flush stdio.
			 */
			write(2, failedTest, sizeof(failedTest) - 1);
			write(2, diag->explanation, strlen(diag->explanation));
			write(2, &newline, 1);
			_exit(-1);
		}
		diag++;
	}
	return 0;
}
ElectricFence-2.2.2/tstheap.c100644    764    764        2330  5707641010  14475 0ustar  brucebruce#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include "efence.h"

/*
 * This is a simple program to exercise the allocator. It allocates and frees
 * memory in a pseudo-random fashion. It should run silently, using up time
 * and resources on your system until you stop it or until it has gone
 * through TEST_DURATION (or the argument) iterations of the loop.
 */

extern C_LINKAGE double drand48(void); /* For pre-ANSI C systems */

#define	POOL_SIZE	1024
#define	LARGEST_BUFFER	30000
#define	TEST_DURATION	1000000

void *	pool[POOL_SIZE];

#ifdef	FAKE_DRAND48
/*
 * Add -DFAKE_DRAND48 to your compile flags if your system doesn't
 * provide drand48().
 */

#ifndef	ULONG_MAX
#define	ULONG_MAX	~(1L)
#endif

double
drand48(void)
{
	return (random() / (double)ULONG_MAX);
}
#endif

int
main(int argc, char * * argv)
{
	int	count = 0;
	int	duration = TEST_DURATION;

	if ( argc >= 2 )
		duration = atoi(argv[1]);

	for ( ; count < duration; count++ ) {
		void * *	element = &pool[(int)(drand48() * POOL_SIZE)];
		size_t		size = (size_t)(drand48() * (LARGEST_BUFFER + 1));

		if ( *element ) {
			free( *element );
			*element = 0;
		}
		else if ( size > 0 ) {
			*element = malloc(size);
		}
	}
	return 0;
}
ElectricFence-2.2.2/CHANGES100644    764    764        2025  6704677201  13666 0ustar  brucebruce2.2.2	Oops. Shared library must be position-independent code.

2.2.0
	Merge in bug-fixes, multi-thread patch, shared library patch,
	debian/ subdirectory used for building the Debian package

2.0.1
	Add work-arounds for kernel and library bugs under HP-UX.	
	HP has been notified and will repair these soon.

2.0.2
	Add support for DEC Alpha. Add %a pattern for printing addresses, which
	assumes they are passed in a void *.

2.0.3 30-Sep-1993
	When realloc is passed a zero address, it should work the same
	way as malloc(). Fix forward declaration of mprotect() in page.c to
	use void *, not caddr_t, for addresses. IRIX 5.0.1 complained about that.

2.0.4 29-May-1994
	Don't attempt to allow access to a zero-sized page when
	EF_ALLOW_MALLOC_0 is set. Attempt to un-map memory from
	Page_Delete(). If that doesn't work, fall back by protecting the
	page from all references. Un-mapping small segments of a mapping
	used to crash my SGI IRIX 5.0 system. I assume that nobody is running
	5.0 any longer.

2.0.5 20-January-1995
	Port to Linux.
ElectricFence-2.2.2/COPYING100644    764    764       43076  5707644137  13765 0ustar  brucebruce		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                          675 Mass Ave, Cambridge, MA 02139, USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	Appendix: How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
ElectricFence-2.2.2/debian/ 40755    764    764           0  6704221021  14002 5ustar  brucebruceElectricFence-2.2.2/debian/README.debian100644    764    764        1356  6704221021  16205 0ustar  brucebruceelectric-fence for DEBIAN
-------------------------

The official maintainer of this package is Siggy Brentrup <bsb@debian.org>.
But he apparently lost his net.access, so this version was made
by joost witteveen, <joostje@debian.org>.

This package now also contains a shared library of electric fence.
Thus, you don't need to recompile any programmes any more, all
you need to do is

LD_PRELOAD=libefence.so.0.0  your-buggy-programme

and efence's malloc will be used.

Oh, and note that if you're using c++, you and want to statically link
your c++ programmes, you shouldn't use g++ to link libefence.a, but
rather
    gcc -o myprog myprog.o -lstdc++ -lg++ -lefence 
(if you use g++, the order is different, and efence's malloc doesn't get used)


ElectricFence-2.2.2/debian/changelog100644    764    764        2431  6704213033  15755 0ustar  brucebruceelectric-fence (2.0.5-4.1) unstable; urgency=low

  * Orphaned the package:
    (Siggy Brentrup has left the project a long while ago)
  * Now point to the correct manpage (Fix #8122).
  * upstream changelog file named correctly (Fix #9618).
  * Now point to the upstream location (Fix #17354, #28059).
  * Don't install libefence.so.0 executable (Fix #25993).

 -- Vincent Renardias <vincent@waw.com>  Wed, 13 Jan 1999 01:41:31 +0100

electric-fence (2.0.5-4) unstable; urgency=low

  * recompiled for libc6; added an extra condition around the sys_errlist
    declaration.
  * added a libefence.so.0.0 shared library. 
  * non-maintainer release.
  
 -- joost witteveen <joostje@debian.org>  Fri, 19 Sep 1997 15:11:31 +0200

electric-fence (2.0.5-3) unstable; urgency=low

  * Changed to new package format (Bug #7118)
  * Added extended description (Bug #3582)
  * Multi-architecture support (hopefully) (Bug #4045)

 -- Siggy Brentrup <bsb@debian.org>  Wed, 5 Feb 1997 17:17:17 +0100

electric-fence (2.0.5-2) unstable; urgency=low

  * converted to ELF directory structure
  * cleaned up debian.control
  * minor changes to debian.rules

 -- Siggy Brentrup <bsb@uni-muenster.de>  Wed, 20 Jan 1996 00:00:00 +0100

Local variables:
mode: debian-changelog
add-log-mailing-address: "bsb@debian.org"
End:
ElectricFence-2.2.2/debian/control100644    764    764         430  6704213033  15463 0ustar  brucebruceSource: electric-fence
Section: devel
Priority: extra
Maintainer: Debian QA Group <debian-qa@lists.debian.org>
Standards-Version: 2.1.2.2

Package: electric-fence
Architecture: any
Description: A malloc(3) debugger
 Use virtual memory hardware to detect illegal memory accesses.

ElectricFence-2.2.2/debian/control.multi100644    764    764         436  6276102332  16625 0ustar  brucebruceSource: efence
Section: unknown
Priority: extra
Maintainer: Siggy Brentrup <bsb@debian.org>
Standards-Version: 2.1.1.0

Package: efence
Architecture: any
Depends: ${shlibs:Depends}
Description: Missing
 Missing

Package: efence-doc
Architecture: all
Description: Documentation
 Missing
ElectricFence-2.2.2/debian/copyright100644    764    764         555  6704220646  16033 0ustar  brucebruceThis package was debianized by Siggy Brentrup bsb@debian.org on
Wed, 5 Feb 1997 15:53:23 +0100.

The canonical version of the source code is available at
http://perens.com/FreeSoftware/ElectricFence .

Copyright:

(c) 1987-1999 Bruce Perens <bruce@perens.com>
The program is distributed under the GNU General Public License which
can be found in the file COPYING.

ElectricFence-2.2.2/debian/diversions.ex100644    764    764          43  6276102332  16566 0ustar  brucebruce<FILE> <Diverted to> <Packagename>
ElectricFence-2.2.2/debian/info.ex100644    764    764        1014  6276102332  15373 0ustar  brucebruce# This is a configuration files for installing a .info menu
# The Description to be placed into the directory
DESCR="Description"

# The section this info file should be placed in (Regexp) folllowed by
# the new section name to be created if the Regexp does not match
# (Optional. If not given the .info will be appended to the directory)
#SECTION_MATCH="Regexp"
#SECTION_NAME="New Section Name"

# The file referred to from the Info directory
FILE=efence.info

# Optional. The files to be copied to /usr/info
#FILES=*.info
ElectricFence-2.2.2/debian/rules100755    764    764        3476  6704213033  15175 0ustar  brucebruce#!/usr/bin/make -f
# Sample debian.rules file - for GNU Hello (1.3).
# Copyright 1994,1995 by Ian Jackson.
# I hereby give you perpetual unlimited permission to copy,
# modify and relicense this file, provided that you do not remove
 # my name from the file itself.  (I assert my moral right of
# paternity under the Copyright, Designs and Patents Act 1988.)
# This file may have to be extensively modified
#
# Modified to be a prototype for debmake by Christoph Lameter <clameter@debian.org>

package=electric-fence

build:
	$(checkdir)
	if [ -x configure ]; then ./configure --prefix=/usr; fi
	make CFLAGS="-O2 -g -Wall"
	rm *.o
	make CFLAGS="-O2 -g -Wall -fPIC" libefence.so.0.0 
	touch build

clean:
	$(checkdir)
	rm -f build
	rm -f libefence.so.0.0
	-make clean
	-rm -f `find . -name "*~"`
	-rm -rf debian/tmp debian/files* core debian/substvars

binary-indep:	checkroot build
	$(checkdir)
# There are no architecture-independent files to be uploaded
# generated by this package.  If there were any they would be
# made here.

binary-arch:	checkroot build
	$(checkdir)
	-rm -rf debian/tmp
	install -d debian/tmp
	cd debian/tmp;install -d `cat ../dirs`
	make install prefix=`pwd`/debian/tmp/usr
	install -m 644 -o root -g root libefence.so.0.0 debian/tmp/usr/lib
	
# Must have debmake installed for this to work. Otherwise please copy
# /usr/bin/debstd into the debian directory and change debstd to debian/debstd
	debstd CHANGES README 
	dpkg-gencontrol
	chown -R root.root debian/tmp
	chmod -R go=rX debian/tmp
	dpkg --build debian/tmp ..

define checkdir
	test -f debian/rules
endef

# Below here is fairly generic really

binary:		binary-indep binary-arch

source diff:
	@echo >&2 'source and diff are obsolete - use dpkg-source -b'; false

checkroot:
	$(checkdir)
	test root = "`whoami`"

.PHONY: binary binary-arch binary-indep clean checkroot
ElectricFence-2.2.2/debian/rules.multi100644    764    764        2674  6276102333  16326 0ustar  brucebruce#!/usr/bin/make -f
# Sample debian.rules file - for GNU Hello (1.3).
# Copyright 1994,1995 by Ian Jackson.
# I hereby give you perpetual unlimited permission to copy,
# modify and relicense this file, provided that you do not remove
# my name from the file itself.  (I assert my moral right of
# paternity under the Copyright, Designs and Patents Act 1988.)
# This file may have to be extensively modified
#
# Modified to be a prototype for debmake by Christoph Lameter <clameter@debian.org>

package=efence

build:
	$(checkdir)
	make

	touch build

clean:
	$(checkdir)
	-rm -f build
	-make clean
	-rm `find . -name "*~"`
	-rm -rf debian/tmp debian/*/tmp debian/files* core

binary-indep:	checkroot build
	$(checkdir)
# There are no architecture-independent files to be uploaded
# generated by this package.  If there were any they would be
# made here.

binary-arch:	checkroot build
	$(checkdir)
	-rm -rf debian/tmp debian/*/tmp
	install -d debian/tmp/usr/{bin,sbin}
	make install DESTDIR=`pwd`/debian/tmp
	debmstd $(package) CHANGES INSTALL README* TODO
	dpkg-gencontrol
	chown -R root.root debian/tmp
	chmod -R go=rX debian/tmp
	dpkg --build debian/tmp ..

define checkdir
	test -f debian/rules
endef

# Below here is fairly generic really

binary:		binary-indep binary-arch

source diff:
	@echo >&2 'source and diff are obsolete - use dpkg-source -b'; false

checkroot:
	$(checkdir)
	test root = "`whoami`"

.PHONY: binary binary-arch binary-indep clean checkroot
ElectricFence-2.2.2/debian/dirs100664    764    764          54  6704213033  14730 0ustar  brucebruceusr/lib
usr/doc/electric-fence
usr/man/man3
ElectricFence-2.2.2/efence.3100644    764    764       33376  6704253663  14243 0ustar  brucebruce.TH efence 3 27-April-1993
.SH NAME
efence \- Electric Fence Malloc Debugger
.SH SYNOPSIS
.nf
.ft B
#include <stdlib.h>
.ft
.fi
.LP
.nf
.ft B
void * malloc (size_t size);
.ft
.fi
.LP
.nf
.ft B
void free (void *ptr);
.ft
.fi
.LP
.nf
.ft B
void * realloc (void *ptr, size_t size);
.ft
.fi
.LP
.nf
.ft B
void * calloc (size_t nelem, size_t elsize);
.ft
.fi
.LP
.nf
.ft B
void * memalign (size_t alignment, size_t size);
.ft
.fi
.LP
.nf
.ft B
void * valloc (size_t size);
.ft
.fi
.LP
.nf
.ft B
extern int EF_ALIGNMENT;
.ft
.fi
.LP
.nf
.ft B
extern int EF_PROTECT_BELOW;
.ft
.fi
.LP
.nf
.ft B
extern int EF_PROTECT_FREE;
.ft
.fi
.LP
.nf
.ft B
extern int EF_ALLOW_MALLOC_0;
.ft
.fi
.LP
.nf
.ft B
extern int EF_FILL;
.ft
.fi
.SH DESCRIPTION
.I Electric Fence
helps you detect two common programming bugs:
software that overruns the boundaries of a malloc() memory
allocation, and software that touches a memory allocation that has been
released by free(). Unlike other malloc() debuggers, Electric Fence will
detect
.I read
accesses as well as writes, and it will pinpoint the exact instruction that
causes an error. It has been in use at Pixar since 1987, and at many other
sites for years.
.LP
Electric Fence uses the virtual memory hardware of your computer to place an
inaccessible memory page immediately after (or before, at the user's option)
each memory allocation. When software reads or writes this inaccessible page,
the
hardware issues a segmentation fault, stopping the program at the offending
instruction. It is then trivial to find the erroneous statement using your
favorite debugger. In a similar manner, memory that has been released by
free() is made inaccessible, and any code that touches it will get a
segmentation fault.
.LP
Simply linking your application with libefence.a will allow you to detect
most, but not all, malloc buffer overruns and accesses of free memory.
If you want to be reasonably sure that you've found
.I all
bugs of this type, you'll have to read and understand the rest of this
man page.
.SH USAGE
Link your program with the library
.B libefence.a .
Make sure you are
.I not
linking with
.B -lmalloc,
.B -lmallocdebug,
or with other malloc-debugger or malloc-enhancer libraries.
You can only use one at a time.
If your system administrator
has installed Electric Fence for public use, you'll be able to use the
.B -lefence
argument to the linker, otherwise you'll have to put the path-name for
.B libefence.a
in the linker's command line.
You can also use dynamic linking. If you're using a Bourne shell, the
statement 
.B export LD_PRELOAD=libefence.so.0.0
will cause Electric Fence to be loaded to run all dynamic executables.
The command
.B ef
.I command
runs a single command under Electric Fence.
.LP
Some systems will require special arguments to the linker to assure that
you are using the Electric Fence malloc() and not the one from your C library.
.LP
Run your program
.I using a debugger. 
It's easier to work this way than to create a
.B core
file and post-mortem debug it. Electric Fence can create
.I huge
core files, and some operating systems will thus take minutes simply to dump
core! Some operating systems will not create usable core files from programs
that are linked with Electric Fence.
If your program has one of the errors detected by Electric Fence, it will
get a segmentation fault (SIGSEGV) at the offending instruction. Use the
debugger to locate the erroneous statement, and repair it.
.SH GLOBAL AND ENVIRONMENT VARIABLES
Electric Fence has four configuration switches that can be enabled via
the shell environment, or by setting the value of global integer variables
using a debugger. These switches change what bugs Electric Fence will detect,
so it's important that you know how to use them.
.TP
EF_ALIGNMENT
This is an integer that specifies the alignment for any memory allocations
that will be returned by malloc(), calloc(), and realloc().
The value is specified in
bytes, thus a value of 4 will cause memory to be aligned to 32-bit boundaries
unless your system doesn't have a 8-bit characters. EF_ALIGNMENT is set to
sizeof(int) by default, since that is generally the word-size of your CPU.
If your program requires that allocations be aligned to 64-bit
boundaries and you have a 32-bit
.B int
you'll have to set this value to 8. This is the case when compiling with the
.B -mips2
flag on MIPS-based systems such as those from SGI.
The memory allocation that is returned by Electric Fence malloc() is aligned
using the value in EF_ALIGNMENT, and
.I its size the multiple of
.I that value
that is greater than or equal to the requested size.
For this reason, you will sometimes want to set EF_ALIGNMENT to 0 (no
alignment), so that
you can detect overruns of less than your CPU's word size. Be sure to read
the section
.I WORD-ALIGNMENT AND OVERRUN DETECTION
in this manual page before you try this.
To change this value, set EF_ALIGNMENT in the shell environment to an
integer value, or assign
to the global integer variable EF_ALIGNMENT using a debugger.
.TP
EF_PROTECT_BELOW
Electric Fence usually places an inaccessible page immediately after each
memory allocation, so that software that runs past the end of the allocation
will be detected. Setting EF_PROTECT_BELOW to 1 causes Electric Fence
to place the inaccessible page
.I before
the allocation in the address space, so that under-runs will be detected
instead of over-runs.
When EF_PROTECT_BELOW is set, the EF_ALIGNMENT parameter is ignored.
All allocations will be aligned to virtual-memory-page boundaries, and
their size will be the exact size that was requested.
To change this value, set EF_PROTECT_BELOW in the shell environment to an
integer value, or assign to the global integer variable EF_PROTECT_BELOW using
a debugger.
.TP
EF_PROTECT_FREE
Electric Fence usually returns free memory to a pool from which it may be
re-allocated. If you suspect that a program may be touching free memory,
set EF_PROTECT_FREE to 1. This will cause Electric Fence to never re-allocate
memory once it has been freed, so that any access to free memory will be
detected. Some programs will use tremendous amounts of memory when this
parameter is set.
To change this value, set EF_PROTECT_FREE in the shell environment to an
integer value, or assign to the global integer variable EF_PROTECT_FREE using
a debugger.
.TP
EF_ALLOW_MALLOC_0
By default, Electric Fence traps calls to malloc() with a size of zero, because
they are often the result of a software bug. If EF_ALLOW_MALLOC_0 is non-zero,
the software will not trap calls to malloc() with a size of zero.
To change this value, set EF_ALLOC_MALLOC_0 in the shell environment to an
integer value, or assign to the global integer variable EF_ALLOC_MALLOC_0 using
a debugger.
.TP
EF_FILL
When set to a value between 0 and 255, every byte of allocated memory is
initialized to that value. This can help detect reads of uninitialized memory.
When set to -1, some memory is filled with zeroes
(the operating system default on most systems) and some memory will retain
the values written to it during its last use.
.SH WORD-ALIGNMENT AND OVERRUN DETECTION
There is a conflict between the alignment restrictions that malloc() operates
under and the debugging strategy used by Electric Fence. When detecting
overruns, Electric Fence malloc() allocates two or more virtual memory
pages for each allocation. The last page is made inaccessible in such a way
that any read, write, or execute access will cause a segmentation fault.
Then, Electric Fence malloc() will return an address such that the first
byte after
the end of the allocation is on the inaccessible page.
Thus, any overrun
of the allocation will cause a segmentation fault.
.LP
It follows that the
address returned by malloc() is the address of the inaccessible page minus
the size of the memory allocation.
Unfortunately, malloc() is required to return
.I word-aligned
allocations, since many CPUs can only access a word when its address is aligned.
The conflict happens when software makes a memory allocation using a size that
is not a multiple of the word size, and expects to do word accesses to that
allocation. The location of the inaccessible page is fixed by hardware at
a word-aligned address. If Electric Fence malloc() is to return an aligned
address, it must increase the size of the allocation to a multiple of the
word size.
In addition, the functions memalign() and valloc() must honor explicit
specifications on the alignment of the memory allocation, and this, as well
can only be implemented by increasing the size of the allocation.
Thus, there will be situations in which the end of a memory allocation
contains some padding space, and accesses of that padding space will not
be detected, even if they are overruns.
.LP
Electric Fence provides the variable EF_ALIGNMENT so that the user can
control the default alignment used by malloc(), calloc(), and realloc().
To debug overruns as small as a single byte, you can set EF_ALIGNMENT to
zero. This will result in Electric Fence malloc() returning unaligned
addresses for allocations with sizes that are not a multiple of the word
size. This is not a problem in most cases, because compilers must pad the
size of objects so that alignment restrictions are honored when storing
those objects in arrays. The problem surfaces when software allocates
odd-sized buffers for objects that must be word-aligned. One case of this
is software that allocates a buffer to contain a structure and a
string, and the string has an odd size (this example was in a popular TIFF
library). If word references are made to un-aligned buffers, you will see
a bus error (SIGBUS) instead of a segmentation fault. The only way to fix
this is to re-write the offending code to make byte references or not make
odd-sized allocations, or to set EF_ALIGNMENT to the word size.
.LP
Another example of software incompatible with
EF_ALIGNMENT < word-size
is the strcmp() function and other string functions on SunOS (and probably
Solaris), which make word-sized accesses to character strings, and may
attempt to access up to three bytes beyond the end of a string. These
result in a segmentation fault (SIGSEGV). The only way around this is to
use versions of the string functions that perform byte references instead
of word references.
.SH INSTRUCTIONS FOR DEBUGGING YOUR PROGRAM
.TP
1.
Link with libefence.a as explained above.
.TP
2.
Run your program in a debugger and fix any overruns or accesses to free memory.
.TP
3.
Quit the debugger.
.TP
4.
Set EF_PROTECT_BELOW = 1 in the shell environment.
.TP
5.
Repeat step 2, this time repairing underruns if they occur.
.TP
6.
Quit the debugger.
.TP
7.
Read the restrictions in the section on
.I WORD-ALIGNMENT AND OVERRUN DETECTION.
See if you can
set EF_ALIGNMENT to 0 and repeat step 2. Sometimes this will be too much work,
or there will be problems with library routines for which you don't have the
source, that will prevent you from doing this.
.SH MEMORY USAGE AND EXECUTION SPEED
Since Electric Fence uses at least two virtual memory pages for each of its
allocations, it's a terrible memory hog. I've sometimes found it necessary to
add a swap file using swapon(8) so that the system would have enough virtual
memory to debug my program. Also, the way we manipulate memory results in
various cache and translation buffer entries being flushed with each call
to malloc or free. The end result is that your program will be much slower
and use more resources while you are debugging it with Electric Fence.
.LP
Don't leave libefence.a linked into production software! Use it only
for debugging.
.SH MAILING LIST
There is a mailing list to support Electric Fence. You can subscribe using the
mail form at
http://lists.perens.com/mailman/listinfo/electric-fence .
.SH AUTHOR
Bruce Perens
.SH WARNINGS
I have tried to do as good a job as I can on this software, but I doubt
that it is even theoretically possible to make it bug-free.
This software has no warranty. It will not detect some bugs that you might
expect it to detect, and will indicate that some non-bugs are bugs.
.SH LICENSE
Copyright 1987-1999 Bruce Perens. All rights reserved.
.br
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, Version 2,
as published by the Free Software Foundation. A copy of this license is
distributed with this software in the file "COPYING".

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Read the
file "COPYING" for more details.
.SH CONTACTING THE AUTHOR
.nf
Bruce Perens
1563 Solano Ave. #349
Berkeley, CA 94707
Telephone: 510-526-1165
Internet: bruce@perens.com
.fi
.ft
.SH FILES
/dev/zero: Source of memory pages (via mmap(2)).
.SH SEE ALSO
malloc(3), mmap(2), mprotect(2), swapon(8)
.SH DIAGNOSTICS
Segmentation Fault: Examine the offending statement for violation of the
boundaries of a memory allocation.
.br
Bus Error: See the section on
.I WORD-ALIGNMENT AND OVERRUN DETECTION.
in this manual page.
.SH BUGS
My explanation of the alignment issue could be improved.
.LP
Some Sun systems running SunOS 4.1 were reported to signal an access to a
protected page with
.B  SIGBUS
rather than
.B SIGSEGV,
I suspect this is an undocumented feature of a particular Sun hardware
version, not just the operating system.
On these systems, eftest will fail with a bus error until you modify the
Makefile to define
.B PAGE_PROTECTION_VIOLATED_SIGNAL
as
.B SIGBUS.
.LP
There are, without doubt, other bugs and porting issues. Please contact me via
e-mail if you have any bug reports, ideas, etc.
.SH WHAT'S BETTER
.I Purify
does a much more thorough job than Electric Fence, and does not have
the huge memory overhead.
.I Checkergcc,
a modified version of the GNU C Compiler that instruments all memory
references,
is available on Linux systems and where GCC is used. It performs some of the
same tasks as Purify, but only on code that it has compiled.
ElectricFence-2.2.2/ef.sh100664    764    764         623  6704233532  13600 0ustar  brucebruce#!/bin/bash

#
# Simple script to run electric fence on stuff.  (needs libefence.so).
#
# $Id: ef,v 1.1 1999/03/31 21:31:23 kefka Exp $
#

# Usage check.
if [ "$1" = "" ]; then
	echo "$0: Usage: ef [executable] [arguments]."
	echo "	Runs the executable under the Electric Fence malloc debugger."
	exit
fi

# Set the environment to load eletric fence.
(\
export LD_PRELOAD=libefence.so.0.0;\
exec $*;\
)
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2008 Oliver Maruhn