WinDBG/Exts/CodeAnalyzer/gdbplus/gdb-7.7/gdb/heap.c
/*
 * Given a reference, a variable or a pointer to a heap block, with known size,
 * 	Return its aggregated reachable in-use blocks
 */
Given a reference, a variable or a pointer to a heap block, with known size,
Return its aggregated reachable in-use blocks
Given a reference a variable or a pointer to a heap block with known size Return its aggregated reachable in - use blocks
CA_BOOL
calc_aggregate_size(const struct object_reference *ref,
					size_t var_len,
					CA_BOOL all_reachable_blocks,
					struct inuse_block *inuse_blocks,
					unsigned long num_inuse_blocks,
					size_t *total_size,
					unsigned long *total_count)
{
	address_t addr, cursor, end;
	size_t ptr_sz = g_ptr_bit >> 3;
	size_t aggr_size = 0;
	unsigned long aggr_count = 0;
	struct inuse_block *blk;
	size_t bitmap_sz = ((num_inuse_blocks+15)*2/32) * sizeof(unsigned int);
	static unsigned int* qv_bitmap = NULL;	
	static unsigned long bitmap_capacity = 0;	
	*total_size = 0;
	*total_count = 0;
	if (bitmap_capacity < num_inuse_blocks)
	{
		if (qv_bitmap)
			free (qv_bitmap);
		qv_bitmap = (unsigned int*) malloc(bitmap_sz);
		if (!qv_bitmap)
		{
			bitmap_capacity = 0;
			CA_PRINT("Out of Memory\n");
			return CA_FALSE;
		}
		bitmap_capacity = num_inuse_blocks;
	}
	memset(qv_bitmap, 0, bitmap_sz);
	if (ref->storage_type == ENUM_REGISTER || ref->storage_type == ENUM_HEAP)
	{
		if (var_len != ptr_sz)
			return CA_FALSE;
		blk = find_inuse_block(ref->vaddr, inuse_blocks, num_inuse_blocks);
		if (blk)
		{
			if (all_reachable_blocks && blk->reachable.aggr_size)
			{
				*total_size  = blk->reachable.aggr_size;
				*total_count = blk->reachable.aggr_count;
				return CA_TRUE;
			}
			else
			{
				cursor = blk->addr;
				end  = cursor + blk->size;
				aggr_size  = blk->size;
				aggr_count = 1;
				set_visited(qv_bitmap, blk - inuse_blocks);
			}
		}
		else
			return CA_FALSE;
	}
	else
	{
		if (all_reachable_blocks && var_len == ptr_sz)
		{
			if(read_memory_wrapper(NULL, ref->vaddr, (void*)&addr, ptr_sz))
			{
				blk = find_inuse_block(addr, inuse_blocks, num_inuse_blocks);
				if (blk)
				{
					if (blk->reachable.aggr_size)
					{
						*total_size  = blk->reachable.aggr_size;
						*total_count = blk->reachable.aggr_count;
						return CA_TRUE;
					}
				}
				else
					return CA_FALSE;
			}
			else
				return CA_FALSE;
		}
		cursor = ref->vaddr;
		end  = cursor + var_len;
	}
	cursor = ALIGN(cursor, ptr_sz);
	while (cursor < end)
	{
		if(!read_memory_wrapper(NULL, cursor, (void*)&addr, ptr_sz))
			break;
		blk = find_inuse_block(addr, inuse_blocks, num_inuse_blocks);
		if (blk && !is_queued_or_visited(qv_bitmap, blk - inuse_blocks))
		{
			if (all_reachable_blocks)
			{
				unsigned long sub_count = 0;
				aggr_size += heap_aggregate_size(blk, inuse_blocks, num_inuse_blocks, qv_bitmap, &sub_count);
				aggr_count += sub_count;
			}
			else
			{
				aggr_size += blk->size;
				aggr_count++;
				set_visited(qv_bitmap, blk - inuse_blocks);
			}
		}
		cursor += ptr_sz;
	}
	if (all_reachable_blocks && aggr_size)
	{
		if (ref->storage_type == ENUM_REGISTER || ref->storage_type == ENUM_HEAP)
		{
			blk = find_inuse_block(ref->vaddr, inuse_blocks, num_inuse_blocks);
			blk->reachable.aggr_size = aggr_size;
			blk->reachable.aggr_count = aggr_count;
		}
		else if (var_len == ptr_sz)
		{
			if (read_memory_wrapper(NULL, ref->vaddr, (void*)&addr, ptr_sz))
			{
				blk = find_inuse_block(addr, inuse_blocks, num_inuse_blocks);
				if (blk)
				{
					blk->reachable.aggr_size = aggr_size;
					blk->reachable.aggr_count = aggr_count;
				}
			}
		}
	}
	*total_size  = aggr_size;
	*total_count = aggr_count;
	return CA_TRUE;
}
CA_BOOL calc_aggregate_size ( const struct object_reference * ref , size_t var_len , CA_BOOL all_reachable_blocks , struct inuse_block * inuse_blocks , unsigned long num_inuse_blocks , size_t * total_size , unsigned long * total_count ) { address_t addr , cursor , end ; size_t ptr_sz = g_ptr_bit >> 3 ; size_t aggr_size = 0 ; unsigned long aggr_count = 0 ; struct inuse_block * blk ; size_t bitmap_sz = ( ( num_inuse_blocks + 15 ) * 2 / 32 ) * sizeof ( unsigned int ) ; static unsigned int * qv_bitmap = NULL ; static unsigned long bitmap_capacity = 0 ; * total_size = 0 ; * total_count = 0 ; if ( bitmap_capacity < num_inuse_blocks ) { if ( qv_bitmap ) free ( qv_bitmap ) ; qv_bitmap = ( unsigned int * ) malloc ( bitmap_sz ) ; if ( ! qv_bitmap ) { bitmap_capacity = 0 ; CA_PRINT ( " \n " ) ; return CA_FALSE ; } bitmap_capacity = num_inuse_blocks ; } memset ( qv_bitmap , 0 , bitmap_sz ) ; if ( ref -> storage_type == ENUM_REGISTER || ref -> storage_type == ENUM_HEAP ) { if ( var_len != ptr_sz ) return CA_FALSE ; blk = find_inuse_block ( ref -> vaddr , inuse_blocks , num_inuse_blocks ) ; if ( blk ) { if ( all_reachable_blocks && blk -> reachable . aggr_size ) { * total_size = blk -> reachable . aggr_size ; * total_count = blk -> reachable . aggr_count ; return CA_TRUE ; } else { cursor = blk -> addr ; end = cursor + blk -> size ; aggr_size = blk -> size ; aggr_count = 1 ; set_visited ( qv_bitmap , blk - inuse_blocks ) ; } } else return CA_FALSE ; } else { if ( all_reachable_blocks && var_len == ptr_sz ) { if ( read_memory_wrapper ( NULL , ref -> vaddr , ( void * ) & addr , ptr_sz ) ) { blk = find_inuse_block ( addr , inuse_blocks , num_inuse_blocks ) ; if ( blk ) { if ( blk -> reachable . aggr_size ) { * total_size = blk -> reachable . aggr_size ; * total_count = blk -> reachable . aggr_count ; return CA_TRUE ; } } else return CA_FALSE ; } else return CA_FALSE ; } cursor = ref -> vaddr ; end = cursor + var_len ; } cursor = ALIGN ( cursor , ptr_sz ) ; while ( cursor < end ) { if ( ! read_memory_wrapper ( NULL , cursor , ( void * ) & addr , ptr_sz ) ) break ; blk = find_inuse_block ( addr , inuse_blocks , num_inuse_blocks ) ; if ( blk && ! is_queued_or_visited ( qv_bitmap , blk - inuse_blocks ) ) { if ( all_reachable_blocks ) { unsigned long sub_count = 0 ; aggr_size += heap_aggregate_size ( blk , inuse_blocks , num_inuse_blocks , qv_bitmap , & sub_count ) ; aggr_count += sub_count ; } else { aggr_size += blk -> size ; aggr_count ++ ; set_visited ( qv_bitmap , blk - inuse_blocks ) ; } } cursor += ptr_sz ; } if ( all_reachable_blocks && aggr_size ) { if ( ref -> storage_type == ENUM_REGISTER || ref -> storage_type == ENUM_HEAP ) { blk = find_inuse_block ( ref -> vaddr , inuse_blocks , num_inuse_blocks ) ; blk -> reachable . aggr_size = aggr_size ; blk -> reachable . aggr_count = aggr_count ; } else if ( var_len == ptr_sz ) { if ( read_memory_wrapper ( NULL , ref -> vaddr , ( void * ) & addr , ptr_sz ) ) { blk = find_inuse_block ( addr , inuse_blocks , num_inuse_blocks ) ; if ( blk ) { blk -> reachable . aggr_size = aggr_size ; blk -> reachable . aggr_count = aggr_count ; } } } } * total_size = aggr_size ; * total_count = aggr_count ; return CA_TRUE ; }
Given a reference, a variable or a pointer to a heap block, with known size,
      Return its aggregated reachable in-use blocks
Given a reference a variable or a pointer to a heap block with known size Return its aggregated reachable in - use blocks
// Bit flags of whether a block is queued/visited // in terms of number of blocks handled // ground return values // Prepare bitmap with the clean state // Each block uses two bits(queued/visited) // Input is a pointer to an in-use memory block // cached result is available, return now // search starts with the memory block // input reference is an object with given size, e.g. a local/global variable // input is of pointer size, which is candidate for cache value // We now have a range of memory to search // can we cache the result? // return happily