mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 18:14:07 +08:00
perf/core improvements and fixes:
perf record: Ravi Bangoria: - Provide an option to print perf_event_open args and syscall return value. This was already possible using -v, but then lots of other debug info would be output as well, provide a way to show just the syscall args and return value, e.g.: # perf --debug perf-event-open=1 record perf_event_attr: size 112 { sample_period, sample_freq } 4000 sample_type IP|TID|TIME|PERIOD read_format ID disabled 1 inherit 1 <SNIP> ksymbol 1 bpf_event 1 ------------------------------------------------------------ sys_perf_event_open: pid 4308 cpu 0 group_fd -1 flags 0x8 = 4 core: - Remove map->groups, we can get that information in other ways, reduces the size of a key data structure and paves the way to have it shared by multiple threads. - Use 'struct map_symbol' in more places, where we already were using a 'struct map' + 'struct symbol', this helps passing that usual pair of information across callchain, browser code, etc. - Add 'struct map_groups' (where the map_symbol->map is) to 'struct map_symbol', to ease annotation code, for instance, where we call from functions in one map we're browsing to functions in another DSO, mapped in another 'struct map'. event parsing: Ian Rogers: - Use YYABORT to clear stack after failure, plugging leaks Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCXcrz4AAKCRCyPKLppCJ+ J5HsAQCq3T5bSxa9OxC5w/+Gu4I+bhSlrUvSpzW9ymOaRDDdQAD/WwEcy+Z9OeKI Hd4hwALG7CkNH74bU7SKASFwZvrukgk= =G4y0 -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-5.5-20191112' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: perf record: Ravi Bangoria: - Provide an option to print perf_event_open args and syscall return value. This was already possible using -v, but then lots of other debug info would be output as well, provide a way to show just the syscall args and return value, e.g.: # perf --debug perf-event-open=1 record perf_event_attr: size 112 { sample_period, sample_freq } 4000 sample_type IP|TID|TIME|PERIOD read_format ID disabled 1 inherit 1 <SNIP> ksymbol 1 bpf_event 1 ------------------------------------------------------------ sys_perf_event_open: pid 4308 cpu 0 group_fd -1 flags 0x8 = 4 core: - Remove map->groups, we can get that information in other ways, reduces the size of a key data structure and paves the way to have it shared by multiple threads. - Use 'struct map_symbol' in more places, where we already were using a 'struct map' + 'struct symbol', this helps passing that usual pair of information across callchain, browser code, etc. - Add 'struct map_groups' (where the map_symbol->map is) to 'struct map_symbol', to ease annotation code, for instance, where we call from functions in one map we're browsing to functions in another DSO, mapped in another 'struct map'. event parsing: Ian Rogers: - Use YYABORT to clear stack after failure, plugging leaks Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
b0aeb45bad
@ -24,6 +24,8 @@ OPTIONS
|
|||||||
data-convert - data convert command debug messages
|
data-convert - data convert command debug messages
|
||||||
stderr - write debug output (option -v) to stderr
|
stderr - write debug output (option -v) to stderr
|
||||||
in browser mode
|
in browser mode
|
||||||
|
perf-event-open - Print perf_event_open() arguments and
|
||||||
|
return value
|
||||||
|
|
||||||
--buildid-dir::
|
--buildid-dir::
|
||||||
Setup buildid cache directory. It has higher priority than
|
Setup buildid cache directory. It has higher priority than
|
||||||
|
@ -7,7 +7,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
|
|||||||
char *endptr, *tok, *name;
|
char *endptr, *tok, *name;
|
||||||
struct map *map = ms->map;
|
struct map *map = ms->map;
|
||||||
struct addr_map_symbol target = {
|
struct addr_map_symbol target = {
|
||||||
.map = map,
|
.ms = { .map = map, },
|
||||||
};
|
};
|
||||||
|
|
||||||
tok = strchr(ops->raw, ',');
|
tok = strchr(ops->raw, ',');
|
||||||
@ -38,9 +38,9 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
|
|||||||
return -1;
|
return -1;
|
||||||
target.addr = map__objdump_2mem(map, ops->target.addr);
|
target.addr = map__objdump_2mem(map, ops->target.addr);
|
||||||
|
|
||||||
if (map_groups__find_ams(&target) == 0 &&
|
if (map_groups__find_ams(ms->mg, &target) == 0 &&
|
||||||
map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
|
map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
|
||||||
ops->target.sym = target.sym;
|
ops->target.sym = target.ms.sym;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ static void process_basic_block(struct addr_map_symbol *start,
|
|||||||
struct addr_map_symbol *end,
|
struct addr_map_symbol *end,
|
||||||
struct branch_flags *flags)
|
struct branch_flags *flags)
|
||||||
{
|
{
|
||||||
struct symbol *sym = start->sym;
|
struct symbol *sym = start->ms.sym;
|
||||||
struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
|
struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
|
||||||
struct block_range_iter iter;
|
struct block_range_iter iter;
|
||||||
struct block_range *entry;
|
struct block_range *entry;
|
||||||
@ -301,9 +301,9 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
|
|||||||
struct perf_annotate *ann)
|
struct perf_annotate *ann)
|
||||||
{
|
{
|
||||||
if (!ann->use_stdio2)
|
if (!ann->use_stdio2)
|
||||||
return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, &ann->opts);
|
return symbol__tty_annotate(&he->ms, evsel, &ann->opts);
|
||||||
|
|
||||||
return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, &ann->opts);
|
return symbol__tty_annotate2(&he->ms, evsel, &ann->opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hists__find_annotations(struct hists *hists,
|
static void hists__find_annotations(struct hists *hists,
|
||||||
|
@ -412,8 +412,8 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
|
|||||||
sizeof(key), callcmp);
|
sizeof(key), callcmp);
|
||||||
if (!caller) {
|
if (!caller) {
|
||||||
/* found */
|
/* found */
|
||||||
if (node->map)
|
if (node->ms.map)
|
||||||
addr = map__unmap_ip(node->map, node->ip);
|
addr = map__unmap_ip(node->ms.map, node->ip);
|
||||||
else
|
else
|
||||||
addr = node->ip;
|
addr = node->ip;
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
|
|||||||
if (rep->symbol_ipc && sym && !sym->annotate2) {
|
if (rep->symbol_ipc && sym && !sym->annotate2) {
|
||||||
struct evsel *evsel = hists_to_evsel(he->hists);
|
struct evsel *evsel = hists_to_evsel(he->hists);
|
||||||
|
|
||||||
symbol__annotate2(sym, he->ms.map, evsel,
|
symbol__annotate2(&he->ms, evsel,
|
||||||
&annotation__default_options, NULL);
|
&annotation__default_options, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2172,7 +2172,7 @@ static void save_task_callchain(struct perf_sched *sched,
|
|||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sym = node->sym;
|
sym = node->ms.sym;
|
||||||
if (sym) {
|
if (sym) {
|
||||||
if (!strcmp(sym->name, "schedule") ||
|
if (!strcmp(sym->name, "schedule") ||
|
||||||
!strcmp(sym->name, "__schedule") ||
|
!strcmp(sym->name, "__schedule") ||
|
||||||
|
@ -143,12 +143,12 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = symbol__annotate(sym, map, evsel, 0, &top->annotation_opts, NULL);
|
err = symbol__annotate(&he->ms, evsel, 0, &top->annotation_opts, NULL);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
top->sym_filter_entry = he;
|
top->sym_filter_entry = he;
|
||||||
} else {
|
} else {
|
||||||
char msg[BUFSIZ];
|
char msg[BUFSIZ];
|
||||||
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
|
symbol__strerror_disassemble(&he->ms, err, msg, sizeof(msg));
|
||||||
pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
|
pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ static void perf_top__show_details(struct perf_top *top)
|
|||||||
printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
|
printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
|
||||||
printf(" Events Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt);
|
printf(" Events Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt);
|
||||||
|
|
||||||
more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, &top->annotation_opts);
|
more = symbol__annotate_printf(&he->ms, top->sym_evsel, &top->annotation_opts);
|
||||||
|
|
||||||
if (top->evlist->enabled) {
|
if (top->evlist->enabled) {
|
||||||
if (top->zero)
|
if (top->zero)
|
||||||
|
@ -59,7 +59,7 @@ int test_dwarf_unwind__krava_1(struct thread *thread);
|
|||||||
static int unwind_entry(struct unwind_entry *entry, void *arg)
|
static int unwind_entry(struct unwind_entry *entry, void *arg)
|
||||||
{
|
{
|
||||||
unsigned long *cnt = (unsigned long *) arg;
|
unsigned long *cnt = (unsigned long *) arg;
|
||||||
char *symbol = entry->sym ? entry->sym->name : NULL;
|
char *symbol = entry->ms.sym ? entry->ms.sym->name : NULL;
|
||||||
static const char *funcs[MAX_STACK] = {
|
static const char *funcs[MAX_STACK] = {
|
||||||
"test__arch_unwind_sample",
|
"test__arch_unwind_sample",
|
||||||
"test_dwarf_unwind__thread",
|
"test_dwarf_unwind__thread",
|
||||||
|
@ -410,7 +410,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
|
|||||||
struct evsel *evsel,
|
struct evsel *evsel,
|
||||||
struct hist_browser_timer *hbt)
|
struct hist_browser_timer *hbt)
|
||||||
{
|
{
|
||||||
struct map_symbol *ms = browser->b.priv;
|
struct map_symbol *ms = browser->b.priv, target_ms;
|
||||||
struct disasm_line *dl = disasm_line(browser->selection);
|
struct disasm_line *dl = disasm_line(browser->selection);
|
||||||
struct annotation *notes;
|
struct annotation *notes;
|
||||||
char title[SYM_TITLE_MAX_SIZE];
|
char title[SYM_TITLE_MAX_SIZE];
|
||||||
@ -430,8 +430,11 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target_ms.mg = ms->mg;
|
||||||
|
target_ms.map = ms->map;
|
||||||
|
target_ms.sym = dl->ops.target.sym;
|
||||||
pthread_mutex_unlock(¬es->lock);
|
pthread_mutex_unlock(¬es->lock);
|
||||||
symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
|
symbol__tui_annotate(&target_ms, evsel, hbt, browser->opts);
|
||||||
sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
|
sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
|
||||||
ui_browser__show_title(&browser->b, title);
|
ui_browser__show_title(&browser->b, title);
|
||||||
return true;
|
return true;
|
||||||
@ -874,7 +877,7 @@ int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
|
|||||||
struct hist_browser_timer *hbt,
|
struct hist_browser_timer *hbt,
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts);
|
return symbol__tui_annotate(ms, evsel, hbt, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
|
int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
|
||||||
@ -888,16 +891,12 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
|
|||||||
return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
|
return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__tui_annotate(struct symbol *sym, struct map *map,
|
int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct hist_browser_timer *hbt,
|
struct hist_browser_timer *hbt,
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct annotation *notes = symbol__annotation(sym);
|
struct annotation *notes = symbol__annotation(sym);
|
||||||
struct map_symbol ms = {
|
|
||||||
.map = map,
|
|
||||||
.sym = sym,
|
|
||||||
};
|
|
||||||
struct annotate_browser browser = {
|
struct annotate_browser browser = {
|
||||||
.b = {
|
.b = {
|
||||||
.refresh = annotate_browser__refresh,
|
.refresh = annotate_browser__refresh,
|
||||||
@ -905,7 +904,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
|
|||||||
.write = annotate_browser__write,
|
.write = annotate_browser__write,
|
||||||
.filter = disasm_line__filter,
|
.filter = disasm_line__filter,
|
||||||
.extra_title_lines = 1, /* for hists__scnprintf_title() */
|
.extra_title_lines = 1, /* for hists__scnprintf_title() */
|
||||||
.priv = &ms,
|
.priv = ms,
|
||||||
.use_navkeypressed = true,
|
.use_navkeypressed = true,
|
||||||
},
|
},
|
||||||
.opts = opts,
|
.opts = opts,
|
||||||
@ -915,13 +914,13 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
|
|||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (map->dso->annotate_warned)
|
if (ms->map->dso->annotate_warned)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
err = symbol__annotate2(sym, map, evsel, opts, &browser.arch);
|
err = symbol__annotate2(ms, evsel, opts, &browser.arch);
|
||||||
if (err) {
|
if (err) {
|
||||||
char msg[BUFSIZ];
|
char msg[BUFSIZ];
|
||||||
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
|
symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
|
||||||
ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
|
ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
|
||||||
goto out_free_offsets;
|
goto out_free_offsets;
|
||||||
}
|
}
|
||||||
|
@ -2405,16 +2405,15 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)
|
|||||||
static int
|
static int
|
||||||
add_annotate_opt(struct hist_browser *browser __maybe_unused,
|
add_annotate_opt(struct hist_browser *browser __maybe_unused,
|
||||||
struct popup_action *act, char **optstr,
|
struct popup_action *act, char **optstr,
|
||||||
struct map *map, struct symbol *sym)
|
struct map_symbol *ms)
|
||||||
{
|
{
|
||||||
if (sym == NULL || map->dso->annotate_warned)
|
if (ms->sym == NULL || ms->map->dso->annotate_warned)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (asprintf(optstr, "Annotate %s", sym->name) < 0)
|
if (asprintf(optstr, "Annotate %s", ms->sym->name) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
act->ms.map = map;
|
act->ms = *ms;
|
||||||
act->ms.sym = sym;
|
|
||||||
act->fn = do_annotate;
|
act->fn = do_annotate;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -3115,20 +3114,17 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events,
|
|||||||
nr_options += add_annotate_opt(browser,
|
nr_options += add_annotate_opt(browser,
|
||||||
&actions[nr_options],
|
&actions[nr_options],
|
||||||
&options[nr_options],
|
&options[nr_options],
|
||||||
bi->from.map,
|
&bi->from.ms);
|
||||||
bi->from.sym);
|
if (bi->to.ms.sym != bi->from.ms.sym)
|
||||||
if (bi->to.sym != bi->from.sym)
|
|
||||||
nr_options += add_annotate_opt(browser,
|
nr_options += add_annotate_opt(browser,
|
||||||
&actions[nr_options],
|
&actions[nr_options],
|
||||||
&options[nr_options],
|
&options[nr_options],
|
||||||
bi->to.map,
|
&bi->to.ms);
|
||||||
bi->to.sym);
|
|
||||||
} else {
|
} else {
|
||||||
nr_options += add_annotate_opt(browser,
|
nr_options += add_annotate_opt(browser,
|
||||||
&actions[nr_options],
|
&actions[nr_options],
|
||||||
&options[nr_options],
|
&options[nr_options],
|
||||||
browser->selection->map,
|
browser->selection);
|
||||||
browser->selection->sym);
|
|
||||||
}
|
}
|
||||||
skip_annotation:
|
skip_annotation:
|
||||||
nr_options += add_thread_opt(browser, &actions[nr_options],
|
nr_options += add_thread_opt(browser, &actions[nr_options],
|
||||||
|
@ -54,10 +54,10 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym,
|
static int perf_gtk__get_offset(char *buf, size_t size, struct map_symbol *ms,
|
||||||
struct map *map, struct disasm_line *dl)
|
struct disasm_line *dl)
|
||||||
{
|
{
|
||||||
u64 start = map__rip_2objdump(map, sym->start);
|
u64 start = map__rip_2objdump(ms->map, ms->sym->start);
|
||||||
|
|
||||||
strcpy(buf, "");
|
strcpy(buf, "");
|
||||||
|
|
||||||
@ -91,10 +91,11 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
|
static int perf_gtk__annotate_symbol(GtkWidget *window, struct map_symbol *ms,
|
||||||
struct map *map, struct evsel *evsel,
|
struct evsel *evsel,
|
||||||
struct hist_browser_timer *hbt __maybe_unused)
|
struct hist_browser_timer *hbt __maybe_unused)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct disasm_line *pos, *n;
|
struct disasm_line *pos, *n;
|
||||||
struct annotation *notes;
|
struct annotation *notes;
|
||||||
GType col_types[MAX_ANN_COLS];
|
GType col_types[MAX_ANN_COLS];
|
||||||
@ -144,7 +145,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1);
|
gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1);
|
||||||
if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos))
|
if (perf_gtk__get_offset(s, sizeof(s), ms, pos))
|
||||||
gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1);
|
gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1);
|
||||||
if (perf_gtk__get_line(s, sizeof(s), pos))
|
if (perf_gtk__get_line(s, sizeof(s), pos))
|
||||||
gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1);
|
gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1);
|
||||||
@ -160,23 +161,23 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
|
static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct hist_browser_timer *hbt)
|
struct hist_browser_timer *hbt)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
GtkWidget *window;
|
GtkWidget *window;
|
||||||
GtkWidget *notebook;
|
GtkWidget *notebook;
|
||||||
GtkWidget *scrolled_window;
|
GtkWidget *scrolled_window;
|
||||||
GtkWidget *tab_label;
|
GtkWidget *tab_label;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (map->dso->annotate_warned)
|
if (ms->map->dso->annotate_warned)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
err = symbol__annotate(sym, map, evsel, 0, &annotation__default_options, NULL);
|
err = symbol__annotate(ms, evsel, 0, &annotation__default_options, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
char msg[BUFSIZ];
|
char msg[BUFSIZ];
|
||||||
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
|
symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
|
||||||
ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
|
ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -234,7 +235,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
|
|||||||
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window,
|
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window,
|
||||||
tab_label);
|
tab_label);
|
||||||
|
|
||||||
perf_gtk__annotate_symbol(scrolled_window, sym, map, evsel, hbt);
|
perf_gtk__annotate_symbol(scrolled_window, ms, evsel, hbt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +243,7 @@ int hist_entry__gtk_annotate(struct hist_entry *he,
|
|||||||
struct evsel *evsel,
|
struct evsel *evsel,
|
||||||
struct hist_browser_timer *hbt)
|
struct hist_browser_timer *hbt)
|
||||||
{
|
{
|
||||||
return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
|
return symbol__gtk_annotate(&he->ms, evsel, hbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void perf_gtk__show_annotations(void)
|
void perf_gtk__show_annotations(void)
|
||||||
|
@ -243,7 +243,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
|
|||||||
char *endptr, *tok, *name;
|
char *endptr, *tok, *name;
|
||||||
struct map *map = ms->map;
|
struct map *map = ms->map;
|
||||||
struct addr_map_symbol target = {
|
struct addr_map_symbol target = {
|
||||||
.map = map,
|
.ms = { .map = map, },
|
||||||
};
|
};
|
||||||
|
|
||||||
ops->target.addr = strtoull(ops->raw, &endptr, 16);
|
ops->target.addr = strtoull(ops->raw, &endptr, 16);
|
||||||
@ -271,9 +271,9 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
|
|||||||
find_target:
|
find_target:
|
||||||
target.addr = map__objdump_2mem(map, ops->target.addr);
|
target.addr = map__objdump_2mem(map, ops->target.addr);
|
||||||
|
|
||||||
if (map_groups__find_ams(&target) == 0 &&
|
if (map_groups__find_ams(ms->mg, &target) == 0 &&
|
||||||
map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
|
map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
|
||||||
ops->target.sym = target.sym;
|
ops->target.sym = target.ms.sym;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
|
|||||||
struct map *map = ms->map;
|
struct map *map = ms->map;
|
||||||
struct symbol *sym = ms->sym;
|
struct symbol *sym = ms->sym;
|
||||||
struct addr_map_symbol target = {
|
struct addr_map_symbol target = {
|
||||||
.map = map,
|
.ms = { .map = map, },
|
||||||
};
|
};
|
||||||
const char *c = strchr(ops->raw, ',');
|
const char *c = strchr(ops->raw, ',');
|
||||||
u64 start, end;
|
u64 start, end;
|
||||||
@ -391,9 +391,9 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
|
|||||||
* Actual navigation will come next, with further understanding of how
|
* Actual navigation will come next, with further understanding of how
|
||||||
* the symbol searching and disassembly should be done.
|
* the symbol searching and disassembly should be done.
|
||||||
*/
|
*/
|
||||||
if (map_groups__find_ams(&target) == 0 &&
|
if (map_groups__find_ams(ms->mg, &target) == 0 &&
|
||||||
map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
|
map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
|
||||||
ops->target.sym = target.sym;
|
ops->target.sym = target.ms.sym;
|
||||||
|
|
||||||
if (!ops->target.outside) {
|
if (!ops->target.outside) {
|
||||||
ops->target.offset = target.addr - start;
|
ops->target.offset = target.addr - start;
|
||||||
@ -865,14 +865,15 @@ static int __symbol__account_cycles(struct cyc_hist *ch,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
|
static int __symbol__inc_addr_samples(struct map_symbol *ms,
|
||||||
struct annotated_source *src, int evidx, u64 addr,
|
struct annotated_source *src, int evidx, u64 addr,
|
||||||
struct perf_sample *sample)
|
struct perf_sample *sample)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
struct sym_hist *h;
|
struct sym_hist *h;
|
||||||
|
|
||||||
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
|
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, ms->map->unmap_ip(ms->map, addr));
|
||||||
|
|
||||||
if ((addr < sym->start || addr >= sym->end) &&
|
if ((addr < sym->start || addr >= sym->end) &&
|
||||||
(addr != sym->end || sym->start != sym->end)) {
|
(addr != sym->end || sym->start != sym->end)) {
|
||||||
@ -939,17 +940,17 @@ alloc_histograms:
|
|||||||
return notes->src;
|
return notes->src;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
|
static int symbol__inc_addr_samples(struct map_symbol *ms,
|
||||||
struct evsel *evsel, u64 addr,
|
struct evsel *evsel, u64 addr,
|
||||||
struct perf_sample *sample)
|
struct perf_sample *sample)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct annotated_source *src;
|
struct annotated_source *src;
|
||||||
|
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
src = symbol__hists(sym, evsel->evlist->core.nr_entries);
|
src = symbol__hists(sym, evsel->evlist->core.nr_entries);
|
||||||
return (src) ? __symbol__inc_addr_samples(sym, map, src, evsel->idx,
|
return src ? __symbol__inc_addr_samples(ms, src, evsel->idx, addr, sample) : 0;
|
||||||
addr, sample) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int symbol__account_cycles(u64 addr, u64 start,
|
static int symbol__account_cycles(u64 addr, u64 start,
|
||||||
@ -997,17 +998,17 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
|
|||||||
* it starts on the function start.
|
* it starts on the function start.
|
||||||
*/
|
*/
|
||||||
if (start &&
|
if (start &&
|
||||||
(start->sym == ams->sym ||
|
(start->ms.sym == ams->ms.sym ||
|
||||||
(ams->sym &&
|
(ams->ms.sym &&
|
||||||
start->addr == ams->sym->start + ams->map->start)))
|
start->addr == ams->ms.sym->start + ams->ms.map->start)))
|
||||||
saddr = start->al_addr;
|
saddr = start->al_addr;
|
||||||
if (saddr == 0)
|
if (saddr == 0)
|
||||||
pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
|
pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
|
||||||
ams->addr,
|
ams->addr,
|
||||||
start ? start->addr : 0,
|
start ? start->addr : 0,
|
||||||
ams->sym ? ams->sym->start + ams->map->start : 0,
|
ams->ms.sym ? ams->ms.sym->start + ams->ms.map->start : 0,
|
||||||
saddr);
|
saddr);
|
||||||
err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
|
err = symbol__account_cycles(ams->al_addr, saddr, ams->ms.sym, cycles);
|
||||||
if (err)
|
if (err)
|
||||||
pr_debug2("account_cycles failed %d\n", err);
|
pr_debug2("account_cycles failed %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
@ -1093,13 +1094,13 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
|
|||||||
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
|
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
|
||||||
struct evsel *evsel)
|
struct evsel *evsel)
|
||||||
{
|
{
|
||||||
return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
|
return symbol__inc_addr_samples(&ams->ms, evsel, ams->al_addr, sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
|
int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
|
||||||
struct evsel *evsel, u64 ip)
|
struct evsel *evsel, u64 ip)
|
||||||
{
|
{
|
||||||
return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
|
return symbol__inc_addr_samples(&he->ms, evsel, ip, sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
|
static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
|
||||||
@ -1540,13 +1541,13 @@ static int symbol__parse_objdump_line(struct symbol *sym,
|
|||||||
/* kcore has no symbols, so add the call target symbol */
|
/* kcore has no symbols, so add the call target symbol */
|
||||||
if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
|
if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
|
||||||
struct addr_map_symbol target = {
|
struct addr_map_symbol target = {
|
||||||
.map = map,
|
|
||||||
.addr = dl->ops.target.addr,
|
.addr = dl->ops.target.addr,
|
||||||
|
.ms = { .map = map, },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!map_groups__find_ams(&target) &&
|
if (!map_groups__find_ams(args->ms.mg, &target) &&
|
||||||
target.sym->start == target.al_addr)
|
target.ms.sym->start == target.al_addr)
|
||||||
dl->ops.target.sym = target.sym;
|
dl->ops.target.sym = target.ms.sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation_line__add(&dl->al, ¬es->src->source);
|
annotation_line__add(&dl->al, ¬es->src->source);
|
||||||
@ -1583,10 +1584,9 @@ static void delete_last_nop(struct symbol *sym)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
|
int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen)
|
||||||
int errnum, char *buf, size_t buflen)
|
|
||||||
{
|
{
|
||||||
struct dso *dso = map->dso;
|
struct dso *dso = ms->map->dso;
|
||||||
|
|
||||||
BUG_ON(buflen == 0);
|
BUG_ON(buflen == 0);
|
||||||
|
|
||||||
@ -2143,11 +2143,10 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
|
|||||||
annotation__calc_percent(notes, evsel, symbol__size(sym));
|
annotation__calc_percent(notes, evsel, symbol__size(sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__annotate(struct symbol *sym, struct map *map,
|
int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, size_t privsize,
|
||||||
struct evsel *evsel, size_t privsize,
|
struct annotation_options *options, struct arch **parch)
|
||||||
struct annotation_options *options,
|
|
||||||
struct arch **parch)
|
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct annotation *notes = symbol__annotation(sym);
|
struct annotation *notes = symbol__annotation(sym);
|
||||||
struct annotate_args args = {
|
struct annotate_args args = {
|
||||||
.privsize = privsize,
|
.privsize = privsize,
|
||||||
@ -2177,9 +2176,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args.ms.map = map;
|
args.ms = *ms;
|
||||||
args.ms.sym = sym;
|
notes->start = map__rip_2objdump(ms->map, sym->start);
|
||||||
notes->start = map__rip_2objdump(map, sym->start);
|
|
||||||
|
|
||||||
return symbol__disassemble(sym, &args);
|
return symbol__disassemble(sym, &args);
|
||||||
}
|
}
|
||||||
@ -2335,10 +2333,11 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__annotate_printf(struct symbol *sym, struct map *map,
|
int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
|
struct map *map = ms->map;
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct dso *dso = map->dso;
|
struct dso *dso = map->dso;
|
||||||
char *filename;
|
char *filename;
|
||||||
const char *d_filename;
|
const char *d_filename;
|
||||||
@ -2742,30 +2741,29 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
|
|||||||
resort_source_line(root, &tmp_root);
|
resort_source_line(root, &tmp_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void symbol__calc_lines(struct symbol *sym, struct map *map,
|
static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root,
|
||||||
struct rb_root *root,
|
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
struct annotation *notes = symbol__annotation(sym);
|
struct annotation *notes = symbol__annotation(ms->sym);
|
||||||
|
|
||||||
annotation__calc_lines(notes, map, root, opts);
|
annotation__calc_lines(notes, ms->map, root, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__tty_annotate2(struct symbol *sym, struct map *map,
|
int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
struct dso *dso = map->dso;
|
struct dso *dso = ms->map->dso;
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct rb_root source_line = RB_ROOT;
|
struct rb_root source_line = RB_ROOT;
|
||||||
struct hists *hists = evsel__hists(evsel);
|
struct hists *hists = evsel__hists(evsel);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
|
if (symbol__annotate2(ms, evsel, opts, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (opts->print_lines) {
|
if (opts->print_lines) {
|
||||||
srcline_full_filename = opts->full_path;
|
srcline_full_filename = opts->full_path;
|
||||||
symbol__calc_lines(sym, map, &source_line, opts);
|
symbol__calc_lines(ms, &source_line, opts);
|
||||||
print_summary(&source_line, dso->long_name);
|
print_summary(&source_line, dso->long_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2779,25 +2777,25 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__tty_annotate(struct symbol *sym, struct map *map,
|
int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct annotation_options *opts)
|
struct annotation_options *opts)
|
||||||
{
|
{
|
||||||
struct dso *dso = map->dso;
|
struct dso *dso = ms->map->dso;
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct rb_root source_line = RB_ROOT;
|
struct rb_root source_line = RB_ROOT;
|
||||||
|
|
||||||
if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0)
|
if (symbol__annotate(ms, evsel, 0, opts, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
symbol__calc_percent(sym, evsel);
|
symbol__calc_percent(sym, evsel);
|
||||||
|
|
||||||
if (opts->print_lines) {
|
if (opts->print_lines) {
|
||||||
srcline_full_filename = opts->full_path;
|
srcline_full_filename = opts->full_path;
|
||||||
symbol__calc_lines(sym, map, &source_line, opts);
|
symbol__calc_lines(ms, &source_line, opts);
|
||||||
print_summary(&source_line, dso->long_name);
|
print_summary(&source_line, dso->long_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol__annotate_printf(sym, map, evsel, opts);
|
symbol__annotate_printf(ms, evsel, opts);
|
||||||
|
|
||||||
annotated_source__purge(symbol__annotation(sym)->src);
|
annotated_source__purge(symbol__annotation(sym)->src);
|
||||||
|
|
||||||
@ -3051,9 +3049,10 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
|
|||||||
wops->write_graph);
|
wops->write_graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel,
|
int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct annotation_options *options, struct arch **parch)
|
struct annotation_options *options, struct arch **parch)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
struct annotation *notes = symbol__annotation(sym);
|
struct annotation *notes = symbol__annotation(sym);
|
||||||
size_t size = symbol__size(sym);
|
size_t size = symbol__size(sym);
|
||||||
int nr_pcnt = 1, err;
|
int nr_pcnt = 1, err;
|
||||||
@ -3065,7 +3064,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel,
|
|||||||
if (perf_evsel__is_group_event(evsel))
|
if (perf_evsel__is_group_event(evsel))
|
||||||
nr_pcnt = evsel->core.nr_members;
|
nr_pcnt = evsel->core.nr_members;
|
||||||
|
|
||||||
err = symbol__annotate(sym, map, evsel, 0, options, parch);
|
err = symbol__annotate(ms, evsel, 0, options, parch);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_offsets;
|
goto out_free_offsets;
|
||||||
|
|
||||||
|
@ -349,11 +349,11 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *samp
|
|||||||
struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
|
struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
|
||||||
void symbol__annotate_zero_histograms(struct symbol *sym);
|
void symbol__annotate_zero_histograms(struct symbol *sym);
|
||||||
|
|
||||||
int symbol__annotate(struct symbol *sym, struct map *map,
|
int symbol__annotate(struct map_symbol *ms,
|
||||||
struct evsel *evsel, size_t privsize,
|
struct evsel *evsel, size_t privsize,
|
||||||
struct annotation_options *options,
|
struct annotation_options *options,
|
||||||
struct arch **parch);
|
struct arch **parch);
|
||||||
int symbol__annotate2(struct symbol *sym, struct map *map,
|
int symbol__annotate2(struct map_symbol *ms,
|
||||||
struct evsel *evsel,
|
struct evsel *evsel,
|
||||||
struct annotation_options *options,
|
struct annotation_options *options,
|
||||||
struct arch **parch);
|
struct arch **parch);
|
||||||
@ -380,11 +380,9 @@ enum symbol_disassemble_errno {
|
|||||||
__SYMBOL_ANNOTATE_ERRNO__END,
|
__SYMBOL_ANNOTATE_ERRNO__END,
|
||||||
};
|
};
|
||||||
|
|
||||||
int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
|
int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen);
|
||||||
int errnum, char *buf, size_t buflen);
|
|
||||||
|
|
||||||
int symbol__annotate_printf(struct symbol *sym, struct map *map,
|
int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct annotation_options *options);
|
struct annotation_options *options);
|
||||||
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
|
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
|
||||||
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
|
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
|
||||||
@ -395,20 +393,16 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
|
|||||||
|
|
||||||
bool ui__has_annotation(void);
|
bool ui__has_annotation(void);
|
||||||
|
|
||||||
int symbol__tty_annotate(struct symbol *sym, struct map *map,
|
int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
|
||||||
struct evsel *evsel, struct annotation_options *opts);
|
|
||||||
|
|
||||||
int symbol__tty_annotate2(struct symbol *sym, struct map *map,
|
int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
|
||||||
struct evsel *evsel, struct annotation_options *opts);
|
|
||||||
|
|
||||||
#ifdef HAVE_SLANG_SUPPORT
|
#ifdef HAVE_SLANG_SUPPORT
|
||||||
int symbol__tui_annotate(struct symbol *sym, struct map *map,
|
int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
|
||||||
struct evsel *evsel,
|
|
||||||
struct hist_browser_timer *hbt,
|
struct hist_browser_timer *hbt,
|
||||||
struct annotation_options *opts);
|
struct annotation_options *opts);
|
||||||
#else
|
#else
|
||||||
static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
|
static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
|
||||||
struct map *map __maybe_unused,
|
|
||||||
struct evsel *evsel __maybe_unused,
|
struct evsel *evsel __maybe_unused,
|
||||||
struct hist_browser_timer *hbt __maybe_unused,
|
struct hist_browser_timer *hbt __maybe_unused,
|
||||||
struct annotation_options *opts __maybe_unused)
|
struct annotation_options *opts __maybe_unused)
|
||||||
|
@ -582,8 +582,8 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
call->ip = cursor_node->ip;
|
call->ip = cursor_node->ip;
|
||||||
call->ms.sym = cursor_node->sym;
|
call->ms = cursor_node->ms;
|
||||||
call->ms.map = map__get(cursor_node->map);
|
map__get(call->ms.map);
|
||||||
call->srcline = cursor_node->srcline;
|
call->srcline = cursor_node->srcline;
|
||||||
|
|
||||||
if (cursor_node->branch) {
|
if (cursor_node->branch) {
|
||||||
@ -720,21 +720,21 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
|
|||||||
/* otherwise fall-back to symbol-based comparison below */
|
/* otherwise fall-back to symbol-based comparison below */
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
case CCKEY_FUNCTION:
|
case CCKEY_FUNCTION:
|
||||||
if (node->sym && cnode->ms.sym) {
|
if (node->ms.sym && cnode->ms.sym) {
|
||||||
/*
|
/*
|
||||||
* Compare inlined frames based on their symbol name
|
* Compare inlined frames based on their symbol name
|
||||||
* because different inlined frames will have the same
|
* because different inlined frames will have the same
|
||||||
* symbol start. Otherwise do a faster comparison based
|
* symbol start. Otherwise do a faster comparison based
|
||||||
* on the symbol start address.
|
* on the symbol start address.
|
||||||
*/
|
*/
|
||||||
if (cnode->ms.sym->inlined || node->sym->inlined) {
|
if (cnode->ms.sym->inlined || node->ms.sym->inlined) {
|
||||||
match = match_chain_strings(cnode->ms.sym->name,
|
match = match_chain_strings(cnode->ms.sym->name,
|
||||||
node->sym->name);
|
node->ms.sym->name);
|
||||||
if (match != MATCH_ERROR)
|
if (match != MATCH_ERROR)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
|
match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
|
||||||
node->map, node->sym->start);
|
node->ms.map, node->ms.sym->start);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,7 +742,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
|
|||||||
__fallthrough;
|
__fallthrough;
|
||||||
case CCKEY_ADDRESS:
|
case CCKEY_ADDRESS:
|
||||||
default:
|
default:
|
||||||
match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->map, node->ip);
|
match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->ms.map, node->ip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,8 +1004,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
list_for_each_entry_safe(list, next_list, &src->val, list) {
|
list_for_each_entry_safe(list, next_list, &src->val, list) {
|
||||||
callchain_cursor_append(cursor, list->ip,
|
callchain_cursor_append(cursor, list->ip, &list->ms,
|
||||||
list->ms.map, list->ms.sym,
|
|
||||||
false, NULL, 0, 0, 0, list->srcline);
|
false, NULL, 0, 0, 0, list->srcline);
|
||||||
list_del_init(&list->list);
|
list_del_init(&list->list);
|
||||||
map__zput(list->ms.map);
|
map__zput(list->ms.map);
|
||||||
@ -1044,7 +1043,7 @@ int callchain_merge(struct callchain_cursor *cursor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int callchain_cursor_append(struct callchain_cursor *cursor,
|
int callchain_cursor_append(struct callchain_cursor *cursor,
|
||||||
u64 ip, struct map *map, struct symbol *sym,
|
u64 ip, struct map_symbol *ms,
|
||||||
bool branch, struct branch_flags *flags,
|
bool branch, struct branch_flags *flags,
|
||||||
int nr_loop_iter, u64 iter_cycles, u64 branch_from,
|
int nr_loop_iter, u64 iter_cycles, u64 branch_from,
|
||||||
const char *srcline)
|
const char *srcline)
|
||||||
@ -1060,9 +1059,9 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
node->ip = ip;
|
node->ip = ip;
|
||||||
map__zput(node->map);
|
map__zput(node->ms.map);
|
||||||
node->map = map__get(map);
|
node->ms = *ms;
|
||||||
node->sym = sym;
|
map__get(node->ms.map);
|
||||||
node->branch = branch;
|
node->branch = branch;
|
||||||
node->nr_loop_iter = nr_loop_iter;
|
node->nr_loop_iter = nr_loop_iter;
|
||||||
node->iter_cycles = iter_cycles;
|
node->iter_cycles = iter_cycles;
|
||||||
@ -1107,8 +1106,9 @@ int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *samp
|
|||||||
int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
|
int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
|
||||||
bool hide_unresolved)
|
bool hide_unresolved)
|
||||||
{
|
{
|
||||||
al->map = node->map;
|
al->mg = node->ms.mg;
|
||||||
al->sym = node->sym;
|
al->map = node->ms.map;
|
||||||
|
al->sym = node->ms.sym;
|
||||||
al->srcline = node->srcline;
|
al->srcline = node->srcline;
|
||||||
al->addr = node->ip;
|
al->addr = node->ip;
|
||||||
|
|
||||||
@ -1119,8 +1119,8 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (al->map->groups == &al->machine->kmaps) {
|
if (al->mg == &al->mg->machine->kmaps) {
|
||||||
if (machine__is_host(al->machine)) {
|
if (machine__is_host(al->mg->machine)) {
|
||||||
al->cpumode = PERF_RECORD_MISC_KERNEL;
|
al->cpumode = PERF_RECORD_MISC_KERNEL;
|
||||||
al->level = 'k';
|
al->level = 'k';
|
||||||
} else {
|
} else {
|
||||||
@ -1128,7 +1128,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
|
|||||||
al->level = 'g';
|
al->level = 'g';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (machine__is_host(al->machine)) {
|
if (machine__is_host(al->mg->machine)) {
|
||||||
al->cpumode = PERF_RECORD_MISC_USER;
|
al->cpumode = PERF_RECORD_MISC_USER;
|
||||||
al->level = '.';
|
al->level = '.';
|
||||||
} else if (perf_guest) {
|
} else if (perf_guest) {
|
||||||
@ -1571,7 +1571,7 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
|
|||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
|
rc = callchain_cursor_append(dst, node->ip, &node->ms,
|
||||||
node->branch, &node->branch_flags,
|
node->branch, &node->branch_flags,
|
||||||
node->nr_loop_iter,
|
node->nr_loop_iter,
|
||||||
node->iter_cycles,
|
node->iter_cycles,
|
||||||
@ -1597,5 +1597,5 @@ void callchain_cursor_reset(struct callchain_cursor *cursor)
|
|||||||
cursor->last = &cursor->first;
|
cursor->last = &cursor->first;
|
||||||
|
|
||||||
for (node = cursor->first; node != NULL; node = node->next)
|
for (node = cursor->first; node != NULL; node = node->next)
|
||||||
map__zput(node->map);
|
map__zput(node->ms.map);
|
||||||
}
|
}
|
||||||
|
@ -141,8 +141,7 @@ struct callchain_list {
|
|||||||
*/
|
*/
|
||||||
struct callchain_cursor_node {
|
struct callchain_cursor_node {
|
||||||
u64 ip;
|
u64 ip;
|
||||||
struct map *map;
|
struct map_symbol ms;
|
||||||
struct symbol *sym;
|
|
||||||
const char *srcline;
|
const char *srcline;
|
||||||
bool branch;
|
bool branch;
|
||||||
struct branch_flags branch_flags;
|
struct branch_flags branch_flags;
|
||||||
@ -195,7 +194,7 @@ int callchain_merge(struct callchain_cursor *cursor,
|
|||||||
void callchain_cursor_reset(struct callchain_cursor *cursor);
|
void callchain_cursor_reset(struct callchain_cursor *cursor);
|
||||||
|
|
||||||
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
|
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
|
||||||
struct map *map, struct symbol *sym,
|
struct map_symbol *ms,
|
||||||
bool branch, struct branch_flags *flags,
|
bool branch, struct branch_flags *flags,
|
||||||
int nr_loop_iter, u64 iter_cycles, u64 branch_from,
|
int nr_loop_iter, u64 iter_cycles, u64 branch_from,
|
||||||
const char *srcline);
|
const char *srcline);
|
||||||
|
@ -181,7 +181,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
|
|||||||
if (al->map) {
|
if (al->map) {
|
||||||
struct dso *dso = al->map->dso;
|
struct dso *dso = al->map->dso;
|
||||||
|
|
||||||
err = db_export__dso(dbe, dso, al->machine);
|
err = db_export__dso(dbe, dso, al->mg->machine);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
*dso_db_id = dso->db_id;
|
*dso_db_id = dso->db_id;
|
||||||
@ -249,9 +249,9 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
|
|||||||
* constructing an addr_location struct and then passing it to
|
* constructing an addr_location struct and then passing it to
|
||||||
* db_ids_from_al() to perform the export.
|
* db_ids_from_al() to perform the export.
|
||||||
*/
|
*/
|
||||||
al.sym = node->sym;
|
al.sym = node->ms.sym;
|
||||||
al.map = node->map;
|
al.map = node->ms.map;
|
||||||
al.machine = machine;
|
al.mg = thread->mg;
|
||||||
al.addr = node->ip;
|
al.addr = node->ip;
|
||||||
|
|
||||||
if (al.map && !al.sym)
|
if (al.map && !al.sym)
|
||||||
@ -360,13 +360,13 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = db_export__machine(dbe, al->machine);
|
err = db_export__machine(dbe, al->mg->machine);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
main_thread = thread__main_thread(al->machine, thread);
|
main_thread = thread__main_thread(al->mg->machine, thread);
|
||||||
|
|
||||||
err = db_export__threads(dbe, thread, main_thread, al->machine, &comm);
|
err = db_export__threads(dbe, thread, main_thread, al->mg->machine, &comm);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
@ -380,7 +380,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
|
|||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
if (dbe->cpr) {
|
if (dbe->cpr) {
|
||||||
struct call_path *cp = call_path_from_sample(dbe, al->machine,
|
struct call_path *cp = call_path_from_sample(dbe, al->mg->machine,
|
||||||
thread, sample,
|
thread, sample,
|
||||||
evsel);
|
evsel);
|
||||||
if (cp) {
|
if (cp) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
|
|
||||||
int verbose;
|
int verbose;
|
||||||
|
int debug_peo_args;
|
||||||
bool dump_trace = false, quiet = false;
|
bool dump_trace = false, quiet = false;
|
||||||
int debug_ordered_events;
|
int debug_ordered_events;
|
||||||
static int redirect_to_stderr;
|
static int redirect_to_stderr;
|
||||||
@ -180,6 +181,7 @@ static struct debug_variable {
|
|||||||
{ .name = "ordered-events", .ptr = &debug_ordered_events},
|
{ .name = "ordered-events", .ptr = &debug_ordered_events},
|
||||||
{ .name = "stderr", .ptr = &redirect_to_stderr},
|
{ .name = "stderr", .ptr = &redirect_to_stderr},
|
||||||
{ .name = "data-convert", .ptr = &debug_data_convert },
|
{ .name = "data-convert", .ptr = &debug_data_convert },
|
||||||
|
{ .name = "perf-event-open", .ptr = &debug_peo_args },
|
||||||
{ .name = NULL, }
|
{ .name = NULL, }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
extern int verbose;
|
extern int verbose;
|
||||||
|
extern int debug_peo_args;
|
||||||
extern bool quiet, dump_trace;
|
extern bool quiet, dump_trace;
|
||||||
extern int debug_ordered_events;
|
extern int debug_ordered_events;
|
||||||
extern int debug_data_convert;
|
extern int debug_data_convert;
|
||||||
@ -30,6 +31,14 @@ extern int debug_data_convert;
|
|||||||
#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
|
#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
|
||||||
#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
|
#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Special macro to print perf_event_open arguments/return value. */
|
||||||
|
#define pr_debug2_peo(fmt, ...) { \
|
||||||
|
if (debug_peo_args) \
|
||||||
|
pr_debugN(0, pr_fmt(fmt), ##__VA_ARGS__); \
|
||||||
|
else \
|
||||||
|
pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
#define pr_time_N(n, var, t, fmt, ...) \
|
#define pr_time_N(n, var, t, fmt, ...) \
|
||||||
eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
|
eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
|||||||
struct machine *machine = mg->machine;
|
struct machine *machine = mg->machine;
|
||||||
bool load_map = false;
|
bool load_map = false;
|
||||||
|
|
||||||
al->machine = machine;
|
al->mg = mg;
|
||||||
al->thread = thread;
|
al->thread = thread;
|
||||||
al->addr = addr;
|
al->addr = addr;
|
||||||
al->cpumode = cpumode;
|
al->cpumode = cpumode;
|
||||||
@ -474,13 +474,13 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
|||||||
|
|
||||||
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
|
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
|
||||||
al->level = 'k';
|
al->level = 'k';
|
||||||
mg = &machine->kmaps;
|
al->mg = mg = &machine->kmaps;
|
||||||
load_map = true;
|
load_map = true;
|
||||||
} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
|
} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
|
||||||
al->level = '.';
|
al->level = '.';
|
||||||
} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
|
} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
|
||||||
al->level = 'g';
|
al->level = 'g';
|
||||||
mg = &machine->kmaps;
|
al->mg = mg = &machine->kmaps;
|
||||||
load_map = true;
|
load_map = true;
|
||||||
} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
|
} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
|
||||||
al->level = 'u';
|
al->level = 'u';
|
||||||
|
@ -1524,7 +1524,7 @@ static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
|
|||||||
|
|
||||||
static void display_attr(struct perf_event_attr *attr)
|
static void display_attr(struct perf_event_attr *attr)
|
||||||
{
|
{
|
||||||
if (verbose >= 2) {
|
if (verbose >= 2 || debug_peo_args) {
|
||||||
fprintf(stderr, "%.60s\n", graph_dotted_line);
|
fprintf(stderr, "%.60s\n", graph_dotted_line);
|
||||||
fprintf(stderr, "perf_event_attr:\n");
|
fprintf(stderr, "perf_event_attr:\n");
|
||||||
perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL);
|
perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL);
|
||||||
@ -1540,7 +1540,7 @@ static int perf_event_open(struct evsel *evsel,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
|
pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
|
||||||
pid, cpu, group_fd, flags);
|
pid, cpu, group_fd, flags);
|
||||||
|
|
||||||
fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags);
|
fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags);
|
||||||
@ -1560,9 +1560,9 @@ static int perf_event_open(struct evsel *evsel,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug2("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
|
pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
|
||||||
evsel->core.attr.precise_ip--;
|
evsel->core.attr.precise_ip--;
|
||||||
pr_debug2("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
|
pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
|
||||||
display_attr(&evsel->core.attr);
|
display_attr(&evsel->core.attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1681,12 +1681,12 @@ retry_open:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug2("\nsys_perf_event_open failed, error %d\n",
|
pr_debug2_peo("\nsys_perf_event_open failed, error %d\n",
|
||||||
err);
|
err);
|
||||||
goto try_fallback;
|
goto try_fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug2(" = %d\n", fd);
|
pr_debug2_peo(" = %d\n", fd);
|
||||||
|
|
||||||
if (evsel->bpf_fd >= 0) {
|
if (evsel->bpf_fd >= 0) {
|
||||||
int evt_fd = fd;
|
int evt_fd = fd;
|
||||||
@ -1754,58 +1754,58 @@ try_fallback:
|
|||||||
*/
|
*/
|
||||||
if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
|
if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
|
||||||
perf_missing_features.aux_output = true;
|
perf_missing_features.aux_output = true;
|
||||||
pr_debug2("Kernel has no attr.aux_output support, bailing out\n");
|
pr_debug2_peo("Kernel has no attr.aux_output support, bailing out\n");
|
||||||
goto out_close;
|
goto out_close;
|
||||||
} else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) {
|
} else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) {
|
||||||
perf_missing_features.bpf = true;
|
perf_missing_features.bpf = true;
|
||||||
pr_debug2("switching off bpf_event\n");
|
pr_debug2_peo("switching off bpf_event\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) {
|
} else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) {
|
||||||
perf_missing_features.ksymbol = true;
|
perf_missing_features.ksymbol = true;
|
||||||
pr_debug2("switching off ksymbol\n");
|
pr_debug2_peo("switching off ksymbol\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) {
|
} else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) {
|
||||||
perf_missing_features.write_backward = true;
|
perf_missing_features.write_backward = true;
|
||||||
pr_debug2("switching off write_backward\n");
|
pr_debug2_peo("switching off write_backward\n");
|
||||||
goto out_close;
|
goto out_close;
|
||||||
} else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) {
|
} else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) {
|
||||||
perf_missing_features.clockid_wrong = true;
|
perf_missing_features.clockid_wrong = true;
|
||||||
pr_debug2("switching off clockid\n");
|
pr_debug2_peo("switching off clockid\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) {
|
} else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) {
|
||||||
perf_missing_features.clockid = true;
|
perf_missing_features.clockid = true;
|
||||||
pr_debug2("switching off use_clockid\n");
|
pr_debug2_peo("switching off use_clockid\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
|
} else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
|
||||||
perf_missing_features.cloexec = true;
|
perf_missing_features.cloexec = true;
|
||||||
pr_debug2("switching off cloexec flag\n");
|
pr_debug2_peo("switching off cloexec flag\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) {
|
} else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) {
|
||||||
perf_missing_features.mmap2 = true;
|
perf_missing_features.mmap2 = true;
|
||||||
pr_debug2("switching off mmap2\n");
|
pr_debug2_peo("switching off mmap2\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.exclude_guest &&
|
} else if (!perf_missing_features.exclude_guest &&
|
||||||
(evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
|
(evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
|
||||||
perf_missing_features.exclude_guest = true;
|
perf_missing_features.exclude_guest = true;
|
||||||
pr_debug2("switching off exclude_guest, exclude_host\n");
|
pr_debug2_peo("switching off exclude_guest, exclude_host\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.sample_id_all) {
|
} else if (!perf_missing_features.sample_id_all) {
|
||||||
perf_missing_features.sample_id_all = true;
|
perf_missing_features.sample_id_all = true;
|
||||||
pr_debug2("switching off sample_id_all\n");
|
pr_debug2_peo("switching off sample_id_all\n");
|
||||||
goto retry_sample_id;
|
goto retry_sample_id;
|
||||||
} else if (!perf_missing_features.lbr_flags &&
|
} else if (!perf_missing_features.lbr_flags &&
|
||||||
(evsel->core.attr.branch_sample_type &
|
(evsel->core.attr.branch_sample_type &
|
||||||
(PERF_SAMPLE_BRANCH_NO_CYCLES |
|
(PERF_SAMPLE_BRANCH_NO_CYCLES |
|
||||||
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
|
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
|
||||||
perf_missing_features.lbr_flags = true;
|
perf_missing_features.lbr_flags = true;
|
||||||
pr_debug2("switching off branch sample type no (cycles/flags)\n");
|
pr_debug2_peo("switching off branch sample type no (cycles/flags)\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
} else if (!perf_missing_features.group_read &&
|
} else if (!perf_missing_features.group_read &&
|
||||||
evsel->core.attr.inherit &&
|
evsel->core.attr.inherit &&
|
||||||
(evsel->core.attr.read_format & PERF_FORMAT_GROUP) &&
|
(evsel->core.attr.read_format & PERF_FORMAT_GROUP) &&
|
||||||
perf_evsel__is_group_leader(evsel)) {
|
perf_evsel__is_group_leader(evsel)) {
|
||||||
perf_missing_features.group_read = true;
|
perf_missing_features.group_read = true;
|
||||||
pr_debug2("switching off group read\n");
|
pr_debug2_peo("switching off group read\n");
|
||||||
goto fallback_missing_features;
|
goto fallback_missing_features;
|
||||||
}
|
}
|
||||||
out_close:
|
out_close:
|
||||||
|
@ -125,13 +125,18 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
|
|||||||
callchain_cursor_commit(cursor);
|
callchain_cursor_commit(cursor);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
struct symbol *sym;
|
||||||
|
struct map *map;
|
||||||
u64 addr = 0;
|
u64 addr = 0;
|
||||||
|
|
||||||
node = callchain_cursor_current(cursor);
|
node = callchain_cursor_current(cursor);
|
||||||
if (!node)
|
if (!node)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (node->sym && node->sym->ignore && print_skip_ignored)
|
sym = node->ms.sym;
|
||||||
|
map = node->ms.map;
|
||||||
|
|
||||||
|
if (sym && sym->ignore && print_skip_ignored)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
|
printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
|
||||||
@ -142,42 +147,42 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
|
|||||||
if (print_ip)
|
if (print_ip)
|
||||||
printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
|
printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
|
||||||
|
|
||||||
if (node->map)
|
if (map)
|
||||||
addr = node->map->map_ip(node->map, node->ip);
|
addr = map->map_ip(map, node->ip);
|
||||||
|
|
||||||
if (print_sym) {
|
if (print_sym) {
|
||||||
printed += fprintf(fp, " ");
|
printed += fprintf(fp, " ");
|
||||||
node_al.addr = addr;
|
node_al.addr = addr;
|
||||||
node_al.map = node->map;
|
node_al.map = map;
|
||||||
|
|
||||||
if (print_symoffset) {
|
if (print_symoffset) {
|
||||||
printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
|
printed += __symbol__fprintf_symname_offs(sym, &node_al,
|
||||||
print_unknown_as_addr,
|
print_unknown_as_addr,
|
||||||
true, fp);
|
true, fp);
|
||||||
} else {
|
} else {
|
||||||
printed += __symbol__fprintf_symname(node->sym, &node_al,
|
printed += __symbol__fprintf_symname(sym, &node_al,
|
||||||
print_unknown_as_addr, fp);
|
print_unknown_as_addr, fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_dso && (!node->sym || !node->sym->inlined)) {
|
if (print_dso && (!sym || !sym->inlined)) {
|
||||||
printed += fprintf(fp, " (");
|
printed += fprintf(fp, " (");
|
||||||
printed += map__fprintf_dsoname(node->map, fp);
|
printed += map__fprintf_dsoname(map, fp);
|
||||||
printed += fprintf(fp, ")");
|
printed += fprintf(fp, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_srcline)
|
if (print_srcline)
|
||||||
printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
|
printed += map__fprintf_srcline(map, addr, "\n ", fp);
|
||||||
|
|
||||||
if (node->sym && node->sym->inlined)
|
if (sym && sym->inlined)
|
||||||
printed += fprintf(fp, " (inlined)");
|
printed += fprintf(fp, " (inlined)");
|
||||||
|
|
||||||
if (!print_oneline)
|
if (!print_oneline)
|
||||||
printed += fprintf(fp, "\n");
|
printed += fprintf(fp, "\n");
|
||||||
|
|
||||||
/* Add srccode here too? */
|
/* Add srccode here too? */
|
||||||
if (bt_stop_list && node->sym &&
|
if (bt_stop_list && sym &&
|
||||||
strlist__has_entry(bt_stop_list, node->sym->name)) {
|
strlist__has_entry(bt_stop_list, sym->name)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,13 +112,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||||||
hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);
|
hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);
|
||||||
|
|
||||||
if (h->branch_info) {
|
if (h->branch_info) {
|
||||||
if (h->branch_info->from.sym) {
|
if (h->branch_info->from.ms.sym) {
|
||||||
symlen = (int)h->branch_info->from.sym->namelen + 4;
|
symlen = (int)h->branch_info->from.ms.sym->namelen + 4;
|
||||||
if (verbose > 0)
|
if (verbose > 0)
|
||||||
symlen += BITS_PER_LONG / 4 + 2 + 3;
|
symlen += BITS_PER_LONG / 4 + 2 + 3;
|
||||||
hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
|
hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
|
||||||
|
|
||||||
symlen = dso__name_len(h->branch_info->from.map->dso);
|
symlen = dso__name_len(h->branch_info->from.ms.map->dso);
|
||||||
hists__new_col_len(hists, HISTC_DSO_FROM, symlen);
|
hists__new_col_len(hists, HISTC_DSO_FROM, symlen);
|
||||||
} else {
|
} else {
|
||||||
symlen = unresolved_col_width + 4 + 2;
|
symlen = unresolved_col_width + 4 + 2;
|
||||||
@ -126,13 +126,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||||||
hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM);
|
hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->branch_info->to.sym) {
|
if (h->branch_info->to.ms.sym) {
|
||||||
symlen = (int)h->branch_info->to.sym->namelen + 4;
|
symlen = (int)h->branch_info->to.ms.sym->namelen + 4;
|
||||||
if (verbose > 0)
|
if (verbose > 0)
|
||||||
symlen += BITS_PER_LONG / 4 + 2 + 3;
|
symlen += BITS_PER_LONG / 4 + 2 + 3;
|
||||||
hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
|
hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
|
||||||
|
|
||||||
symlen = dso__name_len(h->branch_info->to.map->dso);
|
symlen = dso__name_len(h->branch_info->to.ms.map->dso);
|
||||||
hists__new_col_len(hists, HISTC_DSO_TO, symlen);
|
hists__new_col_len(hists, HISTC_DSO_TO, symlen);
|
||||||
} else {
|
} else {
|
||||||
symlen = unresolved_col_width + 4 + 2;
|
symlen = unresolved_col_width + 4 + 2;
|
||||||
@ -149,8 +149,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (h->mem_info) {
|
if (h->mem_info) {
|
||||||
if (h->mem_info->daddr.sym) {
|
if (h->mem_info->daddr.ms.sym) {
|
||||||
symlen = (int)h->mem_info->daddr.sym->namelen + 4
|
symlen = (int)h->mem_info->daddr.ms.sym->namelen + 4
|
||||||
+ unresolved_col_width + 2;
|
+ unresolved_col_width + 2;
|
||||||
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
|
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
|
||||||
symlen);
|
symlen);
|
||||||
@ -164,8 +164,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||||||
symlen);
|
symlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->mem_info->iaddr.sym) {
|
if (h->mem_info->iaddr.ms.sym) {
|
||||||
symlen = (int)h->mem_info->iaddr.sym->namelen + 4
|
symlen = (int)h->mem_info->iaddr.ms.sym->namelen + 4
|
||||||
+ unresolved_col_width + 2;
|
+ unresolved_col_width + 2;
|
||||||
hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
|
hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
|
||||||
symlen);
|
symlen);
|
||||||
@ -175,8 +175,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||||||
symlen);
|
symlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->mem_info->daddr.map) {
|
if (h->mem_info->daddr.ms.map) {
|
||||||
symlen = dso__name_len(h->mem_info->daddr.map->dso);
|
symlen = dso__name_len(h->mem_info->daddr.ms.map->dso);
|
||||||
hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
|
hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
|
||||||
symlen);
|
symlen);
|
||||||
} else {
|
} else {
|
||||||
@ -443,13 +443,13 @@ static int hist_entry__init(struct hist_entry *he,
|
|||||||
memcpy(he->branch_info, template->branch_info,
|
memcpy(he->branch_info, template->branch_info,
|
||||||
sizeof(*he->branch_info));
|
sizeof(*he->branch_info));
|
||||||
|
|
||||||
map__get(he->branch_info->from.map);
|
map__get(he->branch_info->from.ms.map);
|
||||||
map__get(he->branch_info->to.map);
|
map__get(he->branch_info->to.ms.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
map__get(he->mem_info->iaddr.map);
|
map__get(he->mem_info->iaddr.ms.map);
|
||||||
map__get(he->mem_info->daddr.map);
|
map__get(he->mem_info->daddr.ms.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
|
if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
|
||||||
@ -492,13 +492,13 @@ err_rawdata:
|
|||||||
|
|
||||||
err_infos:
|
err_infos:
|
||||||
if (he->branch_info) {
|
if (he->branch_info) {
|
||||||
map__put(he->branch_info->from.map);
|
map__put(he->branch_info->from.ms.map);
|
||||||
map__put(he->branch_info->to.map);
|
map__put(he->branch_info->to.ms.map);
|
||||||
zfree(&he->branch_info);
|
zfree(&he->branch_info);
|
||||||
}
|
}
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
map__put(he->mem_info->iaddr.map);
|
map__put(he->mem_info->iaddr.ms.map);
|
||||||
map__put(he->mem_info->daddr.map);
|
map__put(he->mem_info->daddr.ms.map);
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
map__zput(he->ms.map);
|
map__zput(he->ms.map);
|
||||||
@ -692,6 +692,7 @@ __hists__add_entry(struct hists *hists,
|
|||||||
.ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0,
|
.ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0,
|
||||||
},
|
},
|
||||||
.ms = {
|
.ms = {
|
||||||
|
.mg = al->mg,
|
||||||
.map = al->map,
|
.map = al->map,
|
||||||
.sym = al->sym,
|
.sym = al->sym,
|
||||||
},
|
},
|
||||||
@ -759,6 +760,7 @@ struct hist_entry *hists__add_entry_block(struct hists *hists,
|
|||||||
.block_info = block_info,
|
.block_info = block_info,
|
||||||
.hists = hists,
|
.hists = hists,
|
||||||
.ms = {
|
.ms = {
|
||||||
|
.mg = al->mg,
|
||||||
.map = al->map,
|
.map = al->map,
|
||||||
.sym = al->sym,
|
.sym = al->sym,
|
||||||
},
|
},
|
||||||
@ -893,8 +895,9 @@ iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
|
|||||||
if (iter->curr >= iter->total)
|
if (iter->curr >= iter->total)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
al->map = bi[i].to.map;
|
al->mg = bi[i].to.ms.mg;
|
||||||
al->sym = bi[i].to.sym;
|
al->map = bi[i].to.ms.map;
|
||||||
|
al->sym = bi[i].to.ms.sym;
|
||||||
al->addr = bi[i].to.addr;
|
al->addr = bi[i].to.addr;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -912,7 +915,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
|
|||||||
|
|
||||||
bi = iter->priv;
|
bi = iter->priv;
|
||||||
|
|
||||||
if (iter->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
|
if (iter->hide_unresolved && !(bi[i].from.ms.sym && bi[i].to.ms.sym))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1069,6 +1072,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
|||||||
.comm = thread__comm(al->thread),
|
.comm = thread__comm(al->thread),
|
||||||
.ip = al->addr,
|
.ip = al->addr,
|
||||||
.ms = {
|
.ms = {
|
||||||
|
.mg = al->mg,
|
||||||
.map = al->map,
|
.map = al->map,
|
||||||
.sym = al->sym,
|
.sym = al->sym,
|
||||||
},
|
},
|
||||||
@ -1251,16 +1255,16 @@ void hist_entry__delete(struct hist_entry *he)
|
|||||||
map__zput(he->ms.map);
|
map__zput(he->ms.map);
|
||||||
|
|
||||||
if (he->branch_info) {
|
if (he->branch_info) {
|
||||||
map__zput(he->branch_info->from.map);
|
map__zput(he->branch_info->from.ms.map);
|
||||||
map__zput(he->branch_info->to.map);
|
map__zput(he->branch_info->to.ms.map);
|
||||||
free_srcline(he->branch_info->srcline_from);
|
free_srcline(he->branch_info->srcline_from);
|
||||||
free_srcline(he->branch_info->srcline_to);
|
free_srcline(he->branch_info->srcline_to);
|
||||||
zfree(&he->branch_info);
|
zfree(&he->branch_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
map__zput(he->mem_info->iaddr.map);
|
map__zput(he->mem_info->iaddr.ms.map);
|
||||||
map__zput(he->mem_info->daddr.map);
|
map__zput(he->mem_info->daddr.ms.map);
|
||||||
mem_info__zput(he->mem_info);
|
mem_info__zput(he->mem_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,8 +1968,9 @@ static void ip__resolve_ams(struct thread *thread,
|
|||||||
|
|
||||||
ams->addr = ip;
|
ams->addr = ip;
|
||||||
ams->al_addr = al.addr;
|
ams->al_addr = al.addr;
|
||||||
ams->sym = al.sym;
|
ams->ms.mg = al.mg;
|
||||||
ams->map = al.map;
|
ams->ms.sym = al.sym;
|
||||||
|
ams->ms.map = al.map;
|
||||||
ams->phys_addr = 0;
|
ams->phys_addr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1985,8 +1986,9 @@ static void ip__resolve_data(struct thread *thread,
|
|||||||
|
|
||||||
ams->addr = addr;
|
ams->addr = addr;
|
||||||
ams->al_addr = al.addr;
|
ams->al_addr = al.addr;
|
||||||
ams->sym = al.sym;
|
ams->ms.mg = al.mg;
|
||||||
ams->map = al.map;
|
ams->ms.sym = al.sym;
|
||||||
|
ams->ms.map = al.map;
|
||||||
ams->phys_addr = phys_addr;
|
ams->phys_addr = phys_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2006,8 +2008,9 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
|||||||
return mi;
|
return mi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip)
|
static char *callchain_srcline(struct map_symbol *ms, u64 ip)
|
||||||
{
|
{
|
||||||
|
struct map *map = ms->map;
|
||||||
char *srcline = NULL;
|
char *srcline = NULL;
|
||||||
|
|
||||||
if (!map || callchain_param.key == CCKEY_FUNCTION)
|
if (!map || callchain_param.key == CCKEY_FUNCTION)
|
||||||
@ -2019,7 +2022,7 @@ static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip)
|
|||||||
bool show_addr = callchain_param.key == CCKEY_ADDRESS;
|
bool show_addr = callchain_param.key == CCKEY_ADDRESS;
|
||||||
|
|
||||||
srcline = get_srcline(map->dso, map__rip_2objdump(map, ip),
|
srcline = get_srcline(map->dso, map__rip_2objdump(map, ip),
|
||||||
sym, show_sym, show_addr, ip);
|
ms->sym, show_sym, show_addr, ip);
|
||||||
srcline__tree_insert(&map->dso->srclines, ip, srcline);
|
srcline__tree_insert(&map->dso->srclines, ip, srcline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2042,6 +2045,7 @@ static int add_callchain_ip(struct thread *thread,
|
|||||||
struct iterations *iter,
|
struct iterations *iter,
|
||||||
u64 branch_from)
|
u64 branch_from)
|
||||||
{
|
{
|
||||||
|
struct map_symbol ms;
|
||||||
struct addr_location al;
|
struct addr_location al;
|
||||||
int nr_loop_iter = 0;
|
int nr_loop_iter = 0;
|
||||||
u64 iter_cycles = 0;
|
u64 iter_cycles = 0;
|
||||||
@ -2099,8 +2103,11 @@ static int add_callchain_ip(struct thread *thread,
|
|||||||
iter_cycles = iter->cycles;
|
iter_cycles = iter->cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
srcline = callchain_srcline(al.map, al.sym, al.addr);
|
ms.mg = al.mg;
|
||||||
return callchain_cursor_append(cursor, ip, al.map, al.sym,
|
ms.map = al.map;
|
||||||
|
ms.sym = al.sym;
|
||||||
|
srcline = callchain_srcline(&ms, al.addr);
|
||||||
|
return callchain_cursor_append(cursor, ip, &ms,
|
||||||
branch, flags, nr_loop_iter,
|
branch, flags, nr_loop_iter,
|
||||||
iter_cycles, branch_from, srcline);
|
iter_cycles, branch_from, srcline);
|
||||||
}
|
}
|
||||||
@ -2448,9 +2455,10 @@ check_calls:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int append_inlines(struct callchain_cursor *cursor,
|
static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip)
|
||||||
struct map *map, struct symbol *sym, u64 ip)
|
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
|
struct map *map = ms->map;
|
||||||
struct inline_node *inline_node;
|
struct inline_node *inline_node;
|
||||||
struct inline_list *ilist;
|
struct inline_list *ilist;
|
||||||
u64 addr;
|
u64 addr;
|
||||||
@ -2471,8 +2479,11 @@ static int append_inlines(struct callchain_cursor *cursor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(ilist, &inline_node->val, list) {
|
list_for_each_entry(ilist, &inline_node->val, list) {
|
||||||
ret = callchain_cursor_append(cursor, ip, map,
|
struct map_symbol ilist_ms = {
|
||||||
ilist->symbol, false,
|
.map = map,
|
||||||
|
.sym = ilist->symbol,
|
||||||
|
};
|
||||||
|
ret = callchain_cursor_append(cursor, ip, &ilist_ms, false,
|
||||||
NULL, 0, 0, 0, ilist->srcline);
|
NULL, 0, 0, 0, ilist->srcline);
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@ -2488,22 +2499,21 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
|
|||||||
const char *srcline = NULL;
|
const char *srcline = NULL;
|
||||||
u64 addr = entry->ip;
|
u64 addr = entry->ip;
|
||||||
|
|
||||||
if (symbol_conf.hide_unresolved && entry->sym == NULL)
|
if (symbol_conf.hide_unresolved && entry->ms.sym == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (append_inlines(cursor, entry->map, entry->sym, entry->ip) == 0)
|
if (append_inlines(cursor, &entry->ms, entry->ip) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert entry->ip from a virtual address to an offset in
|
* Convert entry->ip from a virtual address to an offset in
|
||||||
* its corresponding binary.
|
* its corresponding binary.
|
||||||
*/
|
*/
|
||||||
if (entry->map)
|
if (entry->ms.map)
|
||||||
addr = map__map_ip(entry->map, entry->ip);
|
addr = map__map_ip(entry->ms.map, entry->ip);
|
||||||
|
|
||||||
srcline = callchain_srcline(entry->map, entry->sym, addr);
|
srcline = callchain_srcline(&entry->ms, addr);
|
||||||
return callchain_cursor_append(cursor, entry->ip,
|
return callchain_cursor_append(cursor, entry->ip, &entry->ms,
|
||||||
entry->map, entry->sym,
|
|
||||||
false, NULL, 0, 0, 0, srcline);
|
false, NULL, 0, 0, 0, srcline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,6 @@ void map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
|
|||||||
map->map_ip = map__map_ip;
|
map->map_ip = map__map_ip;
|
||||||
map->unmap_ip = map__unmap_ip;
|
map->unmap_ip = map__unmap_ip;
|
||||||
RB_CLEAR_NODE(&map->rb_node);
|
RB_CLEAR_NODE(&map->rb_node);
|
||||||
map->groups = NULL;
|
|
||||||
map->erange_warned = false;
|
map->erange_warned = false;
|
||||||
refcount_set(&map->refcnt, 1);
|
refcount_set(&map->refcnt, 1);
|
||||||
}
|
}
|
||||||
@ -244,18 +243,11 @@ struct map *map__new2(u64 start, struct dso *dso)
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Use this and __map__is_kmodule() for map instances that are in
|
|
||||||
* machine->kmaps, and thus have map->groups->machine all properly set, to
|
|
||||||
* disambiguate between the kernel and modules.
|
|
||||||
*
|
|
||||||
* When the need arises, introduce map__is_{kernel,kmodule)() that
|
|
||||||
* checks (map->groups != NULL && map->groups->machine != NULL &&
|
|
||||||
* map->dso->kernel) before calling __map__is_{kernel,kmodule}())
|
|
||||||
*/
|
|
||||||
bool __map__is_kernel(const struct map *map)
|
bool __map__is_kernel(const struct map *map)
|
||||||
{
|
{
|
||||||
return machine__kernel_map(map->groups->machine) == map;
|
if (!map->dso->kernel)
|
||||||
|
return false;
|
||||||
|
return machine__kernel_map(map__kmaps((struct map *)map)->machine) == map;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __map__is_extra_kernel_map(const struct map *map)
|
bool __map__is_extra_kernel_map(const struct map *map)
|
||||||
@ -395,7 +387,6 @@ struct map *map__clone(struct map *from)
|
|||||||
refcount_set(&map->refcnt, 1);
|
refcount_set(&map->refcnt, 1);
|
||||||
RB_CLEAR_NODE(&map->rb_node);
|
RB_CLEAR_NODE(&map->rb_node);
|
||||||
dso__get(map->dso);
|
dso__get(map->dso);
|
||||||
map->groups = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
@ -589,7 +580,6 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
|
|||||||
void map_groups__insert(struct map_groups *mg, struct map *map)
|
void map_groups__insert(struct map_groups *mg, struct map *map)
|
||||||
{
|
{
|
||||||
maps__insert(&mg->maps, map);
|
maps__insert(&mg->maps, map);
|
||||||
map->groups = mg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __maps__purge(struct maps *maps)
|
static void __maps__purge(struct maps *maps)
|
||||||
@ -710,20 +700,20 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
|
|||||||
return maps__find_symbol_by_name(&mg->maps, name, mapp);
|
return maps__find_symbol_by_name(&mg->maps, name, mapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int map_groups__find_ams(struct addr_map_symbol *ams)
|
int map_groups__find_ams(struct map_groups *mg, struct addr_map_symbol *ams)
|
||||||
{
|
{
|
||||||
if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
|
if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
|
||||||
if (ams->map->groups == NULL)
|
if (mg == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
ams->map = map_groups__find(ams->map->groups, ams->addr);
|
ams->ms.map = map_groups__find(mg, ams->addr);
|
||||||
if (ams->map == NULL)
|
if (ams->ms.map == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
|
ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
|
||||||
ams->sym = map__find_symbol(ams->map, ams->al_addr);
|
ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
|
||||||
|
|
||||||
return ams->sym ? 0 : -1;
|
return ams->ms.sym ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t maps__fprintf(struct maps *maps, FILE *fp)
|
static size_t maps__fprintf(struct maps *maps, FILE *fp)
|
||||||
@ -756,11 +746,11 @@ static void __map_groups__insert(struct map_groups *mg, struct map *map)
|
|||||||
{
|
{
|
||||||
__maps__insert(&mg->maps, map);
|
__maps__insert(&mg->maps, map);
|
||||||
__maps__insert_name(&mg->maps, map);
|
__maps__insert_name(&mg->maps, map);
|
||||||
map->groups = mg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
|
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE *fp)
|
||||||
{
|
{
|
||||||
|
struct maps *maps = &mg->maps;
|
||||||
struct rb_root *root;
|
struct rb_root *root;
|
||||||
struct rb_node *next, *first;
|
struct rb_node *next, *first;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@ -825,7 +815,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
|
|||||||
}
|
}
|
||||||
|
|
||||||
before->end = map->start;
|
before->end = map->start;
|
||||||
__map_groups__insert(pos->groups, before);
|
__map_groups__insert(mg, before);
|
||||||
if (verbose >= 2 && !use_browser)
|
if (verbose >= 2 && !use_browser)
|
||||||
map__fprintf(before, fp);
|
map__fprintf(before, fp);
|
||||||
map__put(before);
|
map__put(before);
|
||||||
@ -842,7 +832,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
|
|||||||
after->start = map->end;
|
after->start = map->end;
|
||||||
after->pgoff += map->end - pos->start;
|
after->pgoff += map->end - pos->start;
|
||||||
assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
|
assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
|
||||||
__map_groups__insert(pos->groups, after);
|
__map_groups__insert(mg, after);
|
||||||
if (verbose >= 2 && !use_browser)
|
if (verbose >= 2 && !use_browser)
|
||||||
map__fprintf(after, fp);
|
map__fprintf(after, fp);
|
||||||
map__put(after);
|
map__put(after);
|
||||||
@ -860,12 +850,6 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
|
|
||||||
FILE *fp)
|
|
||||||
{
|
|
||||||
return maps__fixup_overlappings(&mg->maps, map, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX This should not really _copy_ te maps, but refcount them.
|
* XXX This should not really _copy_ te maps, but refcount them.
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +42,6 @@ struct map {
|
|||||||
u64 (*unmap_ip)(struct map *, u64);
|
u64 (*unmap_ip)(struct map *, u64);
|
||||||
|
|
||||||
struct dso *dso;
|
struct dso *dso;
|
||||||
struct map_groups *groups;
|
|
||||||
refcount_t refcnt;
|
refcount_t refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, const char
|
|||||||
|
|
||||||
struct addr_map_symbol;
|
struct addr_map_symbol;
|
||||||
|
|
||||||
int map_groups__find_ams(struct addr_map_symbol *ams);
|
int map_groups__find_ams(struct map_groups *mg, struct addr_map_symbol *ams);
|
||||||
|
|
||||||
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE *fp);
|
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE *fp);
|
||||||
|
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
struct map_groups;
|
||||||
struct map;
|
struct map;
|
||||||
struct symbol;
|
struct symbol;
|
||||||
|
|
||||||
struct map_symbol {
|
struct map_symbol {
|
||||||
|
struct map_groups *mg;
|
||||||
struct map *map;
|
struct map *map;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct addr_map_symbol {
|
struct addr_map_symbol {
|
||||||
struct map *map;
|
struct map_symbol ms;
|
||||||
struct symbol *sym;
|
|
||||||
u64 addr;
|
u64 addr;
|
||||||
u64 al_addr;
|
u64 al_addr;
|
||||||
u64 phys_addr;
|
u64 phys_addr;
|
||||||
|
@ -410,7 +410,7 @@ do { \
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mi->daddr.map || !mi->iaddr.map) {
|
if (!mi->daddr.ms.map || !mi->iaddr.ms.map) {
|
||||||
stats->nomap++;
|
stats->nomap++;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,7 @@ PE_NAME opt_pmu_config
|
|||||||
do { \
|
do { \
|
||||||
parse_events_terms__delete($2); \
|
parse_events_terms__delete($2); \
|
||||||
parse_events_terms__delete(orig_terms); \
|
parse_events_terms__delete(orig_terms); \
|
||||||
|
free(list); \
|
||||||
free($1); \
|
free($1); \
|
||||||
free(pattern); \
|
free(pattern); \
|
||||||
YYABORT; \
|
YYABORT; \
|
||||||
@ -550,7 +551,7 @@ tracepoint_name opt_event_config
|
|||||||
free($1.event);
|
free($1.event);
|
||||||
if (err) {
|
if (err) {
|
||||||
free(list);
|
free(list);
|
||||||
return -1;
|
YYABORT;
|
||||||
}
|
}
|
||||||
$$ = list;
|
$$ = list;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ struct perf_env perf_env;
|
|||||||
* implementing 'verbose' and 'eprintf'.
|
* implementing 'verbose' and 'eprintf'.
|
||||||
*/
|
*/
|
||||||
int verbose;
|
int verbose;
|
||||||
|
int debug_peo_args;
|
||||||
|
|
||||||
int eprintf(int level, int var, const char *fmt, ...);
|
int eprintf(int level, int var, const char *fmt, ...);
|
||||||
|
|
||||||
|
@ -294,17 +294,17 @@ static SV *perl_process_callchain(struct perf_sample *sample,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->sym) {
|
if (node->ms.sym) {
|
||||||
HV *sym = newHV();
|
HV *sym = newHV();
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
hv_undef(elem);
|
hv_undef(elem);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
|
if (!hv_stores(sym, "start", newSVuv(node->ms.sym->start)) ||
|
||||||
!hv_stores(sym, "end", newSVuv(node->sym->end)) ||
|
!hv_stores(sym, "end", newSVuv(node->ms.sym->end)) ||
|
||||||
!hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
|
!hv_stores(sym, "binding", newSVuv(node->ms.sym->binding)) ||
|
||||||
!hv_stores(sym, "name", newSVpvn(node->sym->name,
|
!hv_stores(sym, "name", newSVpvn(node->ms.sym->name,
|
||||||
node->sym->namelen)) ||
|
node->ms.sym->namelen)) ||
|
||||||
!hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
|
!hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
|
||||||
hv_undef(sym);
|
hv_undef(sym);
|
||||||
hv_undef(elem);
|
hv_undef(elem);
|
||||||
@ -312,8 +312,8 @@ static SV *perl_process_callchain(struct perf_sample *sample,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->map) {
|
if (node->ms.map) {
|
||||||
struct map *map = node->map;
|
struct map *map = node->ms.map;
|
||||||
const char *dsoname = "[unknown]";
|
const char *dsoname = "[unknown]";
|
||||||
if (map && map->dso) {
|
if (map && map->dso) {
|
||||||
if (symbol_conf.show_kernel_path && map->dso->long_name)
|
if (symbol_conf.show_kernel_path && map->dso->long_name)
|
||||||
|
@ -428,24 +428,24 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
|
|||||||
pydict_set_item_string_decref(pyelem, "ip",
|
pydict_set_item_string_decref(pyelem, "ip",
|
||||||
PyLong_FromUnsignedLongLong(node->ip));
|
PyLong_FromUnsignedLongLong(node->ip));
|
||||||
|
|
||||||
if (node->sym) {
|
if (node->ms.sym) {
|
||||||
PyObject *pysym = PyDict_New();
|
PyObject *pysym = PyDict_New();
|
||||||
if (!pysym)
|
if (!pysym)
|
||||||
Py_FatalError("couldn't create Python dictionary");
|
Py_FatalError("couldn't create Python dictionary");
|
||||||
pydict_set_item_string_decref(pysym, "start",
|
pydict_set_item_string_decref(pysym, "start",
|
||||||
PyLong_FromUnsignedLongLong(node->sym->start));
|
PyLong_FromUnsignedLongLong(node->ms.sym->start));
|
||||||
pydict_set_item_string_decref(pysym, "end",
|
pydict_set_item_string_decref(pysym, "end",
|
||||||
PyLong_FromUnsignedLongLong(node->sym->end));
|
PyLong_FromUnsignedLongLong(node->ms.sym->end));
|
||||||
pydict_set_item_string_decref(pysym, "binding",
|
pydict_set_item_string_decref(pysym, "binding",
|
||||||
_PyLong_FromLong(node->sym->binding));
|
_PyLong_FromLong(node->ms.sym->binding));
|
||||||
pydict_set_item_string_decref(pysym, "name",
|
pydict_set_item_string_decref(pysym, "name",
|
||||||
_PyUnicode_FromStringAndSize(node->sym->name,
|
_PyUnicode_FromStringAndSize(node->ms.sym->name,
|
||||||
node->sym->namelen));
|
node->ms.sym->namelen));
|
||||||
pydict_set_item_string_decref(pyelem, "sym", pysym);
|
pydict_set_item_string_decref(pyelem, "sym", pysym);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->map) {
|
if (node->ms.map) {
|
||||||
const char *dsoname = get_dsoname(node->map);
|
const char *dsoname = get_dsoname(node->ms.map);
|
||||||
|
|
||||||
pydict_set_item_string_decref(pyelem, "dso",
|
pydict_set_item_string_decref(pyelem, "dso",
|
||||||
_PyUnicode_FromString(dsoname));
|
_PyUnicode_FromString(dsoname));
|
||||||
@ -1127,7 +1127,7 @@ static void python_export_sample_table(struct db_export *dbe,
|
|||||||
|
|
||||||
tuple_set_u64(t, 0, es->db_id);
|
tuple_set_u64(t, 0, es->db_id);
|
||||||
tuple_set_u64(t, 1, es->evsel->db_id);
|
tuple_set_u64(t, 1, es->evsel->db_id);
|
||||||
tuple_set_u64(t, 2, es->al->machine->db_id);
|
tuple_set_u64(t, 2, es->al->mg->machine->db_id);
|
||||||
tuple_set_u64(t, 3, es->al->thread->db_id);
|
tuple_set_u64(t, 3, es->al->thread->db_id);
|
||||||
tuple_set_u64(t, 4, es->comm_db_id);
|
tuple_set_u64(t, 4, es->comm_db_id);
|
||||||
tuple_set_u64(t, 5, es->dso_db_id);
|
tuple_set_u64(t, 5, es->dso_db_id);
|
||||||
|
@ -287,10 +287,12 @@ sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
|
|||||||
return strcmp(right->ms.sym->name, left->ms.sym->name);
|
return strcmp(right->ms.sym->name, left->ms.sym->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
|
static int _hist_entry__sym_snprintf(struct map_symbol *ms,
|
||||||
u64 ip, char level, char *bf, size_t size,
|
u64 ip, char level, char *bf, size_t size,
|
||||||
unsigned int width)
|
unsigned int width)
|
||||||
{
|
{
|
||||||
|
struct symbol *sym = ms->sym;
|
||||||
|
struct map *map = ms->map;
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
|
|
||||||
if (verbose > 0) {
|
if (verbose > 0) {
|
||||||
@ -325,7 +327,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
|
|||||||
static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
|
static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
|
||||||
size_t size, unsigned int width)
|
size_t size, unsigned int width)
|
||||||
{
|
{
|
||||||
return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
|
return _hist_entry__sym_snprintf(&he->ms, he->ip,
|
||||||
he->level, bf, size, width);
|
he->level, bf, size, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +388,7 @@ struct sort_entry sort_srcline = {
|
|||||||
|
|
||||||
static char *addr_map_symbol__srcline(struct addr_map_symbol *ams)
|
static char *addr_map_symbol__srcline(struct addr_map_symbol *ams)
|
||||||
{
|
{
|
||||||
return map__srcline(ams->map, ams->al_addr, ams->sym);
|
return map__srcline(ams->ms.map, ams->al_addr, ams->ms.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -769,15 +771,15 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
if (!left->branch_info || !right->branch_info)
|
if (!left->branch_info || !right->branch_info)
|
||||||
return cmp_null(left->branch_info, right->branch_info);
|
return cmp_null(left->branch_info, right->branch_info);
|
||||||
|
|
||||||
return _sort__dso_cmp(left->branch_info->from.map,
|
return _sort__dso_cmp(left->branch_info->from.ms.map,
|
||||||
right->branch_info->from.map);
|
right->branch_info->from.ms.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
|
static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
|
||||||
size_t size, unsigned int width)
|
size_t size, unsigned int width)
|
||||||
{
|
{
|
||||||
if (he->branch_info)
|
if (he->branch_info)
|
||||||
return _hist_entry__dso_snprintf(he->branch_info->from.map,
|
return _hist_entry__dso_snprintf(he->branch_info->from.ms.map,
|
||||||
bf, size, width);
|
bf, size, width);
|
||||||
else
|
else
|
||||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
||||||
@ -791,8 +793,8 @@ static int hist_entry__dso_from_filter(struct hist_entry *he, int type,
|
|||||||
if (type != HIST_FILTER__DSO)
|
if (type != HIST_FILTER__DSO)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return dso && (!he->branch_info || !he->branch_info->from.map ||
|
return dso && (!he->branch_info || !he->branch_info->from.ms.map ||
|
||||||
he->branch_info->from.map->dso != dso);
|
he->branch_info->from.ms.map->dso != dso);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -801,15 +803,15 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
if (!left->branch_info || !right->branch_info)
|
if (!left->branch_info || !right->branch_info)
|
||||||
return cmp_null(left->branch_info, right->branch_info);
|
return cmp_null(left->branch_info, right->branch_info);
|
||||||
|
|
||||||
return _sort__dso_cmp(left->branch_info->to.map,
|
return _sort__dso_cmp(left->branch_info->to.ms.map,
|
||||||
right->branch_info->to.map);
|
right->branch_info->to.ms.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
|
static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
|
||||||
size_t size, unsigned int width)
|
size_t size, unsigned int width)
|
||||||
{
|
{
|
||||||
if (he->branch_info)
|
if (he->branch_info)
|
||||||
return _hist_entry__dso_snprintf(he->branch_info->to.map,
|
return _hist_entry__dso_snprintf(he->branch_info->to.ms.map,
|
||||||
bf, size, width);
|
bf, size, width);
|
||||||
else
|
else
|
||||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
||||||
@ -823,8 +825,8 @@ static int hist_entry__dso_to_filter(struct hist_entry *he, int type,
|
|||||||
if (type != HIST_FILTER__DSO)
|
if (type != HIST_FILTER__DSO)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return dso && (!he->branch_info || !he->branch_info->to.map ||
|
return dso && (!he->branch_info || !he->branch_info->to.ms.map ||
|
||||||
he->branch_info->to.map->dso != dso);
|
he->branch_info->to.ms.map->dso != dso);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -839,10 +841,10 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
from_l = &left->branch_info->from;
|
from_l = &left->branch_info->from;
|
||||||
from_r = &right->branch_info->from;
|
from_r = &right->branch_info->from;
|
||||||
|
|
||||||
if (!from_l->sym && !from_r->sym)
|
if (!from_l->ms.sym && !from_r->ms.sym)
|
||||||
return _sort__addr_cmp(from_l->addr, from_r->addr);
|
return _sort__addr_cmp(from_l->addr, from_r->addr);
|
||||||
|
|
||||||
return _sort__sym_cmp(from_l->sym, from_r->sym);
|
return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -856,10 +858,10 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
to_l = &left->branch_info->to;
|
to_l = &left->branch_info->to;
|
||||||
to_r = &right->branch_info->to;
|
to_r = &right->branch_info->to;
|
||||||
|
|
||||||
if (!to_l->sym && !to_r->sym)
|
if (!to_l->ms.sym && !to_r->ms.sym)
|
||||||
return _sort__addr_cmp(to_l->addr, to_r->addr);
|
return _sort__addr_cmp(to_l->addr, to_r->addr);
|
||||||
|
|
||||||
return _sort__sym_cmp(to_l->sym, to_r->sym);
|
return _sort__sym_cmp(to_l->ms.sym, to_r->ms.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
|
static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
|
||||||
@ -868,8 +870,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
|
|||||||
if (he->branch_info) {
|
if (he->branch_info) {
|
||||||
struct addr_map_symbol *from = &he->branch_info->from;
|
struct addr_map_symbol *from = &he->branch_info->from;
|
||||||
|
|
||||||
return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
|
return _hist_entry__sym_snprintf(&from->ms, from->addr, he->level, bf, size, width);
|
||||||
he->level, bf, size, width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
||||||
@ -881,8 +882,7 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
|
|||||||
if (he->branch_info) {
|
if (he->branch_info) {
|
||||||
struct addr_map_symbol *to = &he->branch_info->to;
|
struct addr_map_symbol *to = &he->branch_info->to;
|
||||||
|
|
||||||
return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
|
return _hist_entry__sym_snprintf(&to->ms, to->addr, he->level, bf, size, width);
|
||||||
he->level, bf, size, width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
|
||||||
@ -896,8 +896,8 @@ static int hist_entry__sym_from_filter(struct hist_entry *he, int type,
|
|||||||
if (type != HIST_FILTER__SYMBOL)
|
if (type != HIST_FILTER__SYMBOL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return sym && !(he->branch_info && he->branch_info->from.sym &&
|
return sym && !(he->branch_info && he->branch_info->from.ms.sym &&
|
||||||
strstr(he->branch_info->from.sym->name, sym));
|
strstr(he->branch_info->from.ms.sym->name, sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
|
static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
|
||||||
@ -908,8 +908,8 @@ static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
|
|||||||
if (type != HIST_FILTER__SYMBOL)
|
if (type != HIST_FILTER__SYMBOL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return sym && !(he->branch_info && he->branch_info->to.sym &&
|
return sym && !(he->branch_info && he->branch_info->to.ms.sym &&
|
||||||
strstr(he->branch_info->to.sym->name, sym));
|
strstr(he->branch_info->to.ms.sym->name, sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sort_entry sort_dso_from = {
|
struct sort_entry sort_dso_from = {
|
||||||
@ -1017,16 +1017,13 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
|
|||||||
size_t size, unsigned int width)
|
size_t size, unsigned int width)
|
||||||
{
|
{
|
||||||
uint64_t addr = 0;
|
uint64_t addr = 0;
|
||||||
struct map *map = NULL;
|
struct map_symbol *ms = NULL;
|
||||||
struct symbol *sym = NULL;
|
|
||||||
|
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
addr = he->mem_info->daddr.addr;
|
addr = he->mem_info->daddr.addr;
|
||||||
map = he->mem_info->daddr.map;
|
ms = &he->mem_info->daddr.ms;
|
||||||
sym = he->mem_info->daddr.sym;
|
|
||||||
}
|
}
|
||||||
return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
|
return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width);
|
||||||
width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
@ -1046,16 +1043,13 @@ static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
|
|||||||
size_t size, unsigned int width)
|
size_t size, unsigned int width)
|
||||||
{
|
{
|
||||||
uint64_t addr = 0;
|
uint64_t addr = 0;
|
||||||
struct map *map = NULL;
|
struct map_symbol *ms = NULL;
|
||||||
struct symbol *sym = NULL;
|
|
||||||
|
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
addr = he->mem_info->iaddr.addr;
|
addr = he->mem_info->iaddr.addr;
|
||||||
map = he->mem_info->iaddr.map;
|
ms = &he->mem_info->iaddr.ms;
|
||||||
sym = he->mem_info->iaddr.sym;
|
|
||||||
}
|
}
|
||||||
return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
|
return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width);
|
||||||
width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -1065,9 +1059,9 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
struct map *map_r = NULL;
|
struct map *map_r = NULL;
|
||||||
|
|
||||||
if (left->mem_info)
|
if (left->mem_info)
|
||||||
map_l = left->mem_info->daddr.map;
|
map_l = left->mem_info->daddr.ms.map;
|
||||||
if (right->mem_info)
|
if (right->mem_info)
|
||||||
map_r = right->mem_info->daddr.map;
|
map_r = right->mem_info->daddr.ms.map;
|
||||||
|
|
||||||
return _sort__dso_cmp(map_l, map_r);
|
return _sort__dso_cmp(map_l, map_r);
|
||||||
}
|
}
|
||||||
@ -1078,7 +1072,7 @@ static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
|
|||||||
struct map *map = NULL;
|
struct map *map = NULL;
|
||||||
|
|
||||||
if (he->mem_info)
|
if (he->mem_info)
|
||||||
map = he->mem_info->daddr.map;
|
map = he->mem_info->daddr.ms.map;
|
||||||
|
|
||||||
return _hist_entry__dso_snprintf(map, bf, size, width);
|
return _hist_entry__dso_snprintf(map, bf, size, width);
|
||||||
}
|
}
|
||||||
@ -1208,8 +1202,8 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||||||
if (left->cpumode > right->cpumode) return -1;
|
if (left->cpumode > right->cpumode) return -1;
|
||||||
if (left->cpumode < right->cpumode) return 1;
|
if (left->cpumode < right->cpumode) return 1;
|
||||||
|
|
||||||
l_map = left->mem_info->daddr.map;
|
l_map = left->mem_info->daddr.ms.map;
|
||||||
r_map = right->mem_info->daddr.map;
|
r_map = right->mem_info->daddr.ms.map;
|
||||||
|
|
||||||
/* if both are NULL, jump to sort on al_addr instead */
|
/* if both are NULL, jump to sort on al_addr instead */
|
||||||
if (!l_map && !r_map)
|
if (!l_map && !r_map)
|
||||||
@ -1264,14 +1258,14 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
|
|||||||
{
|
{
|
||||||
|
|
||||||
uint64_t addr = 0;
|
uint64_t addr = 0;
|
||||||
struct map *map = NULL;
|
struct map_symbol *ms = NULL;
|
||||||
struct symbol *sym = NULL;
|
|
||||||
char level = he->level;
|
char level = he->level;
|
||||||
|
|
||||||
if (he->mem_info) {
|
if (he->mem_info) {
|
||||||
|
struct map *map = he->mem_info->daddr.ms.map;
|
||||||
|
|
||||||
addr = cl_address(he->mem_info->daddr.al_addr);
|
addr = cl_address(he->mem_info->daddr.al_addr);
|
||||||
map = he->mem_info->daddr.map;
|
ms = &he->mem_info->daddr.ms;
|
||||||
sym = he->mem_info->daddr.sym;
|
|
||||||
|
|
||||||
/* print [s] for shared data mmaps */
|
/* print [s] for shared data mmaps */
|
||||||
if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
|
if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
|
||||||
@ -1283,8 +1277,7 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
|
|||||||
else if (!map)
|
else if (!map)
|
||||||
level = 'X';
|
level = 'X';
|
||||||
}
|
}
|
||||||
return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
|
return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width);
|
||||||
width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sort_entry sort_mispredict = {
|
struct sort_entry sort_mispredict = {
|
||||||
|
@ -934,7 +934,7 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
|
|||||||
* we still are sure to have a reference to this DSO via
|
* we still are sure to have a reference to this DSO via
|
||||||
* *curr_map->dso.
|
* *curr_map->dso.
|
||||||
*/
|
*/
|
||||||
dsos__add(&map->groups->machine->dsos, curr_dso);
|
dsos__add(&kmaps->machine->dsos, curr_dso);
|
||||||
/* kmaps already got it */
|
/* kmaps already got it */
|
||||||
map__put(curr_map);
|
map__put(curr_map);
|
||||||
dso__set_loaded(curr_dso);
|
dso__set_loaded(curr_dso);
|
||||||
|
@ -1588,7 +1588,7 @@ int dso__load(struct dso *dso, struct map *map)
|
|||||||
char *name;
|
char *name;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
u_int i;
|
u_int i;
|
||||||
struct machine *machine;
|
struct machine *machine = NULL;
|
||||||
char *root_dir = (char *) "";
|
char *root_dir = (char *) "";
|
||||||
int ss_pos = 0;
|
int ss_pos = 0;
|
||||||
struct symsrc ss_[2];
|
struct symsrc ss_[2];
|
||||||
@ -1617,17 +1617,13 @@ int dso__load(struct dso *dso, struct map *map)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map->groups)
|
|
||||||
machine = map->groups->machine;
|
|
||||||
else
|
|
||||||
machine = NULL;
|
|
||||||
|
|
||||||
if (dso->kernel) {
|
if (dso->kernel) {
|
||||||
if (dso->kernel == DSO_TYPE_KERNEL)
|
if (dso->kernel == DSO_TYPE_KERNEL)
|
||||||
ret = dso__load_kernel_sym(dso, map);
|
ret = dso__load_kernel_sym(dso, map);
|
||||||
else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
|
else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
|
||||||
ret = dso__load_guest_kernel_sym(dso, map);
|
ret = dso__load_guest_kernel_sym(dso, map);
|
||||||
|
|
||||||
|
machine = map__kmaps(map)->machine;
|
||||||
if (machine__is(machine, "x86_64"))
|
if (machine__is(machine, "x86_64"))
|
||||||
machine__map_x86_64_entry_trampolines(machine, dso);
|
machine__map_x86_64_entry_trampolines(machine, dso);
|
||||||
goto out;
|
goto out;
|
||||||
@ -2027,15 +2023,9 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
const char *kallsyms_filename = NULL;
|
const char *kallsyms_filename = NULL;
|
||||||
struct machine *machine;
|
struct machine *machine = map__kmaps(map)->machine;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
if (!map->groups) {
|
|
||||||
pr_debug("Guest kernel map hasn't the point to groups\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
machine = map->groups->machine;
|
|
||||||
|
|
||||||
if (machine__is_default_guest(machine)) {
|
if (machine__is_default_guest(machine)) {
|
||||||
/*
|
/*
|
||||||
* if the user specified a vmlinux filename, use it and only
|
* if the user specified a vmlinux filename, use it and only
|
||||||
|
@ -107,8 +107,8 @@ struct ref_reloc_sym {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct addr_location {
|
struct addr_location {
|
||||||
struct machine *machine;
|
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
|
struct map_groups *mg;
|
||||||
struct map *map;
|
struct map *map;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
const char *srcline;
|
const char *srcline;
|
||||||
|
@ -80,9 +80,10 @@ static int entry(u64 ip, struct unwind_info *ui)
|
|||||||
if (__report_module(&al, ip, ui))
|
if (__report_module(&al, ip, ui))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
e->ip = ip;
|
e->ip = ip;
|
||||||
e->map = al.map;
|
e->ms.mg = al.mg;
|
||||||
e->sym = al.sym;
|
e->ms.map = al.map;
|
||||||
|
e->ms.sym = al.sym;
|
||||||
|
|
||||||
pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
|
pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
|
||||||
al.sym ? al.sym->name : "''",
|
al.sym ? al.sym->name : "''",
|
||||||
|
@ -575,9 +575,10 @@ static int entry(u64 ip, struct thread *thread,
|
|||||||
struct unwind_entry e;
|
struct unwind_entry e;
|
||||||
struct addr_location al;
|
struct addr_location al;
|
||||||
|
|
||||||
e.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
|
e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
|
||||||
e.ip = ip;
|
e.ip = ip;
|
||||||
e.map = al.map;
|
e.ms.map = al.map;
|
||||||
|
e.ms.mg = al.mg;
|
||||||
|
|
||||||
pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
|
pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
|
||||||
al.sym ? al.sym->name : "''",
|
al.sym ? al.sym->name : "''",
|
||||||
|
@ -4,17 +4,15 @@
|
|||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include "util/map_symbol.h"
|
||||||
|
|
||||||
struct map;
|
|
||||||
struct map_groups;
|
struct map_groups;
|
||||||
struct perf_sample;
|
struct perf_sample;
|
||||||
struct symbol;
|
|
||||||
struct thread;
|
struct thread;
|
||||||
|
|
||||||
struct unwind_entry {
|
struct unwind_entry {
|
||||||
struct map *map;
|
struct map_symbol ms;
|
||||||
struct symbol *sym;
|
u64 ip;
|
||||||
u64 ip;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
|
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
|
||||||
|
Loading…
Reference in New Issue
Block a user