123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- .TH DUMA 3 10-September-2005
- .SH NAME
- DUMA \- DUMA Malloc Debugger
- .SH SYNOPSIS
- .nf
- .ft B
- #include <stdlib.h>
- .ft
- .fi
- .LP
- .nf
- .ft B
- void * malloc (size_t size);
- .ft
- .fi
- .LP
- .nf
- .ft B
- void free (void *ptr);
- .ft
- .fi
- .LP
- .nf
- .ft B
- void * realloc (void *ptr, size_t size);
- .ft
- .fi
- .LP
- .nf
- .ft B
- void * calloc (size_t nelem, size_t elsize);
- .ft
- .fi
- .LP
- .nf
- .ft B
- void * memalign (size_t alignment, size_t size);
- .ft
- .fi
- .LP
- .nf
- .ft B
- void * valloc (size_t size);
- .ft
- .fi
- .LP
- .nf
- .ft B
- extern int DUMA_ALIGNMENT;
- .ft
- .fi
- .LP
- .nf
- .ft B
- extern int DUMA_PROTECT_BELOW;
- .ft
- .fi
- .LP
- .nf
- .ft B
- extern int DUMA_PROTECT_FREE;
- .ft
- .fi
- .LP
- .nf
- .ft B
- extern int DUMA_ALLOW_MALLOC_0;
- .ft
- .fi
- .LP
- .nf
- .ft B
- extern int DUMA_FILL;
- .ft
- .fi
- .SH DESCRIPTION
- .I 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
- .I 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.
- .LP
- 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.
- .LP
- 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
- .I all
- bugs of this type, you'll have to read and understand the rest of this
- man page.
- .SH USAGE
- Link your program with the library
- .B libduma.a .
- Make sure you are
- .I not
- linking with
- .B -lmalloc,
- .B -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
- .B -lduma
- argument to the linker, otherwise you'll have to put the path-name for
- .B libduma.a
- in the linker's command line.
- You can also use dynamic linking. If you're using a Bourne shell, the
- statement
- .B export LD_PRELOAD=libduma.so
- will cause DUMA to be loaded to run all dynamic executables.
- The command
- .B duma
- .I command
- runs a single command under DUMA.
- .LP
- 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.
- .LP
- Run your program
- .I using a debugger.
- It's easier to work this way than to create a
- .B core
- file and post-mortem debug it. DUMA can create
- .I 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.
- .SH 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.
- .TP
- 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
- .B int
- you'll have to set this value to 8. This is the case when compiling with the
- .B -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
- .I its size the multiple of
- .I 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
- .I 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.
- .TP
- 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
- .I 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.
- .TP
- 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.
- .TP
- 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.
- .TP
- 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.
- .TP
- DUMA_MEMCPY_OVERLAP
- Setting this variable to 1 will make DUMA to ignore memcpy region overlapping when
- the destination address is less than source address. It was added as a workaround
- for ARM port where memmove implementation calls memcpy if the overlapping
- destination is safe and produces in false aborts.
- .SH 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.
- .LP
- 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
- .I 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.
- .LP
- 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.
- .LP
- 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.
- .SH INSTRUCTIONS FOR DEBUGGING YOUR PROGRAM
- .TP
- 1.
- Link with libduma.a as explained above.
- .TP
- 2.
- Run your program in a debugger and fix any overruns or accesses to free memory.
- .TP
- 3.
- Quit the debugger.
- .TP
- 4.
- Set DUMA_PROTECT_BELOW = 1 in the shell environment.
- .TP
- 5.
- Repeat step 2, this time repairing underruns if they occur.
- .TP
- 6.
- Quit the debugger.
- .TP
- 7.
- Read the restrictions in the section on
- .I 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.
- .SH 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.
- .LP
- Don't leave libduma.a linked into production software! Use it only
- for debugging.
- .SH AUTHOR
- Hayati Ayguen
- .SH 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.
- .SH LICENSE
- Copyright 1987-1999 Bruce Perens. All rights reserved.
- .br
- 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.
- .SH CONTACTING THE AUTHOR
- .nf
- Bruce Perens
- 1563 Solano Ave. #349
- Berkeley, CA 94707
- Telephone: 510-526-1165
- Internet: bruce@perens.com
- .fi
- .ft
- .SH FILES
- /dev/zero: Source of memory pages (via mmap(2)).
- .SH SEE ALSO
- malloc(3), mmap(2), mprotect(2), swapon(8)
- .SH DIAGNOSTICS
- Segmentation Fault: Examine the offending statement for violation of the
- boundaries of a memory allocation.
- .br
- Bus Error: See the section on
- .I WORD-ALIGNMENT AND OVERRUN DETECTION.
- in this manual page.
- .SH BUGS
- My explanation of the alignment issue could be improved.
- .LP
- Some Sun systems running SunOS 4.1 were reported to signal an access to a
- protected page with
- .B SIGBUS
- rather than
- .B 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
- .B PAGE_PROTECTION_VIOLATED_SIGNAL
- as
- .B SIGBUS.
- .LP
- There are, without doubt, other bugs and porting issues. Please contact me via
- e-mail if you have any bug reports, ideas, etc.
- .SH WHAT'S BETTER
- .I Purify
- does a much more thorough job than DUMA, and does not have
- the huge memory overhead.
- .I 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.
|