blob: 2af8510bd6d279eb277a24e3180b660875ac0652 [file] [log] [blame]
sewardj99a2ceb2007-11-09 12:30:36 +00001/*--------------------------------------------------------------------*/
2/*--- The Omega tool: traces memory allocations and alerts when ---*/
3/*--- the final reference to an allocated block dies. ---*/
4/*--- o_main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Omega, a Valgrind tool for detecting memory
9 leaks as they occur.
10
11 Copyright (C) 2006-2007 Bryan "Brain Murders" Meredith
12 omega@brainmurders.eclipse.co.uk
13 (A note of personal thanks to my employers at Apertio (www.apertio.com)
14 for allowing the use of their time, equipment for 64bit testing and
15 providing moral support.)
16
17 Partly based upon other Valgrind tools
sewardj39f34232007-11-09 23:02:28 +000018 Copyright (C) 2000-2007 Julian Seward, Nicholas Nethercote et al.
sewardj99a2ceb2007-11-09 12:30:36 +000019 jseward@acm.org
20 njn@valgrind.org
21
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful, but
28 WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35 02111-1307, USA.
36
37 The GNU General Public License is contained in the file COPYING.
38*/
39
40/*
41** Read the tool documentation for an explaination of the ideas
42** behind this implementation.
43*/
44
45#include "pub_tool_basics.h"
46#include "pub_tool_libcassert.h"
47#include "pub_tool_tooliface.h"
48#include "pub_tool_hashtable.h"
49#include "pub_tool_libcbase.h"
50#include "pub_tool_libcprint.h"
51#include "pub_tool_libcassert.h"
52#include "pub_tool_mallocfree.h"
53#include "pub_tool_replacemalloc.h"
54#include "pub_tool_machine.h"
55#include "pub_tool_threadstate.h"
56#include "pub_tool_stacktrace.h"
57#include "pub_tool_options.h"
58#include "pub_tool_clreq.h"
59
60#include "coregrind/pub_core_options.h"
61#include "coregrind/pub_core_debugger.h"
62
63#include "libvex_guest_offsets.h"
64
65#include "omega.h"
66
67/*
68** A little sanity in a mad, mad world.
69*/
70#if !(VG_WORDSIZE == 4) && !(VG_WORDSIZE == 8)
71/*
72** We don't handle anything else yet.
73*/
74#error Unsupported VG_WORDSIZE
75#endif
76
77/*
78** 4 lots of debug - always, general, memory and pbit.
79** general, memory and pbit can also be turned off with a master switch.
80** You wont want any of this on unless you are hacking the source around.
81*/
82#define NO_DEBUG(fmt, args...)
83#define O_DEBUG(fmt, args...) VG_(message)(Vg_DebugMsg, fmt, ## args)
84
85// Set to 0 to remove almost all debug from compiled tool
86#if 0
87
88static Bool o_traceMem = True; //False;
89static Bool o_tracePBit = False;
90static Bool o_traceGeneral = True; //False;
91static Bool o_traceStop = True;
92
93#define O_GDEBUG(fmt, args...) \
94 if(o_traceGeneral && !o_traceStop) \
95 { \
96 VG_(message)(Vg_DebugMsg, fmt, ## args); \
97 }
98
99#define O_MDEBUG(fmt, args...) \
100 if(o_traceMem && !o_traceStop) \
101 { \
102 VG_(message)(Vg_DebugMsg, fmt, ## args); \
103 }
104
105#define O_PDEBUG(fmt, args...) \
106 if(o_tracePBit && !o_traceStop) \
107 { \
108 VG_(message)(Vg_DebugMsg, fmt, ## args); \
109 }
110
111#define O_TRACE_ON() {o_traceStop = False;}
112#define O_TRACE_OFF() {o_traceStop = True;}
113#define O_TRACE_MEM_ON() {o_traceMem = True;}
114#define O_TRACE_MEM_OFF() {o_traceMem = False;}
115#define O_TRACE_PBIT_ON() {o_tracePBit = True;}
116#define O_TRACE_PBIT_OFF() {o_tracePBit = False;}
117#define O_TRACE_GENERAL_ON() {o_traceGeneral = True;}
118#define O_TRACE_GENERAL_OFF() {o_traceGeneral = False;}
119#define O_MASTER_DEBUG 1
120
121/*
122** Should we instrument memory loads for debugging?
123** Comment out to stop register loads from showing.
124*/
125//#define O_TRACK_LOADS 1
126#else
127/*
128** No debug included at all.
129*/
130#define O_GDEBUG(fmt, args...)
131#define O_MDEBUG(fmt, args...)
132#define O_PDEBUG(fmt, args...)
133#define O_TRACE_ON()
134#define O_TRACE_OFF()
135#define O_TRACE_MEM_ON()
136#define O_TRACE_MEM_OFF()
137#define O_TRACE_PBIT_ON()
138#define O_TRACE_PBIT_OFF()
139#define O_TRACE_GENERAL_ON()
140#define O_TRACE_GENERAL_OFF()
141
142#endif
143
144/*
145** Need somewhere to give addresses to tracked pointers in registers.
146** We dont write to the locations, just use their addresses.
147** To make it easy to see, use the very top 64K of memory.
148** Note that we might have to map this somewhere else if this is in user space.
149*/
150#if (VG_WORDSIZE == 4)
151#define FAKE_REG_BASE 0xFFFF0000
152#else
153#define FAKE_REG_BASE 0xFFFFFFFFFFFF0000
154#endif
155#define MAP_TO_REG(tid, offset) \
156 (FAKE_REG_BASE + (0x0100 * ((tid) - 1)) + (offset))
157#define OFFSET_FROM_REG(regAddress) \
158 ((regAddress) & 0x00ff)
159#define IS_REG(addr) ((addr >= FAKE_REG_BASE) ? !0 : 0)
160
161static UInt o_isReturnIgnoreReg(Addr reg)
162{
163 /*
164 ** Indicate registers that are 'scratch' registers and should be ignored on
165 ** function return for tracked pointer purposes.
sewardj4cff56d2007-11-10 13:33:56 +0000166
167 JRS 10 Nov 2007: Seems to me this should be somehow related to
168 caller- vs callee-saved classification of registers, but not sure.
169 See docs/internal/register-uses.txt for a summary.
170
171 This fn really ought to be partitioned along VGP_arch_os lines
172 rather than VGA_arch lines, since register conventions are OS
173 dependant as well as CPU dependant.
sewardj99a2ceb2007-11-09 12:30:36 +0000174 */
sewardj4cff56d2007-11-10 13:33:56 +0000175#if defined(VGA_x86)
sewardj99a2ceb2007-11-09 12:30:36 +0000176 switch(OFFSET_FROM_REG(reg))
177 {
sewardj99a2ceb2007-11-09 12:30:36 +0000178 case OFFSET_x86_ECX:
179 case OFFSET_x86_EDX:
sewardj4cff56d2007-11-10 13:33:56 +0000180 return 1;
181 default:
182 return 0;
183 }
sewardj99a2ceb2007-11-09 12:30:36 +0000184#elif defined(VGA_amd64)
sewardj4cff56d2007-11-10 13:33:56 +0000185 switch(OFFSET_FROM_REG(reg))
186 {
sewardj99a2ceb2007-11-09 12:30:36 +0000187 case OFFSET_amd64_RCX:
188 case OFFSET_amd64_RSI:
189 case OFFSET_amd64_RDI:
190 case OFFSET_amd64_R8:
191 case OFFSET_amd64_R9:
192 case OFFSET_amd64_R10:
193 case OFFSET_amd64_R11:
sewardj99a2ceb2007-11-09 12:30:36 +0000194 return 1;
sewardj99a2ceb2007-11-09 12:30:36 +0000195 default:
sewardj4cff56d2007-11-10 13:33:56 +0000196 return 0;
sewardj99a2ceb2007-11-09 12:30:36 +0000197 }
sewardj4cff56d2007-11-10 13:33:56 +0000198#elif defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjdcbb8d32007-11-26 21:34:30 +0000199 VG_(printf)("\nOmega does not currently work on PowerPC/POWER platforms."
sewardj4cff56d2007-11-10 13:33:56 +0000200 " Sorry.\n\n");
201 VG_(exit)(0);
202#else
203# error "Unknown arch"
204#endif
205
206 /*NOTREACHED*/
207 tl_assert(0);
sewardj99a2ceb2007-11-09 12:30:36 +0000208}
209
210
211/*------------------------------------------------------------*/
212/*--- Command Line Option Flags and Values ---*/
213/*------------------------------------------------------------*/
214/*
215** Should we track all memory block allocations or just blocks
216** indicated to us with the MALLOCLIKE_BLOCK user request?
217*/
218static Bool o_onlyMallocLike = False;
219/*
220** Should we show memory that leaks due to a block leaking?
221*/
222static Bool o_showIndirect = False;
223/*
224** Should we show pointers to a block that is deallocated?
225*/
226static Bool o_showHanging = False;
227/*
228** Should we show blocks with only circular references?
229*/
230static Bool o_showCircular = False;
231/*
232** Show interal stats at the end of the run.
233*/
234static Bool o_showInternStats = False;
235/*
236** Should we only show the summary report.
237*/
238static Bool o_showSummaryOnly = True;
239
240/*
241** Should we clear leaked blocks to try and force an error.
242*/
243static Bool o_poison = False;
244
245/*
246** These figures are pure wet finger in the air guestimates.
247** If the user has _lots_ of memory blocks / tracked pointers, they can
248** increase the prime number on the command line.
249*/
250/*
251** Number of PBit Node entries in the hash table.
252*/
253static UInt o_pbitNodeHashSize = 1031;
254/*
255** Number of MemBlock entries in the hash table.
256*/
257static UInt o_memblockHashSize = 65537;
258/*
259** Number of Tracked Pointer entries in the hash table.
260*/
261static UInt o_trackedPointerHashSize = 65537;
262
263/*------------------------------------------------------------*/
264/*--- Statistics ---*/
265/*------------------------------------------------------------*/
266typedef struct
267{
268 unsigned long liveTrackedPointers;
269 unsigned long trackedPointersAllocated;
270 unsigned long liveMemoryBlocks;
271 unsigned long memoryBlocksAllocated;
272 unsigned long shadowMemoryBlocksAllocated;
273 unsigned long memoryBlocksLeaked;
274 unsigned long memoryBlocksLostAndFound;
275 unsigned long pbitNodes;
276} Stats;
277
278static Stats o_stats;
279
280/*------------------------------------------------------------*/
281/*--- PBit Tracking ---*/
282/*------------------------------------------------------------*/
283/*
284** Setup constants for PBit tracking.
285*/
286#if (VG_WORDSIZE == 4)
287#define PBIT_MAJOR_SHIFT 7
288#define PBIT_MINOR_SHIFT 2
289#define PBIT_MINOR_MASK 0x1F
290#elif (VG_WORDSIZE == 8)
291#define PBIT_MAJOR_SHIFT 8
292#define PBIT_MINOR_SHIFT 3
293#define PBIT_MINOR_MASK 0x1F
294#endif
295
296/*
297** Work out how many bytes a UInt of pbits covers
298*/
299#define PBIT_RANGE (sizeof(UInt) * 8 * VG_WORDSIZE)
300
301/*
302** Number of UInts to store in a node so that the node covers 64K
303*/
304#define PBIT_NODE_UINTS ((64 * 1024) / PBIT_RANGE)
305
306/*
307** Memory range covered by a pbit node
308*/
309#define PBIT_NODE_RANGE 0xFFFF
310#define PBIT_NODE_RANGE_MASK (~PBIT_NODE_RANGE)
311#define PBIT_NODE_SHIFT 16
312
313/* Define the pbit storage node. */
314typedef struct {
315 VgHashNode hdr; // Must be first item
316 UInt set_bits; // Count of set bits
317 UInt pbits[PBIT_NODE_UINTS]; // 64K of coverage
318} PBitNode;
319
320/*
321** We use a hash table to track the p-bits.
322** The node is defined just above. The key to a node is the memory
323** address right shifted PBIT_NODE_SHIFT bits.
324*/
325static VgHashTable o_PBits = NULL;
326
327/*
328** For speed, we keep a node to track register allocations and cache the last
329** node that was accessed.
330*/
331static PBitNode o_registerPBits;
332static PBitNode *o_lastPBitNode = NULL;
333static Addr o_lastPBitNodeKey = 0;
334
335/*
336** Convenience macros for working out which bit in which PBIT_NODE_UINT we
337** wish to address.
338*/
339#define PBIT_MAJOR_INDEX( addr ) \
340 (((addr) & PBIT_NODE_RANGE) >> PBIT_MAJOR_SHIFT)
341#define PBIT_MINOR_INDEX( addr ) \
342 (((addr) >> PBIT_MINOR_SHIFT) & PBIT_MINOR_MASK)
343#define PBIT_KEY( addr ) ((Addr)(addr) >> PBIT_NODE_SHIFT)
344
345typedef struct {
346 PBitNode *node;
347 Addr currentAddress;
348 Addr finalAddress;
349} PBitContext;
350
351/*
352** Helper functions for doing fast searches through an address range.
353*/
354static Addr o_firstPBit(PBitContext *context, Addr start, SizeT length);
355static Addr o_nextPBit(PBitContext *context);
356
357/*
358** Basic PBit manipulation.
359*/
360static PBitNode *o_getPBitNode(Addr address, Bool create)
361{
362 Addr key = PBIT_KEY(address);
363
364 O_PDEBUG("o_getPBitNode(%p%s)", address,
365 create ? ", create" : "");
366
367 O_PDEBUG("o_getPBitNode last node %p, last key %p",
368 o_lastPBitNode, o_lastPBitNodeKey);
369
370 if(IS_REG(address))
371 {
372 /*
373 ** This is a register - use the register PBit node.
374 */
375 O_PDEBUG("o_getPBitNode returning register PBit node");
376 return &o_registerPBits;
377 }
378 else if((key == o_lastPBitNodeKey) &&
379 (o_lastPBitNode || !create))
380 {
381 /*
382 ** This is in the same node as last time.
383 */
384 O_PDEBUG("o_getPBitNode returning last PBit node");
385 return o_lastPBitNode;
386 }
387 else
388 {
389 /*
390 ** It's a new node.
391 ** Look it up then cache both the node and the node key.
392 */
393 o_lastPBitNode = VG_(HT_lookup)(o_PBits, key);
394 o_lastPBitNodeKey = key;
395
396 if(!o_lastPBitNode & create)
397 {
398 /*
399 ** We don't have a node for this address. Create one now.
400 */
401 o_lastPBitNode = VG_(malloc)( sizeof(PBitNode) );
402 tl_assert(o_lastPBitNode);
403 VG_(memset)(o_lastPBitNode, 0, sizeof(PBitNode));
404 o_lastPBitNode->hdr.key = key;
405
406 /*
407 ** Add this node into the hash table.
408 */
409 VG_(HT_add_node)(o_PBits, o_lastPBitNode);
410
411 O_PDEBUG("Created PBit node beginning %p for address %p",
412 (key << PBIT_NODE_SHIFT),
413 address);
414
415 o_stats.pbitNodes++;
416
417 }
418 O_PDEBUG("o_getPBitNode returning lookup PBit node");
419
420 return o_lastPBitNode;
421 }
422}
423
424static void o_setPBit( Addr address )
425{
426 /*
427 ** Retrieve the node that contains this address then set the appropriate bit.
428 */
429 PBitNode *pbn = o_getPBitNode(address, True);
430
431 O_PDEBUG("o_setPBit(%p)", address);
432
433 O_PDEBUG("o_setPBit - node = %p, MAJOR = %d, MINOR = %d",
434 pbn,
435 PBIT_MAJOR_INDEX(address),
436 PBIT_MINOR_INDEX(address));
437 /*
438 ** The PBit might not be clear so only tweak things if it is.
439 */
440 if(!(pbn->pbits[PBIT_MAJOR_INDEX(address)] &
441 (1 << PBIT_MINOR_INDEX(address))))
442 {
443 /*
444 ** Set the pbit and increment the convenience count.
445 */
446 pbn->pbits[PBIT_MAJOR_INDEX(address)] |=
447 (1 << PBIT_MINOR_INDEX(address));
448 pbn->set_bits++;
449 }
450
451 O_PDEBUG("o_setPBit done");
452 return;
453}
454
455static void o_clearPBit( Addr address )
456{
457 /*
458 ** Retrieve the node that contains this address. If the node does not exist,
459 ** we assert as this really shouldnt happen.
460 */
461 PBitNode *pbn = o_getPBitNode(address, False);
462
463 O_PDEBUG("o_clearPBit(%p)", address);
464
465 tl_assert(pbn);
466
467 /*
468 ** The PBit might not be set so only tweak things if it is.
469 */
470 if(pbn->pbits[PBIT_MAJOR_INDEX(address)] &
471 (1 << PBIT_MINOR_INDEX(address)))
472 {
473 /*
474 ** Clear the pbit and decrement the convenience count.
475 */
476 pbn->pbits[PBIT_MAJOR_INDEX(address)] &=
477 ~(1 << PBIT_MINOR_INDEX(address));
478 pbn->set_bits--;
479 }
480
481 return;
482}
483
484static Bool o_isPBitSet( Addr address )
485{
486 /*
487 ** Retrieve the node that contains this address. If the node does not exist,
488 ** the Pbit isnt set ;-)
489 */
490 PBitNode *pbn = o_getPBitNode(address, False);
491
492 O_PDEBUG("o_isPBitSet(%p)", address);
493
494 if(!pbn)
495 return 0;
496
497 /*
498 ** Return the Pbit status.
499 */
500 return ((pbn->pbits[PBIT_MAJOR_INDEX(address)] &
501 (1 << PBIT_MINOR_INDEX(address))) != 0);
502}
503
504/*
505** For ease of range checking PBits, we provide the following two functions.
506** The idea is that you call the first one with your start address and range.
507** It returns the first address that is marked by a PBit or 0 if the range is
508** clear (we overlap the supplied range in order to check partial pointers at
509** each end). By calling the second one with the same context until it returns
510** zero, you get all of the PBits within the range. You supply the context so
511** we should be able to nest calls if need be.
512*/
513static Addr o_firstPBit(PBitContext *context, Addr start, SizeT length)
514{
515 const Addr MASK = ~(VG_WORDSIZE - 1);
516
517 tl_assert(context);
518 tl_assert(start > VG_WORDSIZE);
519
520 O_PDEBUG("o_firstPBit(%p, %p)", start, length);
521 /*
522 ** Optimisation for single pointer ranges and bizarre 0 length calls.
523 */
524 if(!length)
525 {
526 return 0;
527 }
528 else if(length <= VG_WORDSIZE)
529 {
530 /*
531 ** Set the current address to 0.
532 */
533 context->currentAddress = 0;
534 return (o_isPBitSet(start)) ? (start & MASK) : 0;
535 }
536
537 /*
538 ** Setup the current and final addresses. Note that we set the current
539 ** address to one aligned address below because of how nextPBit works.
540 */
541 context->currentAddress = ((start & MASK) - VG_WORDSIZE);
542 context->finalAddress = ((start + length - 1) & MASK);
543
544 context->node = o_getPBitNode(context->currentAddress, False);
545
546 O_PDEBUG("o_firstPBit current %p, final %p",
547 context->currentAddress, context->finalAddress);
548
549 return o_nextPBit(context);
550}
551
552static Addr o_nextPBit(PBitContext *context)
553{
554 /*
555 ** Current address is the last address we returned.
556 ** We keep going until we have checked final address.
557 */
558 UInt pbits;
559 Addr startAddr;
560 Addr foundAddr = 0;
561 UInt majorIndex;
562 UInt minorIndex;
563
564 tl_assert(context);
565
566 /*
567 ** When the current address is set to 0, we just exit.
568 */
569 if(context->currentAddress == 0)
570 {
571 return 0;
572 }
573
574 O_PDEBUG("o_nextPBit(%p,%p)",
575 context->currentAddress, context->finalAddress);
576
577 while(!foundAddr &&
578 (context->currentAddress <= context->finalAddress))
579 {
580 /*
581 ** Check if we need another node and get it if we do.
582 */
583 startAddr = context->currentAddress + VG_WORDSIZE;
584
585 O_PDEBUG("o_nextPBit c %p s %p", context->currentAddress, startAddr);
586
587 if(PBIT_KEY(context->currentAddress) !=
588 PBIT_KEY(startAddr))
589 {
590 O_PDEBUG("o_nextPBit getting next node %p",
591 startAddr & PBIT_NODE_RANGE_MASK);
592
593 context->node = o_getPBitNode(startAddr, False);
594 }
595 context->currentAddress = startAddr;
596
597 /*
598 ** Check if we have a node - skip to next node (final address
599 ** permitting) if we dont. This is the 64k of addresses at a time
600 ** comparison.
601 */
602 if(!context->node)
603 {
604 O_PDEBUG("o_nextPbit: no node.");
605
606 if(context->currentAddress > context->finalAddress)
607 {
608 /*
609 ** We have passed the final address - time to stop looking.
610 */
611 O_PDEBUG("o_nextPbit: current > final");
612 continue;
613 }
614 else if((context->currentAddress & PBIT_NODE_RANGE_MASK) !=
615 (context->finalAddress & PBIT_NODE_RANGE_MASK))
616 {
617 /*
618 ** Align to VG_WORDSIZE below the next node range then loop.
619 */
620 O_PDEBUG("o_nextPbit: aligning to next node. (%p, %p)",
621 context->currentAddress,
622 context->finalAddress);
623
624 context->currentAddress += (PBIT_NODE_RANGE + 1);
625 context->currentAddress &= PBIT_NODE_RANGE_MASK;
626 context->currentAddress -= VG_WORDSIZE;
627
628 O_PDEBUG("o_nextPbit: aligned to %p",
629 context->currentAddress);
630
631 continue;
632 }
633 else
634 {
635 /*
636 ** Node range is the same but no node == no pbits.
637 */
638 context->currentAddress = context->finalAddress + VG_WORDSIZE;
639 break;
640 }
641 }
642
643 /*
644 ** The index of the PBit array item we want to check then get the pbits.
645 */
646 majorIndex = PBIT_MAJOR_INDEX(context->currentAddress);
647 minorIndex = PBIT_MINOR_INDEX(context->currentAddress);
648 pbits = context->node->pbits[majorIndex];
649
650 /*
651 ** Mask off addresses below the current address then test.
652 */
653 pbits &= ~((1 << minorIndex) - 1);
654
655 O_PDEBUG("o_nextPbit: major %d, minor %d, bit %p",
656 majorIndex, minorIndex, pbits);
657 /*
658 ** This checks up to PBIT_RANGE at a time (256 addresses on a
659 ** 64bit machine).
660 */
661 if(!pbits)
662 {
663 /*
664 ** No pbits set in this UInt. Set the current address to VG_WORDSIZE
665 ** below the next UInt then loop around.
666 */
667 context->currentAddress += PBIT_RANGE;
668 context->currentAddress &= ~(PBIT_RANGE - 1);
669 context->currentAddress -= VG_WORDSIZE;
670
671 continue;
672 }
673
674 /*
675 ** Now we walk the UInt a bit at a time.
676 */
677 for(;
678 ((minorIndex <= PBIT_MINOR_MASK) &&
679 (context->currentAddress <= context->finalAddress))
680 ; minorIndex++)
681 {
682 if(pbits & (1 << minorIndex))
683 {
684 /*
685 ** We have a match.
686 */
687 foundAddr = context->currentAddress;
688 O_PDEBUG("o_nextPbit found %p", foundAddr);
689 break;
690 }
691 else
692 {
693 context->currentAddress += VG_WORDSIZE;
694 }
695 }
696 }
697
698 /*
699 ** Final range check.
700 */
701 if(foundAddr > context->finalAddress)
702 {
703 foundAddr = 0;
704 }
705
706 /*
707 ** Store the result so that we know where to start from next time.
708 */
709 context->currentAddress = foundAddr;
710
711 O_PDEBUG("o_nextPbit returning %p", foundAddr);
712
713 return foundAddr;
714}
715
716/*------------------------------------------------------------*/
717/*--- Error Report and Suppression Tracking ---*/
718/*------------------------------------------------------------*/
719/*
720** We hold a doubley linked list of Exe contexts for leaks and suppressions.
721** If a block is tagged as leaked then comes back to life, we move it
722** into the suppression list. We always check the suppression list first
723** before adding a record to the leaked list.
724** We keep a count of how may times a record matches as it saves space.
725*/
726struct _BlockRecord {
727 struct _BlockRecord *next;
728 struct _BlockRecord *prev;
729 ExeContext *allocated;
730 ExeContext *leaked;
731 UInt bytes;
732 SizeT count;
733};
734
735typedef struct _BlockRecord BlockRecord;
736
737typedef struct {
738 BlockRecord *start;
739 BlockRecord *end;
740} BlockRecordList;
741static BlockRecordList o_leakRecords = {NULL, NULL};
742static BlockRecordList o_suppressionRecords = {NULL, NULL};
743
744#define DUMP_BLOCK(block) \
745 O_DEBUG("n %p, p %p, a %p, l %p, c %d b %p", \
746 block->next, block->prev, \
747 block->allocated, block->leaked, block->count, \
748 block->bytes);
749
750/*
751** List handling - we need to be able to add and remove a single block
752** from anywhere in the list but the chances are, removals will come from
753** the end, hence using a doubly linked list. We also need to walk the list
754** to find a matching item. Again, we do this backwards as it tends to get
755** a match faster in the case of moving newly leaked block records into
756** the suppression list.
757*/
758static void o_addBlockRecord(BlockRecordList *list, BlockRecord *item)
759{
760 /*
761 ** Catch start case.
762 */
763 tl_assert(list && item);
764
765 NO_DEBUG("o_addBlockRecord pre()");
766 //DUMP_BLOCK(item);
767
768 if(!list->start)
769 {
770 list->start = list->end = item;
771 item->prev = item->next = NULL;
772 }
773 else
774 {
775 /*
776 ** OK, add it onto the end.
777 */
778 item->prev = list->end;
779 item->next = NULL;
780 list->end->next = item;
781 list->end = item;
782 }
783 NO_DEBUG("o_addBlockRecord post()");
784 //DUMP_BLOCK(item);
785 return;
786}
787
788static void o_removeBlockRecord(BlockRecordList *list, BlockRecord *item)
789{
790 /*
791 ** We don't check that the item is in the list.
792 ** Ensure you check with the findBlockRecord function.
793 */
794 tl_assert(list && item);
795
796 NO_DEBUG("o_removeBlockRecord pre()");
797 //DUMP_BLOCK(item);
798 if(item->prev)
799 {
800 /*
801 ** Not at the start.
802 */
803 item->prev->next = item->next;
804 }
805 else
806 {
807 /*
808 ** At the start.
809 */
810 list->start = item->next;
811 }
812
813 if(item->next)
814 {
815 /*
816 ** Not at the end.
817 */
818 item->next->prev = item->prev;
819 }
820 else
821 {
822 /*
823 ** At the end.
824 */
825 list->end = item->prev;
826 }
827
828 NO_DEBUG("o_removeBlockRecord post()");
829 //DUMP_BLOCK(item);
830
831 return;
832}
833
834static BlockRecord *o_findBlockRecord(BlockRecordList *list,
835 ExeContext *allocated,
836 ExeContext *leaked)
837
838{
839 /*
840 ** Search backwards for the block record that matches the contexts.
841 ** We allow leaked to be null so that we can handle the circular checking
842 ** blocks as well which only have an allocated context.
843 */
844 BlockRecord *item = NULL;
845
846 tl_assert(list && allocated);
847
848 item = list->end;
849
850 while(item)
851 {
852 if(VG_(eq_ExeContext)(Vg_HighRes, item->allocated, allocated) &&
853 ((!item->leaked && !leaked) ||
854 ((item->leaked && leaked) &&
855 VG_(eq_ExeContext)(Vg_HighRes, item->leaked, leaked))))
856 {
857 break;
858 }
859
860 item = item->prev;
861 }
862
863 return item;
864}
865
866static Bool o_addLeakedBlock(ExeContext *allocated,
867 ExeContext *leaked,
868 SizeT size)
869{
870 BlockRecord *item = NULL;
871
872 tl_assert(allocated && leaked);
873
874 /*
875 ** See if we already have this block.
876 ** Check the suppression record first.
877 */
878 item = o_findBlockRecord(&o_suppressionRecords, allocated, leaked);
879
880 if(!item)
881 {
882 /*
883 ** Not in the suppression record.
884 ** Try the leaked block list.
885 */
886 item = o_findBlockRecord(&o_leakRecords, allocated, leaked);
887 }
888
889 if(item)
890 {
891 /*
892 ** Just increment the count.
893 */
894 item->count++;
895 item->bytes += size;
896 //O_DEBUG("o_addLeakedBlock - block exists");
897 //DUMP_BLOCK(item);
898 return False;
899 }
900 else
901 {
902 /*
903 ** Create a new block and add it to the leaked list.
904 */
905 item = VG_(malloc)(sizeof(BlockRecord));
906 tl_assert(item);
907
908 item->count = 1;
909 item->bytes = size;
910 item->next = item->prev = NULL;
911 item->allocated = allocated;
912 item->leaked = leaked;
913
914 o_addBlockRecord(&o_leakRecords, item);
915
916 return True;
917 }
918
919}
920
921static Bool o_addSuppressionBlock(ExeContext *allocated,
922 ExeContext *leaked)
923{
924 BlockRecord *item = NULL;
925
926 tl_assert(allocated && leaked);
927
928 /*
929 ** See if we already have this block.
930 ** Check the suppression record first.
931 */
932 item = o_findBlockRecord(&o_suppressionRecords, allocated, leaked);
933
934 if(!item)
935 {
936 /*
937 ** Not in the suppression record.
938 ** Try the leaked block list.
939 */
940 item = o_findBlockRecord(&o_leakRecords, allocated, leaked);
941
942 if(!item)
943 {
944 VG_(tool_panic)("suppressing block that didnt leak :-(");
945 }
946 else
947 {
948 /*
949 ** Move the block to the suppression list.
950 */
951 o_removeBlockRecord(&o_leakRecords, item);
952 o_addBlockRecord(&o_suppressionRecords, item);
953 }
954 }
955 else
956 {
957 /*
958 ** The block is already suppressed - just increase the count.
959 */
960 item->count++;
961
962 //O_DEBUG("o_addSuppressionBlock - block exists");
963 //DUMP_BLOCK(item);
964 return False;
965 }
966
967 return True;
968}
969
970/*------------------------------------------------------------*/
971/*--- Allocated Block and Pointer Tracking ---*/
972/*------------------------------------------------------------*/
973/*
974** Where these structures have address references, they are the address
975** of the item in client memory NOT the address of either of these
976** internal tracking structures.
977*/
978struct _MemBlock;
979typedef struct {
980 VgHashNode hdr; // Must be first item
981 Addr block; // Address of the allocated block start
982 SizeT length; // Length of the allocated block
983 struct _MemBlock *memBlock; // Pointer to the memblock
984} TrackedPointer;
985
986typedef struct _MemBlock {
987 VgHashNode hdr; // Must be first item
988 SizeT length; // Length of the allocated block
989 ExeContext *where; // Where the block was allocated
990 UInt refNum; // Number of back references
991 TrackedPointer **pointers; // Back references to TrackedPointer info
992 struct _MemBlock *shadowing; // Set to memblock of block that we shadow
993 struct _MemBlock *shadowed; // Set to memblock of our shadow
994 ExeContext *leaked; // Where we think the block leaked
995 UInt nonRegCount; // Non register tracked pointers
996 Int external; // Used in circular dependency checking
997
998 TrackedPointer *maybeLast; // Last live tracked pointer on function return
999 ExeContext *funcEnd; // matching exe context for the end of the function
1000 Bool doLeak; // Set if this block should leak on instruction
1001 // end. We have to make instructions atomic or we
1002 // go bang on things like xchng as there is no way
1003 // of telling which value gets overwritten first.
1004 struct _MemBlock *next; // Linked list of blocks that might be leaking at
1005 // instruction end.
1006 int depth; // Depth that the potential leak occurred at.
1007 TrackedPointer *wasLast; // Pointer t
1008
1009 UInt nonScratch; // Number of non-scratch registers.
1010} MemBlock;
1011
1012/*
1013** Shadows?
1014** This helps to solve the problem of where a program does its own memory
1015** management of the kind:
1016
10171 secret *foo = malloc(sizeof(bar) + sizeof(secret) + alignment_correction);
10182 foo->secret_stuff = magic_key;
10193 etc.
10204 foo++;
10215 return (bar*)foo;
1022
1023** If the pointer to foo is shadowed at some internal offset to the block
1024** start, we create a shadow record and link it to the main block so that
1025** we can track references to either. Without this we do a leak alert at
1026** line 4 instead which is undesireable.
1027**
1028** There can only be one shadow to a block unless we need more and someone
1029** wants to code it. A side effect of the current implementation allows a
1030** shadow of a shadow but it is explicitly blocked for now.
1031*/
1032
1033/*
1034** We use separate hash tables to track the pointers and allocated blocks.
1035** The key of each node is the address of the corresponding item in client
1036** memory, shifted right to remove the wasted bits caused by alignment of
1037** pointers in memory.
1038*/
1039#if (VG_WORDSIZE == 4)
1040#define TRACK_MINOR_SHIFT 2
1041#define TRACK_MINOR_MASK ~0x03
1042#elif (VG_WORDSIZE == 8)
1043#define TRACK_MINOR_SHIFT 3
1044#define TRACK_MINOR_MASK ~0x07
1045#endif
1046
1047#define TRACKED_KEY( a ) ((UWord)(a) >> TRACK_MINOR_SHIFT)
1048#define FROM_TRACKED_KEY( a ) ((UWord)(a) << TRACK_MINOR_SHIFT)
1049
1050/*
1051** Storage for the two hash tables we need.
1052*/
1053static VgHashTable o_MemBlocks = NULL;
1054static VgHashTable o_TrackedPointers = NULL;
1055
1056/*
1057** Start of a linked list of blocks that may be leaking during this original
1058** processor instruction. Instructions are broken down inside VEX so a single
1059** original instruction can become many VEX instructions. By not doing leak
1060** reports until the end of the original instruction, everything becomes
1061** atomic again - the stack moves and the popped value appears in the register
1062** in one movement rather than two which cause a leak if the stack is
1063** invalidated before the value appears in the register. xchng works both ways
1064** around and so on.
1065*/
1066static MemBlock *doLeakList = NULL;
1067static UInt doLeakListCount = 0;
1068static Bool doLeakNow = False;
1069
1070/*
1071** Set when we are removing pointers within a free()ed block.
1072*/
1073static Bool o_clearingBlock = False;
1074
1075/*
1076** Set when we are removing pointers within a free()ed block or a
1077** block that leaked. It shows the indirection level in cascades.
1078*/
1079static UInt o_indirectChecking = 0;
1080static ExeContext *o_indirectStack = NULL;
1081
1082/*
1083** Set when the stack is unwinding.
1084*/
1085static Bool o_stackUnwind = False;
1086
1087static void o_killRange(Addr start, SizeT length);
1088
1089/*
1090** This is set to stop us from tracking leaks once we exit main.
1091** (May well need a per thread flag to catch when threads exit as well.)
1092*/
1093static Bool o_inhibitLeakDetect = False;
1094
1095
1096static void o_cleanupTrackedPointers( MemBlock * mb )
1097{
1098 UInt pointerIndex;
1099
1100 for(pointerIndex = 0; pointerIndex < mb->refNum; pointerIndex++)
1101 {
1102 TrackedPointer *p =
1103 VG_(HT_remove)(o_TrackedPointers,
1104 mb->pointers[pointerIndex]->hdr.key);
1105
1106 tl_assert(p);
1107 O_GDEBUG("Removing tracked pointer at %p pointing to %p",
1108 FROM_TRACKED_KEY(p->hdr.key),
1109 mb->hdr.key);
1110
1111 /*
1112 ** Remove the PBit for this tracked pointer.
1113 */
1114 o_clearPBit(FROM_TRACKED_KEY(p->hdr.key));
1115
1116 /*
1117 ** Show any pointers to this block as we deallocate them.
1118 */
1119 if(o_showHanging)
1120 {
1121 if(IS_REG(FROM_TRACKED_KEY(p->hdr.key)))
1122 {
1123 /*
1124 ** Maybe decode registers to names later?
1125 */
1126 O_DEBUG("Removing hanging pointer in a register to block %p",
1127 p->block);
1128 }
1129 else
1130 {
1131 O_DEBUG("Removing hanging pointer at %p to block %p",
1132 FROM_TRACKED_KEY(p->hdr.key),
1133 p->block);
1134 }
1135 }
1136 VG_(free)(p);
1137 o_stats.liveTrackedPointers--;
1138 }
1139
1140 /*
1141 ** Free off the pointers back reference.
1142 */
1143 VG_(free)(mb->pointers);
1144 mb->pointers = NULL;
1145 mb->refNum = 0;
1146
1147 return;
1148}
1149
1150static void o_cleanupMemBlock( MemBlock **mbpp )
1151{
1152 MemBlock *mb;
1153
1154 O_GDEBUG("o_cleanupMemBlock(%p)", mbpp);
1155 /*
1156 ** Sanity check.
1157 */
1158 if(!mbpp || !*mbpp)
1159 {
1160 O_DEBUG("o_cleanupMemBlock passed null memory block pointer.");
1161 return;
1162 }
1163
1164 /*
1165 ** Take a local copy with less indirection.
1166 */
1167 mb = *mbpp;
1168
1169 O_GDEBUG("o_cleanupMemBlock mb=%p", mb->hdr.key);
1170
1171 /*
1172 ** If this is a shadowed block, complain then return.
1173 */
1174 if(mb->shadowing)
1175 {
1176 O_DEBUG("Trying to cleanup a shadow block at %p tracking %p",
1177 mb->hdr.key,
1178 mb->shadowing->hdr.key);
1179 return;
1180 }
1181
1182 /*
1183 ** If a shadow exists, clean it up.
1184 */
1185 if(mb->shadowed)
1186 {
1187 MemBlock *shadowed = mb->shadowed;
1188
1189 /*
1190 ** Cleanup its pointers, remove it from the hash table then
1191 ** free off the block.
1192 */
1193 O_GDEBUG("cleanup shadow pointers");
1194 o_cleanupTrackedPointers(shadowed);
1195 (void)VG_(HT_remove)(o_MemBlocks, shadowed->hdr.key);
1196 VG_(free)(shadowed);
1197
1198 o_stats.liveMemoryBlocks--;
1199 }
1200
1201 /*
1202 ** Free off the tracked pointers.
1203 */
1204 O_GDEBUG("cleanup tracked pointers");
1205 o_cleanupTrackedPointers(mb);
1206
1207 /*
1208 ** Check for tracked pointers inside the allocated block being lost.
1209 */
1210 o_indirectChecking++;
1211 o_clearingBlock = True;
1212 o_killRange(mb->hdr.key,
1213 mb->length);
1214 o_clearingBlock = False;
1215 o_indirectChecking--;
1216
1217 /*
1218 ** Now free off the memory block.
1219 */
1220 VG_(free)(mb);
1221 o_stats.liveMemoryBlocks--;
1222
1223 /*
1224 ** Clear the passed in pointer.
1225 */
1226 *mbpp = NULL;
1227
1228 return;
1229}
1230
1231static void o_addMemBlockReference( MemBlock *mb, TrackedPointer *tp )
1232{
1233 MemBlock *smb = mb;
1234
1235 O_GDEBUG("o_addMemBlockReference tp=%p, mb=%p",
1236 FROM_TRACKED_KEY(tp->hdr.key),
1237 mb->hdr.key);
1238
1239 /*
1240 ** Check if we are shadowing.
1241 */
1242 if(mb->shadowing)
1243 {
1244 /*
1245 ** Get the mem block for the true allocated block.
1246 ** Note that this leaves smb pointing to the shadow block which is
1247 ** what we want.
1248 */
1249 mb = mb->shadowing;
1250 }
1251
1252 /*
1253 ** Check if the block previously leaked.
1254 */
1255 if(!mb->shadowed && !mb->refNum && mb->leaked)
1256 {
1257 /*
1258 ** Seems that the block didnt leak after all.
1259 */
1260 if(o_addSuppressionBlock(mb->where, mb->leaked) && !o_showSummaryOnly)
1261 {
1262 O_DEBUG("Welcome back to the supposedly leaked block at %p. Illegal read?",
1263 mb->hdr.key);
1264
1265 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
1266 O_DEBUG("");
1267 }
1268
1269 mb->leaked = NULL;
1270 o_stats.memoryBlocksLeaked--;
1271 o_stats.memoryBlocksLostAndFound++;
1272 }
1273
1274 /*
1275 ** Populate the tracked pointer then add it to the hash.
1276 ** We use the shadow block so that it points to the correct place.
1277 ** Add the back reference to the mem block.
1278 */
1279 tp->block = smb->hdr.key;
1280 tp->length = mb->length;
1281 tp->memBlock = smb;
1282 VG_(HT_add_node)(o_TrackedPointers, tp);
1283
1284 /*
1285 ** Do we need more memory for pointers?
1286 */
1287 if(!smb->pointers)
1288 {
1289 smb->pointers =
1290 VG_(malloc)((smb->refNum + 8) * sizeof(TrackedPointer *));
1291 tl_assert(smb->pointers);
1292 }
1293 else if(!((smb->refNum + 1) & 7))
1294 {
1295 /*
1296 ** Add space for another 8 back references.
1297 ** Note that this will also shrink us if needed.
1298 */
1299 smb->pointers =
1300 VG_(realloc)(smb->pointers, ((smb->refNum + 8) * sizeof(Addr)));
1301 tl_assert(smb->pointers);
1302 }
1303
1304 smb->pointers[smb->refNum] = tp;
1305
1306 /*
1307 ** Track register and memory pointers.
1308 */
1309 if(!IS_REG(FROM_TRACKED_KEY(smb->pointers[smb->refNum]->hdr.key)))
1310 {
1311 smb->nonRegCount++;
1312 }
1313 else if(!o_isReturnIgnoreReg(FROM_TRACKED_KEY(smb->pointers[smb->refNum]->hdr.key)))
1314 {
1315 smb->nonScratch++;
1316 }
1317
1318 /*
1319 ** Clear the maybeLast and funcEnd. Adding a reference means that
1320 ** the cached one wasnt the last.
1321 */
1322 smb->maybeLast = NULL;
1323 smb->funcEnd = NULL;
1324
1325 /*
1326 ** Clear the doLeak flag - we just added a reference so the block survived
1327 ** the instruction.
1328 */
1329 smb->doLeak = False;
1330
1331 smb->refNum++;
1332 O_MDEBUG("Added tracked pointer at %p pointing to %s%p",
1333 FROM_TRACKED_KEY(tp->hdr.key),
1334 smb->shadowing ? "(S)" : "",
1335 smb->hdr.key);
1336
1337 return;
1338}
1339
1340static void o_removePointerFromList(MemBlock *mb, TrackedPointer *tp)
1341{
1342 UInt pointerNum;
1343
1344 O_GDEBUG("removePointerFromList tp=%p mb=%p",
1345 FROM_TRACKED_KEY(tp->hdr.key),
1346 mb->hdr.key);
1347
1348 /*
1349 ** Check that this tracked pointer belongs to this block.
1350 */
1351 tl_assert(tp->memBlock == mb);
1352
1353 /*
1354 ** Find the tracked pointer in the memory blocks' list.
1355 */
1356 for(pointerNum = 0; pointerNum < mb->refNum; pointerNum++)
1357 {
1358 if(mb->pointers[pointerNum] == tp)
1359 {
1360 /*
1361 ** Found it.
1362 ** If this is not the last pointer in the list, copy the last
1363 ** one over it.
1364 */
1365 if((pointerNum + 1) != mb->refNum)
1366 {
1367 mb->pointers[pointerNum] = mb->pointers[(mb->refNum - 1)];
1368 }
1369
1370 break;
1371 }
1372 }
1373
1374 /*
1375 ** Track register and memory pointers.
1376 */
1377 if(!IS_REG(FROM_TRACKED_KEY(tp->hdr.key)))
1378 {
1379 mb->nonRegCount--;
1380 }
1381 else if(!o_isReturnIgnoreReg(FROM_TRACKED_KEY(tp->hdr.key)))
1382 {
1383 mb->nonScratch--;
1384 }
1385
1386 mb->refNum--;
1387
1388 return;
1389}
1390
1391static void o_doLeakReport(MemBlock *mb);
1392static void o_removeMemBlockReference( MemBlock *mb, TrackedPointer *tp )
1393{
1394 MemBlock *smb = NULL;
1395 SizeT refCount = 0;
1396 UInt nonRegCount = 0;
1397 Bool shadowed = False;
1398
1399 /*
1400 ** We need the tracked pointer object.
1401 */
1402 tl_assert(tp);
1403
1404 /*
1405 ** If we dont have the memory block, get it from the tracked pointer.
1406 */
1407 if(!mb)
1408 {
1409 mb = tp->memBlock;
1410 }
1411 tl_assert(mb);
1412
1413 O_GDEBUG("o_removeMemBlockReference tp=%p, mb=%p",
1414 FROM_TRACKED_KEY(tp->hdr.key),
1415 mb->hdr.key);
1416
1417 smb = mb;
1418 refCount = smb->refNum;
1419 nonRegCount = smb->nonRegCount;
1420
1421 O_GDEBUG("(A)refCount %d, o_stackUnwind %c, nonRegCount %d, isReg %c",
1422 refCount,
1423 (o_stackUnwind ? 'Y' : 'N'),
1424 nonRegCount,
1425 IS_REG(FROM_TRACKED_KEY(tp->hdr.key)) ? 'Y' : 'N');
1426
1427 /*
1428 ** Check if we are shadowing.
1429 */
1430 if(mb->shadowing)
1431 {
1432 /*
1433 ** Get the mem block for the true allocated block.
1434 ** Note that this leaves smb pointing to the shadow which is correct.
1435 */
1436 mb = mb->shadowing;
1437#if defined(O_MASTER_DEBUG)
1438 if(!o_traceStop)
1439 {
1440 int count;
1441 for(count = 0; count < mb->refNum && count < 6; count++)
1442 O_GDEBUG(" %p", FROM_TRACKED_KEY(mb->pointers[count]->hdr.key));
1443 }
1444#endif
1445 refCount += mb->refNum;
1446 shadowed = True;
1447 nonRegCount += mb->nonRegCount;
1448 }
1449 else if(mb->shadowed)
1450 {
1451 /*
1452 ** Get the mem block for the shadow as we need the refNum from it.
1453 */
1454 MemBlock *tmb = mb->shadowed;
1455#if defined(O_MASTER_DEBUG)
1456 if(!o_traceStop)
1457 {
1458 int count;
1459 for(count = 0; count < tmb->refNum && count < 6; count++)
1460 O_GDEBUG(" %p", FROM_TRACKED_KEY(tmb->pointers[count]->hdr.key));
1461 }
1462#endif
1463 refCount += tmb->refNum;
1464 shadowed = True;
1465 nonRegCount += tmb->nonRegCount;
1466 }
1467#if defined(O_MASTER_DEBUG)
1468 else if(!o_traceStop)
1469 {
1470 int count;
1471 for(count = 0; count < mb->refNum && count < 6; count++)
1472 O_GDEBUG(" %p", FROM_TRACKED_KEY(mb->pointers[count]->hdr.key));
1473
1474 }
1475#endif
1476
1477 O_GDEBUG("(B)rCnt %d, nRCnt %d, ns %d, shad %c, free %c",
1478 refCount,
1479 nonRegCount,
1480 mb->nonScratch,
1481 (shadowed ? 'Y' : 'N'),
1482 (o_clearingBlock ? 'Y' : 'N'));
1483 /*
1484 ** We really should have at least one tracked pointer.
1485 */
1486 tl_assert(refCount);
1487
1488#if defined(O_MASTER_DEBUG)
1489 if(!o_traceStop)
1490 {
1491 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 8);O_DEBUG("");
1492 }
1493#endif
1494
1495 /*
1496 ** We remove the tracked pointer from the hash table but do not delete it.
1497 ** This allows a slight gain where a tracked pointer can immediately be
1498 ** reused rather than free()ed off and a new one malloc()ed.
1499 ** We then remove the back reference from the memory block and
1500 ** squeal if it is the last one. We don't clean the tracked pointer as this
1501 ** is a waste if it is going to be free()ed off.
1502 ** If warn indirect is set and this is an indirect check, do nothing.
1503 */
1504 (void)VG_(HT_remove)(o_TrackedPointers, tp->hdr.key);
1505
1506 O_GDEBUG("Removing tracked pointer at %p pointing to %p",
1507 FROM_TRACKED_KEY(tp->hdr.key),
1508 smb->hdr.key);
1509
1510 if((refCount <= 1) // Last pointer
1511
1512 /*
1513 ** Catch cascades of memory blocks when we call free().
1514 */
1515 || (o_clearingBlock && !shadowed && !mb->nonScratch &&
1516 (nonRegCount == 1) && !IS_REG(FROM_TRACKED_KEY(tp->hdr.key)))
1517
1518#if defined(VGA_x86)
1519 /*
1520 ** Losing all in memory pointers within a basic block is not a good sign.
1521 */
1522 || (!o_stackUnwind && (nonRegCount == 1) &&
1523 !IS_REG(FROM_TRACKED_KEY(tp->hdr.key)))
1524#endif
1525 )
1526 {
1527 if((!o_inhibitLeakDetect)
1528 /*
1529 ** Don't report when there are just register based pointers left and
1530 ** we have already reported the block as leaked.
1531 */
1532 && !(mb->leaked && IS_REG(FROM_TRACKED_KEY(tp->hdr.key)))
1533 )
1534 {
1535 /*
1536 ** Set the doLeak flag for the block and add it to the doLeakList.
1537 ** We also need to stash the indirect depth value for possibly reporting
1538 ** later. Finally, if maybeLast matches the pointer that is being removed
1539 ** and thus causing the leak, we leave maybeLast and funcEnd otherwise, we
1540 ** zero them.
1541 */
1542 mb->depth = o_indirectChecking;
1543 if(mb->maybeLast != tp)
1544 {
1545 mb->maybeLast = NULL;
1546 mb->funcEnd = NULL;
1547 }
1548
1549 /*
1550 ** Cascades triggered by a doLeak being actioned should report
1551 ** immediately, rather than being added to the doLeakList. Likewise
1552 ** cascades caused by freeing a block.
1553 */
1554 if(doLeakNow || o_clearingBlock)
1555 {
1556 o_doLeakReport(mb);
1557 }
1558 else
1559 {
1560 mb->doLeak = True;
1561 mb->next = doLeakList;
1562 doLeakList = mb;
1563 doLeakListCount++;
1564 }
1565 }
1566 }
1567
1568 /*
1569 ** Finally, remove the pointer from the blocks' list.
1570 */
1571 o_removePointerFromList(smb, tp);
1572
1573 return;
1574}
1575
1576static void o_doLeakReport(MemBlock *mb)
1577{
1578 Bool doReport = True;
1579
1580 if(mb->maybeLast)
1581 {
1582 // This is the suspected last pointer - use the cached stacktrace
1583 O_MDEBUG("maybe last was the last");
1584 tl_assert(mb->funcEnd);
1585 mb->leaked = mb->funcEnd;
1586 o_indirectStack = mb->funcEnd;
1587 }
1588 else if(mb->depth && o_indirectStack)
1589 {
1590 O_MDEBUG("indirect with indirect stack set");
1591 // We are cascading - use the cached stacktrace, if there is one
1592 mb->leaked = o_indirectStack;
1593 }
1594 else
1595 {
1596 O_MDEBUG("creating new context maybeLast=0");
1597 // Get the current stacktrace
sewardj39f34232007-11-09 23:02:28 +00001598 mb->leaked = VG_(record_ExeContext)(VG_(get_running_tid)(),
1599 0/*first_ip_delta*/);
sewardj99a2ceb2007-11-09 12:30:36 +00001600 }
1601
1602 doReport = o_addLeakedBlock(mb->where, mb->leaked, mb->length);
1603 /*
1604 ** Report the probable leak.
1605 */
1606 o_stats.memoryBlocksLeaked++;
1607
1608 if(doReport && !o_showSummaryOnly)
1609 {
1610 if(mb->depth)
1611 {
1612 if(o_showIndirect)
1613 {
1614 VG_(message)(Vg_UserMsg,
1615 "Probably indirectly (level %d) leaking block of %d(%p) bytes",
1616 mb->depth,
1617 mb->length,
1618 mb->length);
1619 }
1620 }
1621 else
1622 {
1623 VG_(message)(Vg_UserMsg,
1624 "Probably leaking block of %d(%p) bytes",
1625 mb->length,
1626 mb->length);
1627 }
1628
1629 if(!mb->depth || o_showIndirect)
1630 {
1631 VG_(pp_ExeContext)(mb->leaked);
1632
1633 VG_(message)(Vg_UserMsg,
1634 " Block at %p allocated", mb->hdr.key);
1635 VG_(pp_ExeContext)(mb->where);
1636 VG_(message)(Vg_UserMsg,"");
1637 }
1638
1639 /*
1640 ** Only attach the debugger for the first leaking block in the chain
1641 ** and only when show summary is disabled (--instant-reports).
1642 */
1643 if(!mb->depth && VG_(clo_db_attach))
1644 {
1645 VG_(start_debugger)(VG_(get_running_tid)());
1646 }
1647 }
1648
1649 /*
1650 ** Check for tracked pointers inside the allocated block being lost.
1651 */
1652 o_indirectChecking++;
1653 o_killRange(mb->hdr.key, mb->length);
1654 o_indirectChecking--;
1655
1656 /*
1657 ** Poison the block if requested.
1658 */
1659 if(o_poison)
1660 VG_(memset)((Addr *)mb->hdr.key, 0, mb->length);
1661
1662 return;
1663}
1664
1665static Bool o_setupShadow(TrackedPointer *tp, Addr address)
1666{
1667 Bool doneShadow = False;
1668 MemBlock *mb = NULL;
1669 MemBlock *smb = NULL;
1670
1671 O_MDEBUG("setup shadow tp %p block %p address %p",
1672 FROM_TRACKED_KEY(tp->hdr.key), tp->block, address);
1673 /*
1674 ** Get the memory block for the tracked pointer.
1675 ** It should exist.
1676 */
1677 mb = tp->memBlock;
1678 tl_assert(mb);
1679
1680 /*
1681 ** If this is a shadow block, get the main block as well.
1682 ** It should exist.
1683 */
1684 smb = mb;
1685 if(mb->shadowing)
1686 {
1687 mb = mb->shadowing;
1688 tl_assert(mb);
1689 }
1690
1691 /*
1692 ** If the block is already shadowed at address, bail out and let the
1693 ** normal code handle it.
1694 */
1695 if(mb->shadowed)
1696 {
1697 if(mb->shadowed->hdr.key == address)
1698 {
1699 O_MDEBUG("already shadowed %p", address);
1700 return False;
1701 }
1702 /*
1703 ** Get the shadow block.
1704 */
1705 smb = mb->shadowed;
1706 tl_assert(smb);
1707 }
1708
1709 /*
1710 ** Check if address is within the block that we are tracking.
1711 ** If it is then we need to work out whether to create a
1712 ** new shadow or move an eixsting one.
1713 */
1714 if((address > mb->hdr.key) &&
1715 (address < (mb->hdr.key + mb->length)))
1716 {
1717 doneShadow = True;
1718
1719 O_MDEBUG("About to shadow internal address %p to block %p in %p",
1720 address,
1721 mb->hdr.key,
1722 FROM_TRACKED_KEY(tp->hdr.key));
1723
1724 if(smb == mb)
1725 {
1726 O_MDEBUG("creating new shadow");
1727 /*
1728 ** Create a new shadow for the block.
1729 */
1730 smb = VG_(malloc)( sizeof(MemBlock) );
1731 tl_assert(smb);
1732
1733 o_stats.shadowMemoryBlocksAllocated++;
1734 o_stats.liveMemoryBlocks++;
1735
1736 VG_(memset)(smb, 0, sizeof(MemBlock));
1737 smb->hdr.key = address;
1738 smb->length = 0;
1739 smb->where = 0; // Dont need this in the shadow.
1740 smb->shadowing = mb;
1741 mb->shadowed = smb;
1742 VG_(HT_add_node(o_MemBlocks, smb));
1743
1744 /*
1745 ** Move the tracked pointer from the main block to the shadow.
1746 */
1747 (void)VG_(HT_remove)(o_TrackedPointers, tp->hdr.key);
1748 o_removePointerFromList(mb, tp);
1749 o_addMemBlockReference(smb, tp);
1750 }
1751 else if((smb->refNum == 1) &&
1752 (smb == tp->memBlock))
1753 {
1754 O_MDEBUG("moving existing shadow at %p", smb->hdr.key);
1755 /*
1756 ** Move the existing shadow.
1757 */
1758 (void)VG_(HT_remove)(o_MemBlocks, smb->hdr.key);
1759 smb->hdr.key = address;
1760 smb->where = 0; // Dont need this in the shadow.
1761 VG_(HT_add_node(o_MemBlocks, smb));
1762
1763 /*
1764 ** Tweak the existing tracked pointer, leaving the PBit alone.
1765 */
1766 tp->block = address;
1767 }
1768 else
1769 {
1770 /*
1771 ** A shadow exists and has pointers assigned to it.
1772 ** We do not allow more than one shadow so deregister and
1773 ** free this tracked pointer and clear its PBit.
1774 */
1775 O_MDEBUG("Prevented second shadow %p (first %p) for %p",
1776 address,
1777 mb->shadowed,
1778 mb->hdr.key);
1779
1780 o_clearPBit(FROM_TRACKED_KEY(tp->hdr.key));
1781 o_removeMemBlockReference(NULL, tp);
1782 VG_(free)(tp);
1783
1784 o_stats.liveTrackedPointers--;
1785 }
1786
1787 O_MDEBUG("shadow creation / reallocation done");
1788 }
1789 else if((smb != mb) &&
1790 (address == mb->hdr.key))
1791 {
1792 /*
1793 ** Hmmm.
1794 ** Looks like we are setting the tracked pointer to the block start.
1795 ** If it was previously pointing at the shadow block, we need to move it
1796 ** manually.
1797 */
1798 if(tp->block == smb->hdr.key)
1799 {
1800 O_MDEBUG("moving pointer from shadow to main");
1801
1802 if(smb->refNum == 1)
1803 {
1804 doneShadow = True;
1805
1806 O_MDEBUG("destroying shadow of %p at %p",
1807 mb->hdr.key,
1808 smb->hdr.key);
1809 /*
1810 ** Remove the shadow block and move the pointer.
1811 */
1812 (void)VG_(HT_remove)(o_MemBlocks, smb->hdr.key);
1813 mb->shadowed = 0;
1814 VG_(free)(smb->pointers);
1815 VG_(free)(smb);
1816 o_stats.liveMemoryBlocks--;
1817
1818 (void)VG_(HT_remove)(o_TrackedPointers, tp->hdr.key);
1819 o_addMemBlockReference(mb, tp);
1820 }
1821 else
1822 {
1823 /*
1824 ** Let the normal code move the pointer.
1825 */
1826 }
1827 }
1828 }
1829 else
1830 {
1831 O_MDEBUG("tracked pointer out of range");
1832 }
1833
1834 return doneShadow;
1835}
1836
1837static void o_killTrackedPointer(Addr addr)
1838{
1839 TrackedPointer *tp = VG_(HT_lookup)(o_TrackedPointers, TRACKED_KEY(addr));
1840
1841 /*
1842 ** We really should have the tracked pointer.
1843 */
1844 tl_assert(tp);
1845
1846 /*
1847 ** Remove the tracked pointer from its memory block, causing
1848 ** a leak report as required then free it.
1849 */
1850 o_clearPBit(addr);
1851
1852 O_MDEBUG("Removing tracked pointer to %p at %p",
1853 tp->block, FROM_TRACKED_KEY(tp->hdr.key));
1854
1855 o_removeMemBlockReference(NULL, tp);
1856
1857 VG_(free)(tp);
1858
1859 o_stats.liveTrackedPointers--;
1860 return;
1861}
1862
1863static void o_killRange(Addr start, SizeT length)
1864{
1865 /*
1866 ** We need to check the PBits for the addresses starting at start.
1867 ** We use the firstPBit / nextPBit functions to get us a list of set
1868 ** pbits in the specified range.
1869 */
1870 PBitContext pb;
1871 Addr a;
1872
1873 O_MDEBUG("killing range %p bytes from %p", length, start);
1874
1875
1876 a = o_firstPBit(&pb, start, length);
1877 while(a)
1878 {
1879 o_killTrackedPointer(a);
1880 a = o_nextPBit(&pb);
1881 }
1882 O_MDEBUG("killing range %p bytes from %p done.", length, start);
1883}
1884
1885static void o_duplicateTrackedPointers(Addr dst, Addr src, SizeT length)
1886{
1887 /*
1888 ** For each set PBit in the src block, create a new tracked pointer
1889 ** in the destination block, pointing to the same memory block.
1890 */
1891 PBitContext pb;
1892 Addr address;
1893
1894 O_MDEBUG("o_duplicateTrackedPointers(%p, %p %d(%p))",
1895 dst, src, length, length);
1896
1897 address = o_firstPBit(&pb, src, length);
1898
1899 while(address)
1900 {
1901 /*
1902 ** Create a tracked pointer at the appropriate place within the new
1903 ** block of memory.
1904 */
1905 TrackedPointer *tp = VG_(HT_lookup)(o_TrackedPointers, TRACKED_KEY(address));
1906 Int diff = dst - src;
1907 TrackedPointer *ntp = VG_(malloc)((sizeof(TrackedPointer)));
1908 MemBlock *mb = NULL;
1909
1910 tl_assert(tp);
1911
1912 o_stats.liveTrackedPointers++;
1913 o_stats.trackedPointersAllocated++;
1914
1915 /*
1916 ** Get the memory block from the tracked pointer at this address.
1917 */
1918 mb = tp->memBlock;
1919
1920 if(!mb)
1921 {
1922 O_DEBUG("Oops! Copying pointer at %p to block that leaked(%p)",
1923 address, tp->block);
1924 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
1925 O_DEBUG("");
1926
1927 VG_(tool_panic)("we lost track of a pointer :-(");
1928 }
1929
1930 tl_assert(ntp);
1931
1932 VG_(memset)(ntp, 0, sizeof(TrackedPointer));
1933 ntp->hdr.key = TRACKED_KEY(address + diff);
1934 o_addMemBlockReference(mb, ntp);
1935
1936 /*
1937 ** Set the PBit for this tracked pointer.
1938 */
1939 o_setPBit(address + diff);
1940
1941 address = o_nextPBit(&pb);
1942 }
1943
1944}
1945
1946static void o_createMemBlock(ThreadId tid, Addr start, SizeT size)
1947{
1948 MemBlock *mb = VG_(malloc)(sizeof(MemBlock));
1949 tl_assert(mb);
1950
1951 o_stats.memoryBlocksAllocated++;
1952 o_stats.liveMemoryBlocks++;
1953
1954 VG_(memset)(mb, 0, sizeof(MemBlock));
1955
1956 /*
1957 ** Populate the block. Note that we have no pointers until one is written
1958 ** into memory.
1959 */
1960 mb->hdr.key = start;
1961 mb->length = size;
sewardj39f34232007-11-09 23:02:28 +00001962 mb->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
sewardj99a2ceb2007-11-09 12:30:36 +00001963
1964 /*
1965 O_DEBUG("Creating new MemBlock (%p) key = %p, length %d",
1966 mb, (void *)start, size);
1967 VG_(pp_ExeContext)(mb->where);
1968 */
1969
1970 /*
1971 ** Add this node into the hash table.
1972 */
1973 VG_(HT_add_node)(o_MemBlocks, mb);
1974}
1975
1976static void o_destroyMemBlock(ThreadId tid, Addr start)
1977{
1978 /*
1979 ** Destroy our memory block.
1980 */
1981 MemBlock *mb = VG_(HT_remove)(o_MemBlocks, start);
1982
1983 /*
1984 ** The block really should exist, unless this is a double free attempt...
1985 */
1986 if(!mb)
1987 {
1988 O_DEBUG("Double/Invalid call to free(%p)", start);
1989 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
1990 O_DEBUG("");
1991 }
1992 else
1993 {
1994 if(mb->leaked)
1995 {
1996 /*
1997 ** Seems that the block didnt leak after all.
1998 ** *sigh*
1999 ** Why do so many libs access memory in blocks they free()ed?
2000 */
2001 if(o_addSuppressionBlock(mb->where, mb->leaked) && !o_showSummaryOnly)
2002 {
2003 O_DEBUG("Welcome back (and goodbye) to the supposedly leaked block at %p",
2004 start);
2005 }
2006 o_stats.memoryBlocksLeaked--;
2007 o_stats.memoryBlocksLostAndFound++;
2008 }
2009 /*
2010 ** Clean up the block - we pass a pointer pointer so that we can
2011 ** set it to NULL during the cleanup process.
2012 */
2013 o_cleanupMemBlock(&mb);
2014 }
2015
2016 return;
2017}
2018
2019
2020static void o_setupMaybeLast(Addr a)
2021{
2022 int refCount = 0;
2023 /*
2024 ** Maybe returning a value - set the maybeLast and funcEnd members
2025 ** in the memory block this register points to if it is the last
2026 ** item.
2027 */
2028 TrackedPointer *tp = VG_(HT_lookup)(o_TrackedPointers, TRACKED_KEY(a));
2029 /*
2030 ** We really should have the tracked pointer.
2031 */
2032 tl_assert(tp);
2033
2034 refCount = tp->memBlock->refNum;
2035 if(tp->memBlock->shadowing)
2036 {
2037 refCount += tp->memBlock->shadowing->refNum;
2038 }
2039 else if(tp->memBlock->shadowed)
2040 {
2041 refCount += tp->memBlock->shadowed->refNum;
2042 }
2043
2044 if(refCount == 1)
2045 {
2046 // Hmmm, last reference. If we haven't already done so,
2047 // save the context, just in case
2048 tl_assert(!tp->memBlock->maybeLast ||
2049 (tp->memBlock->maybeLast == tp));
2050 if(!tp->memBlock->maybeLast)
2051 {
2052 tp->memBlock->maybeLast = tp;
sewardj39f34232007-11-09 23:02:28 +00002053 tp->memBlock->funcEnd = VG_(record_ExeContext)(VG_(get_running_tid)(),
2054 0/*first_ip_delta*/);
sewardj99a2ceb2007-11-09 12:30:36 +00002055 O_MDEBUG("setting maybeLast to %p in block at %p",
2056 FROM_TRACKED_KEY(tp->hdr.key), tp->block);
2057 }
2058#if defined(O_MASTER_DEBUG)
2059 else
2060 {
2061 O_MDEBUG("leaving maybeLast at %p in block at %p",
2062 FROM_TRACKED_KEY(tp->hdr.key), tp->block);
2063 }
2064#endif
2065 }
2066 O_MDEBUG("leaving register %p", OFFSET_FROM_REG(a));
2067}
2068
2069/*------------------------------------------------------------*/
2070/*--- Helper functions called by instrumentation ---*/
2071/*------------------------------------------------------------*/
2072#if defined(O_TRACK_LOADS)
2073static VG_REGPARM(1)
2074void o_omegaLoadTracker( Addr address )
2075{
2076 O_MDEBUG("o_omegaLoadTracker(%p, %p)", address, *((Addr *)address));
2077
2078 return;
2079}
2080#endif
2081
2082static VG_REGPARM(2)
2083void o_omegaScratchRemover( Addr start, Addr length )
2084{
2085 O_MDEBUG("o_omegaScratchRemover(%p, %p)", start, length);
2086 o_killRange(start, length);
2087
2088 return;
2089}
2090
2091static VG_REGPARM(1)
2092void o_endOfInstruction( Addr address )
2093{
2094 /*
2095 ** Any generated leaks should report immediately.
2096 */
2097 doLeakNow = True;
2098
2099 O_MDEBUG("o_endOfInstruction %p doLeakListCount = %d",
2100 address, doLeakListCount);
2101
2102 if(doLeakListCount)
2103 {
2104 if(doLeakListCount > 1)
2105 {
2106 /*
2107 ** Reverse the list so the reports come out in the correct order.
2108 */
2109 MemBlock *front = NULL;
2110 MemBlock *temp = NULL;
2111
2112 do
2113 {
2114 temp = doLeakList->next;
2115
2116 if(front)
2117 {
2118 doLeakList->next = front;
2119 }
2120 else
2121 {
2122 doLeakList->next = NULL;
2123 }
2124 front = doLeakList;
2125
2126 doLeakList = temp;
2127 }
2128 while(doLeakList);
2129
2130 /*
2131 ** Now do the leak reports.
2132 */
2133 while(front)
2134 {
2135 temp = front;
2136 front = front->next;
2137
2138 if(temp->doLeak)
2139 {
2140 temp->doLeak = False;
2141 o_doLeakReport(temp);
2142 }
2143 else
2144 {
2145 O_MDEBUG("block at %p survived!", temp->hdr.key);
2146 }
2147 }
2148 }
2149 else
2150 {
2151 if(doLeakList->doLeak)
2152 {
2153 /*
2154 ** The block has leaked. Report it.
2155 */
2156 o_doLeakReport(doLeakList);
2157 }
2158 else
2159 {
2160 O_MDEBUG("block at %p survived!", doLeakList->hdr.key);
2161 }
2162
2163 doLeakList->doLeak = False;
2164 doLeakList = NULL;
2165 }
2166 }
2167
2168 O_MDEBUG("o_endOfInstruction done");
2169
2170 o_indirectStack = NULL;
2171 doLeakListCount = 0;
2172 doLeakNow = False;
2173}
2174
2175static
2176void o_omegaFunctionReturn( void )
2177{
2178 PBitContext pb;
2179 Addr a = 0;
2180
2181 /*
2182 ** Zap scratch registers.
2183 */
2184
2185#if defined(VGA_x86)
2186 a = o_firstPBit(&pb,
2187 MAP_TO_REG(VG_(get_running_tid)(), OFFSET_x86_ECX),
2188 OFFSET_x86_EDI + 4);
2189#elif defined(VGA_amd64)
2190 a = o_firstPBit(&pb,
2191 MAP_TO_REG(VG_(get_running_tid)(), OFFSET_amd64_RCX),
2192 OFFSET_amd64_R15 + 8);
2193#endif
2194 doLeakNow = True;
2195 while(a)
2196 {
2197 if(o_isReturnIgnoreReg(OFFSET_FROM_REG(a)))
2198 {
2199 O_MDEBUG("killing register %p", OFFSET_FROM_REG(a));
2200 o_killTrackedPointer(a);
2201 }
2202 a = o_nextPBit(&pb);
2203 }
2204 doLeakNow = False;
2205
2206 /*
2207 ** Now work out if we might be returning a value in the accumulator.
2208 */
2209#if defined(VGA_x86)
2210 a = MAP_TO_REG(VG_(get_running_tid)(), OFFSET_x86_EAX);
2211#elif defined(VGA_amd64)
2212 a = MAP_TO_REG(VG_(get_running_tid)(), OFFSET_amd64_RAX);
2213#endif
2214 if(o_isPBitSet(a))
2215 o_setupMaybeLast(a);
2216
2217#if defined(VGA_amd64)
2218 // Also need to check for the RDX register as it is a second return reg
2219 a = MAP_TO_REG(VG_(get_running_tid)(), OFFSET_amd64_RDX);
2220 if(o_isPBitSet(a))
2221 o_setupMaybeLast(a);
2222#endif
2223 return;
2224}
2225
2226static VG_REGPARM(2)
2227void o_omegaDetector( Addr address, Addr value)
2228{
2229 TrackedPointer *tp = NULL;
2230 MemBlock *mb = NULL;
2231
2232 /*
2233 ** We need to track the registers.
2234 ** To do this, if the address < 256, change it to our local shadow.
2235 **
2236 ** We really want to be able to track the proper shadow but I have no
2237 ** idea yet how to get the address for it. Once I do, use that in
2238 ** preference. Note that all we need is a unique memory location for
2239 ** the register in order to generate a tracked pointer.
2240 */
2241 if(address < 0x100)
2242 {
2243 O_MDEBUG("o_omegaDetector(%p, %p)", address, value);
2244 address = MAP_TO_REG(VG_(get_running_tid)(), address);
2245 }
2246 else
2247 {
2248 /*
2249 ** Check aligned - if not, align it and retrive the stored value.
2250 */
2251 if(address & ~TRACK_MINOR_MASK)
2252 {
2253 address &= TRACK_MINOR_MASK;
2254 value = *((Addr *)address);
2255 }
2256 O_MDEBUG("o_omegaDetector(%p, %p)", address, value);
2257 }
2258
2259 /*
2260 ** Done the alignment tweaks so do the more expensive lookups.
2261 */
2262 if(o_isPBitSet(address))
2263 {
2264 tp = VG_(HT_lookup)(o_TrackedPointers, TRACKED_KEY(address));
2265
2266 if(tp && (tp->block == value))
2267 {
2268 /*
2269 ** Unlikely but it seems that we are writing the same value back into
2270 ** the tracked pointer - don't process further for a small gain.
2271 */
2272 //O_DEBUG("writing duplicate into tracked pointer.");
2273 return;
2274 }
2275
2276 /*
2277 ** We always auto shadow.
2278 ** Note that auto shadowing only works if you overwrite a tracked pointer.
2279 ** Checking for the creation of a new tracked pointer at some internal
2280 ** address is too much overhead as we would have to scan backwards to find
2281 ** a memory block then check if the value is within it. For those cases,
2282 ** we need to get something going with the client request system.
2283 */
2284 if(tp && value)
2285 {
2286 if(o_setupShadow(tp, value))
2287 {
2288 return;
2289 }
2290 }
2291
2292 /*
2293 ** Remove the tracked pointer and clear the PBit,
2294 ** if we have one.
2295 */
2296 if(tp)
2297 {
2298 tl_assert(tp->hdr.key == TRACKED_KEY(address));
2299 O_MDEBUG("Removing tracked pointer to %p at %p",
2300 tp->block, FROM_TRACKED_KEY(tp->hdr.key));
2301 o_clearPBit(address);
2302 o_removeMemBlockReference(NULL, tp);
2303 }
2304 }
2305
2306 /*
2307 ** Get the mem block now - it might not exist if tp was the last
2308 ** reference to it. It might not exist anyway.
2309 */
2310 if(value)
2311 {
2312 mb = VG_(HT_lookup)(o_MemBlocks, value);
2313 }
2314
2315 /*
2316 ** If we have a memblock, clean the tracked pointer then add it.
2317 ** If not, free the tracked pointer.
2318 */
2319 if(mb)
2320 {
2321 if(!tp)
2322 {
2323 /*
2324 ** No tracked pointer - create one now.
2325 */
2326 tp = VG_(malloc)(sizeof(TrackedPointer));
2327 tl_assert(tp);
2328 o_stats.trackedPointersAllocated++;
2329 o_stats.liveTrackedPointers++;
2330 }
2331 VG_(memset)(tp, 0, sizeof(TrackedPointer));
2332 tp->hdr.key = TRACKED_KEY(address);
2333 o_addMemBlockReference(mb, tp);
2334 /*
2335 ** Set the PBit for this tracked pointer.
2336 */
2337 o_setPBit(address);
2338
2339 O_MDEBUG("Added tracked pointer to %p at %p",
2340 tp->block, FROM_TRACKED_KEY(tp->hdr.key));
2341
2342 }
2343 else if(tp)
2344 {
2345 VG_(free)(tp);
2346 o_stats.liveTrackedPointers--;
2347 }
2348
2349 return;
2350}
2351
2352/*------------------------------------------------------------*/
2353/*--- malloc() et al replacement wrappers ---*/
2354/*------------------------------------------------------------*/
2355
2356static
2357void* o_newBlock ( ThreadId tid, SizeT size, SizeT align, Bool is_zeroed )
2358{
2359 void* p = NULL;
2360
2361O_TRACE_ON();
2362#if defined(O_MASTER_DEBUG)
2363 if(!o_traceStop)
2364 {
2365 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 8);O_DEBUG("");
2366 }
2367#endif
2368
2369 O_MDEBUG("newBlock(%d, %d, %d, %d)",
2370 tid,
2371 size,
2372 align,
2373 (int)is_zeroed);
2374
2375 /*
2376 ** Allocate and zero if necessary.
2377 */
2378 p = VG_(cli_malloc)( align, size );
2379 if(!p)
2380 {
2381 O_DEBUG("Out of memory!");
2382 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
2383 O_DEBUG("");
2384
2385 return NULL;
2386 }
2387
2388 if(is_zeroed)
2389 {
2390 VG_(memset)(p, 0, size);
2391 }
2392
2393 if(!o_onlyMallocLike)
2394 {
2395 /*
2396 ** Create a new MemBlock.
2397 */
2398 o_createMemBlock(tid, (Addr)p, size);
2399 }
2400
2401 O_MDEBUG("o_newBlock returning %p", p);
2402
2403 return p;
2404}
2405
2406static
2407void o_dieBlock ( ThreadId tid, void* p )
2408{
2409 /*
2410 ** Free off the allocated memory block.
2411 */
2412 O_MDEBUG("o_dieBlock(%d, %p)", tid, p);
2413
2414 /*
2415 ** Check if we have a potentially valid pointer
2416 */
2417 if(!p)
2418 {
2419 return;
2420 }
2421
2422 /*
2423 ** If we are doing malloc like block handling, only free off the memory.
2424 */
2425 if(!o_onlyMallocLike)
2426 {
2427 o_destroyMemBlock(tid, (Addr)p);
2428 }
2429
2430 /*
2431 ** Actually free the heap block.
2432 */
2433 VG_(cli_free)( p );
2434
2435 return;
2436}
2437
2438static void* o_malloc ( ThreadId tid, SizeT n )
2439{
2440 return o_newBlock( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
2441}
2442
2443static void* o__builtin_new ( ThreadId tid, SizeT n )
2444{
2445 return o_newBlock( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
2446}
2447
2448static void* o__builtin_vec_new ( ThreadId tid, SizeT n )
2449{
2450 return o_newBlock( tid, n, VG_(clo_alignment), /*is_zeroed*/False );
2451}
2452
2453static void* o_calloc ( ThreadId tid, SizeT m, SizeT size )
2454{
2455 return o_newBlock( tid, m*size, VG_(clo_alignment), /*is_zeroed*/True );
2456}
2457
2458static void *o_memalign ( ThreadId tid, SizeT align, SizeT n )
2459{
2460 return o_newBlock( tid, n, align, False );
2461}
2462
2463static void o_free ( ThreadId tid, void* p )
2464{
2465 o_dieBlock( tid, p );
2466}
2467
2468static void o__builtin_delete ( ThreadId tid, void* p )
2469{
2470 o_dieBlock( tid, p );
2471}
2472
2473static void o__builtin_vec_delete ( ThreadId tid, void* p )
2474{
2475 o_dieBlock( tid, p );
2476}
2477
2478static void* o_realloc ( ThreadId tid, void* p_old, SizeT new_size )
2479{
2480 MemBlock *mb = NULL;
2481 void *p_new = NULL;
2482
2483 O_MDEBUG("o_realloc p_old %p, new_size %d",
2484 p_old, new_size);
2485
2486 if(!p_old)
2487 {
2488 /*
2489 ** Pointer == NULL so let new block do the work.
2490 */
2491 return o_newBlock(tid, new_size, VG_(clo_alignment), /*is_zeroed*/False);
2492 }
2493
2494 mb = VG_(HT_lookup)(o_MemBlocks, (Addr)p_old);
2495
2496 /*
2497 ** Check that we have this memory block.
2498 */
2499 if(!mb)
2500 {
2501 /*
2502 ** Log the bad call but return p_old so the program can continue.
2503 ** This might not be a good thing but some of the libraries are a
2504 ** little weird and returning NULL as per the spec blows them up...
2505 */
2506 O_DEBUG("Invalid call to realloc(%p)", p_old);
2507 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
2508 O_DEBUG("");
2509
2510 return p_old;
2511 }
2512
2513 if(mb->leaked)
2514 {
2515 /*
2516 ** Seems that the block didnt leak after all.
2517 */
2518 if(o_addSuppressionBlock(mb->where, mb->leaked) && !o_showSummaryOnly)
2519 {
2520 O_DEBUG("Welcome back to the supposedly leaked block at %p",
2521 p_old);
2522 }
2523 mb->leaked = NULL;
2524 o_stats.memoryBlocksLeaked--;
2525 o_stats.memoryBlocksLostAndFound++;
2526 }
2527
2528 if(new_size)
2529 {
2530 if(new_size > mb->length)
2531 {
2532 /*
2533 ** Make a new block, copy the data into it then free the old block.
2534 ** We lose all tracked pointers but that is to be expected as this is
2535 ** a new block at a new address. However, any tracked pointers within
2536 ** must be preserved.
2537 */
2538
2539 p_new = o_newBlock(tid, new_size, VG_(clo_alignment), False);
2540 tl_assert(p_new);
2541
2542 VG_(memcpy)(p_new, p_old, mb->length);
2543
2544 o_duplicateTrackedPointers((Addr)p_new, (Addr)p_old, mb->length);
2545 }
2546 else
2547 {
2548 /*
2549 ** Return the existing block.
2550 */
2551 return p_old;
2552 }
2553 }
2554
2555 /*
2556 ** This will remove all of the old tracked pointers within.
2557 */
2558 o_dieBlock(tid, p_old);
2559
2560 return p_new;
2561}
2562
2563static void o_dieMemStack(Addr start, SizeT length)
2564{
2565 /*
2566 ** Flag that this is a stack unwind.
2567 */
2568 o_stackUnwind = True;
2569 o_killRange(start, length);
2570 o_stackUnwind = False;
2571}
2572
2573static void o_post_clo_init(void)
2574{
2575 /*
2576 ** Allocate the hash tables.
2577 ** Note that we can improve performance at the cost of memory by initialising
2578 ** with a larger prime number so more of the key part of the address is
2579 ** unique. The defaults are probably OK for many programs but we expose them
2580 ** on the command line to make it easier for users to change them.
2581 */
2582 o_PBits = VG_(HT_construct)( "omega pbits" );
2583 tl_assert(o_PBits);
2584
2585 o_MemBlocks = VG_(HT_construct)( "omega memblocks" );
2586 tl_assert(o_MemBlocks);
2587
2588 o_TrackedPointers = VG_(HT_construct)( "omega tracked ptrs" );
2589 tl_assert(o_TrackedPointers);
2590
2591 /*
2592 ** We need precise instructions so that we can work out the range of the
2593 ** original machine instruction in terms of grouping together lumps of IR.
2594 ** We lose out big time on optimisation but we have to take the hit in order
2595 ** to deal with instructions like pop and xchg.
2596 */
2597 VG_(clo_vex_control).iropt_precise_memory_exns = True;
2598
2599}
2600
2601static IRSB *
2602o_instrument(VgCallbackClosure* closure,
2603 IRSB* bb_in,
2604 VexGuestLayout* layout,
2605 VexGuestExtents* vge,
2606 IRType gWordTy, IRType hWordTy)
2607{
2608 IRDirty* di;
2609 Int i;
2610 IRSB* bb;
2611 IRType type;
2612 Addr mask;
2613 IRStmt* stackReg = NULL;
2614
2615#if 0 //defined(O_MASTER_DEBUG)
2616
2617 static int thisBlock = 0;
2618 thisBlock++;
2619 if(thisBlock == 11377)
2620 {
2621 O_TRACE_ON();
2622 }
2623 else if(thisBlock == 11390)
2624 {
2625 VG_(tool_panic)("hit stop block");
2626 }
2627#endif
2628
2629 if (gWordTy != hWordTy)
2630 {
2631 /* We don't currently support this case. */
2632 VG_(tool_panic)("host/guest word size mismatch");
2633 }
2634
2635 /*
2636 ** Set up BB
2637 */
2638 bb = emptyIRSB();
2639 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2640 bb->next = deepCopyIRExpr(bb_in->next);
2641 bb->jumpkind = bb_in->jumpkind;
2642
2643#if (VG_WORDSIZE == 4)
2644 type = Ity_I32;
2645 mask = ~0x03;
2646#elif (VG_WORDSIZE == 8)
2647 type = Ity_I64;
2648 mask = ~0x07;
2649#endif
2650
2651 for (i = 0; i < bb_in->stmts_used; i++)
2652 {
2653 IRStmt* st = bb_in->stmts[i];
2654 if (!st || st->tag == Ist_NoOp)
2655 {
2656 continue;
2657 }
2658
2659 di = NULL;
2660
2661 switch (st->tag)
2662 {
2663 case Ist_AbiHint:
2664 /*
2665 ** An area just went undefined. There may be pointers in this
2666 ** scratch area that we should now ignore.
2667 ** Make sure that we do so.
2668 */
2669 if(stackReg)
2670 {
2671 addStmtToIRSB( bb, stackReg );
2672 stackReg = NULL;
2673 }
2674 di = unsafeIRDirty_0_N( 2, "o_omegaScratchRemover",
2675 &o_omegaScratchRemover,
2676 mkIRExprVec_2(st->Ist.AbiHint.base,
2677 mkIRExpr_HWord(st->Ist.AbiHint.len)));
2678 /*
2679 ** Add in the original instruction second.
2680 */
2681 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2682 break;
2683
2684 case Ist_Store:
2685 if(stackReg)
2686 {
2687 addStmtToIRSB( bb, stackReg );
2688 stackReg = NULL;
2689 }
2690 if(typeOfIRExpr(bb->tyenv, st->Ist.Store.addr) == type)
2691 {
2692 /*
2693 ** We have an address of native size.
2694 */
2695 if(typeOfIRExpr(bb->tyenv, st->Ist.Store.data) == type)
2696 {
2697 /*
2698 ** We have data of native size - check if this is a pointer being
2699 ** written.
2700 */
2701 di = unsafeIRDirty_0_N( 2, "o_omegaDetector", &o_omegaDetector,
2702 mkIRExprVec_2(st->Ist.Store.addr,
2703 st->Ist.Store.data));
2704 /*
2705 ** Add in the original instruction second.
2706 */
2707 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2708 addStmtToIRSB( bb, st );
2709 st = NULL;
2710 }
2711 else
2712 {
2713 /*
2714 ** There is no way that the data is a pointer but we still have to
2715 ** check if a pointer will be overwritten.
2716 */
2717 di = unsafeIRDirty_0_N( 2, "o_omegaDetector", &o_omegaDetector,
2718 mkIRExprVec_2(st->Ist.Store.addr,
2719 mkIRExpr_HWord(0)));
2720 /*
2721 ** Add in the original instruction first.
2722 */
2723 addStmtToIRSB( bb, st );
2724 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2725 st = NULL;
2726 }
2727 }
2728 else
2729 {
2730 O_GDEBUG("o_instrument address type(%p) not a pointer",
2731 typeOfIRExpr(bb->tyenv, st->Ist.Store.addr));
2732 }
2733
2734 break;
2735
2736 case Ist_IMark:
2737 /*
2738 ** Call the end of instruction callback. This is to check what actually
2739 ** leaked as opposed to what appeared to leak in a transient fashion
2740 ** due to instructions getting broken up into more simple IR
2741 ** instructions. Note that stack register updates are moved to
2742 ** the end of the orginal instruction so that things like 'pop' get
2743 ** the values into registers BEFORE the stack is invalidated.
2744 */
2745 if(stackReg)
2746 {
2747 addStmtToIRSB( bb, stackReg );
2748 stackReg = NULL;
2749 }
2750 di = unsafeIRDirty_0_N( 1, "o_endOfInstruction", &o_endOfInstruction,
2751 mkIRExprVec_1(mkIRExpr_HWord(st->Ist.IMark.addr)));
2752 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2753 addStmtToIRSB( bb, st );
2754#if defined(VGA_x86)
2755 /*
2756 ** Make sure the EIP sim cpu register gets updated or our stack
2757 ** traces go a little Pete Tong...
2758 ** If this duplicates, the ir optimisation will knock one of them out.
2759 */
2760 addStmtToIRSB( bb, IRStmt_Put(OFFSET_x86_EIP,
2761 mkIRExpr_HWord(st->Ist.IMark.addr)));
2762#endif
2763 st = NULL;
2764 break;
2765
2766 case Ist_Put:
2767 /*
2768 ** Track the general purpose registers.
2769 */
2770 switch(st->Ist.Put.offset & mask)
2771 {
2772#if defined(VGA_x86)
2773 case OFFSET_x86_ESP:
2774#elif defined(VGA_amd64)
2775 case OFFSET_amd64_RSP:
2776#endif
2777 /*
2778 ** Save the stack register update - we will add it at the end of
2779 ** the instruction.
2780 */
2781 stackReg = st;
2782 st = NULL;
2783 break;
2784
2785#if defined(VGA_x86)
2786
2787 case OFFSET_x86_EAX:
2788 case OFFSET_x86_EBX:
2789 case OFFSET_x86_ECX:
2790 case OFFSET_x86_EDX:
2791 case OFFSET_x86_ESI:
2792 case OFFSET_x86_EDI:
2793 case OFFSET_x86_EBP:
2794
2795#if 0 //defined(O_MASTER_DEBUG)
2796 case OFFSET_x86_EIP:
2797#endif
2798
2799#elif defined(VGA_amd64)
2800
2801 case OFFSET_amd64_RAX:
2802 case OFFSET_amd64_RBX:
2803 case OFFSET_amd64_RCX:
2804 case OFFSET_amd64_RDX:
2805 case OFFSET_amd64_RSI:
2806 case OFFSET_amd64_RDI:
2807 case OFFSET_amd64_RBP:
2808 case OFFSET_amd64_R8:
2809 case OFFSET_amd64_R9:
2810 case OFFSET_amd64_R10:
2811 case OFFSET_amd64_R11:
2812 case OFFSET_amd64_R12:
2813 case OFFSET_amd64_R13:
2814 case OFFSET_amd64_R14:
2815 case OFFSET_amd64_R15:
2816
2817#if 0 //defined(O_MASTER_DEBUG)
2818 case OFFSET_amd64_RIP:
2819#endif
2820
sewardj4cff56d2007-11-10 13:33:56 +00002821#elif defined(VGA_ppc32) || defined(VGA_ppc64)
2822 default:
sewardjdcbb8d32007-11-26 21:34:30 +00002823 VG_(printf)("\nOmega does not currently work on PowerPC/POWER platforms."
sewardj4cff56d2007-11-10 13:33:56 +00002824 " Sorry.\n\n");
2825 VG_(exit)(0);
sewardj99a2ceb2007-11-09 12:30:36 +00002826#else
2827
2828#error Unknown arch
2829
2830#endif
2831 {
2832 if(typeOfIRExpr(bb->tyenv, st->Ist.Put.data) == type)
2833 {
2834 /*
2835 ** This is a put to a register in the simulated processor of data
2836 ** that could be a pointer.
2837 */
2838 di = unsafeIRDirty_0_N( 2, "o_omegaDetector", &o_omegaDetector,
2839 mkIRExprVec_2(mkIRExpr_HWord(st->Ist.Put.offset),
2840 st->Ist.Put.data));
2841 }
2842 else
2843 {
2844 /*
2845 ** There is no way that the data is a pointer but we still have
2846 ** to check if a pointer in a register will be overwritten.
2847 */
2848 di = unsafeIRDirty_0_N( 2, "o_omegaDetector", &o_omegaDetector,
2849 mkIRExprVec_2(mkIRExpr_HWord(st->Ist.Put.offset),
2850 mkIRExpr_HWord(0)));
2851 }
2852 /*
2853 ** Add in the original instruction first.
2854 */
2855 addStmtToIRSB( bb, st );
2856 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2857 st = NULL;
2858 }
2859 break; // Register Cases
2860 }
2861 break; // Ist_Put
2862
2863#if defined(O_TRACK_LOADS)
2864 case Ist_Tmp:
2865 /*
2866 ** Debug to see how 'leaked' references survive.
2867 ** (From experience, mostly through illegal reads from
2868 ** free()ed blocks.)
2869 */
2870 if(st->Ist.Tmp.data->tag == Iex_Load)
2871 {
2872 if(typeOfIRExpr(bb->tyenv, st->Ist.Tmp.data->Iex.Load.addr) == type)
2873 {
2874 di = unsafeIRDirty_0_N( 1, "o_omegaLoadTracker", &o_omegaLoadTracker,
2875 mkIRExprVec_1(st->Ist.Tmp.data->Iex.Load.addr));
2876 /*
2877 ** Add in the original instruction first.
2878 */
2879 addStmtToIRSB( bb, st );
2880 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2881 st = NULL;
2882 }
2883 }
2884 break;
2885#endif
2886
2887 default:
2888 break;
2889 }
2890
2891 /*
2892 ** Add in the original instruction if we havent already done so.
2893 */
2894 if(st)
2895 {
2896 addStmtToIRSB( bb, st );
2897 }
2898 }
2899
2900 if(stackReg)
2901 {
2902 addStmtToIRSB( bb, stackReg );
2903 stackReg = NULL;
2904 }
2905
2906 if(bb->jumpkind == Ijk_Ret)
2907 {
2908 /*
2909 ** The client is doing a return. This is the point to invalidate
2910 ** registers that belong to the callee, possibly generating a
2911 ** leak report. This is to catch things like foo(malloc(128)).
2912 */
2913
2914 di = unsafeIRDirty_0_N( 0, "o_omegaFunctionReturn",
2915 &o_omegaFunctionReturn,
2916 mkIRExprVec_0());
2917 /*
2918 ** Add in the new instruction.
2919 */
2920 addStmtToIRSB( bb, IRStmt_Dirty(di) );
2921 }
2922
2923 return bb;
2924}
2925
2926/*------------------------------------------------------------*/
2927/*--- Client Request Handling ---*/
2928/*------------------------------------------------------------*/
2929static Bool o_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
2930{
2931 if (!VG_IS_TOOL_USERREQ('O','M',arg[0]) &&
2932 VG_USERREQ__MALLOCLIKE_BLOCK != arg[0] &&
2933 VG_USERREQ__FREELIKE_BLOCK != arg[0])
2934 return False;
2935
2936 switch (arg[0])
2937 {
2938 case VG_USERREQ__ENTERING_MAIN:
2939 {
2940 /*
2941 ** Allow leak reports whilst inside main().
2942 */
2943 o_inhibitLeakDetect = False;
2944 }
2945 break;
2946
2947 case VG_USERREQ__LEAVING_MAIN:
2948 {
2949 /*
2950 ** Stop any more leak reports - they won't be helpfull.
2951 */
2952 o_inhibitLeakDetect = True;
2953
2954O_TRACE_OFF();
2955
2956 }
2957 break;
2958
2959 case VG_USERREQ__MALLOCLIKE_BLOCK:
2960 {
2961 if(o_onlyMallocLike)
2962 {
2963 /*
2964 ** Either we use malloc like block or we don't.
2965 ** Trying to auto track and do malloc like block handling together
2966 ** is asking for trouble.
2967 */
2968 Addr p = (Addr)arg[1];
2969 SizeT size = arg[2];
2970
2971 o_createMemBlock(tid, p, size);
2972 }
2973 }
2974 break;
2975
2976 case VG_USERREQ__FREELIKE_BLOCK:
2977 {
2978 if(o_onlyMallocLike)
2979 {
2980 /*
2981 ** Either we use malloc like block or we don't.
2982 ** Trying to auto track and do malloc like block handling together
2983 ** is asking for trouble.
2984 */
2985 Addr p = (Addr)arg[1];
2986
2987 o_destroyMemBlock(tid, p);
2988 }
2989 }
2990 break;
2991 }
2992
2993 return True;
2994}
2995
2996/*------------------------------------------------------------*/
2997/*--- Circular Reference Detection ---*/
2998/*------------------------------------------------------------*/
2999/*
3000** Check for circular references. This is where a memory block holds a
3001** reference to another memory block and vice versa but there are no
3002** references that are external. Like this:
3003
3004 typedef struct
3005 {
3006 void *linkedBlock;
3007 char padding[120];
3008 } block;
3009
3010 block *p1 = NULL;
3011 block *p2 = NULL;
3012
3013 p1 = (block *)malloc(sizeof(block));
3014 p2 = (block *)malloc(sizeof(block));
3015
3016 p1->linkedBlock = p2;
3017 p2->linkedBlock = p1;
3018
3019** As you can see, the blocks wont be seen to leak because they have a live
3020** reference but the reality is that without an external reference, these
3021** blocks are lost to the system.
3022**
3023** To perform this test, we go through the following stages:
3024**
3025** 1) Generate a binary tree of the memory covered by the allocated blocks
3026** 2) Check every tracked pointer of every allocated block and mark the
3027** block if any of them fall outside of an allocated block.
3028** 3) For each block with an external pointer, recursivly walk through the
3029** internal pointers to other blocks, marking the blocks as also having
3030** an external pointer.
3031** 4) Report any blocks without external references.
3032**
3033*/
3034
3035typedef struct _TreeNode{
3036 Addr start;
3037 Addr end;
3038 MemBlock *block;
3039 struct _TreeNode *left;
3040 struct _TreeNode *right;
3041} TreeNode;
3042
3043static TreeNode *o_treeRoot = NULL;
3044static MemBlock **o_memblockList = NULL;
3045static UInt o_memblockListCount = 0;
3046static BlockRecordList o_circularRecords = {NULL, NULL};
3047
3048static
3049TreeNode *o_findTreeNode(Addr addr, TreeNode *start, TreeNode ***parent)
3050{
3051 /*
3052 ** Find the treenode that this address falls within and return it.
3053 ** Return NULL if no matching node is found and return the parent if it is
3054 ** requested.
3055 */
3056
3057 /*
3058 ** If the treeRoot is NULL, we won't be finding anything.
3059 */
3060 if(!o_treeRoot)
3061 {
3062 if(parent)
3063 {
3064 *parent = &o_treeRoot;
3065 }
3066
3067 return NULL;
3068 }
3069
3070 /*
3071 ** The start should be a valid node.
3072 */
3073 tl_assert(start);
3074
3075 if((addr >= start->start) &&
3076 (addr <= start->end))
3077 {
3078 /*
3079 ** Found it
3080 */
3081 return start;
3082 }
3083
3084 if(addr < start->start)
3085 {
3086 /*
3087 ** Less than - go left if we can, return NULL if we can't.
3088 */
3089 if(start->left)
3090 {
3091 return o_findTreeNode(addr, start->left, parent);
3092 }
3093 else
3094 {
3095 if(parent)
3096 {
3097 *parent = &start->left;
3098 }
3099
3100 return NULL;
3101 }
3102 }
3103 else
3104 {
3105 /*
3106 ** Greater than - go right if we can, return NULL if we can't.
3107 */
3108 if(start->right)
3109 {
3110 return o_findTreeNode(addr, start->right, parent);
3111 }
3112 else
3113 {
3114 if(parent)
3115 {
3116 *parent = &start->right;
3117 }
3118
3119 return NULL;
3120 }
3121 }
3122
3123 VG_(tool_panic)("fell out of the binary tree");
3124}
3125
3126static UInt o_buildMemblockTree(void)
3127{
3128 /*
3129 ** Build a binary tree of the addresses covered by the memory blocks.
3130 ** We dont do anything to balance things so this could decompose to a
3131 ** linear structure. Thankfully, we are not in a time critical section.
3132 */
sewardj1c814ec2007-11-11 05:59:22 +00003133 UInt indx;
sewardj99a2ceb2007-11-09 12:30:36 +00003134
3135 o_memblockList = (MemBlock **)VG_(HT_to_array)(o_MemBlocks,
3136 &o_memblockListCount);
3137
sewardj1c814ec2007-11-11 05:59:22 +00003138 for(indx = 0; indx < o_memblockListCount; indx++)
sewardj99a2ceb2007-11-09 12:30:36 +00003139 {
3140 TreeNode **parent = NULL;
3141 TreeNode *tn = NULL;
sewardj1c814ec2007-11-11 05:59:22 +00003142 MemBlock *mb = o_memblockList[indx];
sewardj99a2ceb2007-11-09 12:30:36 +00003143
3144 /*
3145 ** Only process main blocks that havent leaked.
3146 */
3147 if(!mb->shadowing && !mb->leaked)
3148 {
3149 if(o_findTreeNode(mb->hdr.key, o_treeRoot, &parent))
3150 {
3151 VG_(tool_panic)("Failed to grow the binary tree.");
3152 }
3153
3154 /*
3155 ** We should have a pointer to the parent
3156 */
3157 tl_assert(parent);
3158
3159 /*
3160 ** Create and populate the new node
3161 */
3162 tn = VG_(malloc)(sizeof(TreeNode));
3163 VG_(memset)(tn, 0, sizeof(TreeNode));
3164
3165 tn->start = mb->hdr.key;
3166 tn->end = tn->start + mb->length;
3167 tn->block = mb;
3168
3169 /*
3170 ** Add this node into the parent node
3171 */
3172 *parent = tn;
3173 }
3174 }
3175
3176 return o_memblockListCount;
3177}
3178
3179static void o_checkExternalPointers(void)
3180{
sewardj1c814ec2007-11-11 05:59:22 +00003181 UInt indx;
sewardj99a2ceb2007-11-09 12:30:36 +00003182
sewardj1c814ec2007-11-11 05:59:22 +00003183 for(indx = 0; indx < o_memblockListCount; indx++)
sewardj99a2ceb2007-11-09 12:30:36 +00003184 {
sewardj1c814ec2007-11-11 05:59:22 +00003185 MemBlock *mb = o_memblockList[indx];
sewardj99a2ceb2007-11-09 12:30:36 +00003186
3187 /*
3188 ** Only check blocks that haven't leaked.
3189 ** We process through shadow blocks because we want the back references
3190 ** as they still point within the shadowed block.
3191 */
3192 if(!mb->leaked)
3193 {
3194 UInt pointerIndex;
3195
3196 for(pointerIndex = 0; pointerIndex < mb->refNum; pointerIndex++)
3197 {
3198 if(!o_findTreeNode(FROM_TRACKED_KEY(mb->pointers[pointerIndex]->hdr.key),
3199 o_treeRoot, NULL))
3200 {
3201 /*
3202 ** External reference. Mark the block and stop checking.
3203 */
3204 mb->external = 1;
3205 break;
3206 }
3207 }
3208 }
3209 }
3210}
3211
3212static void o_rippleExternelPointers(MemBlock *mb)
3213{
sewardj1c814ec2007-11-11 05:59:22 +00003214 UInt indx;
sewardj99a2ceb2007-11-09 12:30:36 +00003215
3216 if(!mb)
3217 {
3218 /*
3219 ** Iterate through the memory block list marking external blocks
3220 ** so that we dont process the same blocks twice.
3221 */
sewardj1c814ec2007-11-11 05:59:22 +00003222 for(indx = 0; indx < o_memblockListCount; indx++)
sewardj99a2ceb2007-11-09 12:30:36 +00003223 {
sewardj1c814ec2007-11-11 05:59:22 +00003224 if(o_memblockList[indx]->external > 0)
sewardj99a2ceb2007-11-09 12:30:36 +00003225 {
sewardj1c814ec2007-11-11 05:59:22 +00003226 o_memblockList[indx]->external = -1;
3227 o_rippleExternelPointers(o_memblockList[indx]);
sewardj99a2ceb2007-11-09 12:30:36 +00003228 }
3229 }
3230 }
3231 else
3232 {
3233 /*
3234 ** We are recursing.
3235 ** Follow any tracked pointers within our block, marking the target
3236 ** blocks as external and recursing on those blocks.
3237 */
3238 PBitContext pb;
3239 Addr a;
3240 TreeNode *tn = NULL;
3241
3242 a = o_firstPBit(&pb, mb->hdr.key, mb->length);
3243 while(a)
3244 {
3245 tn = o_findTreeNode(a, o_treeRoot, NULL);
3246
3247 /*
3248 ** We really should have a node
3249 */
3250 tl_assert(tn);
3251
3252 /*
3253 ** If we havent already done so, mark the block as external and
3254 ** processed then recurse on it.
3255 */
3256 if(tn->block->external >= 0)
3257 {
3258 tn->block->external = -1;
3259 o_rippleExternelPointers(tn->block);
3260 }
3261
3262 /*
3263 ** Get the next tracked pointer within this block.
3264 */
3265 a = o_nextPBit(&pb);
3266 }
3267 }
3268}
3269
3270static int o_reportCircularBlocks(void)
3271{
3272 int count = 0;
3273 BlockRecord *block = NULL;
sewardj1c814ec2007-11-11 05:59:22 +00003274 int indx;
sewardj99a2ceb2007-11-09 12:30:36 +00003275
3276 /*
3277 ** Iterate through the memory block list reporting any blocks not marked
3278 ** as external.
3279 ** We aggregate the list of blocks as many could come from the same context.
3280 */
sewardj1c814ec2007-11-11 05:59:22 +00003281 for(indx = 0; indx < o_memblockListCount; indx++)
sewardj99a2ceb2007-11-09 12:30:36 +00003282 {
sewardj1c814ec2007-11-11 05:59:22 +00003283 MemBlock * mb = o_memblockList[indx];
sewardj99a2ceb2007-11-09 12:30:36 +00003284 if(!mb->shadowing && !mb->leaked && mb->external == 0)
3285 {
3286 block = o_findBlockRecord(&o_circularRecords, mb->where, NULL);
3287
3288 if(block)
3289 {
3290 /*
3291 ** Just increment the counts.
3292 */
3293 block->bytes += mb->length;
3294 block->count++;
3295 }
3296 else
3297 {
3298 /*
3299 ** Create a new block and add it to the circular records list.
3300 */
3301 BlockRecord *item = VG_(malloc)(sizeof(BlockRecord));
3302 tl_assert(item);
3303
3304 item->count = 1;
3305 item->bytes = mb->length;
3306 item->next = item->prev = NULL;
3307 item->allocated = mb->where;
3308 item->leaked = NULL;
3309
3310 o_addBlockRecord(&o_circularRecords, item);
3311 }
3312 }
3313 }
3314
3315 /*
3316 ** Now report the blocks.
3317 */
3318 block = o_circularRecords.start;
3319 while(block)
3320 {
3321 if(!count)
3322 {
3323 VG_(message)(Vg_UserMsg, "The following blocks only have circular references from other blocks");
3324 }
3325 count++;
3326
3327 VG_(message)(Vg_UserMsg, " Circular loss record %d", count);
3328 VG_(message)(Vg_UserMsg, " Leaked %d (%p) bytes in %d block%sallocated",
3329 block->bytes,
3330 block->bytes,
3331 block->count,
3332 (block->count == 1) ? " " : "s ");
3333 VG_(pp_ExeContext)(block->allocated);
3334 VG_(message)(Vg_UserMsg,"");
3335
3336 /*
3337 ** Get the next block, if any.
3338 */
3339 block = block->next;
3340 }
3341
3342 return count;
3343}
3344
3345static int o_checkCircular(void)
3346{
3347 int count = 0;
3348
3349 /*
3350 ** If there is nothing in the tree, there is nothing to check.
3351 */
3352 if(o_buildMemblockTree())
3353 {
3354 o_checkExternalPointers();
3355 o_rippleExternelPointers(NULL);
3356 count = o_reportCircularBlocks();
3357 }
3358
3359 return count;
3360}
3361
3362static void o_fini(Int exitcode)
3363{
3364 /*
3365 ** Iterate through the leaked block record list,
3366 ** printing out the stats as we go.
3367 */
3368 UInt count = 1;
3369 BlockRecord *record = o_leakRecords.start;
3370
3371 VG_(message)(Vg_UserMsg,"");
3372 VG_(message)(Vg_UserMsg,"");
3373 VG_(message)(Vg_UserMsg,"Omega Leak Summary");
3374 VG_(message)(Vg_UserMsg,"==================");
3375
3376 while(record)
3377 {
3378 VG_(message)(Vg_UserMsg,
3379 "Loss Record %d: Leaked %d (%p) bytes in %d block%s",
3380 count, record->bytes, record->bytes, record->count,
3381 (record->count > 1) ? "s" : "");
3382 VG_(pp_ExeContext)(record->leaked);
3383 VG_(message)(Vg_UserMsg, " Block%s allocated",
3384 (record->count > 1) ? "s" : "");
3385 VG_(pp_ExeContext)(record->allocated);
3386 VG_(message)(Vg_UserMsg,"");
3387
3388 count++;
3389 record = record->next;
3390 }
3391
3392 if(o_showCircular)
3393 {
3394 /*
3395 ** Now check for circular references.
3396 */
3397 count += o_checkCircular();
3398 }
3399
3400 if(count == 1)
3401 {
3402 /*
3403 ** Nothing leaked - assure the user.
3404 */
3405 VG_(message)(Vg_UserMsg,"No leaks to report.");
3406 VG_(message)(Vg_UserMsg,"");
3407 }
3408
3409 /*
3410 ** Remove the leaked blocks from the live blocks count - they wont be
3411 ** coming back now...
3412 */
3413 o_stats.liveMemoryBlocks -= o_stats.memoryBlocksLeaked;
3414
3415 if(o_showInternStats)
3416 {
3417 VG_(printf)("\n\n\n"
3418 "Omega internal statistics summary:\n"
3419 " Tracked Pointers still live: %ld\n"
3420 " Tracked Pointers Allocated: %ld\n"
3421 " Memory Blocks still live: %ld\n"
3422 " Memory Blocks Allocated: %ld\n"
3423 " Shadow Memory Blocks Allocated: %ld\n"
3424 " Memory Blocks Leaked: %ld\n"
3425 " Memory Blocks Lost and Found: %ld\n"
3426 " pbitNodes: %ld\n\n",
3427 o_stats.liveTrackedPointers,
3428 o_stats.trackedPointersAllocated,
3429 o_stats.liveMemoryBlocks,
3430 o_stats.memoryBlocksAllocated,
3431 o_stats.shadowMemoryBlocksAllocated,
3432 o_stats.memoryBlocksLeaked,
3433 o_stats.memoryBlocksLostAndFound,
3434 o_stats.pbitNodes);
3435 }
3436}
3437
3438static Bool o_process_cmd_line_option(Char *arg)
3439{
3440 /*
3441 ** Setup our processing state based upon what the user would like us to do.
3442 */
3443 Int pbithash = 0;
3444 Int mbhash = 0;
3445 Int tphash = 0;
3446
3447 /*
3448 ** Expose the hash sizes for simple performance tweaking.
3449 */
3450 VG_NUM_CLO(arg, "--pbithashsize", pbithash);
3451 VG_NUM_CLO(arg, "--mbhashsize", mbhash);
3452 VG_NUM_CLO(arg, "--tphashsize", tphash);
3453
3454 /*
3455 ** Only tweak upwards for now.
3456 */
3457 if(pbithash > o_pbitNodeHashSize)
3458 o_pbitNodeHashSize = pbithash;
3459
3460 if(mbhash > o_memblockHashSize)
3461 o_memblockHashSize = mbhash;
3462
3463 if(tphash > o_trackedPointerHashSize)
3464 o_trackedPointerHashSize = tphash;
3465
3466 /*
3467 ** Check the flags.
3468 */
3469 if(VG_CLO_STREQ(arg, "--only-malloclike"))
3470 o_onlyMallocLike = True;
3471 else if(VG_CLO_STREQ(arg, "--show-indirect"))
3472 o_showIndirect = True;
3473 else if(VG_CLO_STREQ(arg, "--show-circular"))
3474 o_showCircular = True;
3475 else if(VG_CLO_STREQ(arg, "--show-hanging"))
3476 o_showHanging = True;
3477 else if(VG_CLO_STREQ(arg, "--show-intern-stats"))
3478 o_showInternStats = True;
3479 else if(VG_CLO_STREQ(arg, "--instant-reports"))
3480 o_showSummaryOnly = False;
3481 else if(VG_CLO_STREQ(arg, "--poison"))
3482 o_poison = True;
3483 else
3484 return VG_(replacement_malloc_process_cmd_line_option)(arg);
3485
3486 return True;
3487}
3488
3489static void o_print_usage(void)
3490{
3491 /*
3492 ** Tell the average user what we support.
3493 */
3494 VG_(printf)("");
3495 VG_(printf)(
3496" --only-malloclike only track blocks passed through the\n"
3497" MALLOCLIKE_BLOCK user request.\n"
3498" --show-indirect show indirect leaks from leaked blocks.\n"
3499" --show-circular show blocks that just have circular references.\n"
3500" --instant-reports show leaks as they happen, not just a summary.\n"
3501" --show-hanging show hanging pointers to the block being\n"
3502" deallocated.\n"
3503 );
3504
3505}
3506
3507static void o_print_debug_usage(void)
3508{
3509 /*
3510 ** Tell the inquisitive user what else we support.
3511 */
3512 VG_(printf)("");
3513 VG_(printf)(
3514" --show-intern-stats show some internal statistics from the run.\n"
3515"\n"
3516" IMPORTANT! These next settings must be PRIME NUMBERS\n"
3517"\n"
3518" --pbithashsize=<number> number of pbit nodes to allocate [%d]\n"
3519" --mbhashsize=<number> number of mem block nodes to allocate [%d]\n"
3520" --tphashsize=<number> number of tracked pointer nodes to allocate [%d]\n",
3521 o_pbitNodeHashSize,
3522 o_memblockHashSize,
3523 o_trackedPointerHashSize
3524 );
3525}
3526
3527static void o_memRemapSupport(Addr src, Addr dst, SizeT length)
3528{
3529 /*
3530 ** The track_copy_mem_remap callback has the src and dst the opposite
3531 ** way around to our duplicate tracked pointers function so this tiny
3532 ** wrapper twizzles them around.
3533 */
3534 o_duplicateTrackedPointers(dst, src, length);
3535}
3536
3537static void o_pre_clo_init(void)
3538{
3539 // Details
3540 VG_(details_name) ("exp-omega");
3541 VG_(details_version) ("RC1");
3542 VG_(details_description) ("an instant memory leak detector");
3543 VG_(details_copyright_author)("Copyright (C) 2006-2007, and GNU GPL'd, "
3544 "by Bryan Meredith.");
3545 VG_(details_bug_reports_to) ("omega at brainmurders d eclipse d co d uk");
3546
3547 // Basic functions
3548 VG_(basic_tool_funcs) (o_post_clo_init,
3549 o_instrument,
3550 o_fini);
3551 // Needs
3552 VG_(needs_malloc_replacement) (o_malloc,
3553 o__builtin_new,
3554 o__builtin_vec_new,
3555 o_memalign,
3556 o_calloc,
3557 o_free,
3558 o__builtin_delete,
3559 o__builtin_vec_delete,
3560 o_realloc,
3561 0 );
3562 // Want stack unwinds
3563 VG_(track_die_mem_stack) (o_dieMemStack);
3564 // Need command line input
3565 VG_(needs_command_line_options) (o_process_cmd_line_option,
3566 o_print_usage,
3567 o_print_debug_usage);
3568 // Support MALLOCLIKE and FREELIKE
3569 VG_(needs_client_requests) (o_handle_client_request);
3570
3571 // Wholesale destruction of memory ranges
3572 VG_(track_copy_mem_remap) (o_memRemapSupport );
3573 VG_(track_die_mem_stack_signal)(o_killRange);
3574 VG_(track_die_mem_brk) (o_killRange);
3575 VG_(track_die_mem_munmap) (o_killRange);
3576
3577}
3578
3579VG_DETERMINE_INTERFACE_VERSION(o_pre_clo_init);
3580
3581/*--------------------------------------------------------------------*/
3582/*--- end ---*/
3583/*--------------------------------------------------------------------*/