/* * ---------------------------------------------------------------- * Night Light Memory Allocation Library Functions (memcalls.c) * ---------------------------------------------------------------- * Copyright (C) 1997-2007 Jonas Kvinge * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Last modified by: * Jonas Kvinge (04.10.2006) * */ #define MEMCALLS_C #define LIBRARY #define NEED_SYS_TYPES_H 1 /* Extra types */ #define NEED_SYS_PARAM_H 1 /* Some systems need this */ #define NEED_LIMITS_H 0 /* Kernel limits */ #define NEED_STDARG_H 1 /* va_list, etc */ #define NEED_ERRNO_H 1 /* errno */ #define NEED_CTYPE_H 1 /* isdigit(), etc */ #define NEED_NETINET_IN_H 0 /* in_addr, sockaddr_in, etc */ #define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */ #define NEED_STDIO_H 1 /* Standard C UNIX functions */ #define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */ #define NEED_TIME_H 1 /* time(), etc */ #define NEED_SYSCTL_H 0 /* sysctl(), etc */ #define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */ #define NEED_SYS_UIO_H 0 /* iovec, etc */ #define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */ #define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */ #define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */ #define NEED_UNISTD_H 1 /* Unix standard functions */ #define NEED_STRING_H 1 /* C string functions */ #define NEED_SIGNAL_H 0 /* Signal functions */ #define NEED_SYS_SOCKET_H 0 /* Socket functions */ #define NEED_NETDB_H 0 /* Network database functions */ #define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */ #define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */ #include "config.h" #include "headers.h" #include "defines.h" #include "memcalls_int.h" #ifdef MALLOC_REDEFINE #error "Sanity check: malloc() can't be redefined in here!" #endif /* VARIABLES - JONAS (21.09.2001) */ struct MemTable_Struct *MemTable_Head = NULL; struct MemTable_Struct *MemTable_Tail = NULL; unsigned long int G_Allocations = 0; struct MemTable_Struct *MemHashTable[MALLOC_HASH_SIZE] = { NULL }; size_t MemPrefixSize = (const size_t) sizeof(MALLOC_PREFIX); size_t MemPostfixSize = (const size_t) sizeof(MALLOC_POSTFIX); unsigned short int IgnoreWildPTR = FALSE; /* MEMTABLE_ADD - JONAS (21.09.2001) */ void memtable_add(const void *const PTR, const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, const size_t Size) { struct MemTable_Struct *MemTableS = NULL; struct MemTable_Struct *MemTableS_NEW = NULL; unsigned long int Hash = 0; assert(PTR != NULL); assert(FilePT != NULL); assert(FunctionPT != NULL); MemTableS_NEW = malloc(sizeof(struct MemTable_Struct)); if (MemTableS_NEW == NULL) { return; } memset(MemTableS_NEW, 0, sizeof(struct MemTable_Struct)); MemTableS_NEW->PTR = (const void *const) PTR; MemTableS_NEW->File = (const char *const) FilePT; MemTableS_NEW->Line = (const unsigned short int) Line; MemTableS_NEW->Function = (const char *const) FunctionPT; MemTableS_NEW->Size = Size; MemTableS_NEW->Time = NOW; if (MemTable_Head == NULL) { MemTable_Head = MemTableS_NEW; MemTable_Tail = MemTableS_NEW; } else { MemTableS = MemTable_Tail; MemTableS->Next = MemTableS_NEW; MemTableS_NEW->Prev = MemTableS; MemTable_Tail = MemTableS_NEW; } Hash = MallocHash(PTR); if (MemHashTable[Hash] == NULL) { MemHashTable[Hash] = MemTableS_NEW; } else { for (MemTableS = MemHashTable[Hash] ; (MemTableS->NextH != NULL) ; MemTableS = MemTableS->NextH); MemTableS->NextH = MemTableS_NEW; MemTableS_NEW->PrevH = MemTableS; } G_Allocations++; #ifdef DEBUGPRINT DEBUGPRINT(BITMASK_DEBUG_MEMORY, "%s() - Pointer: %p - File: %s - Line: %d - Function: %s", __FUNCTION__, PTR, FilePT, Line, FunctionPT); #endif } /* MEMTABLE_REM - JONAS (21.09.2001) */ void memtable_rem(struct MemTable_Struct *MemTableS) { struct MemTable_Struct *MemTableH = NULL; unsigned long int Hash = 0; assert(MemTableS != NULL); if (MemTableS->Prev == NULL) { MemTable_Head = MemTableS->Next; } else { MemTableS->Prev->Next = MemTableS->Next; } if (MemTableS->Next == NULL) { MemTable_Tail = MemTableS->Prev; } else { MemTableS->Next->Prev = MemTableS->Prev; } Hash = MallocHash(MemTableS->PTR); for (MemTableH = MemHashTable[Hash] ; ((MemTableH != NULL) && (MemTableH != MemTableS)) ; MemTableH = MemTableH->NextH); assert(MemTableH == MemTableS); if (MemTableH->PrevH != NULL) { MemTableH->PrevH->NextH = MemTableH->NextH; } if (MemTableH->NextH != NULL) { MemTableH->NextH->PrevH = MemTableH->PrevH; } if (MemHashTable[Hash] == MemTableH) { MemHashTable[Hash] = MemTableH->NextH; } G_Allocations--; #ifdef DEBUGPRINT DEBUGPRINT(BITMASK_DEBUG_MEMORY, "%s() - Pointer: %p - File: %s - Line: %d - Function: %s", __FUNCTION__, MemTableS->PTR, MemTableS->File, MemTableS->Line, MemTableS->Function); #endif free(MemTableS); } /* MEMTABLE_GET - JONAS (21.09.2001) */ struct MemTable_Struct *memtable_get(const void *const PTR) { struct MemTable_Struct *MemTableH = MemHashTable[MallocHash(PTR)]; while ((MemTableH != NULL) && (PTR != MemTableH->PTR)) { MemTableH = MemTableH->NextH; } return(MemTableH); } /* MEMALLOC - JONAS (21.09.2001) */ void *memalloc(const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, const size_t MemSize) { void *MemPTR = NULL; void *PrefixPTR = NULL; void *PostfixPTR = NULL; size_t RealSize = MemSize + MemPrefixSize + MemPostfixSize; #ifdef DEBUGPRINT DEBUGPRINT(BITMASK_DEBUG_MEMORY, "%s() - File: %s - Line: %d - Function: %s - Size: %ld", __FUNCTION__, FilePT, Line, FunctionPT, (PRINT_SIZE_T) MemSize); #endif if (MemSize > MALLOC_LIMIT) { fprintf(stderr, "ERROR: Memory request to large from function %s() (%s:%d) (%ld bytes).\n", FunctionPT, FilePT, Line, (PRINT_SIZE_T) MemSize); return(NULL); } PrefixPTR = malloc(RealSize); if (PrefixPTR == NULL) { fprintf(stderr, "ERROR: Memory allocation failure in function %s() (%s:%d): %ld bytes: [%d] %s\n", FunctionPT, FilePT, Line, (PRINT_SIZE_T) MemSize, errno, strerror(errno)); return(NULL); } memset(PrefixPTR, 0, RealSize); PostfixPTR = PrefixPTR + MemPrefixSize + MemSize; MemPTR = PrefixPTR + MemPrefixSize; strcpy(PrefixPTR, MALLOC_PREFIX); strcpy(PostfixPTR, MALLOC_POSTFIX); memtable_add(MemPTR, FilePT, Line, FunctionPT, MemSize); return(MemPTR); } /* MEMREALLOC - JONAS (26.03.2002) */ void *memrealloc(const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, void *const OldPTR, const size_t MemSize) { struct MemTable_Struct *MemTableS = NULL; void *NewPTR = NULL; void *OldPrefixPTR = NULL; void *OldPostfixPTR = NULL; void *NewPrefixPTR = NULL; void *NewPostfixPTR = NULL; size_t RealSize = 0; #ifdef DEBUGPRINT DEBUGPRINT(BITMASK_DEBUG_MEMORY, "%s() - File: %s - Line: %d - Function: %s - Size: %ld", __FUNCTION__, FilePT, Line, FunctionPT, (PRINT_SIZE_T) MemSize); #endif if (OldPTR != NULL) { MemTableS = memtable_get(OldPTR); if (MemTableS == NULL) { if (IgnoreWildPTR == FALSE) { fprintf(stderr, "ERROR: Wild pointer %p from function %s() (%s:%d) passed to function realloc().\n", OldPTR, FunctionPT, FilePT, Line); } } else { if (MemTableS->Size == MemSize) { return(OldPTR); } OldPrefixPTR = OldPTR - MemPrefixSize; OldPostfixPTR = OldPTR + MemTableS->Size; if (strncmp(OldPrefixPTR, MALLOC_PREFIX, MALLOC_PREFIX_LEN) != 0) { fprintf(stderr, "ERROR: Magic memory prefix \"%s\" corrupt on pointer %p from function %s() (%s:%d) passed to function realloc().\n", MALLOC_PREFIX, OldPTR, FunctionPT, FilePT, Line); abort(); } if (strncmp(OldPostfixPTR, MALLOC_POSTFIX, MALLOC_POSTFIX_LEN) != 0) { fprintf(stderr, "ERROR: Magic memory postfix \"%s\" corrupt on pointer %p from function %s() (%s:%d) passed to function realloc().\n", MALLOC_POSTFIX, OldPTR, FunctionPT, FilePT, Line); abort(); } memtable_rem(MemTableS); } } if (MemSize > MALLOC_LIMIT) { fprintf(stderr, "ERROR: Memory request to large from function %s (%s:%d) (%ld bytes).\n", FunctionPT, FilePT, Line, (PRINT_SIZE_T) MemSize); return(NULL); } if (MemSize == 0) { if (OldPrefixPTR != NULL) { free(OldPrefixPTR); } return(NULL); } if (OldPostfixPTR != NULL) { memset(OldPostfixPTR, 0, MemPostfixSize); } RealSize += MemPrefixSize; RealSize += MemSize; RealSize += MemPostfixSize; NewPrefixPTR = realloc(OldPrefixPTR, RealSize); if (NewPrefixPTR == NULL) { if (RealSize > 0) { fprintf(stderr, "ERROR: Memory allocation failure in function %s (%s:%d): %ld bytes: [%d] %s\n", FunctionPT, FilePT, Line, (PRINT_SIZE_T) MemSize, errno, strerror(errno)); } return(NULL); } NewPostfixPTR = NewPrefixPTR + MemPrefixSize + MemSize; NewPTR = NewPrefixPTR + MemPrefixSize; strcpy(NewPrefixPTR, MALLOC_PREFIX); strcpy(NewPostfixPTR, MALLOC_POSTFIX); memtable_add(NewPTR, FilePT, Line, FunctionPT, MemSize); return(NewPTR); } /* MEMCALLOC - JONAS (21.09.2001) */ void *memcalloc(const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, const size_t Elements, const size_t Size) { size_t MemSize = (Size * Elements); void *PTR = memalloc(FilePT, Line, FunctionPT, MemSize); return(PTR); } /* MEMFREE - JONAS (21.09.2001) */ signed short int memfree(const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, void *const MemPTR) { struct MemTable_Struct *MemTableS = NULL; void *PrefixPTR = NULL; void *PostfixPTR = NULL; size_t TotalSize = 0; #ifdef DEBUGPRINT DEBUGPRINT(BITMASK_DEBUG_MEMORY, "%s() - File: %s - Line: %d - Function: %s - Pointer: %p", __FUNCTION__, FilePT, Line, FunctionPT, MemPTR); #endif if (MemPTR == NULL) { return(SUCCESS); } MemTableS = memtable_get(MemPTR); if (MemTableS == NULL) { if (IgnoreWildPTR == FALSE) { fprintf(stderr, "ERROR: Wild pointer %p from function %s (%s:%d) passed to function free().\n", MemPTR, FunctionPT, FilePT, Line); } return(ERROR); } PrefixPTR = MemPTR - MemPrefixSize; PostfixPTR = MemPTR + MemTableS->Size; TotalSize = MemPrefixSize + MemTableS->Size + MemPostfixSize; if (strncmp(PrefixPTR, MALLOC_PREFIX, MALLOC_PREFIX_LEN) != 0) { fprintf(stderr, "ERROR: Magic memory prefix \"%s\" corrupt on pointer %p from function %s (%s:%d) passed to function free().\n", MALLOC_PREFIX, MemPTR, FunctionPT, FilePT, Line); abort(); } if (strncmp(PostfixPTR, MALLOC_POSTFIX, MALLOC_POSTFIX_LEN) != 0) { fprintf(stderr, "ERROR: Magic memory postfix \"%s\" corrupt on pointer %p from function %s (%s:%d) passed to function free().\n", MALLOC_POSTFIX, MemPTR, FunctionPT, FilePT, Line); abort(); } memtable_rem(MemTableS); memset(PrefixPTR, MALLOC_REDBYTE, TotalSize); free(PrefixPTR); return(SUCCESS); }