work/0000775000000000000000000000000014661135731006737 5ustar work/CHANGES0000664000000000000000000000165414661135731007740 0ustar 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. work/COPYING0000664000000000000000000004307014661135731007776 0ustar 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. Copyright (C) 19yy 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. , 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. work/Makefile0000664000000000000000000000405514661135731010403 0ustar 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=$(DESTDIR)/usr BIN_INSTALL_DIR= $(prefix)/bin LIB_INSTALL_DIR= $(prefix)/lib MAN_INSTALL_DIR= $(prefix)/share/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 mkdir -p $(LIB_INSTALL_DIR) $(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 $(LIB_INSTALL_DIR)/libefence.so mkdir -p $(MAN_INSTALL_DIR) $(INSTALL) -m 644 libefence.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 $@ work/README0000664000000000000000000000136214661135731007621 0ustar 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 work/debian/0000775000000000000000000000000014661135731010161 5ustar work/debian/README.debian0000664000000000000000000000170114661135731012261 0ustar electric-fence for DEBIAN ------------------------- This package has been orphaned for a while now, so Matthew Vernon 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 . But he apparently lost his net.access, so this version was made by joost witteveen, . 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) work/debian/README.gdb0000664000000000000000000000237214661135731011600 0ustar 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 work/debian/changelog0000664000000000000000000002120414661135731012032 0ustar electric-fence (2.2.7) unstable; urgency=medium * Fix errors reported by gcc-14 (Closes: #1074933) * Update a lintian override -- Matthew Vernon Tue, 20 Aug 2024 16:52:57 +0100 electric-fence (2.2.6) unstable; urgency=medium * Move to entirely dh-based packaging (Closes: #999103) * Bump standards-version * Lintian-inspired packaging fixes -- Matthew Vernon Fri, 12 Nov 2021 18:58:14 +0000 electric-fence (2.2.5) unstable; urgency=medium * Patch from Helmut Grohne to Fix FTCBFS: (Closes: 853051) + Let dh_auto_build pass cross compilers + Honour DEB_BUILD_OPTIONS=nocheck -- Matthew Vernon Sun, 29 Jan 2017 12:24:45 +0000 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 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 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 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 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 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 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 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 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 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 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 Fri, 5 Dec 2003 16:51:38 +0100 electric-fence (2.1.13) unstable; urgency=high * Link with pthreads (closes: #135122) -- Matthew Vernon 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 and modified by yours truly to make it legal :-) (closes: #59764) * That's all the outstanding bugs fixed for the next release -- Matthew Vernon Tue, 19 Feb 2001 22:09:37 +0000 electric-fence (2.1.11) unstable; urgency=low * Fix daft typo (closes: #105418) -- Matthew Vernon 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 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 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 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 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 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 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 Mon, 16 Oct 2000 18:01:36 +0100 electric-fence (2.1.3) unstable; urgency=low * install libefence.so (closes:48156) -- Matthew Vernon Mon, 07 dec 1999 15:42:00 +0000 electric-fence (2.1.2) unstable; urgency=low * Actually install that gdb documentation -- Matthew Vernon 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 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 Mon, 16 Aug 1999 16:08:22 +0100 electric-fence (2.1-1) unstable; urgency=low * new upstream release (closes: #35853) -- Christian Kurz 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 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 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 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 Wed, 20 Jan 1996 00:00:00 +0100 work/debian/control0000664000000000000000000000172514661135731011571 0ustar Source: electric-fence Section: devel Priority: optional Maintainer: Matthew Vernon Build-Depends: debhelper-compat (= 13) Standards-Version: 4.6.0.1 Package: electric-fence 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. work/debian/copyright0000664000000000000000000000111314661135731012110 0ustar 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 . According to the author Bruce Perens 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 The program is distributed under the GNU General Public License version 2 which can be found in /usr/share/common-licenses/GPL-2 work/debian/dirs0000664000000000000000000000007014661135731011042 0ustar usr/lib usr/share/doc/electric-fence usr/share/man/man3 work/debian/electric-fence.docs0000664000000000000000000000003114661135731013675 0ustar README debian/README.gdb work/debian/electric-fence.lintian-overrides0000664000000000000000000000063414661135731016414 0ustar #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: link-to-shared-library-in-wrong-package 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 work/debian/rules0000775000000000000000000000060514661135731011242 0ustar #!/usr/bin/make -f # See debhelper(7) # output every command that modifies files on the build system. DH_VERBOSE = 1 # see dpkg-buildflags(1) DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/default.mk %: dh $@ override_dh_auto_build: dh_auto_build -- libefence.a libefence.so.0.0 ifeq ($(filter nocheck,$(DEB_BUILD_OPTIONS)),) dh_auto_build # default make target runs tests endif work/efence.c0000664000000000000000000006251314661135731010337 0ustar /* * 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 #include #include #include #include #ifdef USE_SEMAPHORE # include # include #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 \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 #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 work/efence.h0000664000000000000000000000223414661135731010336 0ustar #include #include #include /* * 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 * . */ #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, ...); work/eftest.c0000664000000000000000000001050314661135731010374 0ustar #include #include #include #include #include #include #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; } work/libefence.30000664000000000000000000003436414661135731010751 0ustar .TH efence 3 27-April-1993 .SH NAME efence \- Electric Fence Malloc Debugger .SH SYNOPSIS .nf .ft B #include .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. work/libefence.so0000777000000000000000000000000014661135731017227 2debian/tmp/usr/lib/libefence.so.0ustar work/page.c0000664000000000000000000001007614661135731010023 0ustar #include "efence.h" #include #include #include #include #include #include #include /* * 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 (const char *) 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 work/print.c0000664000000000000000000000716414661135731010247 0ustar #include "efence.h" #include #include #include #include #include /* * 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(); } work/tstheap.c0000664000000000000000000000233014661135731010551 0ustar #include #include #include #include #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; }