FreeBSD/usr.sbin/pmcstat/pmcpl_calltree.c
/*
 * Detect and fix inlined location.
 */
Detect and fix inlined location.
Detect and fix inlined location .
static void
_pmcpl_ct_expand_inline(struct pmcpl_ct_node *ct)
{
	int i, j;
	unsigned fline, line, v;
	uintfptr_t faddr, addr, pc;
	char sourcefile[PATH_MAX];
	char ffuncname[PATH_MAX], funcname[PATH_MAX];
	char buffer[PATH_MAX];
	struct pmcpl_ct_node *child;
	faddr = ct->pct_image->pi_vaddr + ct->pct_func;
	fline = 0;
	if (!pmcstat_image_addr2line(ct->pct_image, faddr,
	    sourcefile, sizeof(sourcefile), &fline,
	    ffuncname, sizeof(ffuncname)))
		return;
	for (i = 0; i < ct->pct_ninstr; i++) {
		addr = ct->pct_image->pi_vaddr +
		    ct->pct_instr[i].pctf_func;
		line = 0;
		if (!pmcstat_image_addr2line(ct->pct_image, addr,
		    sourcefile, sizeof(sourcefile), &line,
		    funcname, sizeof(funcname)))
			continue;
		if (strcmp(funcname, ffuncname) == 0)
			continue;
		if (args.pa_verbosity >= 2)
			fprintf(args.pa_printfile,
			    "WARNING: inlined function at %p %s in %s\n",
			    (void *)addr, funcname, ffuncname);
		snprintf(buffer, sizeof(buffer), "%s@%s",
			funcname, ffuncname);
		child = pmcpl_ct_node_hash_lookup(ct->pct_image,
		    ct->pct_func, ct->pct_sym, sourcefile, buffer);
		assert(child != NULL);
		pc = ct->pct_instr[i].pctf_func;
		for (j = 0; j<pmcstat_npmcs; j++) {
			v = PMCPL_CT_SAMPLE(j,
			    &ct->pct_instr[i].pctf_samples);
			if (v == 0)
				continue;
			pmcpl_ct_instr_add(child, j, pc, v);
			pmcpl_ct_node_update(ct, child, j, v, 0);
			if (j < ct->pct_samples.npmcs)
				ct->pct_samples.sb[j] -=
				    ct->pct_instr[i].pctf_samples.sb[j];
			ct->pct_instr[i].pctf_samples.sb[j] = 0;
		}
	}
}
static void _pmcpl_ct_expand_inline ( struct pmcpl_ct_node * ct ) { int i , j ; unsigned fline , line , v ; uintfptr_t faddr , addr , pc ; char sourcefile [ PATH_MAX ] ; char ffuncname [ PATH_MAX ] , funcname [ PATH_MAX ] ; char buffer [ PATH_MAX ] ; struct pmcpl_ct_node * child ; faddr = ct -> pct_image -> pi_vaddr + ct -> pct_func ; fline = 0 ; if ( ! pmcstat_image_addr2line ( ct -> pct_image , faddr , sourcefile , sizeof ( sourcefile ) , & fline , ffuncname , sizeof ( ffuncname ) ) ) return ; for ( i = 0 ; i < ct -> pct_ninstr ; i ++ ) { addr = ct -> pct_image -> pi_vaddr + ct -> pct_instr [ i ] . pctf_func ; line = 0 ; if ( ! pmcstat_image_addr2line ( ct -> pct_image , addr , sourcefile , sizeof ( sourcefile ) , & line , funcname , sizeof ( funcname ) ) ) continue ; if ( strcmp ( funcname , ffuncname ) == 0 ) continue ; if ( args . pa_verbosity >= 2 ) fprintf ( args . pa_printfile , " \n " , ( void * ) addr , funcname , ffuncname ) ; snprintf ( buffer , sizeof ( buffer ) , " " , funcname , ffuncname ) ; child = pmcpl_ct_node_hash_lookup ( ct -> pct_image , ct -> pct_func , ct -> pct_sym , sourcefile , buffer ) ; assert ( child != NULL ) ; pc = ct -> pct_instr [ i ] . pctf_func ; for ( j = 0 ; j < pmcstat_npmcs ; j ++ ) { v = PMCPL_CT_SAMPLE ( j , & ct -> pct_instr [ i ] . pctf_samples ) ; if ( v == 0 ) continue ; pmcpl_ct_instr_add ( child , j , pc , v ) ; pmcpl_ct_node_update ( ct , child , j , v , 0 ) ; if ( j < ct -> pct_samples . npmcs ) ct -> pct_samples . sb [ j ] -= ct -> pct_instr [ i ] . pctf_samples . sb [ j ] ; ct -> pct_instr [ i ] . pctf_samples . sb [ j ] = 0 ; } } }
Detect and fix inlined location.
Detect and fix inlined location .
/*
	 * Resolve parent and compare to each instr location.
	 */ /*
		 * - Lookup/create inline node by function name.
		 * - Move instr PMCs to the inline node.
		 * - Link nodes.
		 * The lookup create a specific node per image/pc.
		 */