blob: b9cc780e00213c773635eb2e2e022071e15b5913 [file] [log] [blame]
/**********************************************************************
*
* Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful but, except
* as otherwise stated in writing, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Contact Information:
* Imagination Technologies Ltd. <gpl-support@imgtec.com>
* Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
*
******************************************************************************/
#ifndef MEM_DEBUG_C
#define MEM_DEBUG_C
#if defined(PVRSRV_DEBUG_OS_MEMORY)
#include "img_types.h"
#include "services_headers.h"
#if defined (__cplusplus)
extern "C"
{
#endif
#define STOP_ON_ERROR 0
IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
{
IMG_UINT8 *pui8Addr;
for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
{
if (*pui8Addr != ui8Pattern)
{
return IMG_FALSE;
}
}
return IMG_TRUE;
}
IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
{
OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
if (pvCpuVAddr == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
" - referenced %s:%d - allocated %s:%d",
pvCpuVAddr,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
if (((IMG_UINT32)pvCpuVAddr&3) != 0)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
" - referenced %s:%d - allocated %s:%d",
pvCpuVAddr,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
" - referenced %s:%d - allocated %s:%d",
pvCpuVAddr,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
if (uSize != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
" - referenced %s:%d - allocated %s:%d",
pvCpuVAddr, uSize, psInfo->uSize,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
" - referenced %s:%d - allocated %s:%d",
pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
else
{
uSize = psInfo->uSize;
}
if (uSize)
{
if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
" - referenced from %s:%d - allocated from %s:%d",
pvCpuVAddr,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
}
}
if (psInfo->eValid != isAllocated)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
" - referenced %s:%d - freed %s:%d",
pvCpuVAddr, psInfo->eValid == isFree,
pszFileName, uLine,
psInfo->sFileName, psInfo->uLineNo));
while (STOP_ON_ERROR);
}
}
IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
{
IMG_SIZE_T i = 0;
for (; i < 128; i++)
{
*pDest = *pSrc;
if (*pSrc == '\0') break;
pDest++;
pSrc++;
}
}
PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
IMG_UINT32 ui32Size,
IMG_PVOID *ppvCpuVAddr,
IMG_HANDLE *phBlockAlloc,
IMG_CHAR *pszFilename,
IMG_UINT32 ui32Line)
{
OSMEM_DEBUG_INFO *psInfo;
PVRSRV_ERROR eError;
eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
ui32Size + TEST_BUFFER_PADDING,
ppvCpuVAddr,
phBlockAlloc,
pszFilename,
ui32Line);
if (eError != PVRSRV_OK)
{
return eError;
}
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
debug_strcpy(psInfo->sFileName, pszFilename);
psInfo->uLineNo = ui32Line;
psInfo->eValid = isAllocated;
psInfo->uSize = ui32Size;
psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
*ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
#ifdef PVRSRV_LOG_MEMORY_ALLOCS
PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
#endif
return PVRSRV_OK;
}
PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
IMG_UINT32 ui32Size,
IMG_PVOID pvCpuVAddr,
IMG_HANDLE hBlockAlloc,
IMG_CHAR *pszFilename,
IMG_UINT32 ui32Line)
{
OSMEM_DEBUG_INFO *psInfo;
OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
psInfo->uSize = 0;
psInfo->uSizeParityCheck = 0;
psInfo->eValid = isFree;
psInfo->uLineNo = ui32Line;
debug_strcpy(psInfo->sFileName, pszFilename);
return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
}
#if defined (__cplusplus)
}
#endif
#endif
#endif