Here is a patch against 2.1.14.1 that incorporates the following:
 * Merge upstream code from ElectricFence-2.2.2, replacing mutex 
   locking with semaphores.
 * Includes fixes from Fedora's src.rpm

The test program in #241156 runs flawlessly and the problem in #365382 is
also solved.


diff -ruN electric-fence-2.1.14.1/CHANGES electric-fence-debian/CHANGES
--- electric-fence-2.1.14.1/CHANGES	1998-03-12 20:48:59.000000000 +0100
+++ electric-fence-debian/CHANGES	1999-04-13 19:27:29.000000000 +0200
@@ -1,5 +1,8 @@
-2.1	Remove work-arounds, most operating systems and C libraries have
-	been fixed now.
+2.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.	
diff -ruN electric-fence-2.1.14.1/COPYING electric-fence-debian/COPYING
--- electric-fence-2.1.14.1/COPYING	1998-03-12 20:50:45.000000000 +0100
+++ electric-fence-debian/COPYING	1995-01-20 06:21:35.000000000 +0100
@@ -279,7 +279,7 @@
 
 		     END OF TERMS AND CONDITIONS
 
-	    How to Apply These Terms to Your New Programs
+	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
diff -ruN electric-fence-2.1.14.1/debian/changelog electric-fence-debian/debian/changelog
--- electric-fence-2.1.14.1/debian/changelog	2006-01-10 07:12:09.000000000 +0100
+++ electric-fence-debian/debian/changelog	2006-04-29 23:44:22.000000000 +0200
@@ -1,3 +1,10 @@
+electric-fence (2.2.2) unstable; urgency=low
+
+  * New upstream release with patches from Fedora
+    Closes: #241156, #365382
+
+ -- Botond Botyanszki <[EMAIL PROTECTED]>  Sun, 29 Apr 2006 23:41:42 +0200
+
 electric-fence (2.1.14.1) unstable; urgency=low
 
   * Non-maintainer upload.
diff -ruN electric-fence-2.1.14.1/debian/rules electric-fence-debian/debian/rules
--- electric-fence-2.1.14.1/debian/rules	2003-12-07 16:51:54.000000000 +0100
+++ electric-fence-debian/debian/rules	2006-04-29 22:56:54.000000000 +0200
@@ -18,11 +18,7 @@
 build: build-stamp
 build-stamp:
 	dh_testdir
-	#if [ -x configure ]; then ./configure --prefix=/usr; fi
-	make CFLAGS="-O2 -g -Wall -fPIC"
-	gcc -g -shared -Wl,-soname,libefence.so.0 -o libefence.so.0.0 efence.o page.o print.o -lc -lpthread
-	rm *.o
-	make CFLAGS="-O2 -g -Wall"
+	make
 	touch build-stamp
 
 clean:
diff -ruN electric-fence-2.1.14.1/efence.c electric-fence-debian/efence.c
--- electric-fence-2.1.14.1/efence.c	2005-01-15 20:18:20.000000000 +0100
+++ electric-fence-debian/efence.c	2006-04-29 22:28:22.000000000 +0200
@@ -34,7 +34,10 @@
 #include <unistd.h>
 #include <memory.h>
 #include <string.h>
-#include <pthread.h>
+#ifdef USE_SEMAPHORE
+# include <pthread.h>
+# include <semaphore.h>
+#endif
 
 #ifdef	malloc
 #undef	malloc
@@ -44,8 +47,8 @@
 #undef	calloc
 #endif
 
-static const char	version[] = "\n  Electric Fence 2.1"
- " Copyright (C) 1987-1998 Bruce Perens.\n";
+static const char	version[] = "\n  Electric Fence 2.2.0"
+ " Copyright (C) 1987-1999 Bruce Perens <[EMAIL PROTECTED]>\n";
 
 /*
  * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
@@ -129,11 +132,10 @@
 int		EF_ALLOW_MALLOC_0 = -1;
 
 /*
- * EF_FREE_WIPES is set if Electric Fence is to wipe the memory content
- * of freed blocks.  This makes it easier to check if memory is freed or
- * not
+ * EF_FILL is set to 0-255 if Electric Fence should fill all new allocated
+ * memory with the specified value.
  */
-int            EF_FREE_WIPES = -1;
+int		EF_FILL = -1;
 
 /*
  * allocationList points to the array of slot structures used to manage the
@@ -179,49 +181,99 @@
  */
 static int		noAllocationListProtection = 0;
 
+#ifdef USE_SEMAPHORE
+
+#include <stdbool.h>
+
+#pragma weak sem_init
+#pragma weak sem_post
+#pragma weak sem_wait
+
+static int		pthread_initialization = 0;
+
+/*
+ * 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;
 
- /*
- * mutex to enable multithreaded operation
- */
-static pthread_mutex_t mutex ;
-static pid_t mutexpid=0;
-static int locknr=0;
-
-
-static void lock() {
-    if (pthread_mutex_trylock(&mutex)) {
-       if (mutexpid==getpid()) {
-           locknr++;
-           return;
-       } else {
-           pthread_mutex_lock(&mutex);
-       }
-    } 
-    mutexpid=getpid();
-    locknr=1;
-}
-
-static void unlock() {
-    locknr--;
-    if (!locknr) {
-       mutexpid=0;
-       pthread_mutex_unlock(&mutex);
-    }
+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 */
 }
 
-/*
- * internalError is called for those "shouldn't happen" errors in the
- * allocator.
- */
 static void
-internalError(void)
+release()
 {
-	EF_Abort("Internal error in allocator.");
+#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 */
 }
 
 /*
@@ -246,6 +298,14 @@
        if ( EF_DISABLE_BANNER == 0 )
                EF_Print(version);
 
+
+#ifdef USE_SEMAPHORE
+	if (sem_init != NULL && !pthread_initialization && 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
@@ -304,14 +364,13 @@
 			EF_ALLOW_MALLOC_0 = 0;
 	}
 
+	
 	/*
-	 * See if the user wants us to wipe out freed memory.
+	 * Check if we should be filling new memory with a value.
 	 */
-	if ( EF_FREE_WIPES == -1 ) {
-	        if ( (string = getenv("EF_FREE_WIPES")) != 0 )
-	                EF_FREE_WIPES = (atoi(string) != 0);
-	        else
-	                EF_FREE_WIPES = 0;
+	if ( EF_FILL == -1 ) {
+		if ( (string = getenv("EF_FILL")) != 0)
+			EF_FILL = (unsigned char) atoi(string);
 	}
 
 	/*
@@ -360,8 +419,25 @@
 	 * Account for the two slot structures that we've used.
 	 */
 	unUsedSlots = slotCount - 2;
+
+	release();
 }
 
+#ifdef USE_SEMAPHORE
+void
+__libc_malloc_pthread_startup (bool first_time)
+{
+	if (first_time) {
+		pthread_initialization = 1;
+		initialize ();
+	} else {
+		pthread_initialization = 0;
+		if (!semEnabled && sem_init != NULL && sem_init(&EF_sem, 0, 1) >= 0)
+			semEnabled = 1;
+	}
+}
+#endif
+
 /*
  * allocateMoreSlots is called when there are only enough slot structures
  * left to support the allocation of a single malloc buffer.
@@ -432,6 +508,8 @@
 	if ( allocationList == 0 )
 		initialize();
 
+	lock();
+
 	if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
 		EF_Abort("Allocating 0 bytes, probably a bug.");
 
@@ -511,7 +589,7 @@
 		slot++;
 	}
 	if ( !emptySlots[0] )
-		internalError();
+		EF_InternalError("No empty slot 0.");
 
 	if ( !fullSlot ) {
 		/*
@@ -523,7 +601,7 @@
 		size_t	chunkSize = MEMORY_CREATION_SIZE;
 
 		if ( !emptySlots[1] )
-			internalError();
+			EF_InternalError("No empty slot 1.");
 
 		if ( chunkSize < internalSize )
 			chunkSize = internalSize;
@@ -538,6 +616,13 @@
 		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);
 	}
 
 	/*
@@ -582,7 +667,7 @@
 		address += internalSize - bytesPerPage;
 
 		/* Set up the "dead" page. */
-		Page_DenyAccess(address, bytesPerPage);
+		Page_Delete(address, bytesPerPage);
 
 		/* Figure out what address to give the user. */
 		address -= userSize;
@@ -596,8 +681,8 @@
 		address = (char *)fullSlot->internalAddress;
 
 		/* Set up the "dead" page. */
-		Page_DenyAccess(address, bytesPerPage);
-			
+		Page_Delete(address, bytesPerPage);
+
 		address += bytesPerPage;
 
 		/* Set up the "live" page. */
@@ -615,6 +700,8 @@
 	if ( !internalUse )
 		Page_DenyAccess(allocationList, allocationListSize);
 
+	release();
+
 	return address;
 }
 
@@ -680,16 +767,14 @@
 	Slot *	previousSlot = 0;
 	Slot *	nextSlot = 0;
 
-        lock();
-
-        if ( address == 0 ) {
-                unlock();
-                return;
-        }
+	if ( address == 0 )
+		return;
 
 	if ( allocationList == 0 )
 		EF_Abort("free() called before first malloc().");
 
+	lock();
+
 	if ( !noAllocationListProtection )
 		Page_AllowAccess(allocationList, allocationListSize);
 
@@ -713,28 +798,36 @@
 	else
 		slot->mode = FREE;
 
-       if ( EF_FREE_WIPES )
-               memset(slot->userAddress, 0xbd, slot->userSize);
+	/*
+	 * 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.
+	 */
+	Page_Delete(slot->internalAddress, slot->internalSize);
 
 	previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
 	nextSlot = slotForInternalAddress(
 	 ((char *)slot->internalAddress) + slot->internalSize);
 
-	if ( previousSlot
-	 && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
+	if ( previousSlot && previousSlot->mode == slot->mode ) {
 		/* Coalesce previous slot with this one. */
 		previousSlot->internalSize += slot->internalSize;
-		if ( EF_PROTECT_FREE )
-			previousSlot->mode = PROTECTED;
-
 		slot->internalAddress = slot->userAddress = 0;
 		slot->internalSize = slot->userSize = 0;
 		slot->mode = NOT_IN_USE;
 		slot = previousSlot;
 		unUsedSlots++;
 	}
-	if ( nextSlot
-	 && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
+	if ( nextSlot && nextSlot->mode == slot->mode ) {
 		/* Coalesce next slot with this one. */
 		slot->internalSize += nextSlot->internalSize;
 		nextSlot->internalAddress = nextSlot->userAddress = 0;
@@ -746,38 +839,29 @@
 	slot->userAddress = slot->internalAddress;
 	slot->userSize = slot->internalSize;
 
-	/*
-	 * 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.
-	 */
-	Page_DenyAccess(slot->internalAddress, slot->internalSize);
-
 	if ( !noAllocationListProtection )
 		Page_DenyAccess(allocationList, allocationListSize);
 
-        unlock();
+	release();
 }
 
 extern C_LINKAGE void *
 realloc(void * oldBuffer, size_t newSize)
 {
- 	void *	newBuffer;
- 	
- 	if (oldBuffer && newSize==0) {
- 		free(oldBuffer);
- 		return NULL;
- 	}
- 	newBuffer = malloc(newSize);
+	void *	newBuffer = 0;
+
+	if ( allocationList == 0 )
+		initialize();	/* This sets EF_ALIGNMENT */
 
-        lock();
+	lock();
+
+	newBuffer = malloc(newSize);
 
 	if ( oldBuffer ) {
 		size_t	size;
 		Slot *	slot;
 
+
 		Page_AllowAccess(allocationList, allocationListSize);
 		noAllocationListProtection = 1;
 		
@@ -804,7 +888,8 @@
 		
 		/* Internal memory was re-protected in free() */
 	}
-	unlock();
+
+	release();
 
 	return newBuffer;
 }
@@ -812,32 +897,19 @@
 extern C_LINKAGE void *
 malloc(size_t size)
 {
-        void  *allocation;   
- 
-        if ( allocationList == 0 ) {
-                pthread_mutex_init(&mutex, NULL); 
-                initialize();   /* This sets EF_ALIGNMENT */
-        }       
-        lock();
-        allocation=memalign(EF_ALIGNMENT, size); 
-
-        unlock();
+	if ( allocationList == 0 )
+		initialize();	/* This sets EF_ALIGNMENT */
 
-	return allocation;
+	return memalign(EF_ALIGNMENT, size);
 }
 
 extern C_LINKAGE void *
 calloc(size_t nelem, size_t elsize)
 {
 	size_t	size = nelem * elsize;
-        void * allocation;
-        
-        lock();
-       
-        allocation = malloc(size);
-        memset(allocation, 0, size);
-        unlock();
+	void *	allocation = malloc(size);
 
+	memset(allocation, 0, size);
 	return allocation;
 }
 
@@ -848,11 +920,17 @@
 extern C_LINKAGE void *
 valloc (size_t size)
 {
-        void * allocation;
-       
-        lock();
-        allocation= memalign(bytesPerPage, size);
-        unlock();
-       
-        return allocation;
+	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
diff -ruN electric-fence-2.1.14.1/efence.h electric-fence-debian/efence.h
--- electric-fence-2.1.14.1/efence.h	1995-01-20 05:54:06.000000000 +0100
+++ electric-fence-debian/efence.h	1999-04-12 01:11:21.000000000 +0200
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/param.h>
+#include <stdarg.h>
 
 /*
  * ef_number is the largest unsigned integer we'll need. On systems that
@@ -36,7 +37,9 @@
 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_Lock();
-void			EF_UnLock();
+void			EF_Printv(const char * message, va_list args);
+void			EF_InternalError(const char * message, ...);
diff -ruN electric-fence-2.1.14.1/eftest.c electric-fence-debian/eftest.c
--- electric-fence-2.1.14.1/eftest.c	2006-01-10 07:07:40.000000000 +0100
+++ electric-fence-debian/eftest.c	2006-04-29 22:29:32.000000000 +0200
@@ -50,7 +50,7 @@
 static int
 gotSegmentationFault(int (*test)(void))
 {
-	if ( sigsetjmp(env,1) == 0 ) {
+	if ( sigsetjmp(env, 1) == 0 ) {
 		int			status;
 
 		signal(PAGE_PROTECTION_VIOLATED_SIGNAL
diff -ruN electric-fence-2.1.14.1/libefence.3 electric-fence-debian/libefence.3
--- electric-fence-2.1.14.1/libefence.3	2006-01-10 07:09:10.000000000 +0100
+++ electric-fence-debian/libefence.3	2006-04-29 22:40:27.000000000 +0200
@@ -76,7 +76,7 @@
 .LP
 .nf
 .ft B
-extern int EF_FREE_WIPES;
+extern int EF_FILL;
 .ft
 .fi
 .SH DESCRIPTION
@@ -123,16 +123,17 @@
 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.
-On AIX systems, you may have to use the flags
-.br
-.B -bnso
-.B -bnodelcsect
-.B -bI:/lib/syscalls.exp
-.br
-On Sun systems running SunOS 4.X, you'll probably have to use
-.B -Bstatic.
 .LP
 Run your program
 .I using a debugger. 
@@ -222,12 +223,12 @@
 integer value, or assign to the global integer variable EF_ALLOW_MALLOC_0 using
 a debugger.
 .TP
-EF_FREE_WIPES
-By default, Electric Fence releases memory without changing the content
-of the released memory block.  IF EF_FREE_WIPES is non-zero, the software
-will fill the memory block with 0xbd values before it is released.
-This makes it easier to trigger illegal use of released memory, and eaiser
-to understand why a memory access failed during gdb runs.
+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
@@ -321,25 +322,10 @@
 .LP
 Don't leave libefence.a linked into production software! Use it only
 for debugging.
-.SH PORTING
-Electric Fence is written for ANSI C. You should be able to port it with
-simple changes to the Makefile and to page.c,
-which contains the memory management primitives .
-Many POSIX platforms will require only a re-compile.
-The operating system facilities required to port Electric Fence are:
-.IP
-A way to allocate memory pages
-.br
-A way to make selected pages inaccessible.
-.br
-A way to make the pages accessible again.
-.br
-A way to detect when a program touches an inaccessible page.
-.br
-A way to print messages.
-.LP
-Please e-mail me a copy of any changes you have to make, so that I can
-merge them into the distribution.
+.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
@@ -347,16 +333,8 @@
 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.
-Bruce Perens and/or Pixar will not be liable to any claims resulting
-from the use of this software or the ideas within it.
-The entire responsibility for its use must
-be assumed by the user. If you use it and it results in loss of life
-and/or property, tough. If it leads you on a wild goose chase and you waste
-two weeks debugging something, too bad.
-If you can't deal with the above, please don't use the software! I've written
-this in an attempt to help other people, not to get myself sued or prosecuted.
 .SH LICENSE
-Copyright 1987-1995 Bruce Perens. All rights reserved.
+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,
@@ -370,13 +348,10 @@
 .SH CONTACTING THE AUTHOR
 .nf
 Bruce Perens
-c/o Pixar
-1001 West Cutting Blvd., Suite 200
-Richmond, CA 94804
-
-Telephone: 510-215-3502
-Fax: 510-236-0388
-Internet: [EMAIL PROTECTED]
+1563 Solano Ave. #349
+Berkeley, CA 94707
+Telephone: 510-526-1165
+Internet: [EMAIL PROTECTED]
 .fi
 .ft
 .SH FILES
@@ -393,7 +368,7 @@
 .SH BUGS
 My explanation of the alignment issue could be improved.
 .LP
-Some Sun systems running SunOS 4.1 are reported to signal an access to a
+Some Sun systems running SunOS 4.1 were reported to signal an access to a
 protected page with
 .B  SIGBUS
 rather than
@@ -409,7 +384,11 @@
 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
-PURIFY, from Purify Systems, does a much better job than Electric Fence, and
-does much more. It's available at this writing on SPARC and HP.
-I'm not affiliated with Purify, I just think it's a wonderful product
-and you should check it out.
+.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.
diff -ruN electric-fence-2.1.14.1/Makefile electric-fence-debian/Makefile
--- electric-fence-2.1.14.1/Makefile	2002-02-19 22:51:44.000000000 +0100
+++ electric-fence-debian/Makefile	2006-04-29 23:19:55.000000000 +0200
@@ -1,34 +1,22 @@
-ASFLAGS= -mips2
+PIC= -fPIC
+CFLAGS= -g -O2 -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
-MV= mv
-CHMOD= chmod
-CFLAGS= -g
-LIB_INSTALL_DIR= /usr/lib
-MAN_INSTALL_DIR= /usr/man/man3
-
-PACKAGE_SOURCE= README libefence.3 Makefile efence.h \
-	efence.c page.c print.c eftest.c tstheap.c CHANGES COPYING
-
-# Un-comment the following if you are running HP/UX.
-# CFLAGS= -Aa -g -D_HPUX_SOURCE -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
-
-# Un-comment the following if you are running AIX. This makes sure you won't
-# get the shared-library malloc() rather than the Electric Fence malloc().
-# COMPILE THE PROGRAMS YOU ARE DEBUGGING WITH THESE FLAGS, TOO.
-# CFLAGS= -g -bnso -bnodelcsect -bI:/lib/syscalls.exp
-
-# Un-comment the following if you are running SunOS 4.X
-# Note the definition of PAGE_PROTECTION_VIOLATED_SIGNAL. This may vary
-# depend on what version of Sun hardware you have.
-# You'll probably have to link the program you are debugging with -Bstatic
-# as well if using Sun's compiler, -static if using GCC.
-# CFLAGS= -g -Bstatic -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+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 tstheap eftest
+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."
@@ -38,15 +26,19 @@
 	@ echo "Electric Fence confidence test PASSED." 
 	@ echo
 
-install: libefence.a libefence.3
-	$(MV) libefence.a $(LIB_INSTALL_DIR)
-	$(CHMOD) 644 $(LIB_INSTALL_DIR)/libefence.a
-	$(INSTALL) libefence.3 $(MAN_INSTALL_DIR)/libefence.3
-	$(CHMOD) 644 $(MAN_INSTALL_DIR)/libefence.3
+install: libefence.a libefence.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)/libefence.3
 
 clean:
-	- rm -f $(OBJECTS) tstheap.o eftest.o tstheap eftest libefence.a \
-	 libefence.cat ElectricFence.shar
+	- rm -f $(OBJECTS) tstheap.o eftest.o tstheap eftest \
+	 libefence.a libefence.so.0.0 libefence.cat ElectricFence.shar
 
 roff:
 	nroff -man < libefence.3 > libefence.cat
@@ -61,12 +53,19 @@
 	- rm -f libefence.a
 	$(AR) crv libefence.a $(OBJECTS)
 
+libefence.so.0.0: $(OBJECTS)
+	$(CC) -shared -Wl,-soname,libefence.so.0 -o libefence.so.0.0 \
+		$(CFLAGS) $(OBJECTS) -lpthread -lc 
+
 tstheap: libefence.a tstheap.o
 	- rm -f tstheap
-	$(CC) $(CFLAGS) tstheap.o libefence.a -o tstheap -lpthread
+	$(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 -lpthread
+	$(CC) $(CFLAGS) eftest.o libefence.a -o eftest $(LIBS)
 
 $(OBJECTS) tstheap.o eftest.o: efence.h
+
+.c.o:
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
diff -ruN electric-fence-2.1.14.1/page.c electric-fence-debian/page.c
--- electric-fence-2.1.14.1/page.c	2005-01-15 21:00:11.000000000 +0100
+++ electric-fence-debian/page.c	2006-04-29 22:31:42.000000000 +0200
@@ -68,7 +68,7 @@
 	 */
 	allocation = (caddr_t) mmap(
 	 startAddr
-	,size
+	,(int)size
 	,PROT_READ|PROT_WRITE
 	,MAP_PRIVATE|MAP_ANONYMOUS
 	,-1
@@ -120,7 +120,7 @@
 	 */
 	allocation = (caddr_t) mmap(
 	 startAddr
-	,size
+	,(int)size
 	,PROT_READ|PROT_WRITE
 	,MAP_PRIVATE
 	,devZeroFd
@@ -159,6 +159,8 @@
 Page_Delete(void * address, size_t size)
 {
 	Page_DenyAccess(address, size);
+	/* Tell the kernel we will never need it again.  */
+	madvise(address, size, MADV_DONTNEED);
 }
 
 #if defined(_SC_PAGESIZE)
diff -ruN electric-fence-2.1.14.1/print.c electric-fence-debian/print.c
--- electric-fence-2.1.14.1/print.c	2001-07-15 14:00:10.000000000 +0200
+++ electric-fence-debian/print.c	2006-04-29 22:34:11.000000000 +0200
@@ -18,6 +18,19 @@
 #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];
@@ -45,8 +58,8 @@
 		write(2, s, size);
 }
 
-static void
-vprint(const char * pattern, va_list args)
+void
+EF_Printv(const char * pattern, va_list args)
 {
 	static const char	bad_pattern[] =
 	 "\nBad pattern specifier %%%c in EF_Print().\n";
@@ -117,25 +130,35 @@
 }
 
 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); */
+}
 
-	EF_Print("\nElectricFence Aborting: ");
-	vprint(pattern, args);
+void
+EF_Exitv(const char * pattern, va_list args)
+{
+	EF_Print("\nElectricFence Exiting: ");
+	EF_Printv(pattern, args);
 	EF_Print("\n");
 
-	va_end(args);
-
 	/*
-	 * 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.
+	 * I use _exit() because the regular exit() flushes stdio,
+	 * which may cause malloc() or free() to be called.
 	 */
-	kill(getpid(), SIGILL);
-	/* Just in case something handles SIGILL and returns, exit here. */
 	_exit(-1);
 }
 
@@ -146,17 +169,9 @@
 
 	va_start(args, pattern);
 
-	EF_Print("\nElectricFence Exiting: ");
-	vprint(pattern, args);
-	EF_Print("\n");
-
-	va_end(args);
+	EF_Exitv(pattern, args);
 
-	/*
-	 * I use _exit() because the regular exit() flushes stdio,
-	 * which may cause malloc() or free() to be called.
-	 */
-	_exit(-1);
+	/* Not reached: va_end(args); */
 }
 
 void
@@ -165,6 +180,19 @@
 	va_list	args;
 
 	va_start(args, pattern);
-	vprint(pattern, args);
+	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();
 }
diff -ruN electric-fence-2.1.14.1/README electric-fence-debian/README
--- electric-fence-2.1.14.1/README	1998-03-12 20:48:22.000000000 +0100
+++ electric-fence-debian/README	1999-04-12 04:12:03.000000000 +0200
@@ -1,4 +1,4 @@
-This is Electric Fence 2.1
+This 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
@@ -8,39 +8,16 @@
 a bounds violation. It's then trivial to use a debugger to display the
 offending statement.
 
-This version will run on:
-	Linux kernel version 1.1.83 and above. Earlier kernels have problems
-	with the memory protection implementation.
-
-	All System V Revision 4 platforms (and possibly earlier revisions)
-	including:
-		Every 386 System V I've heard of.
-		Solaris 2.x
-		SGI IRIX 5.0 (but not 4.x)
-
-	IBM AIX on the RS/6000.
-
-	SunOS 4.X (using an ANSI C compiler and probably static linking).
-
-	HP/UX 9.01, and possibly earlier versions.
-
-	OSF 1.3 (and possibly earlier versions) on a DECalpha.
-
-On some of these platforms, you'll have to uncomment lines in the Makefile
-that apply to your particular system.
-
-If you test Electric Fence on a platform not mentioned here, please send me a
-report.
-
-It will probably port to any ANSI/POSIX system that provides mmap(), and
-mprotect(), as long as mprotect() has the capability to turn off all access
-to a memory page, and mmap() can use /dev/zero or the MAP_ANONYMOUS flag
-to create virtual memory pages.
+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
-libefence.3 .
+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
-	[EMAIL PROTECTED]
+	[EMAIL PROTECTED]

Reply via email to