diff options
author | attilio <attilio@FreeBSD.org> | 2008-11-25 23:24:29 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2008-11-25 23:24:29 +0000 |
commit | eff98a06a316fa7bfe69fa25e05b4f43234ef0fb (patch) | |
tree | d20d0851527ed4a62980cc01bd4c57e8892a17e1 /usr.sbin/pmcstat | |
parent | d6453c69d2e055205ffd07e3cb6b3370a99f3b82 (diff) | |
download | FreeBSD-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.8 | 14 | ||||
-rw-r--r-- | usr.sbin/pmcstat/pmcstat.c | 26 | ||||
-rw-r--r-- | usr.sbin/pmcstat/pmcstat.h | 1 | ||||
-rw-r--r-- | usr.sbin/pmcstat/pmcstat_log.c | 39 |
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); |