Doxygen Source Code Documentation
efence.c File Reference
#include "efence.h"#include <stdlib.h>#include <unistd.h>#include <memory.h>#include <string.h>#include <fcntl.h>#include <sys/mman.h>#include <stdio.h>#include <errno.h>#include <stdarg.h>#include <signal.h>Go to the source code of this file.
Data Structures | |
| struct | _Slot |
Defines | |
| #define | MEMORY_CREATION_SIZE 1024 * 1024 |
| #define | NUMBER_BUFFER_SIZE 64 |
Typedefs | |
| typedef enum _Mode | Mode |
| typedef _Slot | Slot |
Enumerations | |
| enum | _Mode { NOT_IN_USE = 0, FREE, ALLOCATED, PROTECTED, INTERNAL_USE } |
Functions | |
| void | internalError (void) |
| void | initialize (void) |
| void | allocateMoreSlots (void) |
| C_LINKAGE void * | memalign (size_t alignment, size_t userSize) |
| Slot * | slotForUserAddress (void *address) |
| Slot * | slotForInternalAddress (void *address) |
| Slot * | slotForInternalAddressPreviousTo (void *address) |
| C_LINKAGE void | free (void *address) |
| C_LINKAGE void * | realloc (void *oldBuffer, size_t newSize) |
| C_LINKAGE void * | malloc (size_t size) |
| C_LINKAGE void * | calloc (size_t nelem, size_t elsize) |
| C_LINKAGE void * | valloc (size_t size) |
| const char * | stringErrorReport (void) |
| void * | Page_Create (size_t size) |
| void | mprotectFailed (void) |
| void | Page_AllowAccess (void *address, size_t size) |
| void | Page_DenyAccess (void *address, size_t size) |
| void | Page_Delete (void *address, size_t size) |
| int | getpagesize () |
| size_t | Page_Size (void) |
| void | printNumber (unsigned int number, unsigned int base) |
| void | vprint (const char *pattern, va_list args) |
| void | EF_Abort (const char *pattern,...) |
| void | EF_Exit (const char *pattern,...) |
| void | EF_Print (const char *pattern,...) |
Variables | |
| const char | version [] |
| int | EF_ALIGNMENT = -1 |
| int | EF_PROTECT_FREE = -1 |
| int | EF_PROTECT_BELOW = -1 |
| int | EF_ALLOW_MALLOC_0 = -1 |
| Slot * | allocationList = 0 |
| size_t | allocationListSize = 0 |
| size_t | slotCount = 0 |
| size_t | unUsedSlots = 0 |
| size_t | slotsPerPage = 0 |
| int | internalUse = 0 |
| int | noAllocationListProtection = 0 |
| size_t | bytesPerPage = 0 |
| caddr_t | startAddr = (caddr_t) 0 |
| int | sys_nerr |
| char * | sys_errlist [] |
Define Documentation
|
|
Definition at line 53 of file efence.c. Referenced by initialize(), and memalign(). |
|
|
Definition at line 954 of file efence.c. Referenced by printNumber(). |
Typedef Documentation
|
|
Definition at line 65 of file efence.c. Referenced by main(), SUMA_CreateFileSelectionDialogStruct(), SUMA_CreatePromptDialogStruct(), and SUMA_SetCellEditMode(). |
|
|
|
Enumeration Type Documentation
|
|
Definition at line 58 of file efence.c.
00058 {
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 };
|
Function Documentation
|
|
Definition at line 306 of file efence.c. References allocationListSize, bytesPerPage, free, internalUse, malloc, noAllocationListProtection, Page_AllowAccess(), slotCount, slotsPerPage, and unUsedSlots. Referenced by memalign().
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 }
|
|
||||||||||||
|
Definition at line 751 of file efence.c. References malloc.
00752 {
00753 size_t size = nelem * elsize;
00754 void * allocation = malloc(size);
00755
00756 memset(allocation, 0, size);
00757 return allocation;
00758 }
|
|
||||||||||||
|
Definition at line 1045 of file efence.c. References args, EF_Print(), getpid(), and vprint(). Referenced by free(), internalError(), memalign(), printNumber(), and realloc().
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 }
|
|
||||||||||||
|
Definition at line 1068 of file efence.c. References args, EF_Print(), and vprint(). Referenced by mprotectFailed(), Page_Create(), and Page_Delete().
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 }
|
|
||||||||||||
|
Definition at line 1088 of file efence.c. References args, and vprint(). Referenced by EF_Abort(), EF_Exit(), initialize(), and vprint().
|
|
|
Definition at line 618 of file efence.c. References ALLOCATED, allocationListSize, EF_Abort(), FREE, INTERNAL_USE, _Slot::internalAddress, _Slot::internalSize, internalUse, _Slot::mode, noAllocationListProtection, NOT_IN_USE, Page_AllowAccess(), Page_Delete(), Page_DenyAccess(), PROTECTED, slotForInternalAddress(), slotForInternalAddressPreviousTo(), slotForUserAddress(), unUsedSlots, _Slot::userAddress, and _Slot::userSize.
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 }
|
|
|
Referenced by Page_Size(), and pagesize(). |
|
|
Definition at line 186 of file efence.c. References allocationListSize, bytesPerPage, EF_ALIGNMENT, EF_ALLOW_MALLOC_0, EF_Print(), EF_PROTECT_BELOW, EF_PROTECT_FREE, FREE, getenv(), INTERNAL_USE, _Slot::internalAddress, _Slot::internalSize, MEMORY_CREATION_SIZE, _Slot::mode, Page_Create(), Page_DenyAccess(), Page_Size(), slotCount, slotsPerPage, unUsedSlots, _Slot::userAddress, _Slot::userSize, and version. Referenced by main(), malloc(), and memalign().
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 }
|
|
|
Definition at line 176 of file efence.c. References EF_Abort(). Referenced by memalign().
00177 {
00178 EF_Abort("Internal error in allocator.");
00179 }
|
|
|
Definition at line 742 of file efence.c. References EF_ALIGNMENT, initialize(), and memalign().
00743 {
00744 if ( allocationList == 0 )
00745 initialize(); /* This sets EF_ALIGNMENT */
00746
00747 return memalign(EF_ALIGNMENT, size);
00748 }
|
|
||||||||||||
|
Definition at line 358 of file efence.c. References ALLOCATED, allocateMoreSlots(), allocationListSize, bytesPerPage, EF_Abort(), EF_ALLOW_MALLOC_0, EF_PROTECT_BELOW, FREE, initialize(), INTERNAL_USE, _Slot::internalAddress, internalError(), _Slot::internalSize, internalUse, MEMORY_CREATION_SIZE, _Slot::mode, noAllocationListProtection, NOT_IN_USE, Page_AllowAccess(), Page_Create(), Page_Delete(), Page_DenyAccess(), slotCount, unUsedSlots, _Slot::userAddress, and _Slot::userSize. Referenced by malloc(), mpeg2_malloc(), and valloc().
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 }
|
|
|
Definition at line 882 of file efence.c. References EF_Exit(), and stringErrorReport(). Referenced by Page_AllowAccess(), and Page_DenyAccess().
00883 {
00884 EF_Exit("mprotect() failed: %s", stringErrorReport());
00885 }
|
|
||||||||||||
|
Definition at line 888 of file efence.c. References mprotectFailed(). Referenced by allocateMoreSlots(), free(), memalign(), and realloc().
00889 {
00890 if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
00891 mprotectFailed();
00892 }
|
|
|
Definition at line 841 of file efence.c. References EF_Exit(), startAddr, and stringErrorReport(). Referenced by initialize(), and memalign().
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 }
|
|
||||||||||||
|
Definition at line 902 of file efence.c. References EF_Exit(), Page_DenyAccess(), and stringErrorReport(). Referenced by free(), and memalign().
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 }
|
|
||||||||||||
|
Definition at line 895 of file efence.c. References mprotectFailed(). Referenced by free(), initialize(), memalign(), Page_Delete(), and realloc().
00896 {
00897 if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
00898 mprotectFailed();
00899 }
|
|
|
Definition at line 933 of file efence.c. References getpagesize(). Referenced by initialize().
00934 {
00935 return getpagesize();
00936 }
|
|
||||||||||||
|
Definition at line 957 of file efence.c. References base, EF_Abort(), NUMBER_BUFFER_SIZE, and write(). Referenced by vprint().
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 }
|
|
||||||||||||
|
Definition at line 707 of file efence.c. References allocationListSize, EF_Abort(), free, malloc, noAllocationListProtection, Page_AllowAccess(), Page_DenyAccess(), slotForUserAddress(), and _Slot::userSize.
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 }
|
|
|
Definition at line 584 of file efence.c. References _Slot::internalAddress, and slotCount. Referenced by free().
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 }
|
|
|
Definition at line 603 of file efence.c. References _Slot::internalAddress, _Slot::internalSize, and slotCount. Referenced by free().
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 }
|
|
|
Definition at line 566 of file efence.c. References slotCount, and _Slot::userAddress. Referenced by free(), and realloc().
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 }
|
|
|
Definition at line 791 of file efence.c. References strerror(), sys_errlist, and sys_nerr. Referenced by mprotectFailed(), Page_Create(), and Page_Delete().
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 }
|
|
|
Definition at line 765 of file efence.c. References bytesPerPage, and memalign().
00766 {
00767 return memalign(bytesPerPage, size);
00768 }
|
|
||||||||||||
|
Definition at line 985 of file efence.c. References args, c, EF_Print(), printNumber(), u_int, and write(). Referenced by EF_Abort(), EF_Exit(), and EF_Print().
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 }
|
Variable Documentation
|
|
|
|
|
Definition at line 131 of file efence.c. Referenced by allocateMoreSlots(), free(), initialize(), memalign(), and realloc(). |
|
|
Definition at line 169 of file efence.c. Referenced by allocateMoreSlots(), initialize(), memalign(), and valloc(). |
|
|
Definition at line 88 of file efence.c. Referenced by initialize(), and malloc(). |
|
|
Definition at line 119 of file efence.c. Referenced by initialize(), and memalign(). |
|
|
Definition at line 113 of file efence.c. Referenced by initialize(), and memalign(). |
|
|
Definition at line 101 of file efence.c. Referenced by initialize(). |
|
|
Definition at line 155 of file efence.c. Referenced by allocateMoreSlots(), free(), and memalign(). |
|
|
Definition at line 163 of file efence.c. Referenced by allocateMoreSlots(), free(), memalign(), and realloc(). |
|
|
Definition at line 136 of file efence.c. Referenced by allocateMoreSlots(), initialize(), memalign(), slotForInternalAddress(), slotForInternalAddressPreviousTo(), and slotForUserAddress(). |
|
|
Definition at line 149 of file efence.c. Referenced by allocateMoreSlots(), and initialize(). |
|
|
extern C_LINKAGE int mprotect(caddr_t addr, size_t len, int prot); Definition at line 783 of file efence.c. Referenced by Page_Create(). |
|
|
Definition at line 787 of file efence.c. Referenced by strerror(), and stringErrorReport(). |
|
|
Definition at line 786 of file efence.c. Referenced by strerror(), and stringErrorReport(). |
|
|
Definition at line 143 of file efence.c. Referenced by allocateMoreSlots(), free(), initialize(), and memalign(). |
|
|
Initial value: "\n Electric Fence 2.0.1" " Copyright (C) 1987-1993 Bruce Perens.\n" Definition at line 45 of file efence.c. Referenced by initialize(). |