Beispiel #1
0
void
pmcpl_annotate_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
    uint32_t nsamples, uintfptr_t *cc, int usermode, uint32_t cpu)
{
	struct pmcstat_pcmap *map;
	struct pmcstat_symbol *sym;
	uintfptr_t newpc;
	struct pmcstat_image *image;

	(void) pmcr; (void) nsamples; (void) usermode; (void) cpu;

	map = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, cc[0]);
	if (map == NULL) {
		/* Unknown offset. */
		pmcstat_stats.ps_samples_unknown_offset++;
		return;
	}

	assert(cc[0] >= map->ppm_lowpc && cc[0] < map->ppm_highpc);

	image = map->ppm_image;
	newpc = cc[0] - (map->ppm_lowpc +
		(image->pi_vaddr - image->pi_start));
	sym = pmcstat_symbol_search(image, newpc);
	if (sym == NULL)
		return;

	fprintf(args.pa_graphfile, "%p %s 0x%jx 0x%jx\n",
		(void *)cc[0],
		pmcstat_string_unintern(sym->ps_name),
		(uintmax_t)(sym->ps_start +
		image->pi_vaddr), (uintmax_t)(sym->ps_end +
		image->pi_vaddr));
}
void
pmcpl_annotate_cg_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
    uint32_t nsamples, uintfptr_t *cc, int usermode, uint32_t cpu)
{
	struct pmcstat_pcmap *map;
	struct pmcstat_symbol *sym;
	uintfptr_t newpc;
	struct pmcstat_image *image;
	int i;
	char filename[PATH_MAX], funcname[PATH_MAX];
	unsigned sline;

	(void) pmcr; (void) nsamples; (void) usermode; (void) cpu;

	for (i = 0; i < (int) nsamples; i++) {
		map = NULL;
		sym = NULL;
		image = NULL;
		filename[0] = '\0';
		funcname[0] = '\0';
		sline = 0;

		map = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, cc[i]);
		if (map != NULL) {
			assert(cc[i] >= map->ppm_lowpc && cc[i] < map->ppm_highpc);
			image = map->ppm_image;
			newpc = cc[i] - (map->ppm_lowpc +
				(image->pi_vaddr - image->pi_start));
			sym = pmcstat_symbol_search(image, newpc);
		}

		if (map != NULL && image != NULL && sym != NULL) {
			(void) pmcstat_image_addr2line(image, cc[i],
			    filename, sizeof(filename), &sline, funcname, sizeof(funcname));
		}

		if (map != NULL && sym != NULL) {
			fprintf(args.pa_graphfile, "%p %s %s:%d\n",
			    (void *)(intptr_t)cc[i],
			    funcname,
			    filename,
			    sline);
		} else {
			fprintf(args.pa_graphfile, "%p <unknown> ??:0\n",
			    (void *)(intptr_t)cc[i]);
		}
	}
	fprintf(args.pa_graphfile, "--\n");
}
/*
 * Add the list of symbols in the given section to the list associated
 * with the object.
 */
void
pmcstat_image_add_symbols(struct pmcstat_image *image, Elf *e,
    Elf_Scn *scn, GElf_Shdr *sh)
{
	int firsttime;
	size_t n, newsyms, nshsyms, nfuncsyms;
	struct pmcstat_symbol *symptr;
	char *fnname;
	GElf_Sym sym;
	Elf_Data *data;

	if ((data = elf_getdata(scn, NULL)) == NULL)
		return;

	/*
	 * Determine the number of functions named in this
	 * section.
	 */

	nshsyms = sh->sh_size / sh->sh_entsize;
	for (n = nfuncsyms = 0; n < nshsyms; n++) {
		if (gelf_getsym(data, (int) n, &sym) != &sym)
			return;
		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
			nfuncsyms++;
	}

	if (nfuncsyms == 0)
		return;

	/*
	 * Allocate space for the new entries.
	 */
	firsttime = image->pi_symbols == NULL;
	symptr = reallocarray(image->pi_symbols,
	    image->pi_symcount + nfuncsyms, sizeof(*symptr));
	if (symptr == image->pi_symbols) /* realloc() failed. */
		return;
	image->pi_symbols = symptr;

	/*
	 * Append new symbols to the end of the current table.
	 */
	symptr += image->pi_symcount;

	for (n = newsyms = 0; n < nshsyms; n++) {
		if (gelf_getsym(data, (int) n, &sym) != &sym)
			return;
		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
			continue;

		if (sym.st_shndx == STN_UNDEF)
			continue;

		if (!firsttime && pmcstat_symbol_search(image, sym.st_value))
			continue; /* We've seen this symbol already. */

		if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name))
		    == NULL)
			continue;
#ifdef __arm__
		/* Remove spurious ARM function name. */
		if (fnname[0] == '$' &&
		    (fnname[1] == 'a' || fnname[1] == 't' ||
		    fnname[1] == 'd') &&
		    fnname[2] == '\0')
			continue;
#endif

		symptr->ps_name  = pmcstat_string_intern(fnname);
		symptr->ps_start = sym.st_value - image->pi_vaddr;
		symptr->ps_end   = symptr->ps_start + sym.st_size;

		symptr++;
		newsyms++;
	}

	image->pi_symcount += newsyms;
	if (image->pi_symcount == 0)
		return;

	assert(newsyms <= nfuncsyms);

	/*
	 * Return space to the system if there were duplicates.
	 */
	if (newsyms < nfuncsyms)
		image->pi_symbols = reallocarray(image->pi_symbols,
		    image->pi_symcount, sizeof(*symptr));

	/*
	 * Keep the list of symbols sorted.
	 */
	qsort(image->pi_symbols, image->pi_symcount, sizeof(*symptr),
	    pmcstat_symbol_compare);

	/*
	 * Deal with function symbols that have a size of 'zero' by
	 * making them extend to the next higher address.  These
	 * symbols are usually defined in assembly code.
	 */
	for (symptr = image->pi_symbols;
	     symptr < image->pi_symbols + (image->pi_symcount - 1);
	     symptr++)
		if (symptr->ps_start == symptr->ps_end)
			symptr->ps_end = (symptr+1)->ps_start;
}