summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pmcstat
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2008-11-25 23:24:29 +0000
committerattilio <attilio@FreeBSD.org>2008-11-25 23:24:29 +0000
commiteff98a06a316fa7bfe69fa25e05b4f43234ef0fb (patch)
treed20d0851527ed4a62980cc01bd4c57e8892a17e1 /usr.sbin/pmcstat
parentd6453c69d2e055205ffd07e3cb6b3370a99f3b82 (diff)
downloadFreeBSD-src-eff98a06a316fa7bfe69fa25e05b4f43234ef0fb.zip
FreeBSD-src-eff98a06a316fa7bfe69fa25e05b4f43234ef0fb.tar.gz
Add the -m option to pmcstat.
This option prints the list of sampled PCs along with the function name, the start and end addresses of this where their live within. Reviewed by: jkoshy Tested by: gnn Sponsored by: Nokia
Diffstat (limited to 'usr.sbin/pmcstat')
-rw-r--r--usr.sbin/pmcstat/pmcstat.814
-rw-r--r--usr.sbin/pmcstat/pmcstat.c26
-rw-r--r--usr.sbin/pmcstat/pmcstat.h1
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.c39
4 files changed, 69 insertions, 11 deletions
diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8
index f0a3a47..3ce35cc 100644
--- a/usr.sbin/pmcstat/pmcstat.8
+++ b/usr.sbin/pmcstat/pmcstat.8
@@ -48,6 +48,7 @@
.Op Fl d
.Op Fl g
.Op Fl k Ar kerneldir
+.Op Fl m Ar pathname
.Op Fl n Ar rate
.Op Fl o Ar outputfile
.Op Fl p Ar event-spec
@@ -232,6 +233,19 @@ This directory specifies where
should look for the kernel and its modules.
The default is
.Pa /boot/kernel .
+.It Fl m Ar pathname
+Print the sampled PCs with the name, the start and ending addresses
+of the function within they live.
+The
+.Ar pathname
+argument is mandatory and indicates where informations will be stored.
+If argument
+.Ar pathname
+is a
+.Dq Li -
+this information is sent to the output file specified by the
+.Fl o
+option.
.It Fl n Ar rate
Set the default sampling rate for subsequent sampling mode
PMCs specified on the command line.
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index 228c78d..ea7264c 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -594,7 +594,7 @@ main(int argc, char **argv)
}
while ((option = getopt(argc, argv,
- "CD:EG:M:NO:P:R:S:Wc:dgk:n:o:p:qr:s:t:vw:z:")) != -1)
+ "CD:EG:M:NO:P:R:S:Wc:dgk:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
case 'C': /* cumulative values */
use_cumulative_counts = !use_cumulative_counts;
@@ -644,6 +644,11 @@ main(int argc, char **argv)
args.pa_flags |= FLAG_HAS_KERNELPATH;
break;
+ case 'm':
+ args.pa_flags |= FLAG_WANTS_MAPPINGS;
+ graphfilename = optarg;
+ break;
+
case 'E': /* log process exit */
do_logprocexit = !do_logprocexit;
args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
@@ -827,7 +832,8 @@ main(int argc, char **argv)
if (argc) /* command line present */
args.pa_flags |= FLAG_HAS_COMMANDLINE;
- if (args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS))
+ if (args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS |
+ FLAG_WANTS_MAPPINGS))
args.pa_flags |= FLAG_DO_ANALYSIS;
/*
@@ -839,6 +845,16 @@ main(int argc, char **argv)
errx(EX_USAGE, "ERROR: options -O and -R are mutually "
"exclusive.");
+ /* -m option is allowed with -R only. */
+ if (args.pa_flags & FLAG_WANTS_MAPPINGS && args.pa_inputpath == NULL)
+ errx(EX_USAGE, "ERROR: option -m requires an input file");
+
+ /* -m option is not allowed combined with -g or -G. */
+ if (args.pa_flags & FLAG_WANTS_MAPPINGS &&
+ args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS))
+ errx(EX_USAGE, "ERROR: option -m and -g | -G are mutually "
+ "exclusive");
+
if (args.pa_flags & FLAG_READ_LOGFILE) {
errmsg = NULL;
if (args.pa_flags & FLAG_HAS_COMMANDLINE)
@@ -980,6 +996,12 @@ main(int argc, char **argv)
"for writing", graphfilename);
}
}
+ if (args.pa_flags & FLAG_WANTS_MAPPINGS) {
+ args.pa_graphfile = fopen(graphfilename, "w");
+ if (args.pa_graphfile == NULL)
+ err(EX_OSERR, "ERROR: cannot open \"%s\" for writing",
+ graphfilename);
+ }
/* if we've been asked to process a log file, do that and exit */
if (args.pa_flags & FLAG_READ_LOGFILE) {
diff --git a/usr.sbin/pmcstat/pmcstat.h b/usr.sbin/pmcstat/pmcstat.h
index e46109a..5d6f5f2 100644
--- a/usr.sbin/pmcstat/pmcstat.h
+++ b/usr.sbin/pmcstat/pmcstat.h
@@ -49,6 +49,7 @@
#define FLAG_DO_PRINT 0x00002000 /* -o */
#define FLAG_DO_CALLGRAPHS 0x00004000 /* -G */
#define FLAG_DO_ANALYSIS 0x00008000 /* -g or -G */
+#define FLAG_WANTS_MAPPINGS 0x00010000 /* -m */
#define DEFAULT_SAMPLE_COUNT 65536
#define DEFAULT_WAIT_INTERVAL 5.0
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c
index d895ab7..9814126 100644
--- a/usr.sbin/pmcstat/pmcstat_log.c
+++ b/usr.sbin/pmcstat/pmcstat_log.c
@@ -1969,9 +1969,10 @@ static int
pmcstat_analyze_log(struct pmcstat_args *a)
{
uint32_t cpu, cpuflags;
- uintfptr_t pc;
+ uintfptr_t pc, newpc;
pid_t pid;
struct pmcstat_image *image;
+ struct pmcstat_symbol *sym;
struct pmcstat_process *pp, *ppnew;
struct pmcstat_pcmap *ppm, *ppmtmp;
struct pmclog_ev ev;
@@ -2085,21 +2086,41 @@ pmcstat_analyze_log(struct pmcstat_args *a)
pp = pmcstat_process_lookup(ev.pl_u.pl_cc.pl_pid,
PMCSTAT_ALLOCATE);
- pmcstat_record_callchain(pp,
- ev.pl_u.pl_cc.pl_pmcid, ev.pl_u.pl_cc.pl_npc,
- ev.pl_u.pl_cc.pl_pc,
- PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags), a);
+ if ((a->pa_flags & FLAG_WANTS_MAPPINGS) == 0)
+ pmcstat_record_callchain(pp,
+ ev.pl_u.pl_cc.pl_pmcid,
+ ev.pl_u.pl_cc.pl_npc, ev.pl_u.pl_cc.pl_pc,
+ PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags), a);
- if ((a->pa_flags & FLAG_DO_GPROF) == 0)
+ if ((a->pa_flags &
+ (FLAG_DO_GPROF | FLAG_WANTS_MAPPINGS)) == 0)
break;
pc = ev.pl_u.pl_cc.pl_pc[0];
- if ((ppm = pmcstat_process_find_map(pp, pc)) == NULL &&
- (ppm = pmcstat_process_find_map(pmcstat_kernproc,
- pc)) == NULL) { /* unknown offset */
+ if (PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags) == 0)
+ pp = pmcstat_kernproc;
+ ppm = pmcstat_process_find_map(pp, pc);
+ if (ppm == NULL) {
+
+ /* Unknown offset. */
pmcstat_stats.ps_samples_unknown_offset++;
break;
}
+ if (a->pa_flags & FLAG_WANTS_MAPPINGS) {
+ image = ppm->ppm_image;
+ newpc = pc - (ppm->ppm_lowpc +
+ (image->pi_vaddr - image->pi_start));
+ sym = pmcstat_symbol_search(image, newpc);
+ if (sym == NULL)
+ break;
+ fprintf(a->pa_graphfile, "%p %s 0x%jx 0x%jx\n",
+ (void *)pc,
+ pmcstat_string_unintern(sym->ps_name),
+ (uintmax_t)(sym->ps_start +
+ image->pi_vaddr), (uintmax_t)(sym->ps_end +
+ image->pi_vaddr));
+ break;
+ }
pmcstat_image_increment_bucket(ppm, pc,
ev.pl_u.pl_cc.pl_pmcid, a);
OpenPOWER on IntegriCloud