duma_hlp.h
/*
* DUMA - Red-Zone memory allocator.
* Copyright (C) 2002-2009 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
* License: GNU LGPL (GNU Lesser General Public License, see COPYING-GPL)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE CONTENTS:
* internal implementation file
* contains helper functions for DUMA
*/
/* Function: reduceProtectedMemory
*
* delete reductionSizekB amount of memory, which has already
* been freed but got protected
* return != 0 when more memory reducable
*/
static int reduceProtectedMemory(size_t reductionSizekB) {
struct _DUMA_Slot *slot = _duma_g.allocList;
size_t count = _duma_s.slotCount;
size_t alreadyReducekB = 0;
#ifndef WIN32
/* Windows VirtualFree(,,MEM_RELEASE) can only free whole allocations. not
* parts */
size_t delSize, newSize;
/* 1- try reducing memory to just keep page(s) with userAddress */
for (; count > 0 && alreadyReducekB < reductionSizekB; --count, ++slot)
if (DUMAST_ALL_PROTECTED == slot->state) {
/* free memory above userAddr; keep userAddr protected */
newSize = (char *)slot->userAddress - (char *)slot->internalAddress;
newSize = (newSize + DUMA_PAGE_SIZE) & ~(DUMA_PAGE_SIZE - 1);
delSize = slot->internalSize - newSize;
Page_Delete((char *)slot->internalAddress + newSize, delSize);
alreadyReducekB += (delSize + 1023) >> 10;
slot->state = DUMAST_BEGIN_PROTECTED;
/* but keep the slot and userAddr */
slot->internalSize = newSize;
if (alreadyReducekB >= reductionSizekB) {
_duma_s.sumProtectedMem -= alreadyReducekB;
_duma_s.sumAllocatedMem -= alreadyReducekB;
return 1;
}
}
#endif
/* 2- deallocate all page(s) with userAddress, empty whole slot */
slot = _duma_g.allocList;
count = _duma_s.slotCount;
for (; count > 0 && alreadyReducekB < reductionSizekB; --count, ++slot)
if (DUMAST_BEGIN_PROTECTED == slot->state
#if defined(WIN32)
|| DUMAST_ALL_PROTECTED == slot->state
#endif
) {
/* free all the memory */
Page_Delete(slot->internalAddress, slot->internalSize);
alreadyReducekB += (slot->internalSize + 1023) >> 10;
/* free slot and userAddr */
slot->internalAddress = slot->userAddress = 0;
slot->internalSize = slot->userSize = 0;
slot->state = DUMAST_EMPTY;
slot->allocator = EFA_INT_ALLOC;
#ifndef DUMA_NO_LEAKDETECTION
slot->fileSource = DUMAFS_EMPTY;
slot->filename = 0;
slot->lineno = 0;
#endif
if (alreadyReducekB >= reductionSizekB) {
_duma_s.sumProtectedMem -= alreadyReducekB;
_duma_s.sumAllocatedMem -= alreadyReducekB;
return 1;
}
}
return 0;
}
/* Function: slotForUserAddress
*
* Find the slot structure for a user address.
*/
static struct _DUMA_Slot *slotForUserAddress(void *address) {
struct _DUMA_Slot *slot = _duma_g.allocList;
size_t count = _duma_s.slotCount;
for (; count > 0; --count, ++slot)
if (slot->userAddress == address)
return slot;
return 0;
}
/* Function: nearestSlotForUserAddress
*
* Find the nearest slot structure for a user address.
*/
static struct _DUMA_Slot *nearestSlotForUserAddress(void *userAddress) {
struct _DUMA_Slot *slot = _duma_g.allocList;
size_t count = _duma_s.slotCount;
for (; count > 0; --count, ++slot)
if ((char *)slot->internalAddress <= (char *)userAddress &&
(char *)userAddress <=
(char *)slot->internalAddress + slot->internalSize)
return slot;
return 0;
}
/* Function: _duma_init_slack
*
* Initialise the no mans land, for a given slot
*/
static void _duma_init_slack(struct _DUMA_Slot *slot) {
char *accBegAddr, *accEndAddr;
char *tmpBegAddr, *tmpEndAddr;
#ifdef DUMA_EXPLICIT_INIT
slot->slackfill = _duma_s.SLACKFILL;
#endif
/* nothing to do for zero userSize */
if (!slot->userSize)
return;
/* calculate accessible non-protectable address area */
if ((char *)slot->protAddress < (char *)slot->userAddress) {
/* DUMA_PROTECT_BELOW was 1 when allocating this piece of memory */
accBegAddr = (char *)slot->userAddress;
accEndAddr = (char *)slot->internalAddress + slot->internalSize;
} else {
/* DUMA_PROTECT_BELOW was 0 when allocating this piece of memory */
accBegAddr = (char *)slot->internalAddress;
accEndAddr = (char *)slot->protAddress;
}
tmpBegAddr = accBegAddr;
tmpEndAddr = (char *)slot->userAddress;
while (tmpBegAddr < tmpEndAddr)
*tmpBegAddr++ = (char)_duma_s.SLACKFILL;
tmpBegAddr = (char *)slot->userAddress + slot->userSize;
tmpEndAddr = accEndAddr;
while (tmpBegAddr < tmpEndAddr)
*tmpBegAddr++ = (char)_duma_s.SLACKFILL;
}
/* Function: _duma_check_slack
*
* Checks the integrity of no mans land, for a given slot
*/
static void _duma_check_slack(struct _DUMA_Slot *slot) {
char *accBegAddr, *accEndAddr;
char *tmpBegAddr, *tmpEndAddr;
char slackfill;
#ifdef DUMA_EXPLICIT_INIT
slackfill = (char)slot->slackfill;
#else
slackfill = (char)_duma_s.SLACKFILL;
#endif
/* nothing to do for zero userSize */
if (!slot->userSize)
return;
if (!slot->internalAddress)
return;
/* calculate accessible non-protectable address area */
if ((char *)slot->protAddress < (char *)slot->userAddress) {
/* DUMA_PROTECT_BELOW was 1 when allocating this piece of memory */
accBegAddr = (char *)slot->userAddress;
accEndAddr = (char *)slot->internalAddress + slot->internalSize;
} else {
/* DUMA_PROTECT_BELOW was 0 when allocating this piece of memory */
accBegAddr = (char *)slot->internalAddress;
accEndAddr = (char *)slot->protAddress;
}
tmpBegAddr = accBegAddr;
tmpEndAddr = (char *)slot->userAddress;
while (tmpBegAddr < tmpEndAddr) {
if ((char)slackfill != *tmpBegAddr++) {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_Abort("ptr=%a: detected overwrite of ptrs no mans land below "
"userSpace, size=%d alloced from %s(%i)",
(DUMA_ADDR)slot->userAddress, (DUMA_SIZE)slot->userSize,
slot->filename, slot->lineno);
#else
DUMA_Abort(
"ptr=%a: detected overwrite of ptrs no mans land below userSpace",
(DUMA_ADDR)slot->userAddress);
#endif
}
}
tmpBegAddr = (char *)slot->userAddress + slot->userSize;
tmpEndAddr = accEndAddr;
while (tmpBegAddr < tmpEndAddr) {
if ((char)slackfill != *tmpBegAddr++) {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_Abort("detected overwrite of no mans land above userSpace: ptr=%a, "
"size=%d\nalloced from %s(%i)",
(DUMA_ADDR)slot->userAddress, (DUMA_SIZE)slot->userSize,
slot->filename, slot->lineno);
#else
DUMA_Abort("detected overwrite of no mans land above userSpace: ptr=%a",
(DUMA_ADDR)slot->userAddress);
#endif
}
}
}
/* Function: _duma_check_all_slacks
*
* Checks the integrity of all no mans land
*/
static void _duma_check_all_slacks(void) {
struct _DUMA_Slot *slot = _duma_g.allocList;
size_t count = _duma_s.slotCount;
for (; count > 0; --count, ++slot) {
/* CHECK INTEGRITY OF NO MANS LAND */
if (DUMAST_IN_USE == slot->state && slot->userSize)
_duma_check_slack(slot);
}
}