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
This commit is contained in:
parent
38cc5da78e
commit
c0252222a2
@ -48,6 +48,7 @@
|
|||||||
.Op Fl d
|
.Op Fl d
|
||||||
.Op Fl g
|
.Op Fl g
|
||||||
.Op Fl k Ar kerneldir
|
.Op Fl k Ar kerneldir
|
||||||
|
.Op Fl m Ar pathname
|
||||||
.Op Fl n Ar rate
|
.Op Fl n Ar rate
|
||||||
.Op Fl o Ar outputfile
|
.Op Fl o Ar outputfile
|
||||||
.Op Fl p Ar event-spec
|
.Op Fl p Ar event-spec
|
||||||
@ -232,6 +233,19 @@ This directory specifies where
|
|||||||
should look for the kernel and its modules.
|
should look for the kernel and its modules.
|
||||||
The default is
|
The default is
|
||||||
.Pa /boot/kernel .
|
.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
|
.It Fl n Ar rate
|
||||||
Set the default sampling rate for subsequent sampling mode
|
Set the default sampling rate for subsequent sampling mode
|
||||||
PMCs specified on the command line.
|
PMCs specified on the command line.
|
||||||
|
@ -594,7 +594,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((option = getopt(argc, 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) {
|
switch (option) {
|
||||||
case 'C': /* cumulative values */
|
case 'C': /* cumulative values */
|
||||||
use_cumulative_counts = !use_cumulative_counts;
|
use_cumulative_counts = !use_cumulative_counts;
|
||||||
@ -644,6 +644,11 @@ main(int argc, char **argv)
|
|||||||
args.pa_flags |= FLAG_HAS_KERNELPATH;
|
args.pa_flags |= FLAG_HAS_KERNELPATH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
args.pa_flags |= FLAG_WANTS_MAPPINGS;
|
||||||
|
graphfilename = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'E': /* log process exit */
|
case 'E': /* log process exit */
|
||||||
do_logprocexit = !do_logprocexit;
|
do_logprocexit = !do_logprocexit;
|
||||||
args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
|
args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
|
||||||
@ -827,7 +832,8 @@ main(int argc, char **argv)
|
|||||||
if (argc) /* command line present */
|
if (argc) /* command line present */
|
||||||
args.pa_flags |= FLAG_HAS_COMMANDLINE;
|
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;
|
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 "
|
errx(EX_USAGE, "ERROR: options -O and -R are mutually "
|
||||||
"exclusive.");
|
"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) {
|
if (args.pa_flags & FLAG_READ_LOGFILE) {
|
||||||
errmsg = NULL;
|
errmsg = NULL;
|
||||||
if (args.pa_flags & FLAG_HAS_COMMANDLINE)
|
if (args.pa_flags & FLAG_HAS_COMMANDLINE)
|
||||||
@ -980,6 +996,12 @@ main(int argc, char **argv)
|
|||||||
"for writing", graphfilename);
|
"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 we've been asked to process a log file, do that and exit */
|
||||||
if (args.pa_flags & FLAG_READ_LOGFILE) {
|
if (args.pa_flags & FLAG_READ_LOGFILE) {
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#define FLAG_DO_PRINT 0x00002000 /* -o */
|
#define FLAG_DO_PRINT 0x00002000 /* -o */
|
||||||
#define FLAG_DO_CALLGRAPHS 0x00004000 /* -G */
|
#define FLAG_DO_CALLGRAPHS 0x00004000 /* -G */
|
||||||
#define FLAG_DO_ANALYSIS 0x00008000 /* -g or -G */
|
#define FLAG_DO_ANALYSIS 0x00008000 /* -g or -G */
|
||||||
|
#define FLAG_WANTS_MAPPINGS 0x00010000 /* -m */
|
||||||
|
|
||||||
#define DEFAULT_SAMPLE_COUNT 65536
|
#define DEFAULT_SAMPLE_COUNT 65536
|
||||||
#define DEFAULT_WAIT_INTERVAL 5.0
|
#define DEFAULT_WAIT_INTERVAL 5.0
|
||||||
|
@ -1969,9 +1969,10 @@ static int
|
|||||||
pmcstat_analyze_log(struct pmcstat_args *a)
|
pmcstat_analyze_log(struct pmcstat_args *a)
|
||||||
{
|
{
|
||||||
uint32_t cpu, cpuflags;
|
uint32_t cpu, cpuflags;
|
||||||
uintfptr_t pc;
|
uintfptr_t pc, newpc;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
struct pmcstat_image *image;
|
struct pmcstat_image *image;
|
||||||
|
struct pmcstat_symbol *sym;
|
||||||
struct pmcstat_process *pp, *ppnew;
|
struct pmcstat_process *pp, *ppnew;
|
||||||
struct pmcstat_pcmap *ppm, *ppmtmp;
|
struct pmcstat_pcmap *ppm, *ppmtmp;
|
||||||
struct pmclog_ev ev;
|
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,
|
pp = pmcstat_process_lookup(ev.pl_u.pl_cc.pl_pid,
|
||||||
PMCSTAT_ALLOCATE);
|
PMCSTAT_ALLOCATE);
|
||||||
|
|
||||||
pmcstat_record_callchain(pp,
|
if ((a->pa_flags & FLAG_WANTS_MAPPINGS) == 0)
|
||||||
ev.pl_u.pl_cc.pl_pmcid, ev.pl_u.pl_cc.pl_npc,
|
pmcstat_record_callchain(pp,
|
||||||
ev.pl_u.pl_cc.pl_pc,
|
ev.pl_u.pl_cc.pl_pmcid,
|
||||||
PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags), a);
|
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;
|
break;
|
||||||
|
|
||||||
pc = ev.pl_u.pl_cc.pl_pc[0];
|
pc = ev.pl_u.pl_cc.pl_pc[0];
|
||||||
if ((ppm = pmcstat_process_find_map(pp, pc)) == NULL &&
|
if (PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags) == 0)
|
||||||
(ppm = pmcstat_process_find_map(pmcstat_kernproc,
|
pp = pmcstat_kernproc;
|
||||||
pc)) == NULL) { /* unknown offset */
|
ppm = pmcstat_process_find_map(pp, pc);
|
||||||
|
if (ppm == NULL) {
|
||||||
|
|
||||||
|
/* Unknown offset. */
|
||||||
pmcstat_stats.ps_samples_unknown_offset++;
|
pmcstat_stats.ps_samples_unknown_offset++;
|
||||||
break;
|
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,
|
pmcstat_image_increment_bucket(ppm, pc,
|
||||||
ev.pl_u.pl_cc.pl_pmcid, a);
|
ev.pl_u.pl_cc.pl_pmcid, a);
|
||||||
|
Loading…
Reference in New Issue
Block a user