You are here

Mudflap

For debugging complex bugs in user applications, a powerful tool available in STLinux is Mudflap. Mudflap is an open-source library, integrated with gcc, which instruments all risky pointer or array operations to check whether they are valid or not. Applications built with Mudflap will detect and warn the user if their application overflows a buffer, misuses heap memory, writes through a bad pointer, or commits any of several other classes of C memory usage error.

Mudflap is supported for C and simple C++ code.

Usage

To use Mudflap, your entire application needs to be rebuilt with some additional flags. These vary, depending on whether the application is multi-threaded or not. For single-threaded apps, each individual C file needs to be compiled with:

 -fmudflap -funwind-tables

and the final app has to be linked with:

 -lmudflap -rdynamic

For multithreaded apps, each file should be compiled with:

 -fmudflap -fmudflapth -funwind-tables

and linked with:

 -lmudflapth -rdynamic

An application built with these flags will automatically warn if an error is detected. For example, this simple application writes off the end of an array:

1  int main(void)
2  {
3          int i = 0;
4          char test_array[5];
5          for (i=0;i<6;i++) {
6                  test_array[i] = 'a';
7          }
8          return 0;
9  }
10 

This makefile builds it with Mudflap:

MUDFLAP_OPTIONS = -fmudflap -funwind-tables -lmudflap -rdynamic
 
all: simple_mudflap_test.c
        sh4-linux-gcc $(MUDFLAP_OPTIONS) -g -o simple_mudflap_test simple_mudflap_test.c

When it runs, the error is detected:

target# ./simple_mudflap_test
*******
mudflap violation 1 (check/write): time=946685456.633663 ptr=0x7bf27ca4 size=6
pc=0x29587f98 location=`simple_mudflap_test.c:6 (main)'
      ./simple_mudflap_test(main+0xa4) [0x400864]
      /usr/lib/libmudflap.so.0(__wrap_main+0x11e) [0x29587c1a]
Nearby object 1: checked region begins 0B into and ends 1B after
mudflap object 0x491af8: name=`simple_mudflap_test.c:4 (main) test_array'
bounds=[0x7bf27ca4,0x7bf27ca8] size=5 area=stack check=0r/4w liveness=4
alloc time=946685456.633532 pc=0x29587acc
number of nearby objects: 1
target#

This shows that at line 6 of simple_mudflap_test.c, in function main(), made a write outside valid memory. Mudflap defines "valid memory" as known areas referred to by a C construct, such as a structure, an array or malloced memory. Each of these is referred to as a "Mudflap object". In this case, the error was that application wrote to memory that wasn't in any known Mudflap object. The error message gives all the "nearby" Mudflap objects, in this case just test_array. This may give a clue to what the intended target of the write was.

The most important aspect of using Mudflap with a more complex application is to ensure than all the libraries linked to the application, either statically or dynamically, have been built with Mudflap enabled. Otherwise, any memory allocated in that library will cause a warning when it is accessed.

Mudflap Options

Mudflap can be controlled with a number of options, which are set using the environment variable MUDFLAP_OPTIONS. They can be listed by setting that variable to --help

target# MUDFLAP_OPTIONS="-help" ./simple_mudflap_test
This is a single-threaded thread-unaware GCC "mudflap" memory-checked binary.
Mudflap is Copyright (C) 2002-2004 Free Software Foundation, Inc.
 
The mudflap code can be controlled by an environment variable:
 
$ export MUDFLAP_OPTIONS='<options>'
$ <mudflapped_program>
 
where <options> is a space-separated list of
any of the following options.  Use `-no-OPTION' to disable options.
 
-mode-nop                mudflaps do nothing
-mode-populate           mudflaps populate object tree
-mode-check              mudflaps check for memory violations [active]
-mode-violate            mudflaps always cause violations (diagnostic)
-viol-nop                violations do not change program execution [active]
-viol-abort              violations cause a call to abort()
-viol-segv               violations are promoted to SIGSEGV signals
-viol-gdb                violations fork a gdb process attached to current program
-trace-calls             trace calls to mudflap runtime library
-verbose-trace           trace internal events within mudflap runtime library
-collect-stats           collect statistics on mudflap's operation
-sigusr1-report          print report upon SIGUSR1
-internal-checking       perform more expensive internal checking
-print-leaks             print any memory leaks at program shutdown
-check-initialization    detect uninitialized object reads
-verbose-violations      print verbose messages when memory violations occur [active]
-abbreviate              abbreviate repetitive listings [active]
-timestamps              track object lifetime timestamps [active]
-ignore-reads            ignore read accesses - assume okay
-wipe-stack              wipe stack objects at unwind
-wipe-heap               wipe heap objects at free
-heur-proc-map           support /proc/self/map heuristics
-heur-stack-bound        enable a simple upper stack bound heuristic
-heur-start-end          support _start.._end heuristics
-heur-stdlib             register standard library data (argv, errno, stdin, ...) [active]
-free-queue-length=N     queue N deferred free() calls before performing them [4]
-persistent-count=N      keep a history of N unregistered regions [100]
-crumple-zone=N          surround allocations with crumple zones of N bytes [32]
-lc-adapt=N              adapt mask/shift parameters after N cache misses [1000003]
-backtrace=N             keep an N-level stack trace of each call context [4]
-register-anon-mmaps     anonymous mmaps are registered as valid memory objects
-ignore-fflush           ignore fflush calls - assume okay

Of these, some of the most interesting options are:

-ignore-reads

With this option, Mudflap will only check that memory writes are to valid memory. Memory reads are assumed to be correct. This significantly reduces the performance overhead of running with Mudflap but, of course, may mean that genuine errors are not reported.

-print-leaks

This checks the application for memory leaks, outputting a report on them when the application exits. For example, if we fix the buffer overrun in simple_mudflap_test.c, but add a memory leak...

 1 #include <stdlib.h>
 2
 3 int main(void)
 4 {
 5         int i = 0;
 6         char test_array[5];
 7         int *leaked_ptr = (int*)malloc(56);
 8 
 9         for (i=0;i<5;i++) {
10                 test_array[i] = 'a';
11         }
12         return 0;
13 }

... and run it with the -print-leaks option, the leak is reported:

target# MUDFLAP_OPTIONS="-print-leaks" ./simple_mudflap_test
Leaked object 1:
mudflap object 0x491c68: name=`malloc region'
bounds=[0x491be8,0x491c1f] size=56 area=heap check=0r/0w liveness=0
alloc time=946685233.311422 pc=0x29587332
      ./simple_mudflap_test(main+0x38) [0x400838]
      /usr/lib/libmudflap.so.0(__wrap_main+0x102) [0x2958745e]
number of leaked objects: 1
target# 

If the application has been built with debug info, the address of the allocation can be looked up from the backtrace using the tool addr2line:

target# addr2line -e simple_mudflap_test 0x00400838
/scratch/smithc/mudflap/simple_mudflap_test.c:7

-ignore-fflush

By default, Mudflap will warn when a file descriptor is fflushed if that file descriptor was not registered as a Mudflap object. This can happen with the standard stdin/stdout file descriptors. If a lot of these warnings are seen, they can be suppressed with the -ignore-fflush option.

-register-anon-mmaps

Memory can be allocated through anonymous mmaps. However, by default, Mudflap will not register the mmap as a valid Mudflap object, and so any access to it will cause a warning. The reason for this is that pthread stacks are implemented using an anonymous mmap, so if they were automatically registered then any misuse of stack-allocated memory in pthreads would be missed. If your application regularly, and correctly, accesses anonymous mmaps then this may trigger large number of unwanted warnings which can be suppressed with the -register-anon-mmaps option. Clearly, however, this will also suppress any stack-related warnings generated by pthreads.

More information

The official Mudflap documentation is available on the GCC wiki: http://gcc.gnu.org/wiki/Mudflap_Pointer_Debugging

Architecture: