Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions | Variables
libmalloc.cpp File Reference
#include "libmalloc.h"
#include <memory.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <setjmp.h>
#include <dlfcn.h>
#include <link.h>

Go to the source code of this file.

Classes

struct  Header
struct  Trailer

Defines

#define MARKER0   0xFFFFFFFF
#define MARKER1   0xEEEEEEEE
#define MARKER2_0   0xD8D8D8D8
#define MARKER2_1   0xE8E8E8E8
#define PATTERN_BYTE   0xFE
#define FREE_PATTERN_BYTE   0xDE

Functions

static int Verify (Header *h)
static void Log (int aType, void *aAddr, size_t aSize, void *aOldAddr)
static voidMallocHook (size_t aSize, u_long aLogType)
static void FreeHook (void *aAddr, u_long aLogType)
static voidReallocHook (void *aOldAddr, size_t aSize)
u_long SetMallocFlags (u_long aFlags)
static void Init ()
voidmalloc (size_t aSize)
voidrealloc (void *aPtr, size_t aSize)
void free (void *aPtr)
voidcalloc (size_t aSize, size_t aBsize)
void cfree (void *ptr)
voidmemalign (size_t alignment, size_t size)
voidvalloc (size_t size)
voidpvalloc (size_t size)
void__builtin_new (size_t aSize)
void __builtin_delete (void *aPtr)
void__builtin_vec_new (size_t aSize)
void __builtin_vec_delete (void *aPtr)
void __log_addref (void *p, int oldrc, int newrc)
void __log_release (void *p, int oldrc, int newrc)

Variables

static int gLogFD = -1
static u_long gFlags
static int gFillCount = 0
static int gFirstTime = 1

Class Documentation

struct Header

Definition at line 87 of file libmalloc.cpp.

Collaboration diagram for Header:
Class Members
u_long marker0
u_long marker1
size_t rawSize
size_t size
struct Trailer

Definition at line 94 of file libmalloc.cpp.

Collaboration diagram for Trailer:
Class Members
u_long marker2

Define Documentation

Definition at line 85 of file libmalloc.cpp.

#define MARKER0   0xFFFFFFFF

Definition at line 79 of file libmalloc.cpp.

#define MARKER1   0xEEEEEEEE

Definition at line 80 of file libmalloc.cpp.

#define MARKER2_0   0xD8D8D8D8

Definition at line 81 of file libmalloc.cpp.

#define MARKER2_1   0xE8E8E8E8

Definition at line 82 of file libmalloc.cpp.

#define PATTERN_BYTE   0xFE

Definition at line 84 of file libmalloc.cpp.


Function Documentation

void __builtin_delete ( void aPtr)

Definition at line 564 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  FreeHook(aPtr, malloc_log_delete);
}

Here is the call graph for this function:

void* __builtin_new ( size_t  aSize)

Definition at line 556 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  return MallocHook(aSize, malloc_log_new);
}

Here is the call graph for this function:

Definition at line 580 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  FreeHook(aPtr, malloc_log_delete);
}

Here is the call graph for this function:

void* __builtin_vec_new ( size_t  aSize)

Definition at line 572 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  return MallocHook(aSize, malloc_log_new);
}

Here is the call graph for this function:

void __log_addref ( void p,
int  oldrc,
int  newrc 
)

Definition at line 589 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  if (LIBMALLOC_LOG_RC & gFlags) {
    Log(malloc_log_addref, p, size_t(oldrc), (void*)newrc);
  }
}

Here is the call graph for this function:

void __log_release ( void p,
int  oldrc,
int  newrc 
)

Definition at line 600 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  if (LIBMALLOC_LOG_RC & gFlags) {
    Log(malloc_log_release, p, size_t(oldrc), (void*)newrc);
  }
}

Here is the call graph for this function:

void* calloc ( size_t  aSize,
size_t  aBsize 
)

Definition at line 520 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  size_t size = aSize*aBsize;
  void* ptr = MallocHook(size, malloc_log_malloc);
  if (NULL != ptr) {
    memset(ptr, 0, size);
  }
  return ptr;
}

Here is the call graph for this function:

void cfree ( void ptr)

Definition at line 533 of file libmalloc.cpp.

Here is the call graph for this function:

void free ( void aPtr)

Definition at line 512 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  FreeHook(aPtr, malloc_log_free);
}

Here is the call graph for this function:

static void FreeHook ( void aAddr,
u_long  aLogType 
) [static]

Definition at line 240 of file libmalloc.cpp.

{
  if (0 == aAddr) {
    return;
  }
  if (LIBMALLOC_LOG & gFlags) {
    Log(aLogType, aAddr, 0, 0);
  }
  Header* h = (Header*) ((char*)aAddr - sizeof(Header));
  if (Verify(h)) {
    // Munge the header so that a dup-free will fail the verify
    h->marker0 = 0xDEADBEEF;
    h->marker1 = 0xDEADBEEF;

    // Munge the body of the allocation so that if the user
    // still has a live reference they get messed up
    void* ptr = (void*) ((char*)(h+1));
    memset(ptr, FREE_PATTERN_BYTE, h->rawSize);

    if (0 == (LIBMALLOC_NOFREE & gFlags)) {
      REAL_FREE(h);
    }
  }
  else {
    if (0 == (LIBMALLOC_NOFREE & gFlags)) {
      REAL_FREE(aAddr);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void Init ( void  ) [static]

Definition at line 364 of file libmalloc.cpp.

{
  gFirstTime = 0;
  u_long flags = 0;
  char* s = getenv("LIBMALLOC_LOG");
  if (s) {
    flags = atoi(s);
    if (LIBMALLOC_LOG & flags) {
      char m1[] = "dbgmalloc: enabled memory logging\n";
      write(1, m1, sizeof(m1)-1);
    }
    if (LIBMALLOC_LOG_RC & flags) {
      char m2[] = "dbgmalloc: enabled refcnt logging\n";
      write(1, m2, sizeof(m2)-1);
    }
    if (LIBMALLOC_NOFREE & flags) {
      char m3[] = "dbgmalloc: disabled free\n";
      write(1, m3, sizeof(m3)-1);
    }
  }
  SetMallocFlags(flags);
  s = getenv("LIBMALLOC_FILL");
  if (s) {
    gFillCount = atoi(s);
    char m4[] = "dbgmalloc: adding extra memory fill ";
    write(1, m4, sizeof(m4)-1);
    write(1, s, strlen(s));
    write(1, "\n", 1);
  }
}

Here is the call graph for this function:

static void Log ( int  aType,
void aAddr,
size_t  aSize,
void aOldAddr 
) [static]

Definition at line 189 of file libmalloc.cpp.

{
  malloc_log_entry me;

  me.type = (u_long) aType;
  me.address = (u_long) aAddr;
  me.size = (u_long) aSize;
  me.oldaddress = (u_long) aOldAddr;

  jmp_buf jb;
  setjmp(jb);
  CrawlStack(&me, jb);

  write(gLogFD, &me, sizeof(me) - MAX_STACK_CRAWL*sizeof(char*) +
       me.numpcs*sizeof(char*));
}

Here is the caller graph for this function:

void* malloc ( size_t  aSize)

Definition at line 496 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  return MallocHook(aSize, malloc_log_malloc);
}

Here is the call graph for this function:

static void* MallocHook ( size_t  aSize,
u_long  aLogType 
) [static]

Definition at line 207 of file libmalloc.cpp.

{
  size_t roundedSize = aSize;
  roundedSize = ((roundedSize + 4 + gFillCount) >> 2) << 2;

  void* ptr = REAL_MALLOC(sizeof(Header) + roundedSize + sizeof(Trailer));

  if (NULL != ptr) {
    Header* h = (Header*) ptr;
    h->rawSize = aSize;
    h->size = roundedSize;
    h->marker0 = MARKER0;
    h->marker1 = MARKER1;

    ptr = (void*) ((char*)(h+1));

    // Fill new memory with a pattern to help detect overruns and
    // usage of un-written memory
    memset(ptr, PATTERN_BYTE, roundedSize);

    Trailer* t = (Trailer*) ((char*)ptr + roundedSize);
    t->marker2[0] = MARKER2_0;
    t->marker2[1] = MARKER2_1;

    if (LIBMALLOC_LOG & gFlags) {
      Log(aLogType, ptr, aSize, 0);
    }
  }

  return ptr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* memalign ( size_t  alignment,
size_t  size 
)

Definition at line 541 of file libmalloc.cpp.

{
  ::abort();
}
void* pvalloc ( size_t  size)

Definition at line 551 of file libmalloc.cpp.

{
  ::abort();
}
void* realloc ( void aPtr,
size_t  aSize 
)

Definition at line 504 of file libmalloc.cpp.

{
  if (gFirstTime) {
    Init();
  }
  return ReallocHook(aPtr, aSize);
}

Here is the call graph for this function:

static void* ReallocHook ( void aOldAddr,
size_t  aSize 
) [static]

Definition at line 271 of file libmalloc.cpp.

{
  if (0 == aOldAddr) {
    return MallocHook(aSize, malloc_log_malloc);
  }
  Header* oldh = (Header*) ((char*)aOldAddr - sizeof(Header));
  if (!Verify(oldh)) {
    return REAL_REALLOC(aOldAddr, aSize);
  }
  size_t oldSize = oldh->rawSize;

  size_t roundedSize = aSize;
  roundedSize = ((roundedSize + 4) >> 2) << 2;

  void* ptr = REAL_MALLOC(sizeof(Header) + roundedSize + sizeof(Trailer));

  if (NULL != ptr) {
    Header* h = (Header*) ptr;
    h->rawSize = aSize;
    h->size = roundedSize;
    h->marker0 = MARKER0;
    h->marker1 = MARKER1;

    ptr = (void*) ((char*)(h+1));

    Trailer* t = (Trailer*) ((char*)ptr + roundedSize);
    t->marker2[0] = MARKER2_0;
    t->marker2[1] = MARKER2_1;

    // Copy old memory into new memory (don't copy too much!)
    size_t copy = oldSize;
    if (copy > aSize) copy = aSize;
    memcpy(ptr, aOldAddr, copy);

    // Fill any uncopied memory with the overrun pattern
    size_t fill = roundedSize - copy;
    if (0 != fill) {
      memset((char*)ptr + copy, PATTERN_BYTE, fill);
    }

    if (0 == (LIBMALLOC_NOFREE & gFlags)) {
      REAL_FREE(oldh);
    }
    else {
      // Mark the old header so that a verify will fail if the caller
      // dup free's it.
      oldh->marker0 = 0xDEADBEEF;
      oldh->marker1 = 0xDEADBEEF;

      // Munge the body of the old allocation so that if the user
      // still has a live reference they get messed up
      void* optr = (void*) ((char*)(oldh+1));
      memset(optr, FREE_PATTERN_BYTE, oldh->rawSize);
    }

    if (LIBMALLOC_LOG & gFlags) {
      Log(malloc_log_realloc, ptr, aSize, aOldAddr);
    }
  }
  return ptr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 334 of file libmalloc.cpp.

{
  u_long old = gFlags;
  gFlags = aFlags;

  if ((-1 == gLogFD) && ((LIBMALLOC_LOG|LIBMALLOC_LOG_RC) & gFlags)) {
    gLogFD = open("malloc-log", O_CREAT|O_WRONLY|O_TRUNC, 0666);
    if (gLogFD < 0) {
      gFlags &= ~LIBMALLOC_LOG;
      printf("unable to create malloc-log: %d\n", errno);
    }
  }
  if ((gLogFD >= 0) && (0 == ((LIBMALLOC_LOG|LIBMALLOC_LOG_RC) & gFlags))) {
    close(gLogFD);
    gLogFD = -1;
  }
#ifndef NTO
  if (LIBMALLOC_CHECK & gFlags) {
    mallopt(M_CHECK_ACTION, 1);
  }
#endif

  // Try to guarantee that the address map is always dumped
  atexit(DumpAddressMap);

  return old;
}

Here is the caller graph for this function:

void* valloc ( size_t  size)

Definition at line 546 of file libmalloc.cpp.

{
  ::abort();
}
static int Verify ( Header h) [static]

Definition at line 154 of file libmalloc.cpp.

{
  // Sanity check the header first
  if ((h->marker0 != MARKER0) ||
      (h->marker1 != MARKER1) ||
      (h->rawSize > h->size)) {
    DumpAddressMap();
    abort();
  }

  // Sanity check the trailer second
  Trailer* t = (Trailer*) ((char*)(h + 1) + h->size);
  if ((t->marker2[0] != MARKER2_0) ||
      (t->marker2[1] != MARKER2_1)) {
    DumpAddressMap();
    abort();
  }

  // Verify there were no overruns
  size_t fill = h->size - h->rawSize;
  if (0 != fill) {
    unsigned char* cp = ((unsigned char*)(h + 1)) + h->rawSize;
    unsigned char* end = cp + fill;
    while (cp < end) {
      unsigned char ch = *cp++;
      if (ch != PATTERN_BYTE) {
       DumpAddressMap();
       abort();
      }
    }
  }
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int gFillCount = 0 [static]

Definition at line 77 of file libmalloc.cpp.

int gFirstTime = 1 [static]

Definition at line 362 of file libmalloc.cpp.

u_long gFlags [static]

Definition at line 76 of file libmalloc.cpp.

int gLogFD = -1 [static]

Definition at line 75 of file libmalloc.cpp.