运行测试程序前,在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;
}