运行测试程序前,在VxWorks的Shell下如下操作:
ld < memTrack.o
ld < findMalloc.o
find_malloc
下面是findMalloc的源码
/*
* Memory diagnosics: findMalloc.c
* Author: Richard Dickson (dickson at jlab.org)
*
*/
#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;
}
下面是memTrack的源码
/*
* Memory diagnosics: memTrack.c
*
* Author: Richard Dickson (dickson at jlab.org)
*
*/
/* 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;
}