aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/pmcstat
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2020-08-05 19:05:49 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2020-08-05 19:05:49 +0000
commit94e9ef85c594951f9d9d0e4cd7595e9cd2f792da (patch)
treeaa11a6f0efd70efc1ad0ae0b867c8fb17725a695 /usr.sbin/pmcstat
parent5414a8285faa844f925159b890c676c25f8a8c1c (diff)
downloadsrc-94e9ef85c594951f9d9d0e4cd7595e9cd2f792da.tar.gz
src-94e9ef85c594951f9d9d0e4cd7595e9cd2f792da.zip
pmcstat: implement showing offsets into symbols in top mode
The -I option (and hotkey) is reused for this. Skipping symbol resolution is moved to the new -A option (and hotkey). While arguably this violates POLA I think it's a change for the better. ALso note the -I option was added in head. Differential Revision: https://reviews.freebsd.org/D21658
Notes
Notes: svn path=/head/; revision=363928
Diffstat (limited to 'usr.sbin/pmcstat')
-rw-r--r--usr.sbin/pmcstat/pmcpl_callgraph.c41
-rw-r--r--usr.sbin/pmcstat/pmcstat.815
-rw-r--r--usr.sbin/pmcstat/pmcstat.c13
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.c12
4 files changed, 58 insertions, 23 deletions
diff --git a/usr.sbin/pmcstat/pmcpl_callgraph.c b/usr.sbin/pmcstat/pmcpl_callgraph.c
index 8b5570336c3e..4cae6437486c 100644
--- a/usr.sbin/pmcstat/pmcpl_callgraph.c
+++ b/usr.sbin/pmcstat/pmcpl_callgraph.c
@@ -152,10 +152,12 @@ pmcstat_cgnode_hash_lookup_pc(struct pmcstat_process *pp, pmc_id_t pmcid,
* Try determine the function at this offset. If we can't
* find a function round leave the `pc' value alone.
*/
- if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
- pc = sym->ps_start;
- else
- pmcstat_stats.ps_samples_unknown_function++;
+ if (!(args.pa_flags & (FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET))) {
+ if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
+ pc = sym->ps_start;
+ else
+ pmcstat_stats.ps_samples_unknown_function++;
+ }
for (hash = i = 0; i < sizeof(uintfptr_t); i++)
hash += (pc >> i) & 0xFF;
@@ -485,22 +487,35 @@ pmcstat_cgnode_topprint(struct pmcstat_cgnode *cg,
v = PMCPL_CG_COUNTP(cg);
snprintf(vs, sizeof(vs), "%.1f", v);
v_attrs = PMCSTAT_ATTRPERCENT(v);
- sym = NULL;
/* Format name. */
- if (!(args.pa_flags & FLAG_SKIP_TOP_FN_RES))
- sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
- if (sym != NULL) {
- snprintf(ns, sizeof(ns), "%s",
- pmcstat_string_unintern(sym->ps_name));
- } else
+ sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
+ if (sym == NULL) {
snprintf(ns, sizeof(ns), "%p",
(void *)(cg->pcg_image->pi_vaddr + cg->pcg_func));
+ } else {
+ switch (args.pa_flags & (FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET)) {
+ case FLAG_SKIP_TOP_FN_RES | FLAG_SHOW_OFFSET:
+ case FLAG_SKIP_TOP_FN_RES:
+ snprintf(ns, sizeof(ns), "%p",
+ (void *)(cg->pcg_image->pi_vaddr + cg->pcg_func));
+ break;
+ case FLAG_SHOW_OFFSET:
+ snprintf(ns, sizeof(ns), "%s+%#0lx",
+ pmcstat_string_unintern(sym->ps_name),
+ cg->pcg_func - sym->ps_start);
+ break;
+ default:
+ snprintf(ns, sizeof(ns), "%s",
+ pmcstat_string_unintern(sym->ps_name));
+ break;
+ }
+ }
PMCSTAT_ATTRON(v_attrs);
PMCSTAT_PRINTW("%5.5s", vs);
PMCSTAT_ATTROFF(v_attrs);
- PMCSTAT_PRINTW(" %-10.10s %-20.20s",
+ PMCSTAT_PRINTW(" %-10.10s %-30.30s",
pmcstat_string_unintern(cg->pcg_image->pi_name),
ns);
@@ -624,7 +639,7 @@ pmcpl_cg_topdisplay(void)
qsort(sortbuffer, nentries, sizeof(struct pmcstat_cgnode *),
pmcstat_cgnode_compare);
- PMCSTAT_PRINTW("%5.5s %-10.10s %-20.20s %s\n",
+ PMCSTAT_PRINTW("%5.5s %-10.10s %-30.30s %s\n",
"%SAMP", "IMAGE", "FUNCTION", "CALLERS");
nentries = min(pmcstat_displayheight - 2, nentries);
diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8
index 1291347f8060..86d48db5a8de 100644
--- a/usr.sbin/pmcstat/pmcstat.8
+++ b/usr.sbin/pmcstat/pmcstat.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 25, 2018
+.Dd August 5, 2020
.Dt PMCSTAT 8
.Os
.Sh NAME
@@ -33,6 +33,7 @@
.Nd "performance measurement with performance monitoring hardware"
.Sh SYNOPSIS
.Nm
+.Op Fl A
.Op Fl C
.Op Fl D Ar pathname
.Op Fl E
@@ -123,6 +124,8 @@ process' current and future children.
.Sh OPTIONS
The following options are available:
.Bl -tag -width indent
+.It Fl A
+Skip symbol lookup and display address instead.
.It Fl C
Toggle between showing cumulative or incremental counts for
subsequent counting mode PMCs specified on the command line.
@@ -161,7 +164,7 @@ this information is sent to the output file specified by the
.Fl o
option.
.It Fl I
-Skip symbol lookup and display address instead.
+Show the offset of the instruction pointer into the symbol.
.It Fl L
List all event names.
.It Fl M Ar mapfilename
@@ -222,10 +225,10 @@ specified in
.Ar event-spec .
.It Fl T
Use a top like mode for sampling PMCs. The following hotkeys
-can be used: 'c+a' switch to accumulative mode, 'c+d' switch
-to delta mode, 'm' merge PMCs, 'n' change view, 'p' show next
-PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under threshold
-is seen as a dot.
+can be used: 'A' toggle symbol resolution, 'c+a' switch to accumulative mode, 'c+d'
+switch to delta mode, 'I' toggle showing offsets into symbols, 'm' merge PMCs, 'n'
+change view, 'p' show next PMC, ' ' pause, 'q' quit. calltree only: 'f' cost under
+threshold is seen as a dot.
.It Fl U
Toggle capturing user-space call traces while in kernel mode.
The default is for sampling PMCs to capture user-space callchain information
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index 838e8cac58b4..2524a76de6f8 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -511,8 +511,12 @@ main(int argc, char **argv)
CPU_COPY(&rootmask, &cpumask);
while ((option = getopt(argc, argv,
- "CD:EF:G:ILM:NO:P:R:S:TUWZa:c:def:gi:k:l:m:n:o:p:qr:s:t:u:vw:z:")) != -1)
+ "ACD:EF:G:ILM:NO:P:R:S:TUWZa:c:def:gi:k:l:m:n:o:p:qr:s:t:u:vw:z:")) != -1)
switch (option) {
+ case 'A':
+ args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
+ break;
+
case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE;
args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG;
@@ -586,14 +590,15 @@ main(int argc, char **argv)
args.pa_plugin = PMCSTAT_PL_GPROF;
break;
- case 'I':
- args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
- break;
case 'i':
args.pa_flags |= FLAG_FILTER_THREAD_ID;
args.pa_tid = strtol(optarg, &end, 0);
break;
+ case 'I':
+ args.pa_flags |= FLAG_SHOW_OFFSET;
+ break;
+
case 'k': /* pathname to the kernel */
free(args.pa_kernel);
args.pa_kernel = strdup(optarg);
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c
index 5f88d274f393..4f58ffb2eb65 100644
--- a/usr.sbin/pmcstat/pmcstat_log.c
+++ b/usr.sbin/pmcstat/pmcstat_log.c
@@ -612,6 +612,12 @@ pmcstat_keypress_log(void)
c = wgetch(w);
wprintw(w, "Key: %c => ", c);
switch (c) {
+ case 'A':
+ if (args.pa_flags & FLAG_SKIP_TOP_FN_RES)
+ args.pa_flags &= ~FLAG_SKIP_TOP_FN_RES;
+ else
+ args.pa_flags |= FLAG_SKIP_TOP_FN_RES;
+ break;
case 'c':
wprintw(w, "enter mode 'd' or 'a' => ");
c = wgetch(w);
@@ -623,6 +629,12 @@ pmcstat_keypress_log(void)
wprintw(w, "switching to accumulation mode");
}
break;
+ case 'I':
+ if (args.pa_flags & FLAG_SHOW_OFFSET)
+ args.pa_flags &= ~FLAG_SHOW_OFFSET;
+ else
+ args.pa_flags |= FLAG_SHOW_OFFSET;
+ break;
case 'm':
pmcstat_mergepmc = !pmcstat_mergepmc;
/*