/********************************************************************** * * 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. * 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