*/
#include "pub_tool_basics.h"
+#include "pub_tool_gdbserver.h"
#include "pub_tool_hashtable.h" // For mc_include.h
#include "pub_tool_libcbase.h"
#include "pub_tool_libcassert.h"
case Err_Free:
if (xml) {
emit( " <kind>InvalidFree</kind>\n" );
- emit( " <what>Invalid free() / delete / delete[]</what>\n" );
+ emit( " <what>Invalid free() / delete / delete[]"
+ " / realloc()</what>\n" );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
mc_pp_AddrInfo( VG_(get_error_address)(err),
&extra->Err.Free.ai, False );
} else {
- emit( "Invalid free() / delete / delete[]\n" );
+ emit( "Invalid free() / delete / delete[] / realloc()\n" );
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
mc_pp_AddrInfo( VG_(get_error_address)(err),
&extra->Err.Free.ai, False );
for the --workaround-gcc296-bugs kludge. */
static Bool is_just_below_ESP( Addr esp, Addr aa )
{
+ esp -= VG_STACK_REDZONE_SZB;
if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
return True;
else
if (MC_(in_ignored_range)(a))
return;
+ if (VG_(is_watched)( (isWrite ? write_watchpoint : read_watchpoint), a, szB))
+ return;
+
# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
/* AIX zero-page handling. On AIX, reads from page zero are,
bizarrely enough, legitimate. Writes to page zero aren't,
}
}
-/* Function used when searching MC_Chunk lists */
-static Bool addr_is_in_MC_Chunk(MC_Chunk* mc, Addr a)
+/* Functions used when searching MC_Chunk lists */
+static
+Bool addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk* mc, Addr a)
{
- // Nb: this is not quite right! It assumes that the heap block has
- // a redzone of size MC_MALLOC_REDZONE_SZB. That's true for malloc'd
- // blocks, but not necessarily true for custom-alloc'd blocks. So
- // in some cases this could result in an incorrect description (eg.
- // saying "12 bytes after block A" when really it's within block B.
- // Fixing would require adding redzone size to MC_Chunks, though.
return VG_(addr_is_in_block)( a, mc->data, mc->szB,
MC_MALLOC_REDZONE_SZB );
}
+static
+Bool addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk* mc, Addr a, SizeT rzB)
+{
+ return VG_(addr_is_in_block)( a, mc->data, mc->szB,
+ rzB );
+}
-// Forward declaration
+// Forward declarations
static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
+static Bool mempool_block_maybe_describe( Addr a, AddrInfo* ai );
/* Describe an address as best you can, for error messages,
tl_assert(Addr_Undescribed == ai->tag);
- /* -- Perhaps it's a user-def'd block? -- */
+ /* -- Perhaps it's a user-named block? -- */
if (client_block_maybe_describe( a, ai )) {
return;
}
+ /* -- Perhaps it's in mempool block? -- */
+ if (mempool_block_maybe_describe( a, ai )) {
+ return;
+ }
/* -- Search for a recently freed block which might bracket it. -- */
mc = MC_(get_freed_list_head)();
while (mc) {
- if (addr_is_in_MC_Chunk(mc, a)) {
+ if (addr_is_in_MC_Chunk_default_REDZONE_SZB(mc, a)) {
ai->tag = Addr_Block;
ai->Addr.Block.block_kind = Block_Freed;
ai->Addr.Block.block_desc = "block";
/* -- Search for a currently malloc'd block which might bracket it. -- */
VG_(HT_ResetIter)(MC_(malloc_list));
while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
- if (addr_is_in_MC_Chunk(mc, a)) {
+ if (addr_is_in_MC_Chunk_default_REDZONE_SZB(mc, a)) {
ai->tag = Addr_Block;
ai->Addr.Block.block_kind = Block_Mallocd;
ai->Addr.Block.block_desc = "block";
return;
}
+void MC_(pp_describe_addr) ( Addr a )
+{
+ AddrInfo ai;
+
+ ai.tag = Addr_Undescribed;
+ describe_addr (a, &ai);
+ mc_pp_AddrInfo (a, &ai, /* maybe_gcc */ False);
+}
+
/* Fill in *origin_ec as specified by otag, or NULL it out if otag
does not refer to a known origin. */
static void update_origin ( /*OUT*/ExeContext** origin_ec,
}
}
-// FIXME: does this perhaps want to live somewhere else
-// in this file?
+
static Bool client_block_maybe_describe( Addr a,
/*OUT*/AddrInfo* ai )
{
continue;
// Use zero as the redzone for client blocks.
if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
- /* OK - maybe it's a mempool, too? */
- MC_Mempool* mp = VG_(HT_lookup)(MC_(mempool_list),
- (UWord)cgbs[i].start);
- if (mp != NULL) {
- if (mp->chunks != NULL) {
- MC_Chunk* mc;
- VG_(HT_ResetIter)(mp->chunks);
- while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
- if (addr_is_in_MC_Chunk(mc, a)) {
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_MempoolChunk;
- ai->Addr.Block.block_desc = "block";
- ai->Addr.Block.block_szB = mc->szB;
- ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
- ai->Addr.Block.lastchange = mc->where;
- return True;
- }
- }
- }
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_Mempool;
- ai->Addr.Block.block_desc = "mempool";
- ai->Addr.Block.block_szB = cgbs[i].size;
- ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
- ai->Addr.Block.lastchange = cgbs[i].where;
- return True;
- }
ai->tag = Addr_Block;
ai->Addr.Block.block_kind = Block_UserG;
ai->Addr.Block.block_desc = cgbs[i].desc;
}
+static Bool mempool_block_maybe_describe( Addr a,
+ /*OUT*/AddrInfo* ai )
+{
+ MC_Mempool* mp;
+ tl_assert( MC_(mempool_list) );
+
+ VG_(HT_ResetIter)( MC_(mempool_list) );
+ while ( (mp = VG_(HT_Next)(MC_(mempool_list))) ) {
+ if (mp->chunks != NULL) {
+ MC_Chunk* mc;
+ VG_(HT_ResetIter)(mp->chunks);
+ while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
+ if (addr_is_in_MC_Chunk_with_REDZONE_SZB(mc, a, mp->rzB)) {
+ ai->tag = Addr_Block;
+ ai->Addr.Block.block_kind = Block_MempoolChunk;
+ ai->Addr.Block.block_desc = "block";
+ ai->Addr.Block.block_szB = mc->szB;
+ ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
+ ai->Addr.Block.lastchange = mc->where;
+ return True;
+ }
+ }
+ }
+ }
+ return False;
+}
+
+
/*------------------------------------------------------------*/
/*--- Suppressions ---*/
/*------------------------------------------------------------*/