perf evsel: Require that callchains be resolved before calling fprintf_{sym,callchain}

This way the print routine merely does printing, not requiring access to
the resolving machinery, which helps disentangling the object files and
easing creating subsets with a limited functionality set.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-2ti2jbra8fypdfawwwm3aee3@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent bfbba189
...@@ -569,19 +569,23 @@ static void print_sample_bts(struct perf_sample *sample, ...@@ -569,19 +569,23 @@ static void print_sample_bts(struct perf_sample *sample,
/* print branch_from information */ /* print branch_from information */
if (PRINT_FIELD(IP)) { if (PRINT_FIELD(IP)) {
unsigned int print_opts = output[attr->type].print_ip_opts; unsigned int print_opts = output[attr->type].print_ip_opts;
struct callchain_cursor *cursor = NULL, cursor_callchain;
if (symbol_conf.use_callchain && sample->callchain) { if (symbol_conf.use_callchain && sample->callchain &&
printf("\n"); thread__resolve_callchain(al->thread, &cursor_callchain, evsel,
} else { sample, NULL, NULL, scripting_max_stack) == 0)
printf(" "); cursor = &cursor_callchain;
if (cursor == NULL) {
putchar(' ');
if (print_opts & EVSEL__PRINT_SRCLINE) { if (print_opts & EVSEL__PRINT_SRCLINE) {
print_srcline_last = true; print_srcline_last = true;
print_opts &= ~EVSEL__PRINT_SRCLINE; print_opts &= ~EVSEL__PRINT_SRCLINE;
} }
} } else
perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, putchar('\n');
symbol_conf.use_callchain,
scripting_max_stack, stdout); sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout);
} }
/* print branch_to information */ /* print branch_to information */
...@@ -784,15 +788,15 @@ static void process_event(struct perf_script *script, ...@@ -784,15 +788,15 @@ static void process_event(struct perf_script *script,
printf("%16" PRIu64, sample->weight); printf("%16" PRIu64, sample->weight);
if (PRINT_FIELD(IP)) { if (PRINT_FIELD(IP)) {
if (!symbol_conf.use_callchain) struct callchain_cursor *cursor = NULL, cursor_callchain;
printf(" ");
else if (symbol_conf.use_callchain &&
printf("\n"); thread__resolve_callchain(al->thread, &cursor_callchain, evsel,
sample, NULL, NULL, scripting_max_stack) == 0)
cursor = &cursor_callchain;
perf_evsel__fprintf_sym(evsel, sample, al, 0, putchar(cursor ? '\n' : ' ');
output[attr->type].print_ip_opts, sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
symbol_conf.use_callchain,
scripting_max_stack, stdout);
} }
if (PRINT_FIELD(IREGS)) if (PRINT_FIELD(IREGS))
......
...@@ -1890,14 +1890,16 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse ...@@ -1890,14 +1890,16 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse
if (sample->callchain == NULL) if (sample->callchain == NULL)
return 0; return 0;
if (machine__resolve(trace->host, &al, sample) < 0) { if (machine__resolve(trace->host, &al, sample) < 0 ||
thread__resolve_callchain(al.thread, &callchain_cursor, evsel,
sample, NULL, NULL, scripting_max_stack)) {
pr_err("Problem processing %s callchain, skipping...\n", pr_err("Problem processing %s callchain, skipping...\n",
perf_evsel__name(evsel)); perf_evsel__name(evsel));
return 0; return 0;
} }
return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, return sample__fprintf_callchain(sample, &al, 38, print_opts,
scripting_max_stack, trace->output); &callchain_cursor, trace->output);
} }
static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
......
...@@ -2343,13 +2343,12 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, ...@@ -2343,13 +2343,12 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
return ++printed; return ++printed;
} }
int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, int sample__fprintf_callchain(struct perf_sample *sample,
struct addr_location *al, int left_alignment, struct addr_location *al, int left_alignment,
unsigned int print_opts, unsigned int stack_depth, unsigned int print_opts, struct callchain_cursor *cursor,
FILE *fp) FILE *fp)
{ {
int printed = 0; int printed = 0;
struct callchain_cursor cursor;
struct callchain_cursor_node *node; struct callchain_cursor_node *node;
int print_ip = print_opts & EVSEL__PRINT_IP; int print_ip = print_opts & EVSEL__PRINT_IP;
int print_sym = print_opts & EVSEL__PRINT_SYM; int print_sym = print_opts & EVSEL__PRINT_SYM;
...@@ -2363,22 +2362,15 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * ...@@ -2363,22 +2362,15 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
if (sample->callchain) { if (sample->callchain) {
struct addr_location node_al; struct addr_location node_al;
if (thread__resolve_callchain(al->thread, &cursor, evsel, callchain_cursor_commit(cursor);
sample, NULL, NULL,
stack_depth) != 0) {
if (verbose)
error("Failed to resolve callchain. Skipping\n");
return printed;
}
callchain_cursor_commit(&cursor);
if (print_symoffset) if (print_symoffset)
node_al = *al; node_al = *al;
while (stack_depth) { while (1) {
u64 addr = 0; u64 addr = 0;
node = callchain_cursor_current(&cursor); node = callchain_cursor_current(cursor);
if (!node) if (!node)
break; break;
...@@ -2418,20 +2410,17 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * ...@@ -2418,20 +2410,17 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
if (!print_oneline) if (!print_oneline)
printed += fprintf(fp, "\n"); printed += fprintf(fp, "\n");
stack_depth--;
next: next:
callchain_cursor_advance(&cursor); callchain_cursor_advance(cursor);
} }
} }
return printed; return printed;
} }
int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
struct addr_location *al, int left_alignment, int left_alignment, unsigned int print_opts,
unsigned int print_opts, bool print_callchain, struct callchain_cursor *cursor, FILE *fp)
unsigned int stack_depth, FILE *fp)
{ {
int printed = 0; int printed = 0;
int print_ip = print_opts & EVSEL__PRINT_IP; int print_ip = print_opts & EVSEL__PRINT_IP;
...@@ -2441,9 +2430,9 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample ...@@ -2441,9 +2430,9 @@ int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample
int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
if (print_callchain && sample->callchain) { if (cursor != NULL) {
printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, printed += sample__fprintf_callchain(sample, al, left_alignment,
print_opts, stack_depth, fp); print_opts, cursor, fp);
} else if (!(al->sym && al->sym->ignore)) { } else if (!(al->sym && al->sym->ignore)) {
printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
......
...@@ -395,16 +395,15 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, ...@@ -395,16 +395,15 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
#define EVSEL__PRINT_SRCLINE (1<<5) #define EVSEL__PRINT_SRCLINE (1<<5)
#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6) #define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct callchain_cursor;
struct perf_sample *sample,
struct addr_location *al, int left_alignment, int sample__fprintf_callchain(struct perf_sample *sample, struct addr_location *al,
unsigned int print_opts, int left_alignment, unsigned int print_opts,
unsigned int stack_depth, FILE *fp); struct callchain_cursor *cursor, FILE *fp);
int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
struct addr_location *al, int left_alignment, int left_alignment, unsigned int print_opts,
unsigned int print_opts, bool print_callchain, struct callchain_cursor *cursor, FILE *fp);
unsigned int stack_depth, FILE *fp);
bool perf_evsel__fallback(struct perf_evsel *evsel, int err, bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
char *msg, size_t msgsize); char *msg, size_t msgsize);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment