blob: ba76c40bee4c622289e41647d51f8692beac45cb [file] [log] [blame]
sewardjcb2288b2007-12-02 02:08:17 +00001
sewardj99a2ceb2007-11-09 12:30:36 +00002Title
3=====
sewardjcb2288b2007-12-02 02:08:17 +00004
sewardj99a2ceb2007-11-09 12:30:36 +00005Omega - A Valgrind tool for instant memory leak detection.
sewardjcb2288b2007-12-02 02:08:17 +00006
7Designed by Bryan "Brain Murders" Meredith with grateful thanks to the
8Valgrind team for making their tool and techniques available under the
9GPL and my employer Apertio (www.apertio.com) for allowing the use of
10their time, equipment for 64bit testing and providing moral support.
sewardj99a2ceb2007-11-09 12:30:36 +000011
12Synopsis
13========
sewardjcb2288b2007-12-02 02:08:17 +000014
15Whilst Valgrind's MemCheck tool can currently detect and report that a
16memory leak has occurred, the debugging output only shows where the
17memory that has leaked was allocated. There are no clues as to where
18the last reference to the allocated block was lost. Omega uses a
19modified version of MemCheck's "definedness" ('V' bit tracking)
20technique in order to help track pointers to allocated memory,
21outputting debugging information when the final (hence Omega) pointer
22to an allocated block is over-written or lost through a call to free()
23or the stack unwinding.
sewardj99a2ceb2007-11-09 12:30:36 +000024
25How it Works
26============
sewardj99a2ceb2007-11-09 12:30:36 +000027
sewardjcb2288b2007-12-02 02:08:17 +000028The main task in tracking leaks is when a checking whenever a value is
29written into memory or a register. This can result in the creation of
30a new reference to an allocated block, the destruction of a current
31reference to an allocated block or both. If we determine that either
32the register to be written or the memory location to be written
33contains a pointer that we are tracking, we update our tracking system
34and report if we are losing the last pointer to a block.
35
36Because checking every single write to memory causes a huge overhead,
37we make a couple of assumptions about what constitutes a pointer in
38order to reduce hash table lookups of the internal data. In order to
39optimise checking for pointers during free() and stack unwinding, we
40maintain a set of PBits (Pointer Bits) that allow us to quickly check
41a range of addresses for pointers that will be lost.
sewardj99a2ceb2007-11-09 12:30:36 +000042
43A Simple Example
44----------------
sewardj99a2ceb2007-11-09 12:30:36 +000045
sewardjcb2288b2007-12-02 02:08:17 +000046The program under test calls malloc (or one of the other heap
47allocation functions). We generate an internal record to track the
48address and size of the new block.
sewardj99a2ceb2007-11-09 12:30:36 +000049
sewardjcb2288b2007-12-02 02:08:17 +000050At each time we write to memory or a register is loaded, we check to
51see if we have a tracked pointer record for the location about to be
52written. If so, we remove this record and decrement the reference
53count for the block that it pointed to, generating an alarm if this
54was the last reference. We check if the value that we are writing
55matches the address of an allocated block. If we get a match, we add a
56tracked pointer record for the written address and increment the
57reference count. To speed things up, the internal records are stored
58in hash tables.
59
60When we call free (or one of the other heap de-allocation functions),
61we do cleanup processing on our internal record. There are two key
62activities that must be performed at this point.
sewardj99a2ceb2007-11-09 12:30:36 +000063
641) Clear and deallocate any hanging pointers.
sewardjcb2288b2007-12-02 02:08:17 +000065
662) Recursively remove references to any pointers that are within the
67 memory area that we are about to free.
sewardj99a2ceb2007-11-09 12:30:36 +000068
69As an option, during stage 1 we could report on the hanging pointers.
70
sewardjcb2288b2007-12-02 02:08:17 +000071Note that stack unwinding also performs stage 2 to ensure that we
72don't leak through automatic variables going out of scope.
sewardj99a2ceb2007-11-09 12:30:36 +000073
74'P' bit Propagation
75-------------------
sewardjcb2288b2007-12-02 02:08:17 +000076
77Each time we see an address of a memory block being written into an
78address or register, in addition to setting up the tracked pointer
79record, we also set a PBit to show that there is a tracked record for
80the address. By using PBit lookups and caching the PBit nodes between
81lookups (along with a dedicated PBit node for registers) we can get a
82significant performance gain. The time when PBits really come into
83their own is when we need to clear all of the tracked pointer records
84from a range of memory ie. invalidating the stack, calling
85free(). Using the PBit mechanism, we can check upto 64K in one
86go. This can be a huge gain as many structures do not hold nested
87pointers to allocated memory.
sewardj99a2ceb2007-11-09 12:30:36 +000088
89Stuff that I really want to add
90===============================
sewardjcb2288b2007-12-02 02:08:17 +000091
92Client Calls - This would allow us to track client based memory pool
93implementations, MALLOC_LIKE_BLOCK() etc.
94
95Summary Report - I want some feedback on what the output of the Omega
96should be so watch this space.
97
98Suppression Support - I don't know how much this is needed but it
99would probably be worthwhile.
sewardj99a2ceb2007-11-09 12:30:36 +0000100
101What We Can Detect
102==================
sewardjcb2288b2007-12-02 02:08:17 +0000103
sewardj99a2ceb2007-11-09 12:30:36 +0000104Using the above techniques, we can track the following leaks:
105
106Simple over-write of a tracked pointer.
sewardj99a2ceb2007-11-09 12:30:36 +0000107
sewardjcb2288b2007-12-02 02:08:17 +0000108 lastP = blah;
109
110Tracked pointer being modified (we wont raise a leak report on this -
111we will track the offset within the block - see "Shadowing").
112
113 lastP++;
sewardj99a2ceb2007-11-09 12:30:36 +0000114
115Automatic variable going out of scope.
sewardjcb2288b2007-12-02 02:08:17 +0000116
117 {
118 void *lastP = malloc(64);
119 return;
120 }
sewardj99a2ceb2007-11-09 12:30:36 +0000121
122Tracked pointer within allocated block being returned to OS.
sewardj99a2ceb2007-11-09 12:30:36 +0000123
sewardjcb2288b2007-12-02 02:08:17 +0000124 {
125 void *arrayP = malloc(10 * sizeof(void *));
126 arrayP[1] = malloc(64);
127 free(arrayP);
128 }
sewardj99a2ceb2007-11-09 12:30:36 +0000129
130Shadowing
131=========
sewardj99a2ceb2007-11-09 12:30:36 +0000132
sewardjcb2288b2007-12-02 02:08:17 +0000133This helps to solve the problem of where a program does its own memory
134management of the kind:
sewardj99a2ceb2007-11-09 12:30:36 +0000135
sewardjcb2288b2007-12-02 02:08:17 +0000136 1 secret *foo = malloc(sizeof(bar) + sizeof(secret) + alignment_correction);
137 2 foo->secret_stuff = magic_key;
138 3 etc.
139 4 foo++;
140 5 return (bar*)foo;
sewardj99a2ceb2007-11-09 12:30:36 +0000141
sewardjcb2288b2007-12-02 02:08:17 +0000142If the pointer to foo is shadowed at some internal offset to the block
143start, we create a shadow record and link it to the main block so that
144we can track references to either. Without this we do a leak alert at
145line 4 instead which is undesireable. There can only be one shadow to
146a block unless we really need more and someone wants to code it and
147send me a patch.
sewardj99a2ceb2007-11-09 12:30:36 +0000148
149What We Don't Detect
150--------------------
sewardj99a2ceb2007-11-09 12:30:36 +0000151
sewardjcb2288b2007-12-02 02:08:17 +0000152Actually, we do pretty well here but there are a couple of things you
153need to know about.
sewardj99a2ceb2007-11-09 12:30:36 +0000154
sewardjcb2288b2007-12-02 02:08:17 +00001551) We track pointers in registers. Therefore, whilst the final code
156 reference (on the stack say) may be lost, the pointer can (and
157 does) live on within a register until the register is
158 overwritten. The best way to help prevent this from making late
159 reports is to compile with -O0. On x86, this makes quite a
160 difference, especially to non-trivial functions.
161
1622) Some code is a little naughty when it comes to memory blocks that
163 have been returned to the OS. Memcheck reports these read accesses
164 to free()ed blocks as illegal reads. Omega also reports them as it
165 gets annoyed when it has just reported a block as leaked only for a
166 pointer to appear from "no-where". (Calling free() on a block does
167 not erase the contents of the block so even though Omega removes
168 all tracked pointer records for addresses within the block, the
169 pointers themselves still exist. Once one of these pointers is
170 read, Omega tracks it being loaded into a register at which point,
171 it complains and resumes tracking the "leaked" block.)
sewardj99a2ceb2007-11-09 12:30:36 +0000172
173What Next?
174==========
sewardjcb2288b2007-12-02 02:08:17 +0000175
sewardj99a2ceb2007-11-09 12:30:36 +0000176Feedback!!!
177
sewardjcb2288b2007-12-02 02:08:17 +0000178The core of the tool is done and working. Now I need feedback from
179anyone out there that is interested in using it so I can make the
180output as usefull as it can be.
sewardj99a2ceb2007-11-09 12:30:36 +0000181
sewardjcb2288b2007-12-02 02:08:17 +0000182If anyone is interested in helping me out on this, send your
183patches. I hope to get this accepted into Valgrind so it can get some
184serious attention but I dont know if that will happen so I will try to
185maintain a patch against svn or a tar of the whole thing if that gets
186too troublesome.
sewardj99a2ceb2007-11-09 12:30:36 +0000187
sewardjcb2288b2007-12-02 02:08:17 +0000188Bryan "Brain Murders" Meredith. The current maintainer of Omega is
189Rich Coe <richard.coe@med.ge.com>. Please send all email regarding
190Omega to Rich.