From de90d513b2464d28a17fc4eaada97f4ad742ba00 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:31:33 -0300 Subject: [PATCH 01/15] perf map: Use map->dso->kernel + map__kmaps() in map__kmaps() Its equivalent to using map->groups to obtain the machine struct. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-bdbazuj4ggrmzxdviaqdrdwh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/map.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 466c9b035e19..a4d889c0fa88 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -244,18 +244,11 @@ struct map *map__new2(u64 start, struct dso *dso) 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) { - 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) From f2baa060cd766f4e585339423891e0063179d702 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:09:48 -0300 Subject: [PATCH 02/15] perf symbols: Stop using map->groups, we can use kmaps instead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To test that that function is being called I just added a probe on that place, enabled it via 'perf trace' asking for at most 16 levels of backtraces, system wide, and then ran 'perf top' on another xterm, voilĂ : # perf probe -x ~/bin/perf dso__process_kernel_symbol Added new event: probe_perf:dso__process_kernel_symbol (on dso__process_kernel_symbol in /home/acme/bin/perf) You can now use it in all perf tools, such as: perf record -e probe_perf:dso__process_kernel_symbol -aR sleep 1 # perf trace -e probe_perf:dso__process_kernel_symbol/max-stack=16/ --max-events=2 # perf trace -e probe_perf:dso__process_kernel_symbol/max-stack=16/ --max-events=2 0.000 :17345/17345 probe_perf:dso__process_kernel_symbol(__probe_ip: 5680224) dso__process_kernel_symbol (/home/acme/bin/perf) dso__load_vmlinux (/home/acme/bin/perf) dso__load_vmlinux_path (/home/acme/bin/perf) dso__load (/home/acme/bin/perf) map__load (/home/acme/bin/perf) thread__find_map (/home/acme/bin/perf) machine__resolve (/home/acme/bin/perf) deliver_event (/home/acme/bin/perf) __ordered_events__flush.part.0 (/home/acme/bin/perf) process_thread (/home/acme/bin/perf) start_thread (/usr/lib64/libpthread-2.29.so) 0.064 :17345/17345 probe_perf:dso__process_kernel_symbol(__probe_ip: 5680224) dso__process_kernel_symbol (/home/acme/bin/perf) dso__load_vmlinux (/home/acme/bin/perf) dso__load_vmlinux_path (/home/acme/bin/perf) dso__load (/home/acme/bin/perf) map__load (/home/acme/bin/perf) thread__find_map (/home/acme/bin/perf) machine__resolve (/home/acme/bin/perf) deliver_event (/home/acme/bin/perf) __ordered_events__flush.part.0 (/home/acme/bin/perf) process_thread (/home/acme/bin/perf) start_thread (/usr/lib64/libpthread-2.29.so) # # perf stat -e probe_perf:dso__process_kernel_symbol ^C Performance counter stats for 'system wide': 107,308 probe_perf:dso__process_kernel_symbol 8.215399813 seconds time elapsed # Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-5fy66x5hr5ct9pmw84jkiwvm@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 66f4be1df573..16776d5fbaea 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -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 * *curr_map->dso. */ - dsos__add(&map->groups->machine->dsos, curr_dso); + dsos__add(&kmaps->machine->dsos, curr_dso); /* kmaps already got it */ map__put(curr_map); dso__set_loaded(curr_dso); From 9d355b381b35be1ac4e77600d6b9b27c674c5d5f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 10:14:05 -0300 Subject: [PATCH 03/15] perf map_groups: Pass the object to map_groups__find_ams() We were just passing a map to look for and reuse its map->groups member, but the idea is that this is going away, as a map can be in multiple rb_trees when being reused via a map_node, so do as all the other map_groups methods and pass as its first arg the object being operated on. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-nmi2pbggqloogwl6vxrvex5a@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/annotate/instructions.c | 2 +- tools/perf/util/annotate.c | 6 +++--- tools/perf/util/map.c | 6 +++--- tools/perf/util/map_groups.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c index a50e70baf918..20050fb54948 100644 --- a/tools/perf/arch/s390/annotate/instructions.c +++ b/tools/perf/arch/s390/annotate/instructions.c @@ -38,7 +38,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops, return -1; target.addr = map__objdump_2mem(map, ops->target.addr); - if (map_groups__find_ams(&target) == 0 && + if (map_groups__find_ams(map->groups, &target) == 0 && map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index bee0fee122f8..ecc024495f56 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -271,7 +271,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s find_target: target.addr = map__objdump_2mem(map, ops->target.addr); - if (map_groups__find_ams(&target) == 0 && + if (map_groups__find_ams(map->groups, &target) == 0 && map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; @@ -391,7 +391,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s * Actual navigation will come next, with further understanding of how * the symbol searching and disassembly should be done. */ - if (map_groups__find_ams(&target) == 0 && + if (map_groups__find_ams(map->groups, &target) == 0 && map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; @@ -1544,7 +1544,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, .addr = dl->ops.target.addr, }; - if (!map_groups__find_ams(&target) && + if (!map_groups__find_ams(map->groups, &target) && target.sym->start == target.al_addr) dl->ops.target.sym = target.sym; } diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index a4d889c0fa88..db842568f4be 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -703,12 +703,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 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->map->groups == NULL) + if (mg == NULL) return -1; - ams->map = map_groups__find(ams->map->groups, ams->addr); + ams->map = map_groups__find(mg, ams->addr); if (ams->map == NULL) return -1; } diff --git a/tools/perf/util/map_groups.h b/tools/perf/util/map_groups.h index bfbdbf5a443a..99cb810acc7c 100644 --- a/tools/perf/util/map_groups.h +++ b/tools/perf/util/map_groups.h @@ -100,7 +100,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, const char 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); From d3a022cbdce6f361b1effbff1eb18546690592c8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 09:59:48 -0300 Subject: [PATCH 04/15] perf tools: Add map_groups to 'struct addr_location' From there we can get al->mg->machine, so replace that field with the more useful 'struct map_groups' that for now we're obtaining from al->map->groups, and that is one thing getting into the way of maps being fully shareable. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-4qdducrm32tgrjupcp0kjh1e@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 6 +++--- tools/perf/util/db-export.c | 12 ++++++------ tools/perf/util/event.c | 6 +++--- .../perf/util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/symbol.h | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 9a9b56ed3f0a..89faa644b0bc 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1119,8 +1119,8 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * goto out; } - if (al->map->groups == &al->machine->kmaps) { - if (machine__is_host(al->machine)) { + if (al->mg == &al->mg->machine->kmaps) { + if (machine__is_host(al->mg->machine)) { al->cpumode = PERF_RECORD_MISC_KERNEL; al->level = 'k'; } else { @@ -1128,7 +1128,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * al->level = 'g'; } } else { - if (machine__is_host(al->machine)) { + if (machine__is_host(al->mg->machine)) { al->cpumode = PERF_RECORD_MISC_USER; al->level = '.'; } else if (perf_guest) { diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index 752227b265e7..44b465c0a343 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -181,7 +181,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, if (al->map) { 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) return err; *dso_db_id = dso->db_id; @@ -251,7 +251,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe, */ al.sym = node->sym; al.map = node->map; - al.machine = machine; + al.mg = thread->mg; al.addr = node->ip; if (al.map && !al.sym) @@ -360,13 +360,13 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, if (err) return err; - err = db_export__machine(dbe, al->machine); + err = db_export__machine(dbe, al->mg->machine); if (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) goto out_put; @@ -380,7 +380,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, goto out_put; 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, evsel); if (cp) { diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index fc1e5a991008..0141b26bae47 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -461,7 +461,7 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, struct machine *machine = mg->machine; bool load_map = false; - al->machine = machine; + al->mg = mg; al->thread = thread; al->addr = addr; 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) { al->level = 'k'; - mg = &machine->kmaps; + al->mg = mg = &machine->kmaps; load_map = true; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; - mg = &machine->kmaps; + al->mg = mg = &machine->kmaps; load_map = true; } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) { al->level = 'u'; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 93c03b39cd9c..9e0582717f5f 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -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, 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, 4, es->comm_db_id); tuple_set_u64(t, 5, es->dso_db_id); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index c3bd16d75d5d..0b718cc9fb28 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -107,8 +107,8 @@ struct ref_reloc_sym { }; struct addr_location { - struct machine *machine; struct thread *thread; + struct map_groups *mg; struct map *map; struct symbol *sym; const char *srcline; From 2975489458c59ce2e348b1b3aef5d8d2acb5cc8d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 11:10:00 -0300 Subject: [PATCH 05/15] perf annotate: Pass a 'map_symbol' in places receiving a pair of 'map' and 'symbol' pointers We are already passing things like: symbol__annotate(ms->sym, ms->map, ...) So shorten the signature of such functions to receive the 'map_symbol' pointer. This also paves the way to having the 'struct map_groups' pointer in the 'struct map_symbol' so that we can get rid of 'struct map'->groups. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-23yx8v1t41nzpkpi7rdrozww@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 4 +-- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 6 ++-- tools/perf/ui/browsers/annotate.c | 24 ++++++------- tools/perf/ui/gtk/annotate.c | 27 ++++++++------- tools/perf/util/annotate.c | 56 +++++++++++++++---------------- tools/perf/util/annotate.h | 22 +++++------- 7 files changed, 66 insertions(+), 75 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6ab0cc45b287..680c59fafeaf 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -301,9 +301,9 @@ static int hist_entry__tty_annotate(struct hist_entry *he, struct perf_annotate *ann) { 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, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1e81985b7d56..585805f51f15 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -680,7 +680,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg) if (rep->symbol_ipc && sym && !sym->annotate2) { struct evsel *evsel = hists_to_evsel(he->hists); - symbol__annotate2(sym, he->ms.map, evsel, + symbol__annotate2(&he->ms, evsel, &annotation__default_options, NULL); } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 14c52e4d47f6..dc80044bc46f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -143,12 +143,12 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) 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) { top->sym_filter_entry = he; } else { 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); } @@ -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(" 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->zero) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 82207db8f97c..ad1fe5b6d0cd 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -410,7 +410,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, struct evsel *evsel, 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 annotation *notes; char title[SYM_TITLE_MAX_SIZE]; @@ -430,8 +430,10 @@ static bool annotate_browser__callq(struct annotate_browser *browser, return true; } + target_ms.map = ms->map; + target_ms.sym = dl->ops.target.sym; 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); ui_browser__show_title(&browser->b, title); return true; @@ -874,7 +876,7 @@ int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, 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, @@ -888,16 +890,12 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts); } -int symbol__tui_annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, +int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts) { + struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); - struct map_symbol ms = { - .map = map, - .sym = sym, - }; struct annotate_browser browser = { .b = { .refresh = annotate_browser__refresh, @@ -905,7 +903,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, .write = annotate_browser__write, .filter = disasm_line__filter, .extra_title_lines = 1, /* for hists__scnprintf_title() */ - .priv = &ms, + .priv = ms, .use_navkeypressed = true, }, .opts = opts, @@ -915,13 +913,13 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, if (sym == NULL) return -1; - if (map->dso->annotate_warned) + if (ms->map->dso->annotate_warned) return -1; - err = symbol__annotate2(sym, map, evsel, opts, &browser.arch); + err = symbol__annotate2(ms, evsel, opts, &browser.arch); if (err) { 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); goto out_free_offsets; } diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 8e744af24f7c..22cc240f7371 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -54,10 +54,10 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym, return ret; } -static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym, - struct map *map, struct disasm_line *dl) +static int perf_gtk__get_offset(char *buf, size_t size, struct map_symbol *ms, + struct disasm_line *dl) { - u64 start = map__rip_2objdump(map, sym->start); + u64 start = map__rip_2objdump(ms->map, ms->sym->start); strcpy(buf, ""); @@ -91,10 +91,11 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl) return ret; } -static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, - struct map *map, struct evsel *evsel, +static int perf_gtk__annotate_symbol(GtkWidget *window, struct map_symbol *ms, + struct evsel *evsel, struct hist_browser_timer *hbt __maybe_unused) { + struct symbol *sym = ms->sym; struct disasm_line *pos, *n; struct annotation *notes; GType col_types[MAX_ANN_COLS]; @@ -144,7 +145,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, if (ret) 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); if (perf_gtk__get_line(s, sizeof(s), pos)) 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; } -static int symbol__gtk_annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, +static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt) { + struct symbol *sym = ms->sym; GtkWidget *window; GtkWidget *notebook; GtkWidget *scrolled_window; GtkWidget *tab_label; int err; - if (map->dso->annotate_warned) + if (ms->map->dso->annotate_warned) 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) { 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); 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, tab_label); - perf_gtk__annotate_symbol(scrolled_window, sym, map, evsel, hbt); + perf_gtk__annotate_symbol(scrolled_window, ms, evsel, hbt); return 0; } @@ -242,7 +243,7 @@ int hist_entry__gtk_annotate(struct hist_entry *he, struct evsel *evsel, 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) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ecc024495f56..78ef3cc2eb66 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1583,10 +1583,9 @@ static void delete_last_nop(struct symbol *sym) } } -int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, - int errnum, char *buf, size_t buflen) +int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen) { - struct dso *dso = map->dso; + struct dso *dso = ms->map->dso; BUG_ON(buflen == 0); @@ -2143,11 +2142,10 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel) annotation__calc_percent(notes, evsel, symbol__size(sym)); } -int symbol__annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, size_t privsize, - struct annotation_options *options, - struct arch **parch) +int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, size_t privsize, + struct annotation_options *options, struct arch **parch) { + struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); struct annotate_args args = { .privsize = privsize, @@ -2177,9 +2175,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } - args.ms.map = map; - args.ms.sym = sym; - notes->start = map__rip_2objdump(map, sym->start); + args.ms = *ms; + notes->start = map__rip_2objdump(ms->map, sym->start); return symbol__disassemble(sym, &args); } @@ -2335,10 +2332,11 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start) return 0; } -int symbol__annotate_printf(struct symbol *sym, struct map *map, - struct evsel *evsel, +int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts) { + struct map *map = ms->map; + struct symbol *sym = ms->sym; struct dso *dso = map->dso; char *filename; const char *d_filename; @@ -2742,30 +2740,29 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map, resort_source_line(root, &tmp_root); } -static void symbol__calc_lines(struct symbol *sym, struct map *map, - struct rb_root *root, +static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root, 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, - struct evsel *evsel, +int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel, 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 hists *hists = evsel__hists(evsel); char buf[1024]; - if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0) + if (symbol__annotate2(ms, evsel, opts, NULL) < 0) return -1; if (opts->print_lines) { 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); } @@ -2779,25 +2776,25 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, return 0; } -int symbol__tty_annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, +int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, 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; - if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0) + if (symbol__annotate(ms, evsel, 0, opts, NULL) < 0) return -1; symbol__calc_percent(sym, evsel); if (opts->print_lines) { 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); } - symbol__annotate_printf(sym, map, evsel, opts); + symbol__annotate_printf(ms, evsel, opts); annotated_source__purge(symbol__annotation(sym)->src); @@ -3051,9 +3048,10 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes 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 symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); size_t size = symbol__size(sym); int nr_pcnt = 1, err; @@ -3065,7 +3063,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct evsel *evsel, if (perf_evsel__is_group_event(evsel)) 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) goto out_free_offsets; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 3528bd4f8f21..7075d98f69d9 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -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); 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 annotation_options *options, struct arch **parch); -int symbol__annotate2(struct symbol *sym, struct map *map, +int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *options, struct arch **parch); @@ -380,11 +380,9 @@ enum symbol_disassemble_errno { __SYMBOL_ANNOTATE_ERRNO__END, }; -int symbol__strerror_disassemble(struct symbol *sym, struct map *map, - int errnum, char *buf, size_t buflen); +int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen); -int symbol__annotate_printf(struct symbol *sym, struct map *map, - struct evsel *evsel, +int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *options); void symbol__annotate_zero_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); -int symbol__tty_annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, struct annotation_options *opts); +int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts); -int symbol__tty_annotate2(struct symbol *sym, struct map *map, - struct evsel *evsel, struct annotation_options *opts); +int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts); #ifdef HAVE_SLANG_SUPPORT -int symbol__tui_annotate(struct symbol *sym, struct map *map, - struct evsel *evsel, +int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, struct hist_browser_timer *hbt, struct annotation_options *opts); #else -static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, - struct map *map __maybe_unused, +static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused, struct evsel *evsel __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, struct annotation_options *opts __maybe_unused) From c1529738f5eb5fe7c472e0374ad7954d52566df9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 11:58:21 -0300 Subject: [PATCH 06/15] perf unwind: Use 'struct map_symbol' in 'struct unwind_entry' To help in passing that info around to callchain routines that, for the same reason, are moving to use 'struct map_symbol'. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-epsiibeprpxa8qpwji47uskc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/dwarf-unwind.c | 2 +- tools/perf/util/machine.c | 17 +++++++++-------- tools/perf/util/unwind-libdw.c | 6 +++--- tools/perf/util/unwind-libunwind-local.c | 6 +++--- tools/perf/util/unwind.h | 8 +++----- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index 4f4ecbcbe87e..779ce280a0e9 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c @@ -59,7 +59,7 @@ int test_dwarf_unwind__krava_1(struct thread *thread); static int unwind_entry(struct unwind_entry *entry, void *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] = { "test__arch_unwind_sample", "test_dwarf_unwind__thread", diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e768ef24633f..3874bb89ac79 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2448,9 +2448,10 @@ check_calls: return 0; } -static int append_inlines(struct callchain_cursor *cursor, - struct map *map, struct symbol *sym, u64 ip) +static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip) { + struct symbol *sym = ms->sym; + struct map *map = ms->map; struct inline_node *inline_node; struct inline_list *ilist; u64 addr; @@ -2488,22 +2489,22 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) const char *srcline = NULL; u64 addr = entry->ip; - if (symbol_conf.hide_unresolved && entry->sym == NULL) + if (symbol_conf.hide_unresolved && entry->ms.sym == NULL) return 0; - if (append_inlines(cursor, entry->map, entry->sym, entry->ip) == 0) + if (append_inlines(cursor, &entry->ms, entry->ip) == 0) return 0; /* * Convert entry->ip from a virtual address to an offset in * its corresponding binary. */ - if (entry->map) - addr = map__map_ip(entry->map, entry->ip); + if (entry->ms.map) + addr = map__map_ip(entry->ms.map, entry->ip); - srcline = callchain_srcline(entry->map, entry->sym, addr); + srcline = callchain_srcline(entry->ms.map, entry->ms.sym, addr); return callchain_cursor_append(cursor, entry->ip, - entry->map, entry->sym, + entry->ms.map, entry->ms.sym, false, NULL, 0, 0, 0, srcline); } diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 15f6e46d7124..73c00d776a5f 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -80,9 +80,9 @@ static int entry(u64 ip, struct unwind_info *ui) if (__report_module(&al, ip, ui)) return -1; - e->ip = ip; - e->map = al.map; - e->sym = al.sym; + e->ip = ip; + e->ms.map = al.map; + e->ms.sym = al.sym; pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", al.sym ? al.sym->name : "''", diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index 1800887b2255..6e3873dd9a31 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -575,9 +575,9 @@ static int entry(u64 ip, struct thread *thread, struct unwind_entry e; struct addr_location al; - e.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); - e.ip = ip; - e.map = al.map; + e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); + e.ip = ip; + e.ms.map = al.map; pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", al.sym ? al.sym->name : "''", diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 3a7d00c20d86..50337c966979 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -4,17 +4,15 @@ #include #include +#include "util/map_symbol.h" -struct map; struct map_groups; struct perf_sample; -struct symbol; struct thread; struct unwind_entry { - struct map *map; - struct symbol *sym; - u64 ip; + struct map_symbol ms; + u64 ip; }; typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); From 5f0fef8ac3e7a5707751493293ba8ff2ffc0f8a4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 12:14:32 -0300 Subject: [PATCH 07/15] perf callchain: Use 'struct map_symbol' in 'struct callchain_cursor_node' To ease passing around map+symbol, just like done for other parts of the tree recently. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 4 +-- tools/perf/builtin-sched.c | 2 +- tools/perf/util/callchain.c | 33 +++++++++---------- tools/perf/util/callchain.h | 5 ++- tools/perf/util/db-export.c | 4 +-- tools/perf/util/evsel_fprintf.c | 29 +++++++++------- tools/perf/util/machine.c | 24 +++++++++----- .../util/scripting-engines/trace-event-perl.c | 16 ++++----- .../scripting-engines/trace-event-python.c | 16 ++++----- 9 files changed, 71 insertions(+), 62 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 9661671cc26e..003c85f5f56c 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -412,8 +412,8 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample) sizeof(key), callcmp); if (!caller) { /* found */ - if (node->map) - addr = map__unmap_ip(node->map, node->ip); + if (node->ms.map) + addr = map__unmap_ip(node->ms.map, node->ip); else addr = node->ip; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 5cacc4f84c8d..8a12d71364c3 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2172,7 +2172,7 @@ static void save_task_callchain(struct perf_sched *sched, if (node == NULL) break; - sym = node->sym; + sym = node->ms.sym; if (sym) { if (!strcmp(sym->name, "schedule") || !strcmp(sym->name, "__schedule") || diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 89faa644b0bc..8f89c5a4781f 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -582,8 +582,8 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) return -1; } call->ip = cursor_node->ip; - call->ms.sym = cursor_node->sym; - call->ms.map = map__get(cursor_node->map); + call->ms = cursor_node->ms; + map__get(call->ms.map); call->srcline = cursor_node->srcline; 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 */ __fallthrough; case CCKEY_FUNCTION: - if (node->sym && cnode->ms.sym) { + if (node->ms.sym && cnode->ms.sym) { /* * Compare inlined frames based on their symbol name * because different inlined frames will have the same * symbol start. Otherwise do a faster comparison based * 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, - node->sym->name); + node->ms.sym->name); if (match != MATCH_ERROR) break; } else { 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; } } @@ -742,7 +742,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node, __fallthrough; case CCKEY_ADDRESS: 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; } @@ -1004,8 +1004,7 @@ merge_chain_branch(struct callchain_cursor *cursor, int err = 0; list_for_each_entry_safe(list, next_list, &src->val, list) { - callchain_cursor_append(cursor, list->ip, - list->ms.map, list->ms.sym, + callchain_cursor_append(cursor, list->ip, &list->ms, false, NULL, 0, 0, 0, list->srcline); list_del_init(&list->list); map__zput(list->ms.map); @@ -1044,7 +1043,7 @@ int callchain_merge(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, int nr_loop_iter, u64 iter_cycles, u64 branch_from, const char *srcline) @@ -1060,9 +1059,9 @@ int callchain_cursor_append(struct callchain_cursor *cursor, } node->ip = ip; - map__zput(node->map); - node->map = map__get(map); - node->sym = sym; + map__zput(node->ms.map); + node->ms = *ms; + map__get(node->ms.map); node->branch = branch; node->nr_loop_iter = nr_loop_iter; node->iter_cycles = iter_cycles; @@ -1107,8 +1106,8 @@ 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, bool hide_unresolved) { - al->map = node->map; - al->sym = node->sym; + al->map = node->ms.map; + al->sym = node->ms.sym; al->srcline = node->srcline; al->addr = node->ip; @@ -1571,7 +1570,7 @@ int callchain_cursor__copy(struct callchain_cursor *dst, if (node == NULL) 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->nr_loop_iter, node->iter_cycles, @@ -1597,5 +1596,5 @@ void callchain_cursor_reset(struct callchain_cursor *cursor) cursor->last = &cursor->first; for (node = cursor->first; node != NULL; node = node->next) - map__zput(node->map); + map__zput(node->ms.map); } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 83398e5bbe4b..706bb7bbe1e1 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -141,8 +141,7 @@ struct callchain_list { */ struct callchain_cursor_node { u64 ip; - struct map *map; - struct symbol *sym; + struct map_symbol ms; const char *srcline; bool branch; struct branch_flags branch_flags; @@ -195,7 +194,7 @@ int callchain_merge(struct callchain_cursor *cursor, void callchain_cursor_reset(struct callchain_cursor *cursor); 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, int nr_loop_iter, u64 iter_cycles, u64 branch_from, const char *srcline); diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index 44b465c0a343..d029faf9fc9f 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -249,8 +249,8 @@ static struct call_path *call_path_from_sample(struct db_export *dbe, * constructing an addr_location struct and then passing it to * db_ids_from_al() to perform the export. */ - al.sym = node->sym; - al.map = node->map; + al.sym = node->ms.sym; + al.map = node->ms.map; al.mg = thread->mg; al.addr = node->ip; diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 028df7afb0dc..3b4842840db0 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -125,13 +125,18 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, callchain_cursor_commit(cursor); while (1) { + struct symbol *sym; + struct map *map; u64 addr = 0; node = callchain_cursor_current(cursor); if (!node) 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; 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) printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); - if (node->map) - addr = node->map->map_ip(node->map, node->ip); + if (map) + addr = map->map_ip(map, node->ip); if (print_sym) { printed += fprintf(fp, " "); node_al.addr = addr; - node_al.map = node->map; + node_al.map = map; if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(node->sym, &node_al, + printed += __symbol__fprintf_symname_offs(sym, &node_al, print_unknown_as_addr, true, fp); } else { - printed += __symbol__fprintf_symname(node->sym, &node_al, + printed += __symbol__fprintf_symname(sym, &node_al, print_unknown_as_addr, fp); } } - if (print_dso && (!node->sym || !node->sym->inlined)) { + if (print_dso && (!sym || !sym->inlined)) { printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(node->map, fp); + printed += map__fprintf_dsoname(map, fp); printed += fprintf(fp, ")"); } 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)"); if (!print_oneline) printed += fprintf(fp, "\n"); /* Add srccode here too? */ - if (bt_stop_list && node->sym && - strlist__has_entry(bt_stop_list, node->sym->name)) { + if (bt_stop_list && sym && + strlist__has_entry(bt_stop_list, sym->name)) { break; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 3874bb89ac79..d08c7285c708 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2006,8 +2006,9 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, 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; if (!map || callchain_param.key == CCKEY_FUNCTION) @@ -2019,7 +2020,7 @@ static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip) bool show_addr = callchain_param.key == CCKEY_ADDRESS; 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); } @@ -2042,6 +2043,7 @@ static int add_callchain_ip(struct thread *thread, struct iterations *iter, u64 branch_from) { + struct map_symbol ms; struct addr_location al; int nr_loop_iter = 0; u64 iter_cycles = 0; @@ -2099,8 +2101,10 @@ static int add_callchain_ip(struct thread *thread, iter_cycles = iter->cycles; } - srcline = callchain_srcline(al.map, al.sym, al.addr); - 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, iter_cycles, branch_from, srcline); } @@ -2472,8 +2476,11 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms } list_for_each_entry(ilist, &inline_node->val, list) { - ret = callchain_cursor_append(cursor, ip, map, - ilist->symbol, false, + struct map_symbol ilist_ms = { + .map = map, + .sym = ilist->symbol, + }; + ret = callchain_cursor_append(cursor, ip, &ilist_ms, false, NULL, 0, 0, 0, ilist->srcline); if (ret != 0) @@ -2502,9 +2509,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) if (entry->ms.map) addr = map__map_ip(entry->ms.map, entry->ip); - srcline = callchain_srcline(entry->ms.map, entry->ms.sym, addr); - return callchain_cursor_append(cursor, entry->ip, - entry->ms.map, entry->ms.sym, + srcline = callchain_srcline(&entry->ms, addr); + return callchain_cursor_append(cursor, entry->ip, &entry->ms, false, NULL, 0, 0, 0, srcline); } diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 741f040648b5..0e608a5ef599 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -294,17 +294,17 @@ static SV *perl_process_callchain(struct perf_sample *sample, goto exit; } - if (node->sym) { + if (node->ms.sym) { HV *sym = newHV(); if (!sym) { hv_undef(elem); goto exit; } - if (!hv_stores(sym, "start", newSVuv(node->sym->start)) || - !hv_stores(sym, "end", newSVuv(node->sym->end)) || - !hv_stores(sym, "binding", newSVuv(node->sym->binding)) || - !hv_stores(sym, "name", newSVpvn(node->sym->name, - node->sym->namelen)) || + if (!hv_stores(sym, "start", newSVuv(node->ms.sym->start)) || + !hv_stores(sym, "end", newSVuv(node->ms.sym->end)) || + !hv_stores(sym, "binding", newSVuv(node->ms.sym->binding)) || + !hv_stores(sym, "name", newSVpvn(node->ms.sym->name, + node->ms.sym->namelen)) || !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) { hv_undef(sym); hv_undef(elem); @@ -312,8 +312,8 @@ static SV *perl_process_callchain(struct perf_sample *sample, } } - if (node->map) { - struct map *map = node->map; + if (node->ms.map) { + struct map *map = node->ms.map; const char *dsoname = "[unknown]"; if (map && map->dso) { if (symbol_conf.show_kernel_path && map->dso->long_name) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9e0582717f5f..9581a904af29 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -428,24 +428,24 @@ static PyObject *python_process_callchain(struct perf_sample *sample, pydict_set_item_string_decref(pyelem, "ip", PyLong_FromUnsignedLongLong(node->ip)); - if (node->sym) { + if (node->ms.sym) { PyObject *pysym = PyDict_New(); if (!pysym) Py_FatalError("couldn't create Python dictionary"); 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", - PyLong_FromUnsignedLongLong(node->sym->end)); + PyLong_FromUnsignedLongLong(node->ms.sym->end)); 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", - _PyUnicode_FromStringAndSize(node->sym->name, - node->sym->namelen)); + _PyUnicode_FromStringAndSize(node->ms.sym->name, + node->ms.sym->namelen)); pydict_set_item_string_decref(pyelem, "sym", pysym); } - if (node->map) { - const char *dsoname = get_dsoname(node->map); + if (node->ms.map) { + const char *dsoname = get_dsoname(node->ms.map); pydict_set_item_string_decref(pyelem, "dso", _PyUnicode_FromString(dsoname)); From d46a4cdf49937b0b3abeb2cd7fa5dc65795e7ea7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 15:57:38 -0300 Subject: [PATCH 08/15] pref tools: Make 'struct addr_map_symbol' contain 'struct map_symbol' So that we pass that substructure around and with it consolidate lots of functions that receive a (map, symbol) pair and now can receive just a 'struct map_symbol' pointer. This further paves the way to add 'struct map_groups' to 'struct map_symbol' so that we can have all we need for annotation so that we can ditch 'struct map'->groups, i.e. have the map_groups pointer in a more central place, avoiding the pointer in the 'struct map' that have tons of instances. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-fs90ttd9q12l7989fo7pw81q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/annotate/instructions.c | 6 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/ui/browsers/hists.c | 20 ++--- tools/perf/util/annotate.c | 43 +++++----- tools/perf/util/hist.c | 54 ++++++------ tools/perf/util/machine.c | 8 +- tools/perf/util/map.c | 12 +-- tools/perf/util/map_symbol.h | 3 +- tools/perf/util/mem-events.c | 2 +- tools/perf/util/sort.c | 89 +++++++++----------- 10 files changed, 114 insertions(+), 125 deletions(-) diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c index 20050fb54948..bdd7ab34ce4f 100644 --- a/tools/perf/arch/s390/annotate/instructions.c +++ b/tools/perf/arch/s390/annotate/instructions.c @@ -7,7 +7,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops, char *endptr, *tok, *name; struct map *map = ms->map; struct addr_map_symbol target = { - .map = map, + .ms = { .map = map, }, }; tok = strchr(ops->raw, ','); @@ -39,8 +39,8 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops, target.addr = map__objdump_2mem(map, ops->target.addr); if (map_groups__find_ams(map->groups, &target) == 0 && - map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) - ops->target.sym = target.sym; + map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) + ops->target.sym = target.ms.sym; return 0; } diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 680c59fafeaf..5898662bc8fb 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -83,7 +83,7 @@ static void process_basic_block(struct addr_map_symbol *start, struct addr_map_symbol *end, struct branch_flags *flags) { - struct symbol *sym = start->sym; + struct symbol *sym = start->ms.sym; struct annotation *notes = sym ? symbol__annotation(sym) : NULL; struct block_range_iter iter; struct block_range *entry; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 334afc2139e7..4d2d0acfd41a 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2405,16 +2405,15 @@ do_annotate(struct hist_browser *browser, struct popup_action *act) static int add_annotate_opt(struct hist_browser *browser __maybe_unused, 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; - if (asprintf(optstr, "Annotate %s", sym->name) < 0) + if (asprintf(optstr, "Annotate %s", ms->sym->name) < 0) return 0; - act->ms.map = map; - act->ms.sym = sym; + act->ms = *ms; act->fn = do_annotate; return 1; } @@ -3115,20 +3114,17 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, nr_options += add_annotate_opt(browser, &actions[nr_options], &options[nr_options], - bi->from.map, - bi->from.sym); - if (bi->to.sym != bi->from.sym) + &bi->from.ms); + if (bi->to.ms.sym != bi->from.ms.sym) nr_options += add_annotate_opt(browser, &actions[nr_options], &options[nr_options], - bi->to.map, - bi->to.sym); + &bi->to.ms); } else { nr_options += add_annotate_opt(browser, &actions[nr_options], &options[nr_options], - browser->selection->map, - browser->selection->sym); + browser->selection); } skip_annotation: nr_options += add_thread_opt(browser, &actions[nr_options], diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 78ef3cc2eb66..e0a9e9e49bb1 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -243,7 +243,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s char *endptr, *tok, *name; struct map *map = ms->map; struct addr_map_symbol target = { - .map = map, + .ms = { .map = map, }, }; ops->target.addr = strtoull(ops->raw, &endptr, 16); @@ -272,8 +272,8 @@ find_target: target.addr = map__objdump_2mem(map, ops->target.addr); if (map_groups__find_ams(map->groups, &target) == 0 && - map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) - ops->target.sym = target.sym; + map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) + ops->target.sym = target.ms.sym; 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 symbol *sym = ms->sym; struct addr_map_symbol target = { - .map = map, + .ms = { .map = map, }, }; const char *c = strchr(ops->raw, ','); u64 start, end; @@ -392,8 +392,8 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s * the symbol searching and disassembly should be done. */ if (map_groups__find_ams(map->groups, &target) == 0 && - map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) - ops->target.sym = target.sym; + map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) + ops->target.sym = target.ms.sym; if (!ops->target.outside) { ops->target.offset = target.addr - start; @@ -865,14 +865,15 @@ static int __symbol__account_cycles(struct cyc_hist *ch, 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 perf_sample *sample) { + struct symbol *sym = ms->sym; unsigned offset; 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) && (addr != sym->end || sym->start != sym->end)) { @@ -939,17 +940,17 @@ alloc_histograms: 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 perf_sample *sample) { + struct symbol *sym = ms->sym; struct annotated_source *src; if (sym == NULL) return 0; src = symbol__hists(sym, evsel->evlist->core.nr_entries); - return (src) ? __symbol__inc_addr_samples(sym, map, src, evsel->idx, - addr, sample) : 0; + return src ? __symbol__inc_addr_samples(ms, src, evsel->idx, addr, sample) : 0; } 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. */ if (start && - (start->sym == ams->sym || - (ams->sym && - start->addr == ams->sym->start + ams->map->start))) + (start->ms.sym == ams->ms.sym || + (ams->ms.sym && + start->addr == ams->ms.sym->start + ams->ms.map->start))) saddr = start->al_addr; if (saddr == 0) pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n", ams->addr, 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); - 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) pr_debug2("account_cycles failed %d\n", 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, 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, 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) @@ -1540,13 +1541,13 @@ static int symbol__parse_objdump_line(struct symbol *sym, /* kcore has no symbols, so add the call target symbol */ if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) { struct addr_map_symbol target = { - .map = map, .addr = dl->ops.target.addr, + .ms = { .map = map, }, }; if (!map_groups__find_ams(map->groups, &target) && - target.sym->start == target.al_addr) - dl->ops.target.sym = target.sym; + target.ms.sym->start == target.al_addr) + dl->ops.target.sym = target.ms.sym; } annotation_line__add(&dl->al, ¬es->src->source); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 78749535dbf3..dec996133cdf 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -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); if (h->branch_info) { - if (h->branch_info->from.sym) { - symlen = (int)h->branch_info->from.sym->namelen + 4; + if (h->branch_info->from.ms.sym) { + symlen = (int)h->branch_info->from.ms.sym->namelen + 4; if (verbose > 0) symlen += BITS_PER_LONG / 4 + 2 + 3; 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); } else { 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); } - if (h->branch_info->to.sym) { - symlen = (int)h->branch_info->to.sym->namelen + 4; + if (h->branch_info->to.ms.sym) { + symlen = (int)h->branch_info->to.ms.sym->namelen + 4; if (verbose > 0) symlen += BITS_PER_LONG / 4 + 2 + 3; 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); } else { 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->daddr.sym) { - symlen = (int)h->mem_info->daddr.sym->namelen + 4 + if (h->mem_info->daddr.ms.sym) { + symlen = (int)h->mem_info->daddr.ms.sym->namelen + 4 + unresolved_col_width + 2; hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); @@ -164,8 +164,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) symlen); } - if (h->mem_info->iaddr.sym) { - symlen = (int)h->mem_info->iaddr.sym->namelen + 4 + if (h->mem_info->iaddr.ms.sym) { + symlen = (int)h->mem_info->iaddr.ms.sym->namelen + 4 + unresolved_col_width + 2; hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, symlen); @@ -175,8 +175,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) symlen); } - if (h->mem_info->daddr.map) { - symlen = dso__name_len(h->mem_info->daddr.map->dso); + if (h->mem_info->daddr.ms.map) { + symlen = dso__name_len(h->mem_info->daddr.ms.map->dso); hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, symlen); } else { @@ -443,13 +443,13 @@ static int hist_entry__init(struct hist_entry *he, memcpy(he->branch_info, template->branch_info, sizeof(*he->branch_info)); - map__get(he->branch_info->from.map); - map__get(he->branch_info->to.map); + map__get(he->branch_info->from.ms.map); + map__get(he->branch_info->to.ms.map); } if (he->mem_info) { - map__get(he->mem_info->iaddr.map); - map__get(he->mem_info->daddr.map); + map__get(he->mem_info->iaddr.ms.map); + map__get(he->mem_info->daddr.ms.map); } if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) @@ -492,13 +492,13 @@ err_rawdata: err_infos: if (he->branch_info) { - map__put(he->branch_info->from.map); - map__put(he->branch_info->to.map); + map__put(he->branch_info->from.ms.map); + map__put(he->branch_info->to.ms.map); zfree(&he->branch_info); } if (he->mem_info) { - map__put(he->mem_info->iaddr.map); - map__put(he->mem_info->daddr.map); + map__put(he->mem_info->iaddr.ms.map); + map__put(he->mem_info->daddr.ms.map); } err: map__zput(he->ms.map); @@ -893,8 +893,8 @@ iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) if (iter->curr >= iter->total) return 0; - al->map = bi[i].to.map; - 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; return 1; } @@ -912,7 +912,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a 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; /* @@ -1251,16 +1251,16 @@ void hist_entry__delete(struct hist_entry *he) map__zput(he->ms.map); if (he->branch_info) { - map__zput(he->branch_info->from.map); - map__zput(he->branch_info->to.map); + map__zput(he->branch_info->from.ms.map); + map__zput(he->branch_info->to.ms.map); free_srcline(he->branch_info->srcline_from); free_srcline(he->branch_info->srcline_to); zfree(&he->branch_info); } if (he->mem_info) { - map__zput(he->mem_info->iaddr.map); - map__zput(he->mem_info->daddr.map); + map__zput(he->mem_info->iaddr.ms.map); + map__zput(he->mem_info->daddr.ms.map); mem_info__zput(he->mem_info); } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index d08c7285c708..614094d87f05 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1968,8 +1968,8 @@ static void ip__resolve_ams(struct thread *thread, ams->addr = ip; ams->al_addr = al.addr; - ams->sym = al.sym; - ams->map = al.map; + ams->ms.sym = al.sym; + ams->ms.map = al.map; ams->phys_addr = 0; } @@ -1985,8 +1985,8 @@ static void ip__resolve_data(struct thread *thread, ams->addr = addr; ams->al_addr = al.addr; - ams->sym = al.sym; - ams->map = al.map; + ams->ms.sym = al.sym; + ams->ms.map = al.map; ams->phys_addr = phys_addr; } diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index db842568f4be..6c59f55026c1 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -705,18 +705,18 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 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 (mg == NULL) return -1; - ams->map = map_groups__find(mg, ams->addr); - if (ams->map == NULL) + ams->ms.map = map_groups__find(mg, ams->addr); + if (ams->ms.map == NULL) return -1; } - ams->al_addr = ams->map->map_ip(ams->map, ams->addr); - ams->sym = map__find_symbol(ams->map, ams->al_addr); + ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->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) diff --git a/tools/perf/util/map_symbol.h b/tools/perf/util/map_symbol.h index 5a1aed9f6bb4..f71cbe1a26a9 100644 --- a/tools/perf/util/map_symbol.h +++ b/tools/perf/util/map_symbol.h @@ -13,8 +13,7 @@ struct map_symbol { }; struct addr_map_symbol { - struct map *map; - struct symbol *sym; + struct map_symbol ms; u64 addr; u64 al_addr; u64 phys_addr; diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 3d391583f2ae..aa29589f6904 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -410,7 +410,7 @@ do { \ return -1; } - if (!mi->daddr.map || !mi->iaddr.map) { + if (!mi->daddr.ms.map || !mi->iaddr.ms.map) { stats->nomap++; return -1; } diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 43d1d410854a..6b626e6b111e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -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); } -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, unsigned int width) { + struct symbol *sym = ms->sym; + struct map *map = ms->map; size_t ret = 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, 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); } @@ -386,7 +388,7 @@ struct sort_entry sort_srcline = { 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 @@ -769,15 +771,15 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) if (!left->branch_info || !right->branch_info) return cmp_null(left->branch_info, right->branch_info); - return _sort__dso_cmp(left->branch_info->from.map, - right->branch_info->from.map); + return _sort__dso_cmp(left->branch_info->from.ms.map, + right->branch_info->from.ms.map); } static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { 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); else 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) return -1; - return dso && (!he->branch_info || !he->branch_info->from.map || - he->branch_info->from.map->dso != dso); + return dso && (!he->branch_info || !he->branch_info->from.ms.map || + he->branch_info->from.ms.map->dso != dso); } 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) return cmp_null(left->branch_info, right->branch_info); - return _sort__dso_cmp(left->branch_info->to.map, - right->branch_info->to.map); + return _sort__dso_cmp(left->branch_info->to.ms.map, + right->branch_info->to.ms.map); } static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { 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); else 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) return -1; - return dso && (!he->branch_info || !he->branch_info->to.map || - he->branch_info->to.map->dso != dso); + return dso && (!he->branch_info || !he->branch_info->to.ms.map || + he->branch_info->to.ms.map->dso != dso); } 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_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__sym_cmp(from_l->sym, from_r->sym); + return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym); } 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_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__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, @@ -868,8 +870,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, if (he->branch_info) { struct addr_map_symbol *from = &he->branch_info->from; - return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(&from->ms, from->addr, he->level, bf, size, width); } 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) { struct addr_map_symbol *to = &he->branch_info->to; - return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(&to->ms, to->addr, he->level, bf, size, width); } 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) return -1; - return sym && !(he->branch_info && he->branch_info->from.sym && - strstr(he->branch_info->from.sym->name, sym)); + return sym && !(he->branch_info && he->branch_info->from.ms.sym && + strstr(he->branch_info->from.ms.sym->name, sym)); } 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) return -1; - return sym && !(he->branch_info && he->branch_info->to.sym && - strstr(he->branch_info->to.sym->name, sym)); + return sym && !(he->branch_info && he->branch_info->to.ms.sym && + strstr(he->branch_info->to.ms.sym->name, sym)); } 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) { uint64_t addr = 0; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; if (he->mem_info) { addr = he->mem_info->daddr.addr; - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + ms = &he->mem_info->daddr.ms; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); } int64_t @@ -1046,16 +1043,13 @@ static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { uint64_t addr = 0; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; if (he->mem_info) { addr = he->mem_info->iaddr.addr; - map = he->mem_info->iaddr.map; - sym = he->mem_info->iaddr.sym; + ms = &he->mem_info->iaddr.ms; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); } static int64_t @@ -1065,9 +1059,9 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) struct map *map_r = NULL; if (left->mem_info) - map_l = left->mem_info->daddr.map; + map_l = left->mem_info->daddr.ms.map; 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); } @@ -1078,7 +1072,7 @@ static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, struct map *map = NULL; 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); } @@ -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; - l_map = left->mem_info->daddr.map; - r_map = right->mem_info->daddr.map; + l_map = left->mem_info->daddr.ms.map; + r_map = right->mem_info->daddr.ms.map; /* if both are NULL, jump to sort on al_addr instead */ 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; - struct map *map = NULL; - struct symbol *sym = NULL; + struct map_symbol *ms = NULL; char level = he->level; if (he->mem_info) { + struct map *map = he->mem_info->daddr.ms.map; + addr = cl_address(he->mem_info->daddr.al_addr); - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + ms = &he->mem_info->daddr.ms; /* print [s] for shared data mmaps */ 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) level = 'X'; } - return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size, - width); + return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width); } struct sort_entry sort_mispredict = { From 93fcce96c71931f65c9bb1a0f2303008e6862c97 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:25:11 -0300 Subject: [PATCH 09/15] perf symbols: Use kmaps(map)->machine when we know its a kernel map And then stop using map->groups to achieve that. To test that that branch is being taken, probe the function that is only called from there and then run something like 'perf top' in another xterm: # perf probe -x ~/bin/perf machine__map_x86_64_entry_trampolines Added new event: probe_perf:machine__map_x86_64_entry_trampolines (on machine__map_x86_64_entry_trampolines in /home/acme/bin/perf) You can now use it in all perf tools, such as: perf record -e probe_perf:machine__map_x86_64_entry_trampolines -aR sleep 1 # perf trace -e probe_perf:* 0.000 bash/10614 probe_perf:machine__map_x86_64_entry_trampolines(__probe_ip: 5224944) ^C# Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-lgrrzdxo2p9liq2keivcg887@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 2764863212b1..88f4cfbdb69a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1588,7 +1588,7 @@ int dso__load(struct dso *dso, struct map *map) char *name; int ret = -1; u_int i; - struct machine *machine; + struct machine *machine = NULL; char *root_dir = (char *) ""; int ss_pos = 0; struct symsrc ss_[2]; @@ -1617,17 +1617,13 @@ int dso__load(struct dso *dso, struct map *map) goto out; } - if (map->groups) - machine = map->groups->machine; - else - machine = NULL; - if (dso->kernel) { if (dso->kernel == DSO_TYPE_KERNEL) ret = dso__load_kernel_sym(dso, map); else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) ret = dso__load_guest_kernel_sym(dso, map); + machine = map__kmaps(map)->machine; if (machine__is(machine, "x86_64")) machine__map_x86_64_entry_trampolines(machine, dso); goto out; @@ -2027,15 +2023,9 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map) { int err; const char *kallsyms_filename = NULL; - struct machine *machine; + struct machine *machine = map__kmaps(map)->machine; 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 the user specified a vmlinux filename, use it and only From 08f6680e627edf913c6d6adb9bb9ecc9d57a408d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:02:35 -0300 Subject: [PATCH 10/15] perf tools: Add a 'struct map_groups' pointer to 'struct map_symbol' And fill it whenever we setup a a 'struct map_symbol', now we need to use it, next cset. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-fzwfcnddenz1o7uj1fzw3g46@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/callchain.c | 1 + tools/perf/util/hist.c | 4 ++++ tools/perf/util/machine.c | 3 +++ tools/perf/util/map_symbol.h | 2 ++ tools/perf/util/unwind-libdw.c | 1 + tools/perf/util/unwind-libunwind-local.c | 1 + 6 files changed, 12 insertions(+) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 8f89c5a4781f..5cefce33b66b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1106,6 +1106,7 @@ 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, bool hide_unresolved) { + al->mg = node->ms.mg; al->map = node->ms.map; al->sym = node->ms.sym; al->srcline = node->srcline; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index dec996133cdf..0a8d72ae93ca 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -692,6 +692,7 @@ __hists__add_entry(struct hists *hists, .ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0, }, .ms = { + .mg = al->mg, .map = al->map, .sym = al->sym, }, @@ -759,6 +760,7 @@ struct hist_entry *hists__add_entry_block(struct hists *hists, .block_info = block_info, .hists = hists, .ms = { + .mg = al->mg, .map = al->map, .sym = al->sym, }, @@ -893,6 +895,7 @@ iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) if (iter->curr >= iter->total) return 0; + al->mg = bi[i].to.ms.mg; al->map = bi[i].to.ms.map; al->sym = bi[i].to.ms.sym; al->addr = bi[i].to.addr; @@ -1069,6 +1072,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, .comm = thread__comm(al->thread), .ip = al->addr, .ms = { + .mg = al->mg, .map = al->map, .sym = al->sym, }, diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 614094d87f05..6a0f5c25ce3e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1968,6 +1968,7 @@ static void ip__resolve_ams(struct thread *thread, ams->addr = ip; ams->al_addr = al.addr; + ams->ms.mg = al.mg; ams->ms.sym = al.sym; ams->ms.map = al.map; ams->phys_addr = 0; @@ -1985,6 +1986,7 @@ static void ip__resolve_data(struct thread *thread, ams->addr = addr; ams->al_addr = al.addr; + ams->ms.mg = al.mg; ams->ms.sym = al.sym; ams->ms.map = al.map; ams->phys_addr = phys_addr; @@ -2101,6 +2103,7 @@ static int add_callchain_ip(struct thread *thread, iter_cycles = iter->cycles; } + ms.mg = al.mg; ms.map = al.map; ms.sym = al.sym; srcline = callchain_srcline(&ms, al.addr); diff --git a/tools/perf/util/map_symbol.h b/tools/perf/util/map_symbol.h index f71cbe1a26a9..2964d971aeab 100644 --- a/tools/perf/util/map_symbol.h +++ b/tools/perf/util/map_symbol.h @@ -4,10 +4,12 @@ #include +struct map_groups; struct map; struct symbol; struct map_symbol { + struct map_groups *mg; struct map *map; struct symbol *sym; }; diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 73c00d776a5f..d2a8df01c4a7 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -81,6 +81,7 @@ static int entry(u64 ip, struct unwind_info *ui) return -1; e->ip = ip; + e->ms.mg = al.mg; e->ms.map = al.map; e->ms.sym = al.sym; diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index 6e3873dd9a31..6d53347d6744 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -578,6 +578,7 @@ static int entry(u64 ip, struct thread *thread, e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); e.ip = ip; e.ms.map = al.map; + e.ms.mg = al.mg; pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", al.sym ? al.sym->name : "''", From 94e44b9ca52a72cddd07111a8beb12a2f217c6a2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:52:19 -0300 Subject: [PATCH 11/15] perf annotate: Stop using map->groups, use map_symbol->mg instead These were the last uses of map->groups, next cset will nuke it. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-n3g0foos7l7uxq9nar0zo0vj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/annotate/instructions.c | 2 +- tools/perf/ui/browsers/annotate.c | 1 + tools/perf/util/annotate.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c index bdd7ab34ce4f..2a6662e42f89 100644 --- a/tools/perf/arch/s390/annotate/instructions.c +++ b/tools/perf/arch/s390/annotate/instructions.c @@ -38,7 +38,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops, return -1; target.addr = map__objdump_2mem(map, ops->target.addr); - if (map_groups__find_ams(map->groups, &target) == 0 && + if (map_groups__find_ams(ms->mg, &target) == 0 && map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) ops->target.sym = target.ms.sym; diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index ad1fe5b6d0cd..992705c78bd0 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -430,6 +430,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, return true; } + target_ms.mg = ms->mg; target_ms.map = ms->map; target_ms.sym = dl->ops.target.sym; pthread_mutex_unlock(¬es->lock); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index e0a9e9e49bb1..5ea9a4534848 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -271,7 +271,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s find_target: target.addr = map__objdump_2mem(map, ops->target.addr); - if (map_groups__find_ams(map->groups, &target) == 0 && + if (map_groups__find_ams(ms->mg, &target) == 0 && map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) ops->target.sym = target.ms.sym; @@ -391,7 +391,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s * Actual navigation will come next, with further understanding of how * the symbol searching and disassembly should be done. */ - if (map_groups__find_ams(map->groups, &target) == 0 && + if (map_groups__find_ams(ms->mg, &target) == 0 && map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr) ops->target.sym = target.ms.sym; @@ -1545,7 +1545,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, .ms = { .map = map, }, }; - if (!map_groups__find_ams(map->groups, &target) && + if (!map_groups__find_ams(args->ms.mg, &target) && target.ms.sym->start == target.al_addr) dl->ops.target.sym = target.ms.sym; } From 3f662fc08dddebd7bab654eada1f3e7568959eef Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 1 Nov 2019 17:53:02 -0300 Subject: [PATCH 12/15] perf map: Combine maps__fixup_overlappings with its only use In the process we can kill some of the struct map->groups usage, trying to get rid of this per-full struct map fields getting in the way of sharing a map across father/parent processes. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-e50eqtqw3za24vmbjnqmmcs6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/map.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 6c59f55026c1..27d8508f8a44 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -752,8 +752,9 @@ static void __map_groups__insert(struct map_groups *mg, struct map *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_node *next, *first; int err = 0; @@ -818,7 +819,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp } before->end = map->start; - __map_groups__insert(pos->groups, before); + __map_groups__insert(mg, before); if (verbose >= 2 && !use_browser) map__fprintf(before, fp); map__put(before); @@ -835,7 +836,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp after->start = map->end; after->pgoff += map->end - pos->start; 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) map__fprintf(after, fp); map__put(after); @@ -853,12 +854,6 @@ out: 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. */ From 7b018e298752b9bcaf34eba8e1d3c08e3207dfd8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 Nov 2019 16:55:53 -0300 Subject: [PATCH 13/15] perf map: Remove ->groups from 'struct map' With this 'struct map' uses a bit over 3 cachelines: $ pahole -C map ~/bin/perf /* --- cacheline 2 boundary (128 bytes) --- */ u64 (*unmap_ip)(struct map *, u64); /* 128 8 */ struct dso * dso; /* 136 8 */ refcount_t refcnt; /* 144 4 */ /* size: 152, cachelines: 3, members: 18 */ /* sum members: 145, holes: 1, sum holes: 3 */ /* padding: 4 */ /* forced alignments: 2 */ /* last cacheline: 24 bytes */ } __attribute__((__aligned__(8))); $ We probably can move map->map/unmap_ip() moved to 'struct map_groups', that will shave more 16 bytes, getting this almost to two cachelines. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-ymlv3nzpofv2fugnjnizkrwy@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/map.c | 4 ---- tools/perf/util/map.h | 1 - 2 files changed, 5 deletions(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 27d8508f8a44..359846833a00 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -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->unmap_ip = map__unmap_ip; RB_CLEAR_NODE(&map->rb_node); - map->groups = NULL; map->erange_warned = false; refcount_set(&map->refcnt, 1); } @@ -388,7 +387,6 @@ struct map *map__clone(struct map *from) refcount_set(&map->refcnt, 1); RB_CLEAR_NODE(&map->rb_node); dso__get(map->dso); - map->groups = NULL; } return map; @@ -582,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) { maps__insert(&mg->maps, map); - map->groups = mg; } static void __maps__purge(struct maps *maps) @@ -749,7 +746,6 @@ static void __map_groups__insert(struct map_groups *mg, struct map *map) { __maps__insert(&mg->maps, map); __maps__insert_name(&mg->maps, map); - map->groups = mg; } int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE *fp) diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index c3614195ddc7..365deb6375ab 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -42,7 +42,6 @@ struct map { u64 (*unmap_ip)(struct map *, u64); struct dso *dso; - struct map_groups *groups; refcount_t refcnt; }; From ccd26741f5e6bdf2c18ea38b32e6a347c5648a97 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 Nov 2019 15:11:28 +0530 Subject: [PATCH 14/15] perf tool: Provide an option to print perf_event_open args and return value Perf record with verbose=2 already prints this information along with whole lot of other traces which requires lot of scrolling. Introduce an option to print only perf_event_open() arguments and return value. Sample o/p: $ perf --debug perf-event-open=1 record -- ls > /dev/null ------------------------------------------------------------ perf_event_attr: size 112 { sample_period, sample_freq } 4000 sample_type IP|TID|TIME|PERIOD read_format ID disabled 1 inherit 1 exclude_kernel 1 mmap 1 comm 1 freq 1 enable_on_exec 1 task 1 precise_ip 3 sample_id_all 1 exclude_guest 1 mmap2 1 comm_exec 1 ksymbol 1 bpf_event 1 ------------------------------------------------------------ sys_perf_event_open: pid 4308 cpu 0 group_fd -1 flags 0x8 = 4 sys_perf_event_open: pid 4308 cpu 1 group_fd -1 flags 0x8 = 5 sys_perf_event_open: pid 4308 cpu 2 group_fd -1 flags 0x8 = 6 sys_perf_event_open: pid 4308 cpu 3 group_fd -1 flags 0x8 = 8 sys_perf_event_open: pid 4308 cpu 4 group_fd -1 flags 0x8 = 9 sys_perf_event_open: pid 4308 cpu 5 group_fd -1 flags 0x8 = 10 sys_perf_event_open: pid 4308 cpu 6 group_fd -1 flags 0x8 = 11 sys_perf_event_open: pid 4308 cpu 7 group_fd -1 flags 0x8 = 12 ------------------------------------------------------------ perf_event_attr: type 1 size 112 config 0x9 watermark 1 sample_id_all 1 bpf_event 1 { wakeup_events, wakeup_watermark } 1 ------------------------------------------------------------ sys_perf_event_open: pid -1 cpu 0 group_fd -1 flags 0x8 sys_perf_event_open failed, error -13 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.002 MB perf.data (9 samples) ] Committer notes: Just like the 'verbose' variable this new 'debug_peo_args' needs to be added to util/python.c, since we don't link the debug.o file in the python binding, which ended up making 'perf test python' fail with: # perf test -v python 18: 'import perf' in python : --- start --- test child forked, pid 19237 Traceback (most recent call last): File "", line 1, in ImportError: /tmp/build/perf/python/perf.so: undefined symbol: debug_peo_args test child finished with -1 ---- end ---- 'import perf' in python: FAILED! # After adding that new variable to util/python.c: # perf test -v python 18: 'import perf' in python : --- start --- test child forked, pid 22364 test child finished with 0 ---- end ---- 'import perf' in python: Ok # Signed-off-by: Ravi Bangoria Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Link: http://lore.kernel.org/lkml/20191108094128.28769-1-ravi.bangoria@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf.txt | 2 ++ tools/perf/util/debug.c | 2 ++ tools/perf/util/debug.h | 9 ++++++++ tools/perf/util/evsel.c | 36 +++++++++++++++---------------- tools/perf/util/python.c | 1 + 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt index 401f0ed67439..3f37ded13f8c 100644 --- a/tools/perf/Documentation/perf.txt +++ b/tools/perf/Documentation/perf.txt @@ -24,6 +24,8 @@ OPTIONS data-convert - data convert command debug messages stderr - write debug output (option -v) to stderr in browser mode + perf-event-open - Print perf_event_open() arguments and + return value --buildid-dir:: Setup buildid cache directory. It has higher priority than diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index e55114f0336f..adb656745ecc 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -24,6 +24,7 @@ #include int verbose; +int debug_peo_args; bool dump_trace = false, quiet = false; int debug_ordered_events; static int redirect_to_stderr; @@ -180,6 +181,7 @@ static struct debug_variable { { .name = "ordered-events", .ptr = &debug_ordered_events}, { .name = "stderr", .ptr = &redirect_to_stderr}, { .name = "data-convert", .ptr = &debug_data_convert }, + { .name = "perf-event-open", .ptr = &debug_peo_args }, { .name = NULL, } }; diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index d25ae1c4cee9..f1734abd98dd 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -8,6 +8,7 @@ #include extern int verbose; +extern int debug_peo_args; extern bool quiet, dump_trace; extern int debug_ordered_events; 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_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, ...) \ eprintf_time(n, var, t, fmt, ##__VA_ARGS__) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d4451846af93..1bf60f325608 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -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) { - if (verbose >= 2) { + if (verbose >= 2 || debug_peo_args) { fprintf(stderr, "%.60s\n", graph_dotted_line); fprintf(stderr, "perf_event_attr:\n"); perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL); @@ -1540,7 +1540,7 @@ static int perf_event_open(struct evsel *evsel, int fd; 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); 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; } - 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--; - 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); } @@ -1681,12 +1681,12 @@ retry_open: continue; } - pr_debug2("\nsys_perf_event_open failed, error %d\n", + pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", err); goto try_fallback; } - pr_debug2(" = %d\n", fd); + pr_debug2_peo(" = %d\n", fd); if (evsel->bpf_fd >= 0) { int evt_fd = fd; @@ -1754,58 +1754,58 @@ try_fallback: */ if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) { 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; } else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) { perf_missing_features.bpf = true; - pr_debug2("switching off bpf_event\n"); + pr_debug2_peo("switching off bpf_event\n"); goto fallback_missing_features; } else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) { perf_missing_features.ksymbol = true; - pr_debug2("switching off ksymbol\n"); + pr_debug2_peo("switching off ksymbol\n"); goto fallback_missing_features; } else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) { perf_missing_features.write_backward = true; - pr_debug2("switching off write_backward\n"); + pr_debug2_peo("switching off write_backward\n"); goto out_close; } else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) { perf_missing_features.clockid_wrong = true; - pr_debug2("switching off clockid\n"); + pr_debug2_peo("switching off clockid\n"); goto fallback_missing_features; } else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) { perf_missing_features.clockid = true; - pr_debug2("switching off use_clockid\n"); + pr_debug2_peo("switching off use_clockid\n"); goto fallback_missing_features; } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { perf_missing_features.cloexec = true; - pr_debug2("switching off cloexec flag\n"); + pr_debug2_peo("switching off cloexec flag\n"); goto fallback_missing_features; } else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) { perf_missing_features.mmap2 = true; - pr_debug2("switching off mmap2\n"); + pr_debug2_peo("switching off mmap2\n"); goto fallback_missing_features; } else if (!perf_missing_features.exclude_guest && (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) { 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; } else if (!perf_missing_features.sample_id_all) { 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; } else if (!perf_missing_features.lbr_flags && (evsel->core.attr.branch_sample_type & (PERF_SAMPLE_BRANCH_NO_CYCLES | PERF_SAMPLE_BRANCH_NO_FLAGS))) { 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; } else if (!perf_missing_features.group_read && evsel->core.attr.inherit && (evsel->core.attr.read_format & PERF_FORMAT_GROUP) && perf_evsel__is_group_leader(evsel)) { 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; } out_close: diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 25118605f3f8..83212c65848b 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -65,6 +65,7 @@ struct perf_env perf_env; * implementing 'verbose' and 'eprintf'. */ int verbose; +int debug_peo_args; int eprintf(int level, int var, const char *fmt, ...); From e1e9b78d3957a267346a86c8f2c433f6a332af65 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 8 Nov 2019 23:58:40 -0800 Subject: [PATCH 15/15] perf parse: Use YYABORT to clear stack after failure, plugging leaks Using return rather than YYABORT means that the stack isn't cleared up following a failure. The change to YYABORT means the return value is 1 rather than -1, but the callers just check for a result of 0 (success). Add missing free of a list when an error occurs in event_pmu. Signed-off-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20191109075840.181231-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.y | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 4cac830015be..e2eea4e601b4 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -284,6 +284,7 @@ PE_NAME opt_pmu_config do { \ parse_events_terms__delete($2); \ parse_events_terms__delete(orig_terms); \ + free(list); \ free($1); \ free(pattern); \ YYABORT; \ @@ -550,7 +551,7 @@ tracepoint_name opt_event_config free($1.event); if (err) { free(list); - return -1; + YYABORT; } $$ = list; }