summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Vernon <matthew@debian.org>2012-07-17 18:40:21 +0100
committerMatthew Vernon <matthew@debian.org>2012-07-17 18:40:21 +0100
commitc58af6bfa50d619fea396581f445f6a97ac73bdc (patch)
treef5e5b96e22c2b86e8755dd3f7d10d02f0e88222f
electric-fence (2.2.4) unstable; urgency=medium (high for hurd users)
* Patch from Richard Kettlewell to improve the semaphore strategy of efence. We no longer use recursive mutexes, and the code is instead clearer about when it should and shouldn't be locking. This means that electric-fence builds on hurd, which it hasn't previously. # imported from the archive
-rw-r--r--CHANGES26
-rw-r--r--COPYING339
-rw-r--r--Makefile77
-rw-r--r--README20
-rw-r--r--debian/README.debian26
-rw-r--r--debian/README.gdb41
-rw-r--r--debian/changelog232
-rw-r--r--debian/compat1
-rw-r--r--debian/control26
-rw-r--r--debian/copyright16
-rw-r--r--debian/debhelper.log14
-rw-r--r--debian/dirs3
-rw-r--r--debian/efence.debhelper.log4
-rw-r--r--debian/electric-fence.lintian-overrides7
-rw-r--r--debian/postinst10
-rwxr-xr-xdebian/postrm7
-rwxr-xr-xdebian/rules63
-rw-r--r--debian/substvars2
-rw-r--r--efence.c929
-rw-r--r--efence.h45
-rw-r--r--eftest.c233
-rw-r--r--libefence.3396
l---------libefence.so1
-rw-r--r--page.c185
-rw-r--r--print.c198
-rw-r--r--tstheap.c61
26 files changed, 2962 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..7407ddf
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,26 @@
+2.1 Remove work-arounds, most operating systems and C libraries have
+ been fixed now.
+
+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.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..e77696a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ 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
+
+ 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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e0dd5b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,77 @@
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS=-O0 -fno-builtin-malloc -g -Wall -DUSE_SEMAPHORE -fPIC
+else
+ CFLAGS=-O2 -fno-builtin-malloc -g -Wall -DUSE_SEMAPHORE -fPIC
+endif
+
+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 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.so.0.0 libefence.cat ElectricFence.shar
+
+
+roff:
+ nroff -man < libefence.3 > libefence.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)
+ $(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 $(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 $@
diff --git a/README b/README
new file mode 100644
index 0000000..6227d76
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+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
+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
+libefence.3 .
+
+ Thanks
+
+ Bruce Perens
+ bruce@perens.com
diff --git a/debian/README.debian b/debian/README.debian
new file mode 100644
index 0000000..b069be0
--- /dev/null
+++ b/debian/README.debian
@@ -0,0 +1,26 @@
+electric-fence for DEBIAN
+-------------------------
+
+This package has been orphaned for a while now, so Matthew Vernon
+<matthew@debian.org> has taken it up (the next paragraph is superceded by
+this one). Note also that I've moved the manpage back to libefence.3
+
+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)
+
+
diff --git a/debian/README.gdb b/debian/README.gdb
new file mode 100644
index 0000000..73d9e49
--- /dev/null
+++ b/debian/README.gdb
@@ -0,0 +1,41 @@
+This is a suggested ~/.gdbinit from Ray Dassen - it enables you to use
+Electric Fence from within gdb without having to relink the binary. See
+the gdb docs for more information.
+
+###############################################################################
+# Electric Fence
+#
+# Debian's Electric Fence package provides efence as a shared library, which is
+# very useful.
+###############################################################################
+
+define efence
+ set environment EF_PROTECT_BELOW 0
+ set environment LD_PRELOAD /usr/lib/libefence.so.0.0
+ echo Enabled Electric Fence\n
+end
+document efence
+Enable memory allocation debugging through Electric Fence (efence(3)).
+ See also nofence and underfence.
+end
+
+
+define underfence
+ set environment EF_PROTECT_BELOW 1
+ set environment LD_PRELOAD /usr/lib/libefence.so.0.0
+ echo Enabled Electric Fence for undeflow detection\n
+end
+document underfence
+Enable memory allocation debugging for underflows through Electric Fence
+(efence(3)).
+ See also nofence and efence.
+end
+
+
+define nofence
+ unset environment LD_PRELOAD
+ echo Disabled Electric Fence\n
+end
+document nofence
+Disable memory allocation debugging through Electric Fence (efence(3)).
+end
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..7482215
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,232 @@
+electric-fence (2.2.4) unstable; urgency=medium (high for hurd users)
+
+ * Patch from Richard Kettlewell to improve the semaphore strategy of
+ efence. We no longer use recursive mutexes, and the code is instead
+ clearer about when it should and shouldn't be locking. This means that
+ electric-fence builds on hurd, which it hasn't previously.
+
+ -- Matthew Vernon <matthew@debian.org> Tue, 17 Jul 2012 18:40:21 +0100
+
+electric-fence (2.2.3) unstable; urgency=low
+
+ * Fix the build system such that we actually pass -fno-builtin-malloc to
+ gcc. Thanks to Ian Jackson and Colin Watson for helping me disentangle
+ this (Closes: #679320)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 02 Jul 2012 18:57:41 +0100
+
+electric-fence (2.2.2) unstable; urgency=low
+
+ * patch from Petr Machata to add posix_memalign support (Closes: #599938)
+ * Update standards-version
+ * Update to use debhelper compatibility version 8
+ * Don't ignore errors from make clean
+ * set -e in postrm
+
+ -- Matthew Vernon <matthew@debian.org> Wed, 27 Jun 2012 22:15:04 +0100
+
+electric-fence (2.2.1) unstable; urgency=low
+
+ * patch from Brandon (modified a little) to handle noopt
+ DEB_BUILD_OPTIONS (Closes: #461428)
+ * patch from Fedora (via Botond Botyanszki) replacing mutex locking with
+ semaphores (Closes: #241156, #365382)
+
+ -- Matthew Vernon <matthew@debian.org> Wed, 27 Jun 2012 00:50:42 +0100
+
+electric-fence (2.1.19) unstable; urgency=low
+
+ * patch from Petr Salinger to handle both SIGBUS and SIGSEGV in eftest.c
+ on FreeBSD-based architectures (Closes: #643866)
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 07 Oct 2011 08:38:44 +0100
+
+electric-fence (2.1.18) unstable; urgency=low
+
+ * refine the previous patch to use -fno-builtin-malloc instead
+
+ -- Matthew Vernon <matthew@debian.org> Tue, 27 Sep 2011 21:44:35 +0100
+
+electric-fence (2.1.17) unstable; urgency=low
+
+ * patch from Colin Watson to build with -fno-tree-dse as otherwise gcc
+ >=4.5 mis-optimises AllocateMoreSlots() (Closes: #625756).
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 09 Sep 2011 13:32:50 +0100
+
+electric-fence (2.1.16) unstable; urgency=medium
+
+ * apply patch from Petr Salinger to fix FTBFS on GNU/kfreeBSD
+ (closes: #340420)
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 14 May 2010 15:51:33 +0100
+
+electric-fence (2.1.15) unstable; urgency=low
+
+ * patch from Samuel Thibault to fix pthread support (closes: #541387)
+ * update lintian overrides
+
+ -- Matthew Vernon <matthew@debian.org> Thu, 13 May 2010 21:54:16 +0100
+
+electric-fence (2.1.14) unstable; urgency=low
+
+ * Fix behaviour of realloc() to conform to ANSI (closes: #134867)
+ * Use strerror_r() (closes: #236407)
+ * Correct typo in README.gdb (closes: #242376)
+
+ -- Matthew Vernon <matthew@debian.org> Sat, 15 Jan 2005 20:05:00 +0000
+
+electric-fence (2.1.13-0.1) unstable; urgency=low
+
+ * Non-maintainer upload
+ * eftest.c: uses sig{set,long}jmp() instead of {set,long}jmp() to work on
+ both 2.4 and 2.6 kernels (closes: #203436)
+ * Added a proper description (closes: #209479)
+ * Changed order of commands to build static library without PIC
+ (closes: #154034)
+ * Clarified and fixed manpage:
+ - clarified semantics of EF_PROTECT_FREE (closes: #177800)
+ - EF_ALLOC_MALLOC_0 -> EF_ALLOW_MALLOC_0 (closes: #177807)
+ - mention EF_ALLOW_MALLOC_0 in the synopsis, correct number of conf
+ switches (closes: #177808)
+ * /usr/doc symlink not created any more, added postrm with ldconfig call,
+ added debhelper tokens (closes: #222980)
+
+ -- Martin Pitt <mpitt@debian.org> Fri, 5 Dec 2003 16:51:38 +0100
+
+electric-fence (2.1.13) unstable; urgency=high
+
+ * Link with pthreads (closes: #135122)
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 22 Feb 2001 09:57:50 +0000
+
+electric-fence (2.1.12) unstable; urgency=high
+
+ * Add multithreading support (thanks to infrared@mail.index.hu)
+ (closes: #67838)
+ * Specify the GPL version (closes: #133494)
+ * Patch to allow you to specify that electric-fence should set freed
+ memory to a fixed value - makes things more helpful under gdb in
+ certain circumstances (patch from Petter Reinholdtsen <pere@hungry.com>
+ and modified by yours truly to make it legal :-) (closes: #59764)
+ * That's all the outstanding bugs fixed for the next release
+
+ -- Matthew Vernon <matthew@debian.org> Tue, 19 Feb 2001 22:09:37 +0000
+
+electric-fence (2.1.11) unstable; urgency=low
+
+ * Fix daft typo (closes: #105418)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 16 Jul 2001 08:56:01 +0100
+
+electric-fence (2.1.10) unstable; urgency=low
+
+ * pass int not char as type to va_arg (closes: #104800)
+
+ -- Matthew Vernon <matthew@debian.org> Sun, 15 Jul 2001 13:05:34 +0100
+
+electric-fence (2.1.9) unstable; urgency=low
+
+ * Get the /usr/doc/ stuff right this time (closes: #97010, #97890)
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 18 May 2001 14:28:01 +0100
+
+electric-fence (2.1.8) unstable; urgency=low
+
+ * Remove spurious (int) casts in calls to mmap (closes: #84940)
+
+ -- Matthew Vernon <matthew@debian.org> Wed, 11 Apr 2001 15:48:39 +0100
+
+electric-fence (2.1.7) unstable; urgency=low
+
+ * Check if /usr/doc/electric-fence is a symlink in postinst (closes: #93534)
+
+ -- Matthew Vernon <matthew@debian.org> Tue, 10 Apr 2001 15:41:49 +0100
+
+electric-fence (2.1.6) unstable; urgency=low
+
+ * Make the banner print a correct version (closes: #81413)
+ * Man page into /usr/share/man (closes: #91147,#81450)
+ * Be sure to get rid of /usr/doc/electric-fence (closes: #81023)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 09 Apr 2001 14:52:03 +0100
+
+electric-fence (2.1.5) unstable; urgency=low
+
+ * rename the manpage to correspond to the README file (closes: #77243)
+
+ -- Matthew Vernon <matthew@debian.org> Fri, 17 Nov 2000 18:35:42 +0000
+
+electric-fence (2.1.4) unstable; urgency=low
+
+ * build tidy-ups (closes: #48156, #52927, #56142)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 16 Oct 2000 18:01:36 +0100
+
+electric-fence (2.1.3) unstable; urgency=low
+
+ * install libefence.so (closes:48156)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 07 dec 1999 15:42:00 +0000
+
+electric-fence (2.1.2) unstable; urgency=low
+
+ * Actually install that gdb documentation <sigh>
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 13 Sep 1999 14:08:00 +0100
+
+electric-fence (2.1.1) unstable; urgency=low
+
+ * Taking over this package properly
+ * Version numbering fixed (I hope)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 01 Sep 1999 13:00:00 +0100
+
+electric-fence (2.1-2) unstable; urgency=low
+
+ * Added Ian Jackson's patches (closes: #41314)
+ * Added gdb documentation (closes: #33186)
+
+ -- Matthew Vernon <matthew@debian.org> Mon, 16 Aug 1999 16:08:22 +0100
+
+electric-fence (2.1-1) unstable; urgency=low
+
+ * new upstream release (closes: #35853)
+
+ -- Christian Kurz <shorty@debian.org> Wed, 16 Jun 1999 15:35:09 +0200
+
+electric-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
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+8
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..3496070
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,26 @@
+Source: electric-fence
+Section: devel
+Priority: extra
+Maintainer: Matthew Vernon <matthew@debian.org>
+Build-Depends: debhelper (>= 8)
+Standards-Version: 3.9.1
+
+Package: electric-fence
+Section: devel
+Priority: extra
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: A malloc(3) debugger
+ Electric Fence is a debugger that uses virtual memory hardware to detect
+ illegal memory accesses. It can detect two common programming bugs: software
+ that overruns or underruns 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 read accesses as
+ well as writes, and it will stop and pinpoint the exact instruction that
+ causes an error. It is not as thorough as Purify, however.
+ .
+ In order to debug a program it needs to be linked with Electric Fence's
+ library or dynamic linking needs to be used; README.Debian explains that in
+ detail.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..8358260
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,16 @@
+This package was debianized by Siggy Brentrup bsb@debian.org on
+Wed, 5 Feb 1997 15:53:23 +0100. It is currently maintained by Matthew
+Vernon <matthew@debian.org>.
+
+According to the author Bruce Perens <bruce@pixar.com> we can consider it
+a genuine Debian package.
+But you can download an alternate copy of the source from:
+http://metalab.unc.edu/pub/Linux/devel/lang/c/ElectricFence-2.0.5.tar.gz
+
+Copyright:
+
+(c) 1988, 1993 Bruce Perens <bruce@pixar.com>
+The program is distributed under the GNU General Public License version 2
+which can be found in /usr/share/common-licenses/GPL-2
+
+
diff --git a/debian/debhelper.log b/debian/debhelper.log
new file mode 100644
index 0000000..bd78b3c
--- /dev/null
+++ b/debian/debhelper.log
@@ -0,0 +1,14 @@
+dh_installdirs
+dh_link
+dh_link
+dh_installdocs
+dh_installchangelogs
+dh_strip
+dh_compress
+dh_lintian
+dh_installdeb
+dh_fixperms
+dh_shlibdeps
+dh_gencontrol
+dh_md5sums
+dh_builddeb
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..44bb5f7
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,3 @@
+usr/lib
+usr/share/doc/electric-fence
+usr/share/man/man3
diff --git a/debian/efence.debhelper.log b/debian/efence.debhelper.log
new file mode 100644
index 0000000..ab83856
--- /dev/null
+++ b/debian/efence.debhelper.log
@@ -0,0 +1,4 @@
+dh_installmanpages
+dh_installmanpages
+dh_installmanpages
+dh_installmanpages
diff --git a/debian/electric-fence.lintian-overrides b/debian/electric-fence.lintian-overrides
new file mode 100644
index 0000000..ba0d369
--- /dev/null
+++ b/debian/electric-fence.lintian-overrides
@@ -0,0 +1,7 @@
+#Lintian overrides for electric-fence
+#electric-fence is an unusual package, in that it contains a
+#library that you should never build packages against, as it's a debugging tool
+#
+electric-fence: non-dev-pkg-with-shlib-symlink usr/lib/libefence.so.0.0 usr/lib/libefence.so
+electric-fence: no-shlibs-control-file usr/lib/libefence.so.0.0
+electric-fence: package-name-doesnt-match-sonames libefence0
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000..c03c4f2
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+
+if [ "$1" = "configure" ]; then
+ ldconfig
+fi
+
+#DEBHELPER#
diff --git a/debian/postrm b/debian/postrm
new file mode 100755
index 0000000..f7c5ed7
--- /dev/null
+++ b/debian/postrm
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+if [ "$1" = "remove" ]; then
+ ldconfig
+fi
+
+#DEBHELPER#
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..abad1b2
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,63 @@
+#!/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>
+#
+# Modified to work with debhelper-tools by Christian Kurz <shorty@debian.org>
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+build: build-stamp
+build-stamp:
+ dh_testdir
+ make
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ rm -f libefence.so.0.0
+ dh_clean
+ $(MAKE) clean
+
+# Build architecture-independent files here.
+binary-indep: build
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build
+ dh_testdir
+ dh_testroot
+ dh_clean
+ dh_installdirs usr/lib usr/share/man/man3
+ install -m 644 libefence.a debian/electric-fence/usr/lib
+ install -m 644 libefence.so.0.0 debian/electric-fence/usr/lib
+ dh_link /usr/lib/libefence.so.0.0 /usr/lib/libefence.so.0
+ #ln -s debian/electric-fence/usr/lib/libefence.so.0 ./libefence.so
+ dh_link /usr/lib/libefence.so.0 /usr/lib/libefence.so
+ install -m 644 libefence.3 debian/electric-fence/usr/share/man/man3/libefence.3
+ dh_installdocs README debian/README.gdb
+ dh_installchangelogs
+ dh_installman libefence.3
+ chown -R root.root debian/electric-fence
+ dh_strip
+ dh_compress
+ dh_lintian
+ dh_installdeb
+ dh_fixperms
+ dh_shlibdeps debian/electric-fence/usr/lib/libefence.so.0.0
+ dpkg-shlibdeps debian/electric-fence/usr/lib/libefence.so.0.0
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary
diff --git a/debian/substvars b/debian/substvars
new file mode 100644
index 0000000..775f886
--- /dev/null
+++ b/debian/substvars
@@ -0,0 +1,2 @@
+misc:Depends=
+shlibs:Depends=libc6 (>= 2.3.4), libc6 (>= 2.3.6-6~)
diff --git a/efence.c b/efence.c
new file mode 100644
index 0000000..c3e1d18
--- /dev/null
+++ b/efence.c
@@ -0,0 +1,929 @@
+/*
+ * 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>
+#include <errno.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"
+ " 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;
+
+static void *memalign_locked(size_t alignment, size_t userSize);
+static void free_locked(void *address);
+
+ /*
+ * EF_DISABLE_BANNER is a global variable used to control whether
+ * Electric Fence prints its usual startup message. If the value is
+ * -1, it will be set from the environment default to 0 at run time.
+ */
+int EF_DISABLE_BANNER = -1;
+
+
+/*
+ * 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
+
+#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.
+ */
+static sem_t EF_sem = { 0 };
+static int semEnabled = 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;
+
+ /* Wait for the semaphore. */
+ while (sem_wait(&EF_sem) < 0)
+ /* try again */;
+#endif /* USE_SEMAPHORE */
+}
+
+static void
+release()
+{
+#ifdef USE_SEMAPHORE
+ /* Are we using a semaphore? */
+ if (!semEnabled)
+ return;
+ 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;
+
+ if ( EF_DISABLE_BANNER == -1 ) {
+ if ( (string = getenv("EF_DISABLE_BANNER")) != 0 )
+ EF_DISABLE_BANNER = atoi(string);
+ else
+ EF_DISABLE_BANNER = 0;
+ }
+
+ 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
+ * 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();
+}
+
+#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.
+ */
+static void
+allocateMoreSlots(void)
+{
+ size_t newSize = allocationListSize + bytesPerPage;
+ void * newAllocation;
+ void * oldAllocation = allocationList;
+
+ Page_AllowAccess(allocationList, allocationListSize);
+ noAllocationListProtection = 1;
+ internalUse = 1;
+
+ newAllocation = memalign_locked(EF_ALIGNMENT, newSize);
+ memcpy(newAllocation, allocationList, allocationListSize);
+ memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
+
+ allocationList = (Slot *)newAllocation;
+ allocationListSize = newSize;
+ slotCount += slotsPerPage;
+ unUsedSlots += slotsPerPage;
+
+ free_locked(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.
+ */
+static void *
+memalign_locked(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 ( 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. */
+ Page_Delete(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. */
+ Page_Delete(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);
+
+ return address;
+}
+
+extern C_LINKAGE void *
+memalign(size_t alignment, size_t userSize)
+{
+ void *address;
+ if ( allocationList == 0 )
+ initialize();
+ lock();
+ address = memalign_locked(alignment, userSize);
+ release();
+ return address;
+}
+
+extern C_LINKAGE int
+posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+ /*
+ * Per standard, posix_memalign returns EINVAL when alignment
+ * is not a power of two or power of sizeof(void*). efence
+ * doesn't check the value of alignment in memalign, but then
+ * again, memalign was never specified very well, and on some
+ * systems odd alignments could indeed have been allowed.
+ */
+ if ((alignment & (alignment - 1))
+ || alignment % sizeof (void *))
+ return EINVAL;
+
+ void *ptr = memalign (alignment, size);
+ if (ptr == NULL)
+ return ENOMEM;
+ *memptr = ptr;
+ return 0;
+}
+
+/*
+ * 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;
+}
+
+static void
+free_locked(void * address)
+{
+ Slot * slot;
+ Slot * previousSlot = 0;
+ Slot * nextSlot = 0;
+
+ if ( address == 0 )
+ return;
+
+ 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.
+ */
+ Page_Delete(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);
+}
+
+extern C_LINKAGE void
+free(void * address)
+{
+
+ if ( address == 0 )
+ return;
+
+ if ( allocationList == 0 )
+ EF_Abort("free() called before first malloc().");
+
+ lock();
+ free_locked(address);
+ release();
+}
+
+extern C_LINKAGE void *
+realloc(void * oldBuffer, size_t newSize)
+{
+ void * newBuffer = 0;
+
+ if ( allocationList == 0 )
+ initialize(); /* This sets EF_ALIGNMENT */
+
+ lock();
+
+ newBuffer = memalign_locked(EF_ALIGNMENT, 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_locked(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
diff --git a/efence.h b/efence.h
new file mode 100644
index 0000000..3be53a8
--- /dev/null
+++ b/efence.h
@@ -0,0 +1,45 @@
+#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, ...);
diff --git a/eftest.c b/eftest.c
new file mode 100644
index 0000000..603de52
--- /dev/null
+++ b/eftest.c
@@ -0,0 +1,233 @@
+#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
+#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+#define EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL SIGBUS
+#endif
+#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 sigjmp_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);
+#ifdef EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL
+ signal(EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
+#endif
+ siglongjmp(env, 1);
+}
+
+static int
+gotSegmentationFault(int (*test)(void))
+{
+ if ( sigsetjmp(env,1) == 0 ) {
+ int status;
+
+ signal(PAGE_PROTECTION_VIOLATED_SIGNAL,
+ segmentationFaultHandler);
+#ifdef EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL
+ signal(EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL,
+ segmentationFaultHandler);
+#endif
+
+ status = (*test)();
+ signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
+#ifdef EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL
+ signal(EXTRA_PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
+#endif
+ 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;
+}
diff --git a/libefence.3 b/libefence.3
new file mode 100644
index 0000000..e6b1e10
--- /dev/null
+++ b/libefence.3
@@ -0,0 +1,396 @@
+.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
+int posix_memalign (void ** memptr, 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_DISABLE_BANNER;
+.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 six 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_DISABLE_BANNER
+This is an integer which if nonzero specifies that the usual Electric
+Fence banner and copyright notice should not be printed. This is
+provided for certain circumstances where the banner can be annoying
+(eg, running a regression test suite that also monitors stderr). Note
+that you should almost certainly not set this in your program, because
+then you might leave Electric Fence linked into the production
+version, which would be very bad.
+.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
+When EF_PROTECT_FREE is not set (i. e. set to 0), Electric Fence returns free
+memory to a pool and only checks accesses to it until it is reallocated. 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_ALLOW_MALLOC_0 in the shell environment to an
+integer value, or assign to the global integer variable EF_ALLOW_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 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.
diff --git a/libefence.so b/libefence.so
new file mode 120000
index 0000000..43cbf74
--- /dev/null
+++ b/libefence.so
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libefence.so.0 \ No newline at end of file
diff --git a/page.c b/page.c
new file mode 100644
index 0000000..ab6639f
--- /dev/null
+++ b/page.c
@@ -0,0 +1,185 @@
+#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) )
+extern int sys_nerr;
+/*extern char * sys_errlist[];*/
+#endif
+
+static const char *
+stringErrorReport(void)
+{
+ char err_message[128];
+#if ( defined(sgi) )
+ return strerror(oserror());
+#elif ( defined(_AIX) )
+ return strerror(errno);
+#else
+ return strerror_r(errno,(char *)err_message,128);
+#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)
+{
+ Page_DenyAccess(address, size);
+ /* Tell the kernel we will never need it again. */
+ madvise(address, size, MADV_DONTNEED);
+}
+
+#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
diff --git a/print.c b/print.c
new file mode 100644
index 0000000..b4b8e53
--- /dev/null
+++ b/print.c
@@ -0,0 +1,198 @@
+#include "efence.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.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':
+ { /*Cast used, since char gets promoted to int in ... */
+ char c = (char) va_arg(args, int);
+
+ (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();
+}
diff --git a/tstheap.c b/tstheap.c
new file mode 100644
index 0000000..c712fed
--- /dev/null
+++ b/tstheap.c
@@ -0,0 +1,61 @@
+#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;
+}