xref: /freebsd/usr.sbin/pmcstat/pmcpl_annotate_cg.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
185ec49f3SAdrian Chadd /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
485ec49f3SAdrian Chadd  * Copyright (c) 2005-2007, Joseph Koshy
585ec49f3SAdrian Chadd  * Copyright (c) 2007 The FreeBSD Foundation
685ec49f3SAdrian Chadd  * All rights reserved.
785ec49f3SAdrian Chadd  *
852467047SWarner Losh  * Copyright (c) 2014 Netflix, Inc.
952467047SWarner Losh  * Written by: Adrian Chadd <adrian@FreeBSD.org>
1052467047SWarner Losh  *
1185ec49f3SAdrian Chadd  * Portions of this software were developed by A. Joseph Koshy under
1285ec49f3SAdrian Chadd  * sponsorship from the FreeBSD Foundation and Google, Inc.
1385ec49f3SAdrian Chadd  *
1485ec49f3SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
1585ec49f3SAdrian Chadd  * modification, are permitted provided that the following conditions
1685ec49f3SAdrian Chadd  * are met:
1785ec49f3SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
1885ec49f3SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
1985ec49f3SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
2085ec49f3SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
2185ec49f3SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
2285ec49f3SAdrian Chadd  *
2385ec49f3SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2485ec49f3SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2585ec49f3SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2685ec49f3SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2785ec49f3SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2885ec49f3SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2985ec49f3SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3085ec49f3SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3185ec49f3SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3285ec49f3SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3385ec49f3SAdrian Chadd  * SUCH DAMAGE.
3485ec49f3SAdrian Chadd  */
3585ec49f3SAdrian Chadd 
3685ec49f3SAdrian Chadd /*
3785ec49f3SAdrian Chadd  * Transform a hwpmc(4) log into human readable form, and into
3885ec49f3SAdrian Chadd  * gprof(1) compatible profiles.
3985ec49f3SAdrian Chadd  */
4085ec49f3SAdrian Chadd 
4185ec49f3SAdrian Chadd #include <sys/param.h>
4285ec49f3SAdrian Chadd #include <sys/endian.h>
4385ec49f3SAdrian Chadd #include <sys/gmon.h>
4485ec49f3SAdrian Chadd #include <sys/imgact_aout.h>
4585ec49f3SAdrian Chadd #include <sys/imgact_elf.h>
4685ec49f3SAdrian Chadd #include <sys/mman.h>
4785ec49f3SAdrian Chadd #include <sys/pmc.h>
4885ec49f3SAdrian Chadd #include <sys/queue.h>
4985ec49f3SAdrian Chadd #include <sys/socket.h>
5085ec49f3SAdrian Chadd #include <sys/stat.h>
5185ec49f3SAdrian Chadd #include <sys/wait.h>
5285ec49f3SAdrian Chadd 
5385ec49f3SAdrian Chadd #include <netinet/in.h>
5485ec49f3SAdrian Chadd 
5585ec49f3SAdrian Chadd #include <assert.h>
5685ec49f3SAdrian Chadd #include <err.h>
5785ec49f3SAdrian Chadd #include <errno.h>
5885ec49f3SAdrian Chadd #include <fcntl.h>
5985ec49f3SAdrian Chadd #include <gelf.h>
6085ec49f3SAdrian Chadd #include <libgen.h>
6185ec49f3SAdrian Chadd #include <limits.h>
6285ec49f3SAdrian Chadd #include <netdb.h>
6385ec49f3SAdrian Chadd #include <pmc.h>
6485ec49f3SAdrian Chadd #include <pmclog.h>
6585ec49f3SAdrian Chadd #include <sysexits.h>
6685ec49f3SAdrian Chadd #include <stdint.h>
6785ec49f3SAdrian Chadd #include <stdio.h>
6885ec49f3SAdrian Chadd #include <stdlib.h>
6985ec49f3SAdrian Chadd #include <string.h>
7085ec49f3SAdrian Chadd #include <unistd.h>
7185ec49f3SAdrian Chadd 
7285ec49f3SAdrian Chadd #include "pmcstat.h"
7385ec49f3SAdrian Chadd #include "pmcstat_log.h"
7485ec49f3SAdrian Chadd #include "pmcpl_annotate_cg.h"
7585ec49f3SAdrian Chadd 
7685ec49f3SAdrian Chadd /*
7785ec49f3SAdrian Chadd  * Record a callchain.
7885ec49f3SAdrian Chadd  */
7985ec49f3SAdrian Chadd 
8085ec49f3SAdrian Chadd void
pmcpl_annotate_cg_process(struct pmcstat_process * pp,struct pmcstat_pmcrecord * pmcr,uint32_t nsamples,uintfptr_t * cc,int usermode,uint32_t cpu)8185ec49f3SAdrian Chadd pmcpl_annotate_cg_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
8285ec49f3SAdrian Chadd     uint32_t nsamples, uintfptr_t *cc, int usermode, uint32_t cpu)
8385ec49f3SAdrian Chadd {
8485ec49f3SAdrian Chadd 	struct pmcstat_pcmap *map;
8585ec49f3SAdrian Chadd 	struct pmcstat_symbol *sym;
8685ec49f3SAdrian Chadd 	uintfptr_t newpc;
8785ec49f3SAdrian Chadd 	struct pmcstat_image *image;
8885ec49f3SAdrian Chadd 	int i;
8985ec49f3SAdrian Chadd 	char filename[PATH_MAX], funcname[PATH_MAX];
9085ec49f3SAdrian Chadd 	unsigned sline;
9185ec49f3SAdrian Chadd 
9285ec49f3SAdrian Chadd 	(void) pmcr; (void) nsamples; (void) usermode; (void) cpu;
9385ec49f3SAdrian Chadd 
9485ec49f3SAdrian Chadd 	for (i = 0; i < (int) nsamples; i++) {
9585ec49f3SAdrian Chadd 		map = NULL;
9685ec49f3SAdrian Chadd 		sym = NULL;
9785ec49f3SAdrian Chadd 		image = NULL;
9885ec49f3SAdrian Chadd 		filename[0] = '\0';
9985ec49f3SAdrian Chadd 		funcname[0] = '\0';
10085ec49f3SAdrian Chadd 		sline = 0;
10185ec49f3SAdrian Chadd 
10285ec49f3SAdrian Chadd 		map = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, cc[i]);
10385ec49f3SAdrian Chadd 		if (map != NULL) {
10485ec49f3SAdrian Chadd 			assert(cc[i] >= map->ppm_lowpc && cc[i] < map->ppm_highpc);
10585ec49f3SAdrian Chadd 			image = map->ppm_image;
10685ec49f3SAdrian Chadd 			newpc = cc[i] - (map->ppm_lowpc +
10785ec49f3SAdrian Chadd 				(image->pi_vaddr - image->pi_start));
10885ec49f3SAdrian Chadd 			sym = pmcstat_symbol_search(image, newpc);
10985ec49f3SAdrian Chadd 		}
11085ec49f3SAdrian Chadd 
11185ec49f3SAdrian Chadd 		if (map != NULL && image != NULL && sym != NULL) {
11285ec49f3SAdrian Chadd 			(void) pmcstat_image_addr2line(image, cc[i],
11385ec49f3SAdrian Chadd 			    filename, sizeof(filename), &sline, funcname, sizeof(funcname));
11485ec49f3SAdrian Chadd 		}
11585ec49f3SAdrian Chadd 
11685ec49f3SAdrian Chadd 		if (map != NULL && sym != NULL) {
11785ec49f3SAdrian Chadd 			fprintf(args.pa_graphfile, "%p %s %s:%d\n",
11885ec49f3SAdrian Chadd 			    (void *)cc[i],
11985ec49f3SAdrian Chadd 			    funcname,
12085ec49f3SAdrian Chadd 			    filename,
12185ec49f3SAdrian Chadd 			    sline);
12285ec49f3SAdrian Chadd 		} else {
12385ec49f3SAdrian Chadd 			fprintf(args.pa_graphfile, "%p <unknown> ??:0\n",
12485ec49f3SAdrian Chadd 			    (void *) cc[i]);
12585ec49f3SAdrian Chadd 		}
12685ec49f3SAdrian Chadd 	}
12785ec49f3SAdrian Chadd 	fprintf(args.pa_graphfile, "--\n");
12885ec49f3SAdrian Chadd }
129