Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

efence.c

Go to the documentation of this file.
00001 /*
00002  * Electric Fence - Red-Zone memory allocator.
00003  * Bruce Perens, 1988, 1993
00004  * 
00005  * This is a special version of malloc() and company for debugging software
00006  * that is suspected of overrunning or underrunning the boundaries of a
00007  * malloc buffer, or touching free memory.
00008  *
00009  * It arranges for each malloc buffer to be followed (or preceded)
00010  * in the address space by an inaccessable virtual memory page,
00011  * and for free memory to be inaccessable. If software touches the
00012  * inaccessable page, it will get an immediate segmentation
00013  * fault. It is then trivial to uncover the offending code using a debugger.
00014  *
00015  * An advantage of this product over most malloc debuggers is that this one
00016  * detects reading out of bounds as well as writing, and this one stops on
00017  * the exact instruction that causes the error, rather than waiting until the
00018  * next boundary check.
00019  *
00020  * There is one product that debugs malloc buffer overruns
00021  * better than Electric Fence: "Purify" from Purify Systems, and that's only
00022  * a small part of what Purify does. I'm not affiliated with Purify, I just
00023  * respect a job well done.
00024  *
00025  * This version of malloc() should not be linked into production software,
00026  * since it tremendously increases the time and memory overhead of malloc().
00027  * Each malloc buffer will consume a minimum of two virtual memory pages,
00028  * this is 16 kilobytes on many systems. On some systems it will be necessary
00029  * to increase the amount of swap space in order to debug large programs that
00030  * perform lots of allocation, because of the per-buffer overhead.
00031  */
00032 
00033 #include "efence.h"
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 #include <memory.h>
00037 #include <string.h>
00038 #include <fcntl.h>
00039 #include <sys/mman.h>
00040 #include <stdio.h>
00041 #include <errno.h>
00042 #include <stdarg.h>
00043 #include <signal.h>
00044 
00045 static const char       version[] = "\n  Electric Fence 2.0.1"
00046  " Copyright (C) 1987-1993 Bruce Perens.\n";
00047 
00048 /*
00049  * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
00050  * system at one time. We'll break that memory down into smaller pieces for
00051  * malloc buffers. One megabyte is probably a good value.
00052  */
00053 #define                 MEMORY_CREATION_SIZE    1024 * 1024
00054 
00055 /*
00056  * Enum Mode indicates the status of a malloc buffer.
00057  */
00058 enum _Mode {
00059         NOT_IN_USE = 0, /* Available to represent a malloc buffer. */
00060         FREE,           /* A free buffer. */
00061         ALLOCATED,      /* A buffer that is in use. */
00062         PROTECTED,      /* A freed buffer that can not be allocated again. */
00063         INTERNAL_USE    /* A buffer used internally by malloc(). */
00064 };
00065 typedef enum _Mode      Mode;
00066 
00067 /*
00068  * Struct Slot contains all of the information about a malloc buffer except
00069  * for the contents of its memory.
00070  */
00071 struct _Slot {
00072         void *          userAddress;
00073         void *          internalAddress;
00074         size_t          userSize;
00075         size_t          internalSize;
00076         Mode            mode;
00077 };
00078 typedef struct _Slot    Slot;
00079 
00080 /*
00081  * EF_ALIGNMENT is a global variable used to control the default alignment
00082  * of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
00083  * so that its name matches the name of the environment variable that is used
00084  * to set it. This gives the programmer one less name to remember.
00085  * If the value is -1, it will be set from the environment or sizeof(int)
00086  * at run time.
00087  */
00088 int             EF_ALIGNMENT = -1;
00089 
00090 /*
00091  * EF_PROTECT_FREE is a global variable used to control the disposition of
00092  * memory that is released using free(). It is all-caps so that its name
00093  * matches the name of the environment variable that is used to set it.
00094  * If its value is greater non-zero, memory released by free is made
00095  * inaccessable and never allocated again. Any software that touches free
00096  * memory will then get a segmentation fault. If its value is zero, freed
00097  * memory will be available for reallocation, but will still be inaccessable
00098  * until it is reallocated.
00099  * If the value is -1, it will be set from the environment or to 0 at run-time.
00100  */
00101 int             EF_PROTECT_FREE = -1;
00102 
00103 /*
00104  * EF_PROTECT_BELOW is used to modify the behavior of the allocator. When
00105  * its value is non-zero, the allocator will place an inaccessable page
00106  * immediately _before_ the malloc buffer in the address space, instead
00107  * of _after_ it. Use this to detect malloc buffer under-runs, rather than
00108  * over-runs. It won't detect both at the same time, so you should test your
00109  * software twice, once with this value clear, and once with it set.
00110  * If the value is -1, it will be set from the environment or to zero at
00111  * run-time
00112  */
00113 int             EF_PROTECT_BELOW = -1;
00114 
00115 /*
00116  * EF_ALLOW_MALLOC_0 is set if Electric Fence is to allow malloc(0). I
00117  * trap malloc(0) by default because it is a common source of bugs.
00118  */
00119 int             EF_ALLOW_MALLOC_0 = -1;
00120 
00121 /*
00122  * allocationList points to the array of slot structures used to manage the
00123  * malloc arena.
00124  */
00125 static Slot *           allocationList = 0;
00126 
00127 /*
00128  * allocationListSize is the size of the allocation list. This will always
00129  * be a multiple of the page size.
00130  */
00131 static size_t           allocationListSize = 0;
00132 
00133 /*
00134  * slotCount is the number of Slot structures in allocationList.
00135  */
00136 static size_t           slotCount = 0;
00137 
00138 /*
00139  * unUsedSlots is the number of Slot structures that are currently available
00140  * to represent new malloc buffers. When this number gets too low, we will
00141  * create new slots.
00142  */
00143 static size_t           unUsedSlots = 0;
00144 
00145 /*
00146  * slotsPerPage is the number of slot structures that fit in a virtual
00147  * memory page.
00148  */
00149 static size_t           slotsPerPage = 0;
00150 
00151 /*
00152  * internalUse is set when allocating and freeing the allocatior-internal
00153  * data structures.
00154  */
00155 static int              internalUse = 0;
00156 
00157 /*
00158  * noAllocationListProtection is set to tell malloc() and free() not to
00159  * manipulate the protection of the allocation list. This is only set in
00160  * realloc(), which does it to save on slow system calls, and in
00161  * allocateMoreSlots(), which does it because it changes the allocation list.
00162  */
00163 static int              noAllocationListProtection = 0;
00164 
00165 /*
00166  * bytesPerPage is set at run-time to the number of bytes per virtual-memory
00167  * page, as returned by Page_Size().
00168  */
00169 static size_t           bytesPerPage = 0;
00170 
00171 /*
00172  * internalError is called for those "shouldn't happen" errors in the
00173  * allocator.
00174  */
00175 static void
00176 internalError(void)
00177 {
00178         EF_Abort("Internal error in allocator.");
00179 }
00180 
00181 /*
00182  * initialize sets up the memory allocation arena and the run-time
00183  * configuration information.
00184  */
00185 static void
00186 initialize(void)
00187 {
00188         size_t  size = MEMORY_CREATION_SIZE;
00189         size_t  slack;
00190         char *  string;
00191         Slot *  slot;
00192 
00193         EF_Print(version);
00194 
00195         /*
00196          * Import the user's environment specification of the default
00197          * alignment for malloc(). We want that alignment to be under
00198          * user control, since smaller alignment lets us catch more bugs,
00199          * however some software will break if malloc() returns a buffer
00200          * that is not word-aligned.
00201          *
00202          * I would like
00203          * alignment to be zero so that we could catch all one-byte
00204          * overruns, however if malloc() is asked to allocate an odd-size
00205          * buffer and returns an address that is not word-aligned, or whose
00206          * size is not a multiple of the word size, software breaks.
00207          * This was the case with the Sun string-handling routines,
00208          * which can do word fetches up to three bytes beyond the end of a
00209          * string. I handle this problem in part by providing
00210          * byte-reference-only versions of the string library functions, but
00211          * there are other functions that break, too. Some in X Windows, one
00212          * in Sam Leffler's TIFF library, and doubtless many others.
00213          */
00214         if ( EF_ALIGNMENT == -1 ) {
00215                 if ( (string = getenv("EF_ALIGNMENT")) != 0 )
00216                         EF_ALIGNMENT = (size_t)atoi(string);
00217                 else
00218                         EF_ALIGNMENT = sizeof(int);
00219         }
00220 
00221         /*
00222          * See if the user wants to protect the address space below a buffer,
00223          * rather than that above a buffer.
00224          */
00225         if ( EF_PROTECT_BELOW == -1 ) {
00226                 if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
00227                         EF_PROTECT_BELOW = (atoi(string) != 0);
00228                 else
00229                         EF_PROTECT_BELOW = 0;
00230         }
00231 
00232         /*
00233          * See if the user wants to protect memory that has been freed until
00234          * the program exits, rather than until it is re-allocated.
00235          */
00236         if ( EF_PROTECT_FREE == -1 ) {
00237                 if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
00238                         EF_PROTECT_FREE = (atoi(string) != 0);
00239                 else
00240                         EF_PROTECT_FREE = 0;
00241         }
00242 
00243         /*
00244          * See if the user wants to allow malloc(0).
00245          */
00246         if ( EF_ALLOW_MALLOC_0 == -1 ) {
00247                 if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
00248                         EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
00249                 else
00250                         EF_ALLOW_MALLOC_0 = 0;
00251         }
00252 
00253         /*
00254          * Get the run-time configuration of the virtual memory page size.
00255          */
00256         bytesPerPage = Page_Size();
00257 
00258         /*
00259          * Figure out how many Slot structures to allocate at one time.
00260          */
00261         slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
00262         allocationListSize = bytesPerPage;
00263 
00264         if ( allocationListSize > size )
00265                 size = allocationListSize;
00266 
00267         if ( (slack = size % bytesPerPage) != 0 )
00268                 size += bytesPerPage - slack;
00269 
00270         /*
00271          * Allocate memory, and break it up into two malloc buffers. The
00272          * first buffer will be used for Slot structures, the second will
00273          * be marked free.
00274          */
00275         slot = allocationList = (Slot *)Page_Create(size);
00276         memset((char *)allocationList, 0, allocationListSize);
00277 
00278         slot[0].internalSize = slot[0].userSize = allocationListSize;
00279         slot[0].internalAddress = slot[0].userAddress = allocationList;
00280         slot[0].mode = INTERNAL_USE;
00281         if ( size > allocationListSize ) {
00282                 slot[1].internalAddress = slot[1].userAddress
00283                  = ((char *)slot[0].internalAddress) + slot[0].internalSize;
00284                 slot[1].internalSize
00285                  = slot[1].userSize = size - slot[0].internalSize;
00286                 slot[1].mode = FREE;
00287         }
00288 
00289         /*
00290          * Deny access to the free page, so that we will detect any software
00291          * that treads upon free memory.
00292          */
00293         Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);
00294 
00295         /*
00296          * Account for the two slot structures that we've used.
00297          */
00298         unUsedSlots = slotCount - 2;
00299 }
00300 
00301 /*
00302  * allocateMoreSlots is called when there are only enough slot structures
00303  * left to support the allocation of a single malloc buffer.
00304  */
00305 static void
00306 allocateMoreSlots(void)
00307 {
00308         size_t  newSize = allocationListSize + bytesPerPage;
00309         void *  newAllocation;
00310         void *  oldAllocation = allocationList;
00311 
00312         Page_AllowAccess(allocationList, allocationListSize);
00313         noAllocationListProtection = 1;
00314         internalUse = 1;
00315 
00316         newAllocation = malloc(newSize);
00317         memcpy(newAllocation, allocationList, allocationListSize);
00318         memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
00319 
00320         allocationList = (Slot *)newAllocation;
00321         allocationListSize = newSize;
00322         slotCount += slotsPerPage;
00323         unUsedSlots += slotsPerPage;
00324 
00325         free(oldAllocation);
00326 
00327         /*
00328          * Keep access to the allocation list open at this point, because
00329          * I am returning to memalign(), which needs that access.
00330          */
00331         noAllocationListProtection = 0;
00332         internalUse = 0;
00333 }
00334 
00335 /*
00336  * This is the memory allocator. When asked to allocate a buffer, allocate
00337  * it in such a way that the end of the buffer is followed by an inaccessable
00338  * memory page. If software overruns that buffer, it will touch the bad page
00339  * and get an immediate segmentation fault. It's then easy to zero in on the
00340  * offending code with a debugger.
00341  *
00342  * There are a few complications. If the user asks for an odd-sized buffer,
00343  * we would have to have that buffer start on an odd address if the byte after
00344  * the end of the buffer was to be on the inaccessable page. Unfortunately,
00345  * there is lots of software that asks for odd-sized buffers and then
00346  * requires that the returned address be word-aligned, or the size of the
00347  * buffer be a multiple of the word size. An example are the string-processing
00348  * functions on Sun systems, which do word references to the string memory
00349  * and may refer to memory up to three bytes beyond the end of the string.
00350  * For this reason, I take the alignment requests to memalign() and valloc()
00351  * seriously, and 
00352  * 
00353  * Electric Fence wastes lots of memory. I do a best-fit allocator here
00354  * so that it won't waste even more. It's slow, but thrashing because your
00355  * working set is too big for a system's RAM is even slower. 
00356  */
00357 extern C_LINKAGE void *
00358 memalign(size_t alignment, size_t userSize)
00359 {
00360         register Slot * slot;
00361         register size_t count;
00362         Slot *          fullSlot = 0;
00363         Slot *          emptySlots[2];
00364         size_t          internalSize;
00365         size_t          slack;
00366         char *          address;
00367 
00368 
00369         if ( allocationList == 0 )
00370                 initialize();
00371 
00372         if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
00373                 EF_Abort("Allocating 0 bytes, probably a bug.");
00374 
00375         /*
00376          * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
00377          * and company will be page-aligned.
00378          */
00379         if ( !EF_PROTECT_BELOW && alignment > 1 ) {
00380                 if ( (slack = userSize % alignment) != 0 )
00381                         userSize += alignment - slack;
00382         }
00383 
00384         /*
00385          * The internal size of the buffer is rounded up to the next page-size
00386          * boudary, and then we add another page's worth of memory for the
00387          * dead page.
00388          */
00389         internalSize = userSize + bytesPerPage;
00390         if ( (slack = internalSize % bytesPerPage) != 0 )
00391                 internalSize += bytesPerPage - slack;
00392 
00393         /*
00394          * These will hold the addresses of two empty Slot structures, that
00395          * can be used to hold information for any memory I create, and any
00396          * memory that I mark free.
00397          */
00398         emptySlots[0] = 0;
00399         emptySlots[1] = 0;
00400 
00401         /*
00402          * The internal memory used by the allocator is currently
00403          * inaccessable, so that errant programs won't scrawl on the
00404          * allocator's arena. I'll un-protect it here so that I can make
00405          * a new allocation. I'll re-protect it before I return.
00406          */
00407         if ( !noAllocationListProtection )
00408                 Page_AllowAccess(allocationList, allocationListSize);
00409 
00410         /*
00411          * If I'm running out of empty slots, create some more before
00412          * I don't have enough slots left to make an allocation.
00413          */
00414         if ( !internalUse && unUsedSlots < 7 ) {
00415                 allocateMoreSlots();
00416         }
00417         
00418         /*
00419          * Iterate through all of the slot structures. Attempt to find a slot
00420          * containing free memory of the exact right size. Accept a slot with
00421          * more memory than we want, if the exact right size is not available.
00422          * Find two slot structures that are not in use. We will need one if
00423          * we split a buffer into free and allocated parts, and the second if
00424          * we have to create new memory and mark it as free.
00425          *
00426          */
00427         
00428         for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
00429                 if ( slot->mode == FREE
00430                  && slot->internalSize >= internalSize ) {
00431                         if ( !fullSlot
00432                          ||slot->internalSize < fullSlot->internalSize){
00433                                 fullSlot = slot;
00434                                 if ( slot->internalSize == internalSize
00435                                  && emptySlots[0] )
00436                                         break;  /* All done, */
00437                         }
00438                 }
00439                 else if ( slot->mode == NOT_IN_USE ) {
00440                         if ( !emptySlots[0] )
00441                                 emptySlots[0] = slot;
00442                         else if ( !emptySlots[1] )
00443                                 emptySlots[1] = slot;
00444                         else if ( fullSlot
00445                          && fullSlot->internalSize == internalSize )
00446                                 break;  /* All done. */
00447                 }
00448                 slot++;
00449         }
00450         if ( !emptySlots[0] )
00451                 internalError();
00452 
00453         if ( !fullSlot ) {
00454                 /*
00455                  * I get here if I haven't been able to find a free buffer
00456                  * with all of the memory I need. I'll have to create more
00457                  * memory. I'll mark it all as free, and then split it into
00458                  * free and allocated portions later.
00459                  */
00460                 size_t  chunkSize = MEMORY_CREATION_SIZE;
00461 
00462                 if ( !emptySlots[1] )
00463                         internalError();
00464 
00465                 if ( chunkSize < internalSize )
00466                         chunkSize = internalSize;
00467 
00468                 if ( (slack = chunkSize % bytesPerPage) != 0 )
00469                         chunkSize += bytesPerPage - slack;
00470 
00471                 /* Use up one of the empty slots to make the full slot. */
00472                 fullSlot = emptySlots[0];
00473                 emptySlots[0] = emptySlots[1];
00474                 fullSlot->internalAddress = Page_Create(chunkSize);
00475                 fullSlot->internalSize = chunkSize;
00476                 fullSlot->mode = FREE;
00477                 unUsedSlots--;
00478         }
00479 
00480         /*
00481          * If I'm allocating memory for the allocator's own data structures,
00482          * mark it INTERNAL_USE so that no errant software will be able to
00483          * free it.
00484          */
00485         if ( internalUse )
00486                 fullSlot->mode = INTERNAL_USE;
00487         else
00488                 fullSlot->mode = ALLOCATED;
00489 
00490         /*
00491          * If the buffer I've found is larger than I need, split it into
00492          * an allocated buffer with the exact amount of memory I need, and
00493          * a free buffer containing the surplus memory.
00494          */
00495         if ( fullSlot->internalSize > internalSize ) {
00496                 emptySlots[0]->internalSize
00497                  = fullSlot->internalSize - internalSize;
00498                 emptySlots[0]->internalAddress
00499                  = ((char *)fullSlot->internalAddress) + internalSize;
00500                 emptySlots[0]->mode = FREE;
00501                 fullSlot->internalSize = internalSize;
00502                 unUsedSlots--;
00503         }
00504 
00505         if ( !EF_PROTECT_BELOW ) {
00506                 /*
00507                  * Arrange the buffer so that it is followed by an inaccessable
00508                  * memory page. A buffer overrun that touches that page will
00509                  * cause a segmentation fault.
00510                  */
00511                 address = (char *)fullSlot->internalAddress;
00512 
00513                 /* Set up the "live" page. */
00514                 Page_AllowAccess(
00515                  fullSlot->internalAddress
00516                 ,internalSize - bytesPerPage);
00517                         
00518                 address += internalSize - bytesPerPage;
00519 
00520                 /* Set up the "dead" page. */
00521                 if ( EF_PROTECT_FREE )
00522                         Page_Delete(address, bytesPerPage);
00523                 else
00524                         Page_DenyAccess(address, bytesPerPage);
00525 
00526                 /* Figure out what address to give the user. */
00527                 address -= userSize;
00528         }
00529         else {  /* EF_PROTECT_BELOW != 0 */
00530                 /*
00531                  * Arrange the buffer so that it is preceded by an inaccessable
00532                  * memory page. A buffer underrun that touches that page will
00533                  * cause a segmentation fault.
00534                  */
00535                 address = (char *)fullSlot->internalAddress;
00536 
00537                 /* Set up the "dead" page. */
00538                 if ( EF_PROTECT_FREE )
00539                         Page_Delete(address, bytesPerPage);
00540                 else
00541                         Page_DenyAccess(address, bytesPerPage);
00542                         
00543                 address += bytesPerPage;
00544 
00545                 /* Set up the "live" page. */
00546                 Page_AllowAccess(address, internalSize - bytesPerPage);
00547         }
00548 
00549         fullSlot->userAddress = address;
00550         fullSlot->userSize = userSize;
00551 
00552         /*
00553          * Make the pool's internal memory inaccessable, so that the program
00554          * being debugged can't stomp on it.
00555          */
00556         if ( !internalUse )
00557                 Page_DenyAccess(allocationList, allocationListSize);
00558 
00559         return address;
00560 }
00561 
00562 /*
00563  * Find the slot structure for a user address.
00564  */
00565 static Slot *
00566 slotForUserAddress(void * address)
00567 {
00568         register Slot * slot = allocationList;
00569         register size_t count = slotCount;
00570         
00571         for ( ; count > 0; count-- ) {
00572                 if ( slot->userAddress == address )
00573                         return slot;
00574                 slot++;
00575         }
00576 
00577         return 0;
00578 }
00579 
00580 /*
00581  * Find the slot structure for an internal address.
00582  */
00583 static Slot *
00584 slotForInternalAddress(void * address)
00585 {
00586         register Slot * slot = allocationList;
00587         register size_t count = slotCount;
00588         
00589         for ( ; count > 0; count-- ) {
00590                 if ( slot->internalAddress == address )
00591                         return slot;
00592                 slot++;
00593         }
00594         return 0;
00595 }
00596 
00597 /*
00598  * Given the internal address of a buffer, find the buffer immediately
00599  * before that buffer in the address space. This is used by free() to
00600  * coalesce two free buffers into one.
00601  */
00602 static Slot *
00603 slotForInternalAddressPreviousTo(void * address)
00604 {
00605         register Slot * slot = allocationList;
00606         register size_t count = slotCount;
00607         
00608         for ( ; count > 0; count-- ) {
00609                 if ( ((char *)slot->internalAddress)
00610                  + slot->internalSize == address )
00611                         return slot;
00612                 slot++;
00613         }
00614         return 0;
00615 }
00616 
00617 extern C_LINKAGE void
00618 free(void * address)
00619 {
00620         Slot *  slot;
00621         Slot *  previousSlot = 0;
00622         Slot *  nextSlot = 0;
00623 
00624         if ( address == 0 )
00625                 EF_Abort("free() called for address zero.");
00626 
00627         if ( allocationList == 0 )
00628                 EF_Abort("free() called before first malloc().");
00629 
00630         if ( !noAllocationListProtection )
00631                 Page_AllowAccess(allocationList, allocationListSize);
00632 
00633         slot = slotForUserAddress(address);
00634 
00635         if ( !slot )
00636                 EF_Abort("free(%x): address not from malloc().", address);
00637 
00638         if ( slot->mode != ALLOCATED ) {
00639                 if ( internalUse && slot->mode == INTERNAL_USE )
00640                         /* Do nothing. */;
00641                 else {
00642                         EF_Abort(
00643                          "free(%x): freeing free memory."
00644                         ,address);
00645                 }
00646         }
00647 
00648         if ( EF_PROTECT_FREE )
00649                 slot->mode = PROTECTED;
00650         else
00651                 slot->mode = FREE;
00652 
00653         previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
00654         nextSlot = slotForInternalAddress(
00655          ((char *)slot->internalAddress) + slot->internalSize);
00656 
00657         if ( previousSlot
00658          && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
00659                 /* Coalesce previous slot with this one. */
00660                 previousSlot->internalSize += slot->internalSize;
00661                 if ( EF_PROTECT_FREE )
00662                         previousSlot->mode = PROTECTED;
00663 
00664                 slot->internalAddress = slot->userAddress = 0;
00665                 slot->internalSize = slot->userSize = 0;
00666                 slot->mode = NOT_IN_USE;
00667                 slot = previousSlot;
00668                 unUsedSlots++;
00669         }
00670         if ( nextSlot
00671          && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
00672                 /* Coalesce next slot with this one. */
00673                 slot->internalSize += nextSlot->internalSize;
00674                 nextSlot->internalAddress = nextSlot->userAddress = 0;
00675                 nextSlot->internalSize = nextSlot->userSize = 0;
00676                 nextSlot->mode = NOT_IN_USE;
00677                 unUsedSlots++;
00678         }
00679 
00680         slot->userAddress = slot->internalAddress;
00681         slot->userSize = slot->internalSize;
00682 
00683         /*
00684          * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
00685          * is true, free memory is never reallocated, so it remains access
00686          * denied for the life of the process. When EF_PROTECT_FREE is false, 
00687          * the memory may be re-allocated, at which time access to it will be
00688          * allowed again.
00689          *
00690          * Some operating systems allow munmap() with single-page resolution,
00691          * and allow you to un-map portions of a region, rather than the
00692          * entire region that was mapped with mmap(). On those operating
00693          * systems, we can release protected free pages with Page_Delete(),
00694          * in the hope that the swap space attached to those pages will be
00695          * released as well.
00696          */
00697         if ( EF_PROTECT_FREE )
00698             Page_Delete(slot->internalAddress, slot->internalSize);
00699         else
00700             Page_DenyAccess(slot->internalAddress, slot->internalSize);
00701 
00702         if ( !noAllocationListProtection )
00703                 Page_DenyAccess(allocationList, allocationListSize);
00704 }
00705 
00706 extern C_LINKAGE void *
00707 realloc(void * oldBuffer, size_t newSize)
00708 {
00709         size_t  size;
00710         Slot *  slot;
00711         void *  newBuffer = malloc(newSize);
00712 
00713         if ( allocationList == 0 )
00714                 EF_Abort("realloc() called before first malloc().");
00715 
00716         Page_AllowAccess(allocationList, allocationListSize);
00717         noAllocationListProtection = 1;
00718         
00719         slot = slotForUserAddress(oldBuffer);
00720 
00721         if ( slot == 0 )
00722                 EF_Abort("free(%x): not from malloc().", oldBuffer);
00723 
00724         if ( newSize < (size = slot->userSize) )
00725                 size = newSize;
00726 
00727         if ( size > 0 )
00728                 memcpy(newBuffer, oldBuffer, size);
00729 
00730         free(oldBuffer);
00731         noAllocationListProtection = 0;
00732         Page_DenyAccess(allocationList, allocationListSize);
00733 
00734         if ( size < newSize )
00735                 memset(&(((char *)newBuffer)[size]), 0, newSize - size);
00736         
00737         /* Internal memory was re-protected in free() */
00738         return newBuffer;
00739 }
00740 
00741 extern C_LINKAGE void *
00742 malloc(size_t size)
00743 {
00744         if ( allocationList == 0 )
00745                 initialize();   /* This sets EF_ALIGNMENT */
00746 
00747         return memalign(EF_ALIGNMENT, size);
00748 }
00749 
00750 extern C_LINKAGE void *
00751 calloc(size_t nelem, size_t elsize)
00752 {
00753         size_t  size = nelem * elsize;
00754         void *  allocation = malloc(size);
00755 
00756         memset(allocation, 0, size);
00757         return allocation;
00758 }
00759 
00760 /*
00761  * This will catch more bugs if you remove the page alignment, but it
00762  * will break some software.
00763  */
00764 extern C_LINKAGE void *
00765 valloc (size_t size)
00766 {
00767         return memalign(bytesPerPage, size);
00768 }
00769 
00770 /**********************************************************************
00771    Below here is the original page.c
00772 ***********************************************************************/
00773 
00774 /*
00775  * For some reason, I can't find mprotect() in any of the headers on
00776  * IRIX or SunOS 4.1.2
00777  */
00778 
00779 /**
00780 extern C_LINKAGE int mprotect(caddr_t addr, size_t len, int prot);
00781 **/
00782 
00783 static caddr_t  startAddr = (caddr_t) 0;
00784 
00785 #if ( !defined(sgi) && !defined(_AIX) )
00786 extern int      sys_nerr;
00787 extern char *   sys_errlist[];
00788 #endif
00789 
00790 static const char *
00791 stringErrorReport(void)
00792 {
00793 #if ( defined(sgi) )
00794         return strerror(oserror());
00795 #elif ( defined(_AIX) )
00796         return strerror(errno);
00797 #else
00798         if ( errno > 0 && errno < sys_nerr )
00799                 return sys_errlist[errno];
00800         else
00801                 return "Unknown error.\n";
00802 #endif
00803 }
00804 
00805 /*
00806  * Create memory.
00807  */
00808 #if defined(MAP_ANONYMOUS)
00809 void *
00810 Page_Create(size_t size)
00811 {
00812         caddr_t         allocation;
00813 
00814         /*
00815          * In this version, "startAddr" is a _hint_, not a demand.
00816          * When the memory I map here is contiguous with other
00817          * mappings, the allocator can coalesce the memory from two
00818          * or more mappings into one large contiguous chunk, and thus
00819          * might be able to find a fit that would not otherwise have
00820          * been possible. I could _force_ it to be contiguous by using
00821          * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
00822          * generated by other software, etc.
00823          */
00824         allocation = mmap(
00825          startAddr
00826         ,(int)size
00827         ,PROT_READ|PROT_WRITE
00828         ,MAP_PRIVATE|MAP_ANONYMOUS
00829         ,-1
00830         ,0);
00831 
00832         startAddr = allocation + size;
00833 
00834         if ( allocation == (caddr_t)-1 )
00835                 EF_Exit("mmap() failed: %s", stringErrorReport());
00836 
00837         return (void *)allocation;
00838 }
00839 #else
00840 void *
00841 Page_Create(size_t size)
00842 {
00843         static int      devZeroFd = -1;
00844         caddr_t         allocation;
00845 
00846         if ( devZeroFd == -1 ) {
00847                 devZeroFd = open("/dev/zero", O_RDWR);
00848                 if ( devZeroFd < 0 )
00849                         EF_Exit(
00850                          "open() on /dev/zero failed: %s"
00851                         ,stringErrorReport());
00852         }
00853 
00854         /*
00855          * In this version, "startAddr" is a _hint_, not a demand.
00856          * When the memory I map here is contiguous with other
00857          * mappings, the allocator can coalesce the memory from two
00858          * or more mappings into one large contiguous chunk, and thus
00859          * might be able to find a fit that would not otherwise have
00860          * been possible. I could _force_ it to be contiguous by using
00861          * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
00862          * generated by other software, etc.
00863          */
00864         allocation = mmap(
00865          startAddr
00866         ,(int)size
00867         ,PROT_READ|PROT_WRITE
00868         ,MAP_PRIVATE
00869         ,devZeroFd
00870         ,0);
00871 
00872         startAddr = allocation + size;
00873 
00874         if ( allocation == (caddr_t)-1 )
00875                 EF_Exit("mmap() failed: %s", stringErrorReport());
00876 
00877         return (void *)allocation;
00878 }
00879 #endif
00880 
00881 static void
00882 mprotectFailed(void)
00883 {
00884         EF_Exit("mprotect() failed: %s", stringErrorReport());
00885 }
00886 
00887 void
00888 Page_AllowAccess(void * address, size_t size)
00889 {
00890         if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
00891                 mprotectFailed();
00892 }
00893 
00894 void
00895 Page_DenyAccess(void * address, size_t size)
00896 {
00897         if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
00898                 mprotectFailed();
00899 }
00900 
00901 void
00902 Page_Delete(void * address, size_t size)
00903 {
00904 /*
00905  * My SGI ONYX running IRIX 5.0 crashes reliably when "tstheap 3072" is
00906  * run with the munmap call below compiled in. I'd like to hear how well
00907  * other operating systems handle it, so that I can enable it on those
00908  * systems.
00909  */
00910 #if ( defined(_AIX) )
00911         if ( munmap((caddr_t)address, size) < 0 )
00912                 EF_Exit("munmap() failed: %s", stringErrorReport());
00913 #else
00914         Page_DenyAccess(address, size);
00915 #endif
00916 }
00917 
00918 #if defined(_SC_PAGESIZE)
00919 size_t
00920 Page_Size(void)
00921 {
00922         return (size_t)sysconf(_SC_PAGESIZE);
00923 }
00924 #elif defined(_SC_PAGE_SIZE)
00925 size_t
00926 Page_Size(void)
00927 {
00928         return (size_t)sysconf(_SC_PAGE_SIZE);
00929 }
00930 #else
00931 extern int      getpagesize();
00932 size_t
00933 Page_Size(void)
00934 {
00935         return getpagesize();
00936 }
00937 #endif
00938 
00939 /***********************************************************************
00940   Below here is the original print.c
00941 ************************************************************************/
00942 
00943 /*
00944  * These routines do their printing without using stdio. Stdio can't
00945  * be used because it calls malloc(). Internal routines of a malloc()
00946  * debugger should not re-enter malloc(), so stdio is out.
00947  */
00948 
00949 /*
00950  * NUMBER_BUFFER_SIZE is the longest character string that could be needed
00951  * to represent an unsigned integer. Assuming unsigned integers might be as
00952  * large as 64 bits, and we might print in base 2, let's set it to 64 bytes.
00953  */
00954 #define NUMBER_BUFFER_SIZE      64
00955 
00956 static void
00957 printNumber(unsigned int number, unsigned int base)
00958 {
00959         char            buffer[NUMBER_BUFFER_SIZE];
00960         char *          s = &buffer[NUMBER_BUFFER_SIZE];
00961         int             size;
00962         
00963         do {
00964                 unsigned int    digit;
00965 
00966                 if ( --s == buffer )
00967                         EF_Abort("Internal error printing number.");
00968 
00969                 digit = number % base;
00970 
00971                 if ( digit < 10 )
00972                         *s = '0' + digit;
00973                 else
00974                         *s = 'a' + digit - 10;
00975 
00976         } while ( (number /= base) > 0 );
00977 
00978         size = &buffer[NUMBER_BUFFER_SIZE] - s;
00979 
00980         if ( size > 0 )
00981                 write(2, s, size);
00982 }
00983 
00984 static void
00985 vprint(const char * pattern, va_list args)
00986 {
00987         static const char       bad_pattern[] =
00988          "\nBad pattern specifier %%%c in EF_Print().\n";
00989         const char *    s = pattern;
00990         char            c;
00991 
00992         while ( (c = *s++) != '\0' ) {
00993                 if ( c == '%' ) {
00994                         c = *s++;
00995                         switch ( c ) {
00996                         case '%':
00997                                 (void) write(2, &c, 1);
00998                                 break;
00999                         case 's':
01000                                 {
01001                                         const char *    string;
01002                                         size_t          length;
01003 
01004                                         string = va_arg(args, char *);
01005                                         length = strlen(string);
01006 
01007                                         (void) write(2, string, length);
01008                                 }
01009                                 break;
01010                         case 'd':
01011                                 {
01012                                         int     n = va_arg(args, int);
01013 
01014                                         if ( n < 0 ) {
01015                                                 char    c = '-';
01016                                                 write(2, &c, 1);
01017                                                 n = -n;
01018                                         }
01019                                         printNumber(n, 10);
01020                                 }
01021                                 break;
01022                         case 'x':
01023                                 printNumber(va_arg(args, u_int), 0x10);
01024                                 break;
01025                         case 'c':
01026                                 {
01027                                         char    c = va_arg(args, char);
01028                                         
01029                                         (void) write(2, &c, 1);
01030                                 }
01031                                 break;
01032                         default:
01033                                 {
01034                                         EF_Print(bad_pattern, c);
01035                                 }
01036                 
01037                         }
01038                 }
01039                 else
01040                         (void) write(2, &c, 1);
01041         }
01042 }
01043 
01044 void
01045 EF_Abort(const char * pattern, ...)
01046 {
01047         va_list args;
01048 
01049         va_start(args, pattern);
01050 
01051         EF_Print("\nElectricFence Aborting: ");
01052         vprint(pattern, args);
01053         EF_Print("\n");
01054 
01055         va_end(args);
01056 
01057         /*
01058          * I use kill(getpid(), SIGILL) instead of abort() because some
01059          * mis-guided implementations of abort() flush stdio, which can
01060          * cause malloc() or free() to be called.
01061          */
01062         kill(getpid(), SIGILL);
01063         /* Just in case something handles SIGILL and returns, exit here. */
01064         _exit(-1);
01065 }
01066 
01067 void
01068 EF_Exit(const char * pattern, ...)
01069 {
01070         va_list args;
01071 
01072         va_start(args, pattern);
01073 
01074         EF_Print("\nElectricFence Exiting: ");
01075         vprint(pattern, args);
01076         EF_Print("\n");
01077 
01078         va_end(args);
01079 
01080         /*
01081          * I use _exit() because the regular exit() flushes stdio,
01082          * which may cause malloc() or free() to be called.
01083          */
01084         _exit(-1);
01085 }
01086 
01087 void
01088 EF_Print(const char * pattern, ...)
01089 {
01090         va_list args;
01091 
01092         va_start(args, pattern);
01093         vprint(pattern, args);
01094         va_end(args);
01095 }
 

Powered by Plone

This site conforms to the following standards: