[RFC PATCH 5/9] perf: Support for dwarf mode callchain on perf record

From: Frederic Weisbecker
Date: Wed Oct 13 2010 - 01:08:31 EST


"perf record -g" is the command to record frame pointer based
callchains. This patch extends the "-g" option to support the
dwarf cfi mode.

The new behaviour is:

- "perf record -g" will record frame pointer based callchains
as it did before.

- "perf record -g fp" is the same as "-g" alone

- "perf record -g dwarf" will record frame pointer based kernel
callchains but will ignore the user part. Instead it will dump
user regs and 4000 bytes of stack by default to each samples.

- "perf record -g dwarf,x" does the same but overrides the
default 4000 bytes of user stack dumped to x bytes instead.
The higher is the size, the deeper will be the callchain but
the higher will be the overhead of the profiling and the size
of the output file.

Signed-off-by: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxx>
Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Cyrill Gorcunov <gorcunov@xxxxxxxxxx>
Cc: Tom Zanussi <tzanussi@xxxxxxxxx>
Cc: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Robert Richter <robert.richter@xxxxxxx>
---
tools/perf/builtin-record.c | 76 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ff77b80..132d710 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -32,6 +32,12 @@ enum write_mode_t {
WRITE_APPEND
};

+enum call_graph_mode {
+ CALLCHAIN_NONE,
+ CALLCHAIN_FP,
+ CALLCHAIN_DWARF
+};
+
static int *fd[MAX_NR_CPUS][MAX_COUNTERS];

static u64 user_interval = ULLONG_MAX;
@@ -56,7 +62,6 @@ static int thread_num = 0;
static pid_t child_pid = -1;
static bool no_inherit = false;
static enum write_mode_t write_mode = WRITE_FORCE;
-static bool call_graph = false;
static bool inherit_stat = false;
static bool no_samples = false;
static bool sample_address = false;
@@ -76,6 +81,10 @@ static off_t post_processing_offset;
static struct perf_session *session;
static const char *cpu_list;

+static char callchain_default_opt[] = "fp";
+static unsigned long stack_dump_size = 4000;
+static enum call_graph_mode call_graph = CALLCHAIN_NONE;
+
struct mmap_data {
int counter;
void *base;
@@ -274,9 +283,15 @@ static void create_counter(int counter, int cpu)
attr->mmap_data = track;
}

- if (call_graph)
+ if (call_graph) {
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;

+ if (call_graph == CALLCHAIN_DWARF) {
+ attr->sample_type |= PERF_SAMPLE_UREGS;
+ attr->ustack_dump_size = stack_dump_size;
+ }
+ }
+
if (system_wide)
attr->sample_type |= PERF_SAMPLE_CPU;

@@ -779,6 +794,58 @@ out_delete_session:
return err;
}

+static int
+parse_callchain_opt(const struct option *opt __used, const char *arg,
+ int unset)
+{
+ char *tok;
+
+ /*
+ * --no-call-graph
+ */
+ if (unset)
+ return 0;
+
+ if (!arg)
+ return 0;
+
+ tok = strtok((char *)arg, ",");
+ if (!tok)
+ return -1;
+
+ /* get the output mode */
+ if (!strncmp(tok, "fp", strlen(arg)))
+ call_graph = CALLCHAIN_FP;
+
+ else if (!strncmp(tok, "dwarf", strlen(arg)))
+ call_graph = CALLCHAIN_DWARF;
+
+ else if (!strncmp(tok, "none", strlen(arg)))
+ return 0;
+
+ else
+ return -1;
+
+ /* get the stack dump size */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ return 0;
+
+ /* No stack dump size if we record using frame pointers */
+ if (call_graph == CALLCHAIN_FP) {
+ fprintf(stderr, "Stack dump size is only necessary for -g dwarf\n");
+ return -1;
+ }
+
+ stack_dump_size = strtoul(tok, NULL, 0);
+ if (stack_dump_size == ULONG_MAX) {
+ perror("Incorrect stack dump size\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static const char * const record_usage[] = {
"perf record [<options>] [<command>]",
"perf record [<options>] -- <command> [<options>]",
@@ -816,8 +883,9 @@ static const struct option options[] = {
"child tasks do not inherit counters"),
OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
- OPT_BOOLEAN('g', "call-graph", &call_graph,
- "do call-graph (stack chain/backtrace) recording"),
+ OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "mode,dump_size",
+ "do call-graph (stack chain/backtrace) recording"
+ "Default: fp", &parse_callchain_opt, callchain_default_opt),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('s', "stat", &inherit_stat,
--
1.6.2.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/