svn commit: r185322 - head/usr.sbin/pmcstat

Attilio Rao attilio at FreeBSD.org
Tue Nov 25 15:24:29 PST 2008


Author: attilio
Date: Tue Nov 25 23:24:29 2008
New Revision: 185322
URL: http://svn.freebsd.org/changeset/base/185322

Log:
  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

Modified:
  head/usr.sbin/pmcstat/pmcstat.8
  head/usr.sbin/pmcstat/pmcstat.c
  head/usr.sbin/pmcstat/pmcstat.h
  head/usr.sbin/pmcstat/pmcstat_log.c

Modified: head/usr.sbin/pmcstat/pmcstat.8
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat.8	Tue Nov 25 23:05:46 2008	(r185321)
+++ head/usr.sbin/pmcstat/pmcstat.8	Tue Nov 25 23:24:29 2008	(r185322)
@@ -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.

Modified: head/usr.sbin/pmcstat/pmcstat.c
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat.c	Tue Nov 25 23:05:46 2008	(r185321)
+++ head/usr.sbin/pmcstat/pmcstat.c	Tue Nov 25 23:24:29 2008	(r185322)
@@ -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) {

Modified: head/usr.sbin/pmcstat/pmcstat.h
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat.h	Tue Nov 25 23:05:46 2008	(r185321)
+++ head/usr.sbin/pmcstat/pmcstat.h	Tue Nov 25 23:24:29 2008	(r185322)
@@ -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

Modified: head/usr.sbin/pmcstat/pmcstat_log.c
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat_log.c	Tue Nov 25 23:05:46 2008	(r185321)
+++ head/usr.sbin/pmcstat/pmcstat_log.c	Tue Nov 25 23:24:29 2008	(r185322)
@@ -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 
 			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);


More information about the svn-src-head mailing list