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]