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