FreeBSD/usr.sbin/pmcstat/pmcpl_callgraph.c
/*
 * Look for a callgraph node associated with pmc `pmcid' in the global
 * hash table that corresponds to the given `pc' value in the process
 * `pp'.
 */
Look for a callgraph node associated with pmc `pmcid' in the global
hash table that corresponds to the given `pc' value in the process
`pp'.
Look for a callgraph node associated with pmc ` pmcid ' in the global hash table that corresponds to the given ` pc ' value in the process ` pp ' .
static struct pmcstat_cgnode *
pmcstat_cgnode_hash_lookup_pc(struct pmcstat_process *pp, pmc_id_t pmcid,
    uintfptr_t pc, int usermode)
{
	struct pmcstat_pcmap *ppm;
	struct pmcstat_symbol *sym;
	struct pmcstat_image *image;
	struct pmcstat_cgnode *cg;
	struct pmcstat_cgnode_hash *h;
	uintfptr_t loadaddress;
	unsigned int i, hash;
	ppm = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, pc);
	if (ppm == NULL)
		return (NULL);
	image = ppm->ppm_image;
	loadaddress = ppm->ppm_lowpc + image->pi_vaddr - image->pi_start;
	pc -= loadaddress;	
	if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
		pc = sym->ps_start;
	else
		pmcstat_stats.ps_samples_unknown_function++;
	for (hash = i = 0; i < sizeof(uintfptr_t); i++)
		hash += (pc >> i) & 0xFF;
	hash &= PMCSTAT_HASH_MASK;
	cg = NULL;
	LIST_FOREACH(h, &pmcstat_cgnode_hash[hash], pch_next)
	{
		if (h->pch_pmcid != pmcid)
			continue;
		cg = h->pch_cgnode;
		assert(cg != NULL);
		if (cg->pcg_image == image && cg->pcg_func == pc)
			return (cg);
	}
	cg = pmcstat_cgnode_allocate(image, pc);
	if ((h = malloc(sizeof(*h))) == NULL)
		err(EX_OSERR, "ERROR: Could not allocate callgraph node");
	h->pch_pmcid = pmcid;
	h->pch_cgnode = cg;
	LIST_INSERT_HEAD(&pmcstat_cgnode_hash[hash], h, pch_next);
	pmcstat_cgnode_hash_count++;
	return (cg);
}
static struct pmcstat_cgnode * pmcstat_cgnode_hash_lookup_pc ( struct pmcstat_process * pp , pmc_id_t pmcid , uintfptr_t pc , int usermode ) { struct pmcstat_pcmap * ppm ; struct pmcstat_symbol * sym ; struct pmcstat_image * image ; struct pmcstat_cgnode * cg ; struct pmcstat_cgnode_hash * h ; uintfptr_t loadaddress ; unsigned int i , hash ; ppm = pmcstat_process_find_map ( usermode ? pp : pmcstat_kernproc , pc ) ; if ( ppm == NULL ) return ( NULL ) ; image = ppm -> ppm_image ; loadaddress = ppm -> ppm_lowpc + image -> pi_vaddr - image -> pi_start ; pc -= loadaddress ; if ( ( sym = pmcstat_symbol_search ( image , pc ) ) != NULL ) pc = sym -> ps_start ; else pmcstat_stats . ps_samples_unknown_function ++ ; for ( hash = i = 0 ; i < sizeof ( uintfptr_t ) ; i ++ ) hash += ( pc >> i ) & 0xFF ; hash &= PMCSTAT_HASH_MASK ; cg = NULL ; LIST_FOREACH ( h , & pmcstat_cgnode_hash [ hash ] , pch_next ) { if ( h -> pch_pmcid != pmcid ) continue ; cg = h -> pch_cgnode ; assert ( cg != NULL ) ; if ( cg -> pcg_image == image && cg -> pcg_func == pc ) return ( cg ) ; } cg = pmcstat_cgnode_allocate ( image , pc ) ; if ( ( h = malloc ( sizeof ( * h ) ) ) == NULL ) err ( EX_OSERR , " " ) ; h -> pch_pmcid = pmcid ; h -> pch_cgnode = cg ; LIST_INSERT_HEAD ( & pmcstat_cgnode_hash [ hash ] , h , pch_next ) ; pmcstat_cgnode_hash_count ++ ; return ( cg ) ; }
Look for a callgraph node associated with pmc `pmcid' in the global
 hash table that corresponds to the given `pc' value in the process
 `pp'.
Look for a callgraph node associated with pmc ` pmcid ' in the global hash table that corresponds to the given ` pc ' value in the process ` pp ' .
/* Convert to an offset in the image. */ /*
	 * Try determine the function at this offset.  If we can't
	 * find a function round leave the `pc' value alone.
	 */ /*
	 * We haven't seen this (pmcid, pc) tuple yet, so allocate a
	 * new callgraph node and a new hash table entry for it.
	 */