一个简单的VxWorks内存泄露检测

/*
 * Memory diagnosics: find_malloc.c
 *
 * Author: Richard Dickson ([email protected])
 *
 * $Id: findMalloc.c,v 1.1 1999/11/29 23:27:48 borkhuis Exp $
 *
 */


#include <symLib.h>


char *addr_of_malloc = NULL;
char *addr_of_calloc = NULL;
char *addr_of_free = NULL;


extern SYMTAB_ID sysSymTbl;


int find_malloc(void)
{
 SYM_TYPE type;
 STATUS   status;


 status  = symFindByName(sysSymTbl,
                         "_malloc",
                         &addr_of_malloc,
                         &type);


 status |= symFindByName(sysSymTbl,
                         "_calloc",
                         &addr_of_calloc,
                         &type);


 status |= symFindByName(sysSymTbl,
                         "_free",
                         &addr_of_free,
                         &type);


 return status;

}




/*
 * Memory diagnosics: memTrack.c
 *
 * Author: Richard Dickson ([email protected])
 *
 * $Id: memTrack.c,v 1.1 1999/11/29 23:27:48 borkhuis Exp $
 *
 */


/* Richard Dickson  July, 1998 */
/* Routines to report per task memory allocation */


#include <stdio.h>
#include <stdlib.h>
#include <taskLib.h>
#include <symLib.h>


/* these three must have been initialized by the routine find_malloc before this module is loaded */
extern void *(*addr_of_malloc)(size_t size);
extern void *(*addr_of_calloc)(size_t nelem, size_t size);
extern void  (*addr_of_free)(void *ptr);


extern SYMTAB_ID sysSymTbl;


/****************************************************************************/
long getStackPointer(void)
{ /* assembly routine to return stack pointer value */
 static const short code_array[] = {
                     0x4e56, 0000,/* LINK.W  A6,#0 */
           0x200F,/* MOVE.L  A7,D0 */
           0x4e5e,/* ULNK    A6    */
           0x4e75/* RTS */
                                   };


 return (((long(*)()) code_array)());
}


/****************************************************************************/
void *malloc(size_t size)
{
 WIND_TCB *tcb; /* pointer to task control block */
 void *ret_val;


 ret_val = (*addr_of_malloc)(size+4); /* call real malloc, ask for 4 extra bytes to store TID */


 if (ret_val)
  { /* if malloc success */
   long *sp; /* stack pointer */


   tcb = (WIND_TCB*)taskIdSelf(); /* get TID */
   *(WIND_TCB**)ret_val = tcb; /* put TID at start of malloc buffer */
   tcb->spare1++; /* inc allocated block counter for this task */
   tcb->spare2 += (*((int*)ret_val - 1) - 12); /* vxWorks puts length of buff (+ buf's linked list overhead
                                                   size (8 bytes)) into longword before malloc's return address.
                                                   Subtract 4 more for the extra 4 asked for (total 12) to find
                                                   size of caller's request.  Add this to this tasks total bytes
                                                   allocated */
   sp = (long*)getStackPointer(); /* get stack pointer so the caller of this routine can be found */
   tcb->spare3 = (int)sp[7] - 6; /* caller PC (JSR instruction is 6 bytes long itself) */
  }


 (char*)ret_val += 4; /* adjust malloc return value so caller doesn't see TID info */
 return ret_val; 
}


/****************************************************************************/
void *calloc(size_t nelem, size_t size)
{
 WIND_TCB *tcb; /* pointer to task control block */
 void *ret_val;
 unsigned bytes;


 bytes = nelem*size; /* bytes to calloc */
 ret_val = (*addr_of_calloc)(bytes+4, 1); /* call real calloc, ask for 4 extra bytes to store TID */


 if (ret_val)
  {                                             /* if calloc success */
   long *sp; /* stack pointer */
   tcb = (WIND_TCB*)taskIdSelf();               /* get TID */
   *(WIND_TCB**)ret_val = tcb;                  /* put TID at start of calloc buffer */
   tcb->spare1++;                               /* inc allocated block counter for this task */
   tcb->spare2 += (*((int*)ret_val - 1) - 12);  /* vxWorks puts length of buff (+ buf's linked list overhead
                                                   size (8 bytes)) into longword before calloc's return address.
                                                   Subtract 4 more for the extra 4 asked for (total 12) to find
                                                   size of caller's request.  Add this to this tasks total bytes
                                                   allocated */
   sp = (long*)getStackPointer();               /* get stack pointer so the caller of this routine can be found */
   tcb->spare3 = (int)sp[7] - 6; /* caller PC (JSR instruction is 6 bytes long itself) */
  }


 (char*)ret_val += 4;                           /* adjust calloc return value so caller doesn't see TID info */
 return ret_val; 
}


/****************************************************************************/
void free(void *ptr)
{
 WIND_TCB *tcb;                                 /* pointer to task control block */


 (char*)ptr -= 4; /* adjust pointer for 4 extra bytes asked for by malloc or calloc */
 tcb = *(WIND_TCB**)ptr; /* get TID of task that did malloc or calloc */
 if (!((unsigned)tcb & 0x80000000) && taskIdVerify((int)tcb) == OK)
  { /* if not already freed and TID is real */
   *(unsigned*)ptr |= 0x80000000; /* set top bit in TID to indicate not allocated */
   tcb->spare1--; /* adjust task's allocated block counter */
   tcb->spare2 -= (*((int*)ptr - 1) - 12); /* adjust task's allocated byte counter */
  }


 (*addr_of_free)(ptr); /* call real free routine */


 return; 
}


/****************************************************************************/
#define MAX_TASKS 256


int memTrack(void)
{
 int tid[MAX_TASKS];
 int i, num_tasks;
 int blocks = 0;
 int bytes  = 0;
 char caller[64];
 int actual_addr;
 SYM_TYPE sym_type;


 num_tasks = taskIdListGet(tid, MAX_TASKS); /* get all TIDs */


 printf("\n");
 printf("Task Name            TID  Blocks    Bytes                    Last-caller       PC\n");
 printf("--------------- -------- ------- -------- ------------------------------ --------\n");
 for (i=0; i<num_tasks; i++)
  {
   if (((WIND_TCB*)tid[i])->spare1)
    { /* if blocks allocated by this task */
     blocks += ((WIND_TCB*)tid[i])->spare1; /* add up for total */
     bytes  += ((WIND_TCB*)tid[i])->spare2; /* add up for total */
     symFindByValue(sysSymTbl, /* find caller routine name */
                    ((WIND_TCB*)tid[i])->spare3,
                    caller,
                    &actual_addr,
                    &sym_type); 


     sprintf(caller, "%s + 0x%x", caller, ((WIND_TCB*)tid[i])->spare3 - actual_addr);
     printf("%-15s %8x %7d %8d %30s %8x\n", taskName(tid[i]), tid[i],
                                            ((WIND_TCB*)tid[i])->spare1,
                                            ((WIND_TCB*)tid[i])->spare2,
                                            caller, 
                                            ((WIND_TCB*)tid[i])->spare3);
    }
  }
 printf("TOTAL                  %9d %8d\n", blocks, bytes);


 return 0;
}


你可能感兴趣的:(memory,leak)