Man Linux: Main Page and Category List

NAME

       DUMA - DUMA Malloc Debugger

SYNOPSIS

       #include <stdlib.h>

       void * malloc (size_t size);

       void free (void *ptr);

       void * realloc (void *ptr, size_t size);

       void * calloc (size_t nelem, size_t elsize);

       void * memalign (size_t alignment, size_t size);

       void * valloc (size_t size);

       extern int DUMA_ALIGNMENT;

       extern int DUMA_PROTECT_BELOW;

       extern int DUMA_PROTECT_FREE;

       extern int DUMA_ALLOW_MALLOC_0;

       extern int DUMA_FILL;

DESCRIPTION

       DUMA  helps  you  detect  two  common  programming  bugs: software that
       overruns the boundaries of a malloc() memory allocation,  and  software
       that  touches  a  memory  allocation  that has been released by free().
       Unlike other malloc() debuggers, DUMA will detect read accesses as well
       as  writes,  and  it will pinpoint the exact instruction that causes an
       error. It has been in use at Pixar since 1987, and at many other  sites
       for years.

       DUMA  uses  the  virtual  memory  hardware of your computer to place an
       inaccessible memory page immediately after (or before,  at  the  user’s
       option)  each  memory  allocation.  When  software reads or writes this
       inaccessible page, the hardware issues a segmentation  fault,  stopping
       the  program  at  the offending instruction. It is then trivial to find
       the erroneous statement using your  favorite  debugger.  In  a  similar
       manner,  memory  that has been released by free() is made inaccessible,
       and any code that touches it will get a segmentation fault.

       Simply linking your application with libduma.a will allow you to detect
       most,  but not all, malloc buffer overruns and accesses of free memory.
       If you want to be reasonably sure that you’ve found all  bugs  of  this
       type, you’ll have to read and understand the rest of this man page.

USAGE

       Link  your  program with the library libduma.a .  Make sure you are not
       linking with -lmalloc, -lmallocdebug, or with other malloc-debugger  or
       malloc-enhancer  libraries.   You  can only use one at a time.  If your
       system administrator has installed DUMA for public use, you’ll be  able
       to  use the -lduma argument to the linker, otherwise you’ll have to put
       the path-name for libduma.a in the linker’s command line.  You can also
       use  dynamic  linking.  If  you’re  using a Bourne shell, the statement
       export LD_PRELOAD=libduma.so.0.0 will cause DUMA to be  loaded  to  run
       all  dynamic  executables.   The  command  duma  command  runs a single
       command under DUMA.

       Some systems will require special arguments to  the  linker  to  assure
       that  you  are  using  the  DUMA  malloc()  and not the one from your C
       library.

       Run your program using a debugger.  It’s easier to work this  way  than
       to  create  a  core file and post-mortem debug it. DUMA can create huge
       core files, and some operating systems will thus take minutes simply to
       dump  core!  Some  operating  systems will not create usable core files
       from programs that are linked with DUMA.  If your program  has  one  of
       the errors detected by DUMA, it will get a segmentation fault (SIGSEGV)
       at the offending instruction. Use the debugger to locate the  erroneous
       statement, and repair it.

GLOBAL AND ENVIRONMENT VARIABLES

       DUMA  has four configuration switches that can be enabled via the shell
       environment, or by setting the value of global integer variables  using
       a  debugger.  These switches change what bugs DUMA will detect, so it’s
       important that you know how to use them.

       DUMA_ALIGNMENT
              This is an integer that specifies the alignment for  any  memory
              allocations  that  will  be  returned by malloc(), calloc(), and
              realloc().  The value is specified in bytes, thus a value  of  4
              will cause memory to be aligned to 32-bit boundaries unless your
              system doesn’t have a 8-bit characters. DUMA_ALIGNMENT is set to
              sizeof(int) by default, since that is generally the word-size of
              your CPU.  If your program requires that allocations be  aligned
              to  64-bit  boundaries  and you have a 32-bit int you’ll have to
              set this value to 8. This is the case when  compiling  with  the
              -mips2  flag  on MIPS-based systems such as those from SGI.  The
              memory allocation that is returned by DUMA malloc()  is  aligned
              using  the value in DUMA_ALIGNMENT, and its size the multiple of
              that value that is greater than or equal to the requested  size.
              For  this  reason, you will sometimes want to set DUMA_ALIGNMENT
              to 0 (no alignment), so that you can  detect  overruns  of  less
              than  your  CPU’s  word  size. Be sure to read the section WORD-
              ALIGNMENT AND OVERRUN DETECTION in this manual page  before  you
              try this.  To change this value, set DUMA_ALIGNMENT in the shell
              environment to an integer value, or assign to the global integer
              variable DUMA_ALIGNMENT using a debugger.

       DUMA_PROTECT_BELOW
              DUMA  usually places an inaccessible page immediately after each
              memory allocation, so that software that runs past  the  end  of
              the allocation will be detected. Setting DUMA_PROTECT_BELOW to 1
              causes DUMA to place the inaccessible page before the allocation
              in  the  address  space,  so  that  under-runs  will be detected
              instead of  over-runs.   When  DUMA_PROTECT_BELOW  is  set,  the
              DUMA_ALIGNMENT  parameter  is  ignored.  All allocations will be
              aligned to virtual-memory-page boundaries, and their  size  will
              be the exact size that was requested.  To change this value, set
              DUMA_PROTECT_BELOW in the shell environment to an integer value,
              or  assign  to  the  global  integer variable DUMA_PROTECT_BELOW
              using a debugger.

       DUMA_PROTECT_FREE
              DUMA usually returns free memory to a pool from which it may  be
              re-allocated. If you suspect that a program may be touching free
              memory, set DUMA_PROTECT_FREE to 1.  This  will  cause  DUMA  to
              never  re-allocate  memory  once  it has been freed, so that any
              access to free memory will be detected. Some programs  will  use
              tremendous  amounts  of  memory  when this parameter is set.  To
              change  this  value,  set   DUMA_PROTECT_FREE   in   the   shell
              environment to an integer value, or assign to the global integer
              variable DUMA_PROTECT_FREE using a debugger.

       DUMA_ALLOW_MALLOC_0
              By default, DUMA traps calls to malloc() with a  size  of  zero,
              because  they  are  often  the  result  of  a  software  bug. If
              DUMA_ALLOW_MALLOC_0 is non-zero,  the  software  will  not  trap
              calls  to  malloc()  with a size of zero.  To change this value,
              set DUMA_ALLOC_MALLOC_0 in the shell environment to  an  integer
              value,    or    assign    to   the   global   integer   variable
              DUMA_ALLOC_MALLOC_0 using a debugger.

       DUMA_FILL
              When set to a value between 0 and 255, every byte  of  allocated
              memory  is initialized to that value. This can help detect reads
              of uninitialized memory.  When set to -1, some memory is  filled
              with  zeroes  (the operating system default on most systems) and
              some memory will retain the values written to it during its last
              use.

WORD-ALIGNMENT AND OVERRUN DETECTION

       There  is  a  conflict between the alignment restrictions that malloc()
       operates under and the debugging strategy used by DUMA. When  detecting
       overruns,  DUMA malloc() allocates two or more virtual memory pages for
       each allocation. The last page is made inaccessible in such a way  that
       any  read,  write,  or  execute access will cause a segmentation fault.
       Then, DUMA malloc() will return an address such  that  the  first  byte
       after the end of the allocation is on the inaccessible page.  Thus, any
       overrun of the allocation will cause a segmentation fault.

       It follows that the address returned by malloc() is the address of  the
       inaccessible   page   minus   the   size   of  the  memory  allocation.
       Unfortunately, malloc() is required to return word-aligned allocations,
       since  many  CPUs  can  only access a word when its address is aligned.
       The conflict happens when software makes a memory  allocation  using  a
       size  that  is  not a multiple of the word size, and expects to do word
       accesses to that allocation. The location of the inaccessible  page  is
       fixed  by  hardware  at  a word-aligned address. If DUMA malloc() is to
       return an aligned address, it must increase the size of the  allocation
       to  a multiple of the word size.  In addition, the functions memalign()
       and valloc() must honor explicit specifications on the alignment of the
       memory  allocation,  and  this,  as  well  can  only  be implemented by
       increasing the size of the allocation.  Thus, there will be  situations
       in  which  the  end of a memory allocation contains some padding space,
       and accesses of that padding space will not be detected, even  if  they
       are overruns.

       DUMA  provides the variable DUMA_ALIGNMENT so that the user can control
       the default alignment used by malloc(), calloc(),  and  realloc().   To
       debug overruns as small as a single byte, you can set DUMA_ALIGNMENT to
       zero. This will result in DUMA malloc() returning  unaligned  addresses
       for  allocations  with  sizes that are not a multiple of the word size.
       This is not a problem in most cases, because  compilers  must  pad  the
       size of objects so that alignment restrictions are honored when storing
       those objects in arrays. The problem surfaces when  software  allocates
       odd-sized  buffers  for  objects that must be word-aligned. One case of
       this is software that allocates a buffer to contain a structure  and  a
       string,  and  the string has an odd size (this example was in a popular
       TIFF library). If word references are made to un-aligned  buffers,  you
       will see a bus error (SIGBUS) instead of a segmentation fault. The only
       way to fix this  is  to  re-write  the  offending  code  to  make  byte
       references  or not make odd-sized allocations, or to set DUMA_ALIGNMENT
       to the word size.

       Another example of software incompatible with  DUMA_ALIGNMENT  <  word-
       size  is the strcmp() function and other string functions on SunOS (and
       probably Solaris), which make word-sized accesses to character strings,
       and may attempt to access up to three bytes beyond the end of a string.
       These result in a segmentation fault (SIGSEGV).  The  only  way  around
       this  is  to  use  versions  of  the string functions that perform byte
       references instead of word references.

INSTRUCTIONS FOR DEBUGGING YOUR PROGRAM

       1.     Link with libduma.a as explained above.

       2.     Run your program in a debugger and fix any overruns or  accesses
              to free memory.

       3.     Quit the debugger.

       4.     Set DUMA_PROTECT_BELOW = 1 in the shell environment.

       5.     Repeat step 2, this time repairing underruns if they occur.

       6.     Quit the debugger.

       7.     Read  the  restrictions  in  the  section  on WORD-ALIGNMENT AND
              OVERRUN DETECTION.  See if you can set DUMA_ALIGNMENT to  0  and
              repeat  step  2.  Sometimes this will be too much work, or there
              will be problems with library routines for which you don’t  have
              the source, that will prevent you from doing this.

MEMORY USAGE AND EXECUTION SPEED

       Since  DUMA  uses  at  least  two  virtual memory pages for each of its
       allocations, it’s a  terrible  memory  hog.  I’ve  sometimes  found  it
       necessary  to  add a swap file using swapon(8) so that the system would
       have enough virtual memory to  debug  my  program.  Also,  the  way  we
       manipulate  memory  results  in  various  cache  and translation buffer
       entries being flushed with each call to malloc or free. The end  result
       is  that  your program will be much slower and use more resources while
       you are debugging it with DUMA.

       Don’t leave libduma.a linked into production software! Use it only  for
       debugging.

AUTHOR

       Hayati Ayguen

WARNINGS

       I have tried to do as good a job as I can on this software, but I doubt
       that it is even theoretically  possible  to  make  it  bug-free.   This
       software  has  no warranty. It will not detect some bugs that you might
       expect it to detect, and will indicate that some non-bugs are bugs.

LICENSE

       Copyright 1987-1999 Bruce Perens. All rights reserved.
       This program is free software; you can redistribute it and/or modify it
       under  the  terms  of  the  GNU  General  Public License, Version 2, as
       published by the Free Software Foundation. A copy of  this  license  is
       distributed with this software in the file "COPYING".

       This  program  is  distributed  in the hope that it will be useful, but
       WITHOUT  ANY  WARRANTY;  without   even   the   implied   warranty   of
       MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR PURPOSE. Read the file
       "COPYING" for more details.

CONTACTING THE AUTHOR

       Bruce Perens
       1563 Solano Ave. #349
       Berkeley, CA 94707
       Telephone: 510-526-1165
       Internet: bruce@perens.com

FILES

       /dev/zero: Source of memory pages (via mmap(2)).

SEE ALSO

       malloc(3), mmap(2), mprotect(2), swapon(8)

DIAGNOSTICS

       Segmentation Fault: Examine the offending statement  for  violation  of
       the boundaries of a memory allocation.
       Bus Error: See the section on WORD-ALIGNMENT AND OVERRUN DETECTION.  in
       this manual page.

BUGS

       My explanation of the alignment issue could be improved.

       Some Sun systems running SunOS 4.1 were reported to signal an access to
       a  protected page with SIGBUS rather than SIGSEGV, I suspect this is an
       undocumented feature of a particular Sun hardware version, not just the
       operating  system.   On  these  systems,  dumatest will fail with a bus
       error    until    you     modify     the     Makefile     to     define
       PAGE_PROTECTION_VIOLATED_SIGNAL as SIGBUS.

       There are, without doubt, other bugs and porting issues. Please contact
       me via e-mail if you have any bug reports, ideas, etc.

WHATS BETTER
       Purify does a much more thorough job than DUMA, and does not  have  the
       huge  memory  overhead.   Checkergcc,  a  modified version of the GNU C
       Compiler that instruments all memory references, is available on  Linux
       systems  and  where  GCC is used. It performs some of the same tasks as
       Purify, but only on code that it has compiled.

                               10-September-2005