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(). |