Exemple #1
0
static void
heap_walk(Heap *h,int idx,int depth,HEAPWALKFUNC func)
{
    HeapElement *he;

    if (idx < 0 || idx >= HSIZE(h))
	return;

    he = HARRAY(h,idx);

    func(depth,he->heKey,he->heData);

    heap_walk(h,HLEFT(idx),depth + 1,func);
    heap_walk(h,HRIGHT(idx),depth + 1,func);
}
Exemple #2
0
/*
 * Parse user options and invoke corresponding heap-related functions
 */
CA_BOOL heap_command_impl(char* args)
{
	CA_BOOL rc = CA_TRUE;

	address_t addr = 0;
	CA_BOOL verbose = CA_FALSE;
	CA_BOOL check_leak = CA_FALSE;
	CA_BOOL calc_usage = CA_FALSE;
	CA_BOOL block_info = CA_FALSE;
	CA_BOOL cluster_blocks = CA_FALSE;
	CA_BOOL top_block = CA_FALSE;
	CA_BOOL top_user = CA_FALSE;
	CA_BOOL all_reachable_blocks = CA_FALSE;	// experimental option
	char* expr = NULL;

	// Parse user input options
	// argument is either an address or /v or /leak
	if (args)
	{
		char* options[MAX_NUM_OPTIONS];
		int num_options = ca_parse_options(args, options);
		int i;
		for (i = 0; i < num_options; i++)
		{
			char* option = options[i];
			if (*option == '/')
			{
				if (strcmp(option, "/leak") == 0 || strcmp(option, "/l") == 0)
				{
					check_leak = CA_TRUE;
					if (block_info || cluster_blocks || calc_usage || top_block || top_user || addr)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/verbose") == 0 || strcmp(option, "/v") == 0)
				{
					verbose = CA_TRUE;
				}
				else if (strcmp(option, "/block") == 0 || strcmp(option, "/b") == 0)
				{
					block_info = CA_TRUE;
					if (check_leak || cluster_blocks || calc_usage || top_block || top_user)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/cluster") == 0 || strcmp(option, "/c") == 0)
				{
					cluster_blocks = CA_TRUE;
					if (check_leak || block_info || calc_usage || top_block || top_user)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/usage") == 0 || strcmp(option, "/u") == 0)
				{
					calc_usage = CA_TRUE;
					if (check_leak || block_info || cluster_blocks || top_block || top_user)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/topblock") == 0 || strcmp(option, "/tb") == 0)
				{
					top_block = CA_TRUE;
					if (check_leak || block_info || cluster_blocks || calc_usage || top_user)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/topuser") == 0 || strcmp(option, "/tu") == 0)
				{
					top_user = CA_TRUE;
					if (check_leak || block_info || cluster_blocks || calc_usage || top_block)
					{
						CA_PRINT("Option [%s] conflicts with one of the previous options\n", option);
						return CA_FALSE;
					}
				}
				else if (strcmp(option, "/all") == 0 || strcmp(option, "/a") == 0)
					all_reachable_blocks = CA_TRUE;
				else
				{
					CA_PRINT("Invalid option: [%s]\n", option);
					return CA_FALSE;
				}
			}
			else if (calc_usage)
			{
				expr = option;
				break;
			}
			else if (addr == 0)
				addr = ca_eval_address (option);
			else
			{
				CA_PRINT("Invalid option: [%s]\n", option);
				return CA_FALSE;
			}
		}
	}
	if (check_leak)
	{
		if (addr)
			CA_PRINT("Unexpected address expression\n");
		else
			display_heap_leak_candidates();
	}
	else if (block_info)
	{
		if (!addr)
			CA_PRINT("Heap block address is expected\n");
		else
		{
			struct heap_block heap_block;
			if (get_heap_block_info(addr, &heap_block))
			{
				if (heap_block.inuse)
					CA_PRINT("\t[In-use]\n");
				else
					CA_PRINT("\t[Free]\n");
				CA_PRINT("\t[Address] "PRINT_FORMAT_POINTER"\n", heap_block.addr);
				CA_PRINT("\t[Size]    "PRINT_FORMAT_SIZE"\n", heap_block.size);
				CA_PRINT("\t[Offset]  "PRINT_FORMAT_SIZE"\n", addr - heap_block.addr);
			}
			else
				CA_PRINT("[Error] Failed to query the memory block\n");
		}
	}
	else if (cluster_blocks)
	{
		if (addr)
		{
			if (!heap_walk(addr, verbose))
				CA_PRINT("[Error] Failed to walk heap\n");
		}
		else
			CA_PRINT("Heap block address is expected\n");
	}
	else if (calc_usage)
	{
		if (expr)
			calc_heap_usage(expr);
		else
			CA_PRINT("An expression of heap memory owner is expected\n");
	}
	else if (top_block || top_user)
	{
		unsigned int n = (unsigned int)addr;
		if (n == 0)
			CA_PRINT("A number is expected\n");
		else if (top_user)
			biggest_heap_owners_generic(n, all_reachable_blocks);
		else
			biggest_blocks(n);
	}
	else
	{
		if (addr)
			CA_PRINT("Unexpected address expression\n");
		else if (!heap_walk(addr, verbose))
			CA_PRINT("[Error] Failed to walk heap\n");
	}
	return rc;
}
Exemple #3
0
/*返回实际统计的数目*/
ULONG heap_stats(
    ULONG heapId,
    VOID *usrTbl,
    INT sort,
    INT sortBy,
    VOID *results,
    ULONG cnts)
{
    ULONG loop;
    BYTE *start, *end, *cur;
    HeapStatTbl *tbl = (HeapStatTbl*)usrTbl;
    ULONG entrySize = tbl->entrySize;
    ULONG statSize = tbl->statSize;
    struct rb_node *node;

    vos_mutex_lock(&tbl->mutex);

    /*清空上次的统计结果*/
    tbl->cur = tbl->start;
    tbl->entryIdx = 0;
    tbl->noEntry = 0;
    tbl->root.rb_node = NULL;

    /*遍历heap上所有已使用的chip统计使用情况*/
    heap_walk(heapId, &stat_hook, (VOID*)tbl);

    /*输出统计结果*/
    cnts = (tbl->entryIdx < cnts) ? tbl->entryIdx : cnts;

    if(0 == cnts)
    {
        vos_mutex_unlock(&tbl->mutex);
        return tbl->entryIdx;
    }

    start = tbl->start;

    if(0 == sort)
    {
        end = start + cnts * statSize;
        for(cur = start; cur != end; cur += statSize)
        {
            memcpy(results, cur + sizeof(struct rb_node), entrySize);
            results = (VOID*)((BYTE*)results + entrySize);
        }

        vos_mutex_unlock(&tbl->mutex);
        return tbl->entryIdx;
    }

    end = tbl->cur;
    for(loop = 0; loop < cnts; loop++)
    {
        node = (struct rb_node*)start;

        for(cur = start + statSize; cur != end; cur += statSize)
        {
            /*第一个指针指向的key比第2个大*/
            if(0 < (*(tbl->attrCmp))((VOID*)(cur + sizeof(struct rb_node)),
                                    (VOID*)(node + 1), sortBy))
                node = (struct rb_node*)cur;
        }

        memcpy(results, (VOID*)(node + 1), entrySize);
        results = (VOID*)((BYTE*)results + entrySize);
        memcpy((VOID*)node, (VOID*)start, statSize);

        start += statSize;
    }

    vos_mutex_unlock(&tbl->mutex);
    return tbl->entryIdx;
}
Exemple #4
0
void
heapWalk(HEAP heap,HEAPWALKFUNC func)
{
    heap_walk((Heap*)heap,0,0,func);
}