From 23346f21b277e3aae5e9989e711a11cbe8133a45 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:17:50 -0300 Subject: perf tools: Rename "kernel_info" to "machine" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct kernel_info and kerninfo__ are too vague, what they really describe are machines, virtual ones or hosts. There are more changes to introduce helpers to shorten function calls and to make more clear what is really being done, but I left that for subsequent patches. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-buildid-list.c | 2 +- tools/perf/builtin-kmem.c | 8 +-- tools/perf/builtin-record.c | 36 +++++------ tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 15 ++--- tools/perf/util/event.c | 92 +++++++++++++------------- tools/perf/util/event.h | 4 +- tools/perf/util/header.c | 70 ++++++++++---------- tools/perf/util/header.h | 2 +- tools/perf/util/map.c | 105 +++++++++++++++--------------- tools/perf/util/map.h | 63 ++++++++---------- tools/perf/util/session.c | 4 +- tools/perf/util/session.h | 27 +++++++- tools/perf/util/symbol.c | 132 +++++++++++++++++--------------------- tools/perf/util/symbol.h | 3 +- 16 files changed, 280 insertions(+), 287 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f924b4332be..986b2efcef2 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -571,7 +571,7 @@ static int __cmd_annotate(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->kerninfo_root, stdout); + dsos__fprintf(&session->machines, stdout); perf_session__collapse_resort(&session->hists); perf_session__output_resort(&session->hists, session->event_total[0]); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 623afe3fdcb..b4a265ae3b9 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -46,7 +46,7 @@ static int __cmd_buildid_list(void) if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); - dsos__fprintf_buildid(&session->kerninfo_root, stdout, with_hits); + dsos__fprintf_buildid(&session->machines, stdout, with_hits); perf_session__delete(session); return err; diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ab906cbd5c7..20674759464 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -352,7 +352,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, int n_lines, int is_caller) { struct rb_node *next; - struct kernel_info *kerninfo; + struct machine *machine; printf("%.102s\n", graph_dotted_line); printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); @@ -361,8 +361,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session, next = rb_first(root); - kerninfo = kerninfo__findhost(&session->kerninfo_root); - if (!kerninfo) { + machine = perf_session__find_host_machine(session); + if (!machine) { pr_err("__print_result: couldn't find kernel information\n"); return; } @@ -370,7 +370,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; - struct map_groups *kmaps = &kerninfo->kmaps; + struct map_groups *kmaps = &machine->kmaps; struct map *map; char buf[BUFSIZ]; u64 addr; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 27f992aca8b..83b308a035c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -456,14 +456,14 @@ static void atexit_header(void) } } -static void event__synthesize_guest_os(struct kernel_info *kerninfo, - void *data __attribute__((unused))) +static void event__synthesize_guest_os(struct machine *machine, void *data) { int err; char *guest_kallsyms; char path[PATH_MAX]; + struct perf_session *psession = data; - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) return; /* @@ -475,16 +475,15 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, *in module instead of in guest kernel. */ err = event__synthesize_modules(process_synthesized_event, - session, - kerninfo); + psession, machine); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" - " relocation symbol.\n", kerninfo->pid); + " relocation symbol.\n", machine->pid); - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); guest_kallsyms = path; } @@ -493,13 +492,13 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, * have no _text sometimes. */ err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_text"); + psession, machine, "_text"); if (err < 0) err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_stext"); + psession, machine, "_stext"); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" - " relocation symbol.\n", kerninfo->pid); + " relocation symbol.\n", machine->pid); } static int __cmd_record(int argc, const char **argv) @@ -513,7 +512,7 @@ static int __cmd_record(int argc, const char **argv) int child_ready_pipe[2], go_pipe[2]; const bool forks = argc > 0; char buf; - struct kernel_info *kerninfo; + struct machine *machine; page_size = sysconf(_SC_PAGE_SIZE); @@ -682,31 +681,30 @@ static int __cmd_record(int argc, const char **argv) advance_output(err); } - kerninfo = kerninfo__findhost(&session->kerninfo_root); - if (!kerninfo) { + machine = perf_session__find_host_machine(session); + if (!machine) { pr_err("Couldn't find native kernel information.\n"); return -1; } err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_text"); + session, machine, "_text"); if (err < 0) err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_stext"); + session, machine, "_stext"); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } err = event__synthesize_modules(process_synthesized_event, - session, kerninfo); + session, machine); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } if (perf_guest) - kerninfo__process_allkernels(&session->kerninfo_root, - event__synthesize_guest_os, session); + perf_session__process_machines(session, event__synthesize_guest_os); if (!system_wide && profile_cpu == -1) event__synthesize_thread(target_tid, process_synthesized_event, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 816edae7c5b..49cc367d8c3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -313,7 +313,7 @@ static int __cmd_report(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->kerninfo_root, stdout); + dsos__fprintf(&session->machines, stdout); next = rb_first(&session->stats_by_id); while (next) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index dfd7ea7dabd..c390f340b03 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -854,7 +854,7 @@ static void handle_keypress(struct perf_session *session, int c) case 'Q': printf("exiting.\n"); if (dump_symtab) - dsos__fprintf(&session->kerninfo_root, stderr); + dsos__fprintf(&session->machines, stderr); exit(0); case 's': prompt_symbol(&sym_filter_entry, "Enter details symbol"); @@ -982,7 +982,7 @@ static void event__process_sample(const event_t *self, u64 ip = self->ip.ip; struct sym_entry *syme; struct addr_location al; - struct kernel_info *kerninfo; + struct machine *machine; u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; ++samples; @@ -992,18 +992,17 @@ static void event__process_sample(const event_t *self, ++us_samples; if (hide_user_symbols) return; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_KERNEL: ++kernel_samples; if (hide_kernel_symbols) return; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_GUEST_KERNEL: ++guest_kernel_samples; - kerninfo = kerninfo__find(&session->kerninfo_root, - self->ip.pid); + machine = perf_session__find_machine(session, self->ip.pid); break; case PERF_RECORD_MISC_GUEST_USER: ++guest_us_samples; @@ -1016,7 +1015,7 @@ static void event__process_sample(const event_t *self, return; } - if (!kerninfo && perf_guest) { + if (!machine && perf_guest) { pr_err("Can't find guest [%d]'s kernel information\n", self->ip.pid); return; @@ -1041,7 +1040,7 @@ static void event__process_sample(const event_t *self, * --hide-kernel-symbols, even if the user specifies an * invalid --vmlinux ;-) */ - if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] && + if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { pr_err("The %s file can't be used\n", symbol_conf.vmlinux_name); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e3fa8d3d11b..2f33ca9899b 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -172,17 +172,17 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, int event__synthesize_modules(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo) + struct machine *machine) { struct rb_node *nd; - struct map_groups *kmaps = &kerninfo->kmaps; + struct map_groups *kmaps = &machine->kmaps; u16 misc; /* * kernel uses 0 for user space maps, see kernel/perf_event.c * __perf_event_mmap */ - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) misc = PERF_RECORD_MISC_KERNEL; else misc = PERF_RECORD_MISC_GUEST_KERNEL; @@ -204,7 +204,7 @@ int event__synthesize_modules(event__handler_t process, (sizeof(ev.mmap.filename) - size)); ev.mmap.start = pos->start; ev.mmap.len = pos->end - pos->start; - ev.mmap.pid = kerninfo->pid; + ev.mmap.pid = machine->pid; memcpy(ev.mmap.filename, pos->dso->long_name, pos->dso->long_name_len + 1); @@ -267,7 +267,7 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start) int event__synthesize_kernel_mmap(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo, + struct machine *machine, const char *symbol_name) { size_t size; @@ -288,8 +288,8 @@ int event__synthesize_kernel_mmap(event__handler_t process, */ struct process_symbol_args args = { .name = symbol_name, }; - mmap_name = kern_mmap_name(kerninfo, name_buff); - if (is_host_kernel(kerninfo)) { + mmap_name = machine__mmap_name(machine, name_buff); + if (machine__is_host(machine)) { /* * kernel uses PERF_RECORD_MISC_USER for user space maps, * see kernel/perf_event.c __perf_event_mmap @@ -298,10 +298,10 @@ int event__synthesize_kernel_mmap(event__handler_t process, filename = "/proc/kallsyms"; } else { ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) filename = (char *) symbol_conf.default_guest_kallsyms; else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); filename = path; } } @@ -309,7 +309,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) return -ENOENT; - map = kerninfo->vmlinux_maps[MAP__FUNCTION]; + map = machine->vmlinux_maps[MAP__FUNCTION]; size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), "%s%s", mmap_name, symbol_name) + 1; size = ALIGN(size, sizeof(u64)); @@ -318,7 +318,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, ev.mmap.pgoff = args.start; ev.mmap.start = map->start; ev.mmap.len = map->end - ev.mmap.start; - ev.mmap.pid = kerninfo->pid; + ev.mmap.pid = machine->pid; return process(&ev, session); } @@ -389,18 +389,18 @@ static int event__process_kernel_mmap(event_t *self, { struct map *map; char kmmap_prefix[PATH_MAX]; - struct kernel_info *kerninfo; + struct machine *machine; enum dso_kernel_type kernel_type; bool is_kernel_mmap; - kerninfo = kerninfo__findnew(&session->kerninfo_root, self->mmap.pid); - if (!kerninfo) { - pr_err("Can't find id %d's kerninfo\n", self->mmap.pid); + machine = perf_session__findnew_machine(session, self->mmap.pid); + if (!machine) { + pr_err("Can't find id %d's machine\n", self->mmap.pid); goto out_problem; } - kern_mmap_name(kerninfo, kmmap_prefix); - if (is_host_kernel(kerninfo)) + machine__mmap_name(machine, kmmap_prefix); + if (machine__is_host(machine)) kernel_type = DSO_TYPE_KERNEL; else kernel_type = DSO_TYPE_GUEST_KERNEL; @@ -429,10 +429,9 @@ static int event__process_kernel_mmap(event_t *self, } else strcpy(short_module_name, self->mmap.filename); - map = map_groups__new_module(&kerninfo->kmaps, - self->mmap.start, - self->mmap.filename, - kerninfo); + map = map_groups__new_module(&machine->kmaps, + self->mmap.start, + self->mmap.filename, machine); if (map == NULL) goto out_problem; @@ -449,27 +448,27 @@ static int event__process_kernel_mmap(event_t *self, * Should be there already, from the build-id table in * the header. */ - struct dso *kernel = __dsos__findnew(&kerninfo->dsos__kernel, - kmmap_prefix); + struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, + kmmap_prefix); if (kernel == NULL) goto out_problem; kernel->kernel = kernel_type; - if (__map_groups__create_kernel_maps(&kerninfo->kmaps, - kerninfo->vmlinux_maps, kernel) < 0) + if (__map_groups__create_kernel_maps(&machine->kmaps, + machine->vmlinux_maps, + kernel) < 0) goto out_problem; - event_set_kernel_mmap_len(kerninfo->vmlinux_maps, self); - perf_session__set_kallsyms_ref_reloc_sym(kerninfo->vmlinux_maps, - symbol_name, - self->mmap.pgoff); - if (is_default_guest(kerninfo)) { + event_set_kernel_mmap_len(machine->vmlinux_maps, self); + perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, + symbol_name, + self->mmap.pgoff); + if (machine__is_default_guest(machine)) { /* * preload dso of guest kernel and modules */ - dso__load(kernel, - kerninfo->vmlinux_maps[MAP__FUNCTION], - NULL); + dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], + NULL); } } return 0; @@ -479,7 +478,7 @@ out_problem: int event__process_mmap(event_t *self, struct perf_session *session) { - struct kernel_info *kerninfo; + struct machine *machine; struct thread *thread; struct map *map; u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; @@ -498,8 +497,8 @@ int event__process_mmap(event_t *self, struct perf_session *session) } thread = perf_session__findnew(session, self->mmap.pid); - kerninfo = kerninfo__findhost(&session->kerninfo_root); - map = map__new(&kerninfo->dsos__user, self->mmap.start, + machine = perf_session__find_host_machine(session); + map = map__new(&machine->user_dsos, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.pid, self->mmap.filename, MAP__FUNCTION, session->cwd, session->cwdlen); @@ -546,7 +545,7 @@ void thread__find_addr_map(struct thread *self, struct addr_location *al) { struct map_groups *mg = &self->mg; - struct kernel_info *kerninfo = NULL; + struct machine *machine = NULL; al->thread = self; al->addr = addr; @@ -555,19 +554,19 @@ void thread__find_addr_map(struct thread *self, if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; - kerninfo = kerninfo__findhost(&session->kerninfo_root); - mg = &kerninfo->kmaps; + machine = perf_session__find_host_machine(session); + mg = &machine->kmaps; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; - kerninfo = kerninfo__find(&session->kerninfo_root, pid); - if (!kerninfo) { + machine = perf_session__find_machine(session, pid); + if (!machine) { al->map = NULL; return; } - mg = &kerninfo->kmaps; + mg = &machine->kmaps; } else { /* * 'u' means guest os user space. @@ -603,10 +602,9 @@ try_again: * in the whole kernel symbol list. */ if ((long long)al->addr < 0 && - cpumode == PERF_RECORD_MISC_KERNEL && - kerninfo && - mg != &kerninfo->kmaps) { - mg = &kerninfo->kmaps; + cpumode == PERF_RECORD_MISC_KERNEL && + machine && mg != &machine->kmaps) { + mg = &machine->kmaps; goto try_again; } } else diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 4af2ed5d48a..b364da5b0cb 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -156,12 +156,12 @@ void event__synthesize_threads(event__handler_t process, struct perf_session *session); int event__synthesize_kernel_mmap(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo, + struct machine *machine, const char *symbol_name); int event__synthesize_modules(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo); + struct machine *machine); int event__process_comm(event_t *self, struct perf_session *session); int event__process_lost(event_t *self, struct perf_session *session); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 75d01676802..6227dc4cb2c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -229,10 +229,9 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) int err = 0; u16 kmisc, umisc; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - if (is_host_kernel(pos)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + if (machine__is_host(pos)) { kmisc = PERF_RECORD_MISC_KERNEL; umisc = PERF_RECORD_MISC_USER; } else { @@ -240,11 +239,11 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) umisc = PERF_RECORD_MISC_GUEST_USER; } - err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, - kmisc, fd); + err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid, + kmisc, fd); if (err == 0) - err = __dsos__write_buildid_table(&pos->dsos__user, - pos->pid, umisc, fd); + err = __dsos__write_buildid_table(&pos->user_dsos, + pos->pid, umisc, fd); if (err) break; } @@ -378,11 +377,10 @@ static int dsos__cache_build_ids(struct perf_header *self) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) return -1; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); - ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir); + ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir); } return ret ? -1 : 0; } @@ -394,11 +392,10 @@ static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) struct perf_session, header); struct rb_node *nd; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); - ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits); + ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits); } return ret; @@ -685,13 +682,13 @@ static int __event_process_build_id(struct build_id_event *bev, { int err = -1; struct list_head *head; - struct kernel_info *kerninfo; + struct machine *machine; u16 misc; struct dso *dso; enum dso_kernel_type dso_type; - kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); - if (!kerninfo) + machine = perf_session__findnew_machine(session, bev->pid); + if (!machine) goto out; misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; @@ -699,16 +696,16 @@ static int __event_process_build_id(struct build_id_event *bev, switch (misc) { case PERF_RECORD_MISC_KERNEL: dso_type = DSO_TYPE_KERNEL; - head = &kerninfo->dsos__kernel; + head = &machine->kernel_dsos; break; case PERF_RECORD_MISC_GUEST_KERNEL: dso_type = DSO_TYPE_GUEST_KERNEL; - head = &kerninfo->dsos__kernel; + head = &machine->kernel_dsos; break; case PERF_RECORD_MISC_USER: case PERF_RECORD_MISC_GUEST_USER: dso_type = DSO_TYPE_USER; - head = &kerninfo->dsos__user; + head = &machine->user_dsos; break; default: goto out; @@ -1113,8 +1110,7 @@ int event__process_tracing_data(event_t *self, } int event__synthesize_build_id(struct dso *pos, u16 misc, - event__handler_t process, - struct kernel_info *kerninfo, + event__handler_t process, struct machine *machine, struct perf_session *session) { event_t ev; @@ -1131,7 +1127,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; ev.build_id.header.misc = misc; - ev.build_id.pid = kerninfo->pid; + ev.build_id.pid = machine->pid; ev.build_id.header.size = sizeof(ev.build_id) + len; memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); @@ -1142,7 +1138,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, static int __event_synthesize_build_ids(struct list_head *head, u16 misc, event__handler_t process, - struct kernel_info *kerninfo, + struct machine *machine, struct perf_session *session) { struct dso *pos; @@ -1153,7 +1149,7 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, continue; err = event__synthesize_build_id(pos, misc, process, - kerninfo, session); + machine, session); if (err < 0) return err; } @@ -1166,15 +1162,15 @@ int event__synthesize_build_ids(event__handler_t process, { int err = 0; u16 kmisc, umisc; - struct kernel_info *pos; + struct machine *pos; struct rb_node *nd; if (!dsos__read_build_ids(&session->header, true)) return 0; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct kernel_info, rb_node); - if (is_host_kernel(pos)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct machine, rb_node); + if (machine__is_host(pos)) { kmisc = PERF_RECORD_MISC_KERNEL; umisc = PERF_RECORD_MISC_USER; } else { @@ -1182,11 +1178,11 @@ int event__synthesize_build_ids(event__handler_t process, umisc = PERF_RECORD_MISC_GUEST_USER; } - err = __event_synthesize_build_ids(&pos->dsos__kernel, - kmisc, process, pos, session); + err = __event_synthesize_build_ids(&pos->kernel_dsos, kmisc, + process, pos, session); if (err == 0) - err = __event_synthesize_build_ids(&pos->dsos__user, - umisc, process, pos, session); + err = __event_synthesize_build_ids(&pos->user_dsos, umisc, + process, pos, session); if (err) break; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 27591545814..f39443db070 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -120,7 +120,7 @@ int event__process_tracing_data(event_t *self, int event__synthesize_build_id(struct dso *pos, u16 misc, event__handler_t process, - struct kernel_info *kerninfo, + struct machine *machine, struct perf_session *session); int event__synthesize_build_ids(event__handler_t process, struct perf_session *session); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 7facd016ec9..da3d4e82623 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -245,7 +245,7 @@ void map_groups__init(struct map_groups *self) self->maps[i] = RB_ROOT; INIT_LIST_HEAD(&self->removed_maps[i]); } - self->this_kerninfo = NULL; + self->machine = NULL; } void map_groups__flush(struct map_groups *self) @@ -513,133 +513,130 @@ struct map *maps__find(struct rb_root *maps, u64 ip) return NULL; } -struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, - pid_t pid, const char *root_dir) +struct machine *machines__add(struct rb_root *self, pid_t pid, + const char *root_dir) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo, *pos; + struct machine *pos, *machine = malloc(sizeof(*machine)); - kerninfo = malloc(sizeof(struct kernel_info)); - if (!kerninfo) + if (!machine) return NULL; - kerninfo->pid = pid; - map_groups__init(&kerninfo->kmaps); - kerninfo->root_dir = strdup(root_dir); - RB_CLEAR_NODE(&kerninfo->rb_node); - INIT_LIST_HEAD(&kerninfo->dsos__user); - INIT_LIST_HEAD(&kerninfo->dsos__kernel); - kerninfo->kmaps.this_kerninfo = kerninfo; + machine->pid = pid; + map_groups__init(&machine->kmaps); + machine->root_dir = strdup(root_dir); + RB_CLEAR_NODE(&machine->rb_node); + INIT_LIST_HEAD(&machine->user_dsos); + INIT_LIST_HEAD(&machine->kernel_dsos); + machine->kmaps.machine = machine; while (*p != NULL) { parent = *p; - pos = rb_entry(parent, struct kernel_info, rb_node); + pos = rb_entry(parent, struct machine, rb_node); if (pid < pos->pid) p = &(*p)->rb_left; else p = &(*p)->rb_right; } - rb_link_node(&kerninfo->rb_node, parent, p); - rb_insert_color(&kerninfo->rb_node, kerninfo_root); + rb_link_node(&machine->rb_node, parent, p); + rb_insert_color(&machine->rb_node, self); - return kerninfo; + return machine; } -struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid) +struct machine *machines__find(struct rb_root *self, pid_t pid) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo; - struct kernel_info *default_kerninfo = NULL; + struct machine *machine; + struct machine *default_machine = NULL; while (*p != NULL) { parent = *p; - kerninfo = rb_entry(parent, struct kernel_info, rb_node); - if (pid < kerninfo->pid) + machine = rb_entry(parent, struct machine, rb_node); + if (pid < machine->pid) p = &(*p)->rb_left; - else if (pid > kerninfo->pid) + else if (pid > machine->pid) p = &(*p)->rb_right; else - return kerninfo; - if (!kerninfo->pid) - default_kerninfo = kerninfo; + return machine; + if (!machine->pid) + default_machine = machine; } - return default_kerninfo; + return default_machine; } -struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root) +/* + * FIXME: Why repeatedly search for this? + */ +struct machine *machines__find_host(struct rb_root *self) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo; + struct machine *machine; pid_t pid = HOST_KERNEL_ID; while (*p != NULL) { parent = *p; - kerninfo = rb_entry(parent, struct kernel_info, rb_node); - if (pid < kerninfo->pid) + machine = rb_entry(parent, struct machine, rb_node); + if (pid < machine->pid) p = &(*p)->rb_left; - else if (pid > kerninfo->pid) + else if (pid > machine->pid) p = &(*p)->rb_right; else - return kerninfo; + return machine; } return NULL; } -struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid) +struct machine *machines__findnew(struct rb_root *self, pid_t pid) { char path[PATH_MAX]; const char *root_dir; - int ret; - struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid); + struct machine *machine = machines__find(self, pid); - if (!kerninfo || kerninfo->pid != pid) { + if (!machine || machine->pid != pid) { if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) root_dir = ""; else { if (!symbol_conf.guestmount) goto out; sprintf(path, "%s/%d", symbol_conf.guestmount, pid); - ret = access(path, R_OK); - if (ret) { + if (access(path, R_OK)) { pr_err("Can't access file %s\n", path); goto out; } root_dir = path; } - kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir); + machine = machines__add(self, pid, root_dir); } out: - return kerninfo; + return machine; } -void kerninfo__process_allkernels(struct rb_root *kerninfo_root, - process_kernel_info process, - void *data) +void machines__process(struct rb_root *self, machine__process_t process, void *data) { struct rb_node *nd; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); + for (nd = rb_first(self); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); process(pos, data); } } -char *kern_mmap_name(struct kernel_info *kerninfo, char *buff) +char *machine__mmap_name(struct machine *self, char *buff) { - if (is_host_kernel(kerninfo)) + if (machine__is_host(self)) sprintf(buff, "[%s]", "kernel.kallsyms"); - else if (is_default_guest(kerninfo)) + else if (machine__is_default_guest(self)) sprintf(buff, "[%s]", "guest.kernel.kallsyms"); else - sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid); + sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", self->pid); return buff; } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 30d38d634e0..4c1c2da704b 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "types.h" enum map_type { @@ -19,7 +20,7 @@ extern const char *map_type__name[MAP__NR_TYPES]; struct dso; struct ref_reloc_sym; struct map_groups; -struct kernel_info; +struct machine; struct map { union { @@ -46,23 +47,23 @@ struct kmap { }; struct map_groups { - struct rb_root maps[MAP__NR_TYPES]; - struct list_head removed_maps[MAP__NR_TYPES]; - struct kernel_info *this_kerninfo; + struct rb_root maps[MAP__NR_TYPES]; + struct list_head removed_maps[MAP__NR_TYPES]; + struct machine *machine; }; -/* Native host kernel uses -1 as pid index in kernel_info */ +/* Native host kernel uses -1 as pid index in machine */ #define HOST_KERNEL_ID (-1) #define DEFAULT_GUEST_KERNEL_ID (0) -struct kernel_info { - struct rb_node rb_node; - pid_t pid; - char *root_dir; - struct list_head dsos__user; - struct list_head dsos__kernel; +struct machine { + struct rb_node rb_node; + pid_t pid; + char *root_dir; + struct list_head user_dsos; + struct list_head kernel_dsos; struct map_groups kmaps; - struct map *vmlinux_maps[MAP__NR_TYPES]; + struct map *vmlinux_maps[MAP__NR_TYPES]; }; static inline struct kmap *map__kmap(struct map *self) @@ -124,36 +125,30 @@ int map_groups__clone(struct map_groups *self, size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); -struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, - pid_t pid, const char *root_dir); -struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid); -struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid); -struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root); -char *kern_mmap_name(struct kernel_info *kerninfo, char *buff); +typedef void (*machine__process_t)(struct machine *self, void *data); + +void machines__process(struct rb_root *self, machine__process_t process, void *data); +struct machine *machines__add(struct rb_root *self, pid_t pid, + const char *root_dir); +struct machine *machines__find_host(struct rb_root *self); +struct machine *machines__find(struct rb_root *self, pid_t pid); +struct machine *machines__findnew(struct rb_root *self, pid_t pid); +char *machine__mmap_name(struct machine *self, char *buff); /* * Default guest kernel is defined by parameter --guestkallsyms * and --guestmodules */ -static inline int is_default_guest(struct kernel_info *kerninfo) +static inline bool machine__is_default_guest(struct machine *self) { - if (!kerninfo) - return 0; - return kerninfo->pid == DEFAULT_GUEST_KERNEL_ID; + return self ? self->pid == DEFAULT_GUEST_KERNEL_ID : false; } -static inline int is_host_kernel(struct kernel_info *kerninfo) +static inline bool machine__is_host(struct machine *self) { - if (!kerninfo) - return 0; - return kerninfo->pid == HOST_KERNEL_ID; + return self ? self->pid == HOST_KERNEL_ID : false; } -typedef void (*process_kernel_info)(struct kernel_info *kerninfo, void *data); -void kerninfo__process_allkernels(struct rb_root *kerninfo_root, - process_kernel_info process, - void *data); - static inline void map_groups__insert(struct map_groups *self, struct map *map) { maps__insert(&self->maps[map->type], map); @@ -197,10 +192,8 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); -struct map *map_groups__new_module(struct map_groups *self, - u64 start, - const char *filename, - struct kernel_info *kerninfo); +struct map *map_groups__new_module(struct map_groups *self, u64 start, + const char *filename, struct machine *machine); void map_groups__flush(struct map_groups *self); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b7aade2184b..b745c1c0b6c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -70,7 +70,7 @@ void perf_session__update_sample_type(struct perf_session *self) int perf_session__create_kernel_maps(struct perf_session *self) { int ret; - struct rb_root *root = &self->kerninfo_root; + struct rb_root *root = &self->machines; ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); if (ret >= 0) @@ -97,7 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->cwd = NULL; self->cwdlen = 0; self->unknown_events = 0; - self->kerninfo_root = RB_ROOT; + self->machines = RB_ROOT; self->ordered_samples.flush_limit = ULLONG_MAX; INIT_LIST_HEAD(&self->ordered_samples.samples_head); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 796e2291ebd..71252723a17 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -25,7 +25,7 @@ struct perf_session { unsigned long mmap_window; struct rb_root threads; struct thread *last_match; - struct rb_root kerninfo_root; + struct rb_root machines; struct events_stats events_stats; struct rb_root stats_by_id; unsigned long event_total[PERF_RECORD_MAX]; @@ -102,4 +102,29 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline, const char *input_name); #endif + +static inline +struct machine *perf_session__find_host_machine(struct perf_session *self) +{ + return machines__find_host(&self->machines); +} + +static inline +struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) +{ + return machines__find(&self->machines, pid); +} + +static inline +struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) +{ + return machines__findnew(&self->machines, pid); +} + +static inline +void perf_session__process_machines(struct perf_session *self, + machine__process_t process) +{ + return machines__process(&self->machines, process, self); +} #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e77c33a11de..dc046368b5c 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -485,7 +485,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, symbol_filter_t filter) { struct map_groups *kmaps = map__kmap(map)->kmaps; - struct kernel_info *kerninfo = kmaps->this_kerninfo; + struct machine *machine = kmaps->machine; struct map *curr_map = map; struct symbol *pos; int count = 0; @@ -508,8 +508,8 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, if (strcmp(curr_map->dso->short_name, module)) { if (curr_map != map && - self->kernel == DSO_TYPE_GUEST_KERNEL && - is_default_guest(kerninfo)) { + self->kernel == DSO_TYPE_GUEST_KERNEL && + machine__is_default_guest(machine)) { /* * We assume all symbols of a module are * continuous in * kallsyms, so curr_map @@ -527,13 +527,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, pr_err("%s/proc/{kallsyms,modules} " "inconsistency while looking " "for \"%s\" module!\n", - kerninfo->root_dir, module); + machine->root_dir, module); curr_map = map; goto discard_symbol; } if (curr_map->dso->loaded && - !is_default_guest(kmaps->this_kerninfo)) + !machine__is_default_guest(machine)) goto discard_symbol; } /* @@ -586,7 +586,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); if (curr_map != map && self->kernel == DSO_TYPE_GUEST_KERNEL && - is_default_guest(kmaps->this_kerninfo)) { + machine__is_default_guest(kmaps->machine)) { dso__set_loaded(curr_map->dso, curr_map->type); } @@ -1291,7 +1291,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) char build_id_hex[BUILD_ID_SIZE * 2 + 1]; int ret = -1; int fd; - struct kernel_info *kerninfo; + struct machine *machine; const char *root_dir; dso__set_loaded(self, map->type); @@ -1301,10 +1301,10 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) else if (self->kernel == DSO_TYPE_GUEST_KERNEL) return dso__load_guest_kernel_sym(self, map, filter); - if (map->groups && map->groups->this_kerninfo) - kerninfo = map->groups->this_kerninfo; + if (map->groups && map->groups->machine) + machine = map->groups->machine; else - kerninfo = NULL; + machine = NULL; name = malloc(size); if (!name) @@ -1359,8 +1359,8 @@ more: snprintf(name, size, "%s", self->long_name); break; case DSO__ORIG_GUEST_KMODULE: - if (map->groups && map->groups->this_kerninfo) - root_dir = map->groups->this_kerninfo->root_dir; + if (map->groups && map->groups->machine) + root_dir = map->groups->machine->root_dir; else root_dir = ""; snprintf(name, size, "%s%s", root_dir, self->long_name); @@ -1566,12 +1566,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) struct map *map_groups__new_module(struct map_groups *self, u64 start, const char *filename, - struct kernel_info *kerninfo) + struct machine *machine) { struct map *map; struct dso *dso; - dso = __dsos__findnew(&kerninfo->dsos__kernel, filename); + dso = __dsos__findnew(&machine->kernel_dsos, filename); if (dso == NULL) return NULL; @@ -1579,7 +1579,7 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, if (map == NULL) return NULL; - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) dso->origin = DSO__ORIG_KMODULE; else dso->origin = DSO__ORIG_GUEST_KMODULE; @@ -1587,7 +1587,7 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, return map; } -static int map_groups__create_modules(struct kernel_info *kerninfo) +static int map_groups__create_modules(struct machine *machine) { char *line = NULL; size_t n; @@ -1597,10 +1597,10 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) const char *modules; char path[PATH_MAX]; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) modules = symbol_conf.default_guest_modules; else { - sprintf(path, "%s/proc/modules", kerninfo->root_dir); + sprintf(path, "%s/proc/modules", machine->root_dir); modules = path; } @@ -1608,7 +1608,7 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) if (file == NULL) return -1; - root_dir = kerninfo->root_dir; + root_dir = machine->root_dir; while (!feof(file)) { char name[PATH_MAX]; @@ -1638,8 +1638,8 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = map_groups__new_module(&kerninfo->kmaps, - start, name, kerninfo); + map = map_groups__new_module(&machine->kmaps, start, + name, machine); if (map == NULL) goto out_delete_line; dso__kernel_module_get_build_id(map->dso, root_dir); @@ -1648,7 +1648,7 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) free(line); fclose(file); - return map_groups__set_modules_path(&kerninfo->kmaps, root_dir); + return map_groups__set_modules_path(&machine->kmaps, root_dir); out_delete_line: free(line); @@ -1820,16 +1820,16 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, { int err; const char *kallsyms_filename = NULL; - struct kernel_info *kerninfo; + struct machine *machine; char path[PATH_MAX]; if (!map->groups) { pr_debug("Guest kernel map hasn't the point to groups\n"); return -1; } - kerninfo = map->groups->this_kerninfo; + machine = map->groups->machine; - if (is_default_guest(kerninfo)) { + if (machine__is_default_guest(machine)) { /* * if the user specified a vmlinux filename, use it and only * it, reporting errors to the user if it cannot be used. @@ -1845,7 +1845,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, if (!kallsyms_filename) return -1; } else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); kallsyms_filename = path; } @@ -1856,9 +1856,8 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, out_try_fixup: if (err > 0) { if (kallsyms_filename != NULL) { - kern_mmap_name(kerninfo, path); - dso__set_long_name(self, - strdup(path)); + machine__mmap_name(machine, path); + dso__set_long_name(self, strdup(path)); } map__fixup_start(map); map__fixup_end(map); @@ -1908,15 +1907,14 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp) } } -void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp) +void dsos__fprintf(struct rb_root *machines, FILE *fp) { struct rb_node *nd; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - __dsos__fprintf(&pos->dsos__kernel, fp); - __dsos__fprintf(&pos->dsos__user, fp); + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + __dsos__fprintf(&pos->kernel_dsos, fp); + __dsos__fprintf(&pos->user_dsos, fp); } } @@ -1935,19 +1933,15 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, - FILE *fp, bool with_hits) +size_t dsos__fprintf_buildid(struct rb_root *machines, FILE *fp, bool with_hits) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret += __dsos__fprintf_buildid(&pos->dsos__kernel, - fp, with_hits); - ret += __dsos__fprintf_buildid(&pos->dsos__user, - fp, with_hits); + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); + ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); } return ret; } @@ -1964,14 +1958,12 @@ struct dso *dso__new_kernel(const char *name) return self; } -static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, +static struct dso *dso__new_guest_kernel(struct machine *machine, const char *name) { char buff[PATH_MAX]; - struct dso *self; + struct dso *self = dso__new(name ?: machine__mmap_name(machine, buff)); - kern_mmap_name(kerninfo, buff); - self = dso__new(name ?: buff); if (self != NULL) { dso__set_short_name(self, "[guest.kernel]"); self->kernel = DSO_TYPE_GUEST_KERNEL; @@ -1980,36 +1972,35 @@ static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, return self; } -void dso__read_running_kernel_build_id(struct dso *self, - struct kernel_info *kerninfo) +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine) { char path[PATH_MAX]; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) return; - sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir); + sprintf(path, "%s/sys/kernel/notes", machine->root_dir); if (sysfs__read_build_id(path, self->build_id, sizeof(self->build_id)) == 0) self->has_build_id = true; } -static struct dso *dsos__create_kernel(struct kernel_info *kerninfo) +static struct dso *dsos__create_kernel(struct machine *machine) { const char *vmlinux_name = NULL; struct dso *kernel; - if (is_host_kernel(kerninfo)) { + if (machine__is_host(machine)) { vmlinux_name = symbol_conf.vmlinux_name; kernel = dso__new_kernel(vmlinux_name); } else { - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) vmlinux_name = symbol_conf.default_guest_vmlinux_name; - kernel = dso__new_guest_kernel(kerninfo, vmlinux_name); + kernel = dso__new_guest_kernel(machine, vmlinux_name); } if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel, kerninfo); - dsos__add(&kerninfo->dsos__kernel, kernel); + dso__read_running_kernel_build_id(kernel, machine); + dsos__add(&machine->kernel_dsos, kernel); } return kernel; } @@ -2154,29 +2145,28 @@ out_free_comm_list: return -1; } -int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid) +int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) { - struct kernel_info *kerninfo; struct dso *kernel; + struct machine *machine = machines__findnew(machines, pid); - kerninfo = kerninfo__findnew(kerninfo_root, pid); - if (kerninfo == NULL) + if (machine == NULL) return -1; - kernel = dsos__create_kernel(kerninfo); + kernel = dsos__create_kernel(machine); if (kernel == NULL) return -1; - if (__map_groups__create_kernel_maps(&kerninfo->kmaps, - kerninfo->vmlinux_maps, kernel) < 0) + if (__map_groups__create_kernel_maps(&machine->kmaps, + machine->vmlinux_maps, kernel) < 0) return -1; if (symbol_conf.use_modules && - map_groups__create_modules(kerninfo) < 0) + map_groups__create_modules(machine) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - map_groups__fixup_end(&kerninfo->kmaps); + map_groups__fixup_end(&machine->kmaps); return 0; } @@ -2223,7 +2213,7 @@ char *strxfrchar(char *s, char from, char to) return s; } -int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) +int map_groups__create_guest_kernel_maps(struct rb_root *machines) { int ret = 0; struct dirent **namelist = NULL; @@ -2234,8 +2224,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || symbol_conf.default_guest_kallsyms) { - map_groups__create_kernel_maps(kerninfo_root, - DEFAULT_GUEST_KERNEL_ID); + map_groups__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); } if (symbol_conf.guestmount) { @@ -2256,8 +2245,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) pr_debug("Can't access file %s\n", path); goto failure; } - map_groups__create_kernel_maps(kerninfo_root, - pid); + map_groups__create_kernel_maps(machines, pid); } failure: free(namelist); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 478f5ab3778..ed885b06a02 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -186,8 +186,7 @@ enum dso_origin { char dso__symtab_origin(const struct dso *self); void dso__set_long_name(struct dso *self, char *name); void dso__set_build_id(struct dso *self, void *build_id); -void dso__read_running_kernel_build_id(struct dso *self, - struct kernel_info *kerninfo); +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name); -- cgit v1.2.3-70-g09d2 From 48ea8f5470aa6f35244d1b218316705ea88c0259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:19:05 -0300 Subject: perf machine: Pass buffer size to machine__mmap_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't blindly assume that the size of the buffer is enough, use snprintf. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 4 ++-- tools/perf/util/map.c | 10 +++++----- tools/perf/util/map.h | 2 +- tools/perf/util/symbol.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2f33ca9899b..7400e5147e1 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -288,7 +288,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, */ struct process_symbol_args args = { .name = symbol_name, }; - mmap_name = machine__mmap_name(machine, name_buff); + mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); if (machine__is_host(machine)) { /* * kernel uses PERF_RECORD_MISC_USER for user space maps, @@ -399,7 +399,7 @@ static int event__process_kernel_mmap(event_t *self, goto out_problem; } - machine__mmap_name(machine, kmmap_prefix); + machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); if (machine__is_host(machine)) kernel_type = DSO_TYPE_KERNEL; else diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index da3d4e82623..ee25ee91504 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -629,14 +629,14 @@ void machines__process(struct rb_root *self, machine__process_t process, void *d } } -char *machine__mmap_name(struct machine *self, char *buff) +char *machine__mmap_name(struct machine *self, char *bf, size_t size) { if (machine__is_host(self)) - sprintf(buff, "[%s]", "kernel.kallsyms"); + snprintf(bf, size, "[%s]", "kernel.kallsyms"); else if (machine__is_default_guest(self)) - sprintf(buff, "[%s]", "guest.kernel.kallsyms"); + snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); else - sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", self->pid); + snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid); - return buff; + return bf; } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 4c1c2da704b..6fabad1fd02 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -133,7 +133,7 @@ struct machine *machines__add(struct rb_root *self, pid_t pid, struct machine *machines__find_host(struct rb_root *self); struct machine *machines__find(struct rb_root *self, pid_t pid); struct machine *machines__findnew(struct rb_root *self, pid_t pid); -char *machine__mmap_name(struct machine *self, char *buff); +char *machine__mmap_name(struct machine *self, char *bf, size_t size); /* * Default guest kernel is defined by parameter --guestkallsyms diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index dc046368b5c..c9c0bdd667a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1856,7 +1856,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, out_try_fixup: if (err > 0) { if (kallsyms_filename != NULL) { - machine__mmap_name(machine, path); + machine__mmap_name(machine, path, sizeof(path)); dso__set_long_name(self, strdup(path)); } map__fixup_start(map); @@ -1961,8 +1961,8 @@ struct dso *dso__new_kernel(const char *name) static struct dso *dso__new_guest_kernel(struct machine *machine, const char *name) { - char buff[PATH_MAX]; - struct dso *self = dso__new(name ?: machine__mmap_name(machine, buff)); + char bf[PATH_MAX]; + struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf))); if (self != NULL) { dso__set_short_name(self, "[guest.kernel]"); -- cgit v1.2.3-70-g09d2 From d28c62232e50eab202bcd3f19b5c7a25b8b900b6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:20:43 -0300 Subject: perf machine: Adopt some map_groups functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those functions operated on members now grouped in 'struct machine', so move those methods to this new class. The changes made to 'perf probe' shows that using this abstraction inserting probes on guests almost got supported for free. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Masami Hiramatsu Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 4 +-- tools/perf/util/event.c | 9 ++---- tools/perf/util/map.c | 24 ++++++++++----- tools/perf/util/map.h | 12 ++++---- tools/perf/util/probe-event.c | 20 ++++++------ tools/perf/util/session.c | 7 ++--- tools/perf/util/symbol.c | 71 ++++++++++++++++++------------------------- tools/perf/util/symbol.h | 8 ++--- 8 files changed, 74 insertions(+), 81 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 20674759464..15635612e59 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -370,7 +370,6 @@ static void __print_result(struct rb_root *root, struct perf_session *session, struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; - struct map_groups *kmaps = &machine->kmaps; struct map *map; char buf[BUFSIZ]; u64 addr; @@ -378,8 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = map_groups__find_function(kmaps, addr, - &map, NULL); + sym = machine__find_function(machine, addr, &map, NULL); } else addr = data->ptr; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7400e5147e1..1757b0ffeaa 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -429,9 +429,8 @@ static int event__process_kernel_mmap(event_t *self, } else strcpy(short_module_name, self->mmap.filename); - map = map_groups__new_module(&machine->kmaps, - self->mmap.start, - self->mmap.filename, machine); + map = machine__new_module(machine, self->mmap.start, + self->mmap.filename); if (map == NULL) goto out_problem; @@ -454,9 +453,7 @@ static int event__process_kernel_mmap(event_t *self, goto out_problem; kernel->kernel = kernel_type; - if (__map_groups__create_kernel_maps(&machine->kmaps, - machine->vmlinux_maps, - kernel) < 0) + if (__machine__create_kernel_maps(machine, kernel) < 0) goto out_problem; event_set_kernel_mmap_len(machine->vmlinux_maps, self); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ee25ee91504..44a4df68b3c 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -513,6 +513,19 @@ struct map *maps__find(struct rb_root *maps, u64 ip) return NULL; } +int machine__init(struct machine *self, const char *root_dir, pid_t pid) +{ + map_groups__init(&self->kmaps); + RB_CLEAR_NODE(&self->rb_node); + INIT_LIST_HEAD(&self->user_dsos); + INIT_LIST_HEAD(&self->kernel_dsos); + + self->kmaps.machine = self; + self->pid = pid; + self->root_dir = strdup(root_dir); + return self->root_dir == NULL ? -ENOMEM : 0; +} + struct machine *machines__add(struct rb_root *self, pid_t pid, const char *root_dir) { @@ -523,13 +536,10 @@ struct machine *machines__add(struct rb_root *self, pid_t pid, if (!machine) return NULL; - machine->pid = pid; - map_groups__init(&machine->kmaps); - machine->root_dir = strdup(root_dir); - RB_CLEAR_NODE(&machine->rb_node); - INIT_LIST_HEAD(&machine->user_dsos); - INIT_LIST_HEAD(&machine->kernel_dsos); - machine->kmaps.machine = machine; + if (machine__init(machine, root_dir, pid) != 0) { + free(machine); + return NULL; + } while (*p != NULL) { parent = *p; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6fabad1fd02..881dba4f820 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -134,6 +134,7 @@ struct machine *machines__find_host(struct rb_root *self); struct machine *machines__find(struct rb_root *self, pid_t pid); struct machine *machines__findnew(struct rb_root *self, pid_t pid); char *machine__mmap_name(struct machine *self, char *bf, size_t size); +int machine__init(struct machine *self, const char *root_dir, pid_t pid); /* * Default guest kernel is defined by parameter --guestkallsyms @@ -172,11 +173,11 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, struct map **mapp, symbol_filter_t filter); -static inline -struct symbol *map_groups__find_function(struct map_groups *self, u64 addr, - struct map **mapp, symbol_filter_t filter) +static inline struct symbol *machine__find_function(struct machine *self, + u64 addr, struct map **mapp, + symbol_filter_t filter) { - return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter); + return map_groups__find_symbol(&self->kmaps, MAP__FUNCTION, addr, mapp, filter); } static inline @@ -192,8 +193,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename, struct machine *machine); +struct map *machine__new_module(struct machine *self, u64 start, const char *filename); void map_groups__flush(struct map_groups *self); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9ded38ced23..914c67095d9 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -72,8 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) } static char *synthesize_perf_probe_point(struct perf_probe_point *pp); -static struct map_groups kmap_groups; -static struct map *kmaps[MAP__NR_TYPES]; +static struct machine machine; /* Initialize symbol maps and path of vmlinux */ static int init_vmlinux(void) @@ -92,12 +91,15 @@ static int init_vmlinux(void) goto out; } + ret = machine__init(&machine, "/", 0); + if (ret < 0) + goto out; + kernel = dso__new_kernel(symbol_conf.vmlinux_name); if (kernel == NULL) die("Failed to create kernel dso."); - map_groups__init(&kmap_groups); - ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel); + ret = __machine__create_kernel_maps(&machine, kernel); if (ret < 0) pr_debug("Failed to create kernel maps.\n"); @@ -110,12 +112,12 @@ out: #ifdef DWARF_SUPPORT static int open_vmlinux(void) { - if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { + if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { pr_debug("Failed to load kernel map.\n"); return -EINVAL; } - pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); - return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); + pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name); + return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY); } /* Convert trace point to probe point with debuginfo */ @@ -125,7 +127,7 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, struct symbol *sym; int fd, ret = -ENOENT; - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], tp->symbol, NULL); if (sym) { fd = open_vmlinux(); @@ -1466,7 +1468,7 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, } /* Currently just checking function name from symbol map */ - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], tev->point.symbol, NULL); if (!sym) { pr_warning("Kernel symbol \'%s\' not found.\n", diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b745c1c0b6c..a8dd73ed158 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -69,12 +69,11 @@ void perf_session__update_sample_type(struct perf_session *self) int perf_session__create_kernel_maps(struct perf_session *self) { - int ret; - struct rb_root *root = &self->machines; + struct rb_root *machines = &self->machines; + int ret = machines__create_kernel_maps(machines, HOST_KERNEL_ID); - ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); if (ret >= 0) - ret = map_groups__create_guest_kernel_maps(root); + ret = machines__create_guest_kernel_maps(machines); return ret; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c9c0bdd667a..12359c37240 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1528,21 +1528,20 @@ static char *get_kernel_version(const char *root_dir) return strdup(name); } -static int map_groups__set_modules_path(struct map_groups *self, - const char *root_dir) +static int machine__set_modules_path(struct machine *self) { char *version; char modules_path[PATH_MAX]; - version = get_kernel_version(root_dir); + version = get_kernel_version(self->root_dir); if (!version) return -1; snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", - root_dir, version); + self->root_dir, version); free(version); - return map_groups__set_modules_path_dir(self, modules_path); + return map_groups__set_modules_path_dir(&self->kmaps, modules_path); } /* @@ -1564,14 +1563,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) return self; } -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename, - struct machine *machine) +struct map *machine__new_module(struct machine *self, u64 start, + const char *filename) { struct map *map; - struct dso *dso; + struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename); - dso = __dsos__findnew(&machine->kernel_dsos, filename); if (dso == NULL) return NULL; @@ -1579,28 +1576,27 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, if (map == NULL) return NULL; - if (machine__is_host(machine)) + if (machine__is_host(self)) dso->origin = DSO__ORIG_KMODULE; else dso->origin = DSO__ORIG_GUEST_KMODULE; - map_groups__insert(self, map); + map_groups__insert(&self->kmaps, map); return map; } -static int map_groups__create_modules(struct machine *machine) +static int machine__create_modules(struct machine *self) { char *line = NULL; size_t n; FILE *file; struct map *map; - const char *root_dir; const char *modules; char path[PATH_MAX]; - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) modules = symbol_conf.default_guest_modules; else { - sprintf(path, "%s/proc/modules", machine->root_dir); + sprintf(path, "%s/proc/modules", self->root_dir); modules = path; } @@ -1608,8 +1604,6 @@ static int map_groups__create_modules(struct machine *machine) if (file == NULL) return -1; - root_dir = machine->root_dir; - while (!feof(file)) { char name[PATH_MAX]; u64 start; @@ -1638,17 +1632,16 @@ static int map_groups__create_modules(struct machine *machine) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = map_groups__new_module(&machine->kmaps, start, - name, machine); + map = machine__new_module(self, start, name); if (map == NULL) goto out_delete_line; - dso__kernel_module_get_build_id(map->dso, root_dir); + dso__kernel_module_get_build_id(map->dso, self->root_dir); } free(line); fclose(file); - return map_groups__set_modules_path(&machine->kmaps, root_dir); + return machine__set_modules_path(self); out_delete_line: free(line); @@ -2005,25 +1998,23 @@ static struct dso *dsos__create_kernel(struct machine *machine) return kernel; } -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel) +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) { enum map_type type; for (type = 0; type < MAP__NR_TYPES; ++type) { struct kmap *kmap; - vmlinux_maps[type] = map__new2(0, kernel, type); - if (vmlinux_maps[type] == NULL) + self->vmlinux_maps[type] = map__new2(0, kernel, type); + if (self->vmlinux_maps[type] == NULL) return -1; - vmlinux_maps[type]->map_ip = - vmlinux_maps[type]->unmap_ip = identity__map_ip; + self->vmlinux_maps[type]->map_ip = + self->vmlinux_maps[type]->unmap_ip = identity__map_ip; - kmap = map__kmap(vmlinux_maps[type]); - kmap->kmaps = self; - map_groups__insert(self, vmlinux_maps[type]); + kmap = map__kmap(self->vmlinux_maps[type]); + kmap->kmaps = &self->kmaps; + map_groups__insert(&self->kmaps, self->vmlinux_maps[type]); } return 0; @@ -2145,10 +2136,10 @@ out_free_comm_list: return -1; } -int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) +int machines__create_kernel_maps(struct rb_root *self, pid_t pid) { struct dso *kernel; - struct machine *machine = machines__findnew(machines, pid); + struct machine *machine = machines__findnew(self, pid); if (machine == NULL) return -1; @@ -2156,12 +2147,10 @@ int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) if (kernel == NULL) return -1; - if (__map_groups__create_kernel_maps(&machine->kmaps, - machine->vmlinux_maps, kernel) < 0) + if (__machine__create_kernel_maps(machine, kernel) < 0) return -1; - if (symbol_conf.use_modules && - map_groups__create_modules(machine) < 0) + if (symbol_conf.use_modules && machine__create_modules(machine) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: @@ -2213,7 +2202,7 @@ char *strxfrchar(char *s, char from, char to) return s; } -int map_groups__create_guest_kernel_maps(struct rb_root *machines) +int machines__create_guest_kernel_maps(struct rb_root *self) { int ret = 0; struct dirent **namelist = NULL; @@ -2224,7 +2213,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *machines) if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || symbol_conf.default_guest_kallsyms) { - map_groups__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); + machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID); } if (symbol_conf.guestmount) { @@ -2245,7 +2234,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *machines) pr_debug("Can't access file %s\n", path); goto failure; } - map_groups__create_kernel_maps(machines, pid); + machines__create_kernel_maps(self, pid); } failure: free(namelist); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index ed885b06a02..37b717b861c 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -199,11 +199,9 @@ int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)); -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel); -int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid); -int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root); +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); +int machines__create_kernel_maps(struct rb_root *self, pid_t pid); +int machines__create_guest_kernel_maps(struct rb_root *self); int symbol__init(void); bool symbol_type__is_a(char symbol_type, enum map_type map_type); -- cgit v1.2.3-70-g09d2 From cbf6968098f89d3216d074f06544b5032b344da4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:22:44 -0300 Subject: perf machines: Make the machines class adopt the dsos__fprintf methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now those methods don't operate on a global list of dsos, but on lists of machines, so make this clear by renaming the functions. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-buildid-list.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/session.h | 13 +++++++++++++ tools/perf/util/symbol.c | 22 ++++++++++++++-------- tools/perf/util/symbol.h | 5 ++--- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 986b2efcef2..b57dbcf62af 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -571,7 +571,7 @@ static int __cmd_annotate(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->machines, stdout); + perf_session__fprintf_dsos(session, stdout); perf_session__collapse_resort(&session->hists); perf_session__output_resort(&session->hists, session->event_total[0]); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index b4a265ae3b9..7dc3b2e7a5e 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -46,7 +46,7 @@ static int __cmd_buildid_list(void) if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); - dsos__fprintf_buildid(&session->machines, stdout, with_hits); + perf_session__fprintf_dsos_buildid(session, stdout, with_hits); perf_session__delete(session); return err; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 49cc367d8c3..f1b46eb7ef9 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -313,7 +313,7 @@ static int __cmd_report(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->machines, stdout); + perf_session__fprintf_dsos(session, stdout); next = rb_first(&session->stats_by_id); while (next) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c390f340b03..d95281f588d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -854,7 +854,7 @@ static void handle_keypress(struct perf_session *session, int c) case 'Q': printf("exiting.\n"); if (dump_symtab) - dsos__fprintf(&session->machines, stderr); + perf_session__fprintf_dsos(session, stderr); exit(0); case 's': prompt_symbol(&sym_filter_entry, "Enter details symbol"); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 71252723a17..61ca92e58ad 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -127,4 +127,17 @@ void perf_session__process_machines(struct perf_session *self, { return machines__process(&self->machines, process, self); } + +static inline +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) +{ + return machines__fprintf_dsos(&self->machines, fp); +} + +static inline +size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, + bool with_hits) +{ + return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); +} #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 12359c37240..caa890f8e2c 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1889,26 +1889,32 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) return dso; } -static void __dsos__fprintf(struct list_head *head, FILE *fp) +static size_t __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; + size_t ret = 0; list_for_each_entry(pos, head, node) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - dso__fprintf(pos, i, fp); + ret += dso__fprintf(pos, i, fp); } + + return ret; } -void dsos__fprintf(struct rb_root *machines, FILE *fp) +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp) { struct rb_node *nd; + size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - __dsos__fprintf(&pos->kernel_dsos, fp); - __dsos__fprintf(&pos->user_dsos, fp); + ret += __dsos__fprintf(&pos->kernel_dsos, fp); + ret += __dsos__fprintf(&pos->user_dsos, fp); } + + return ret; } static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, @@ -1926,12 +1932,12 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t dsos__fprintf_buildid(struct rb_root *machines, FILE *fp, bool with_hits) +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 37b717b861c..2cec6a10716 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -162,9 +162,8 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); -void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp); -size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, - FILE *fp, bool with_hits); +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); -- cgit v1.2.3-70-g09d2 From 18acde52b83bd1c8e1d007db519f46d344aa13ed Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 22:26:51 -0300 Subject: perf tools: Create $(OUTPUT)arch/$(ARCH)/util/ directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that "make -C tools/perf O=/tmp/some/path" works again. Problem introduced in: cd932c5 "perf: Move arch specific code into separate arch director" Cc: Ian Munsie Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3ac6b677bec..b86f2ad165a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -187,6 +187,8 @@ ifeq ($(ARCH),x86_64) ARCH := x86 endif +$(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null) + # CFLAGS and LDFLAGS are for the users to override from the command line. # -- cgit v1.2.3-70-g09d2 From 5c0541d53ef3897494768decb09eb8f1087953a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Apr 2010 15:25:23 -0300 Subject: perf symbols: Add machine helper routines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created when writing the first 'perf test' regression testing routine. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 2 +- tools/perf/util/map.h | 25 ++++++++++++--- tools/perf/util/symbol.c | 77 +++++++++++++++++++++++++++++++++++------------ tools/perf/util/symbol.h | 7 +++++ 4 files changed, 86 insertions(+), 25 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 15635612e59..ee05dba9609 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -377,7 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = machine__find_function(machine, addr, &map, NULL); + sym = machine__find_kernel_function(machine, addr, &map, NULL); } else addr = data->ptr; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 881dba4f820..f3913451282 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -30,6 +30,7 @@ struct map { u64 start; u64 end; enum map_type type; + u32 priv; u64 pgoff; /* ip -> dso rip */ @@ -66,6 +67,12 @@ struct machine { struct map *vmlinux_maps[MAP__NR_TYPES]; }; +static inline +struct map *machine__kernel_map(struct machine *self, enum map_type type) +{ + return self->vmlinux_maps[type]; +} + static inline struct kmap *map__kmap(struct map *self) { return (struct kmap *)(self + 1); @@ -173,11 +180,21 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, struct map **mapp, symbol_filter_t filter); -static inline struct symbol *machine__find_function(struct machine *self, - u64 addr, struct map **mapp, - symbol_filter_t filter) +static inline +struct symbol *machine__find_kernel_symbol(struct machine *self, + enum map_type type, u64 addr, + struct map **mapp, + symbol_filter_t filter) +{ + return map_groups__find_symbol(&self->kmaps, type, addr, mapp, filter); +} + +static inline +struct symbol *machine__find_kernel_function(struct machine *self, u64 addr, + struct map **mapp, + symbol_filter_t filter) { - return map_groups__find_symbol(&self->kmaps, MAP__FUNCTION, addr, mapp, filter); + return machine__find_kernel_symbol(self, MAP__FUNCTION, addr, mapp, filter); } static inline diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index caa890f8e2c..4c0146a4906 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1983,23 +1983,23 @@ void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine self->has_build_id = true; } -static struct dso *dsos__create_kernel(struct machine *machine) +static struct dso *machine__create_kernel(struct machine *self) { const char *vmlinux_name = NULL; struct dso *kernel; - if (machine__is_host(machine)) { + if (machine__is_host(self)) { vmlinux_name = symbol_conf.vmlinux_name; kernel = dso__new_kernel(vmlinux_name); } else { - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) vmlinux_name = symbol_conf.default_guest_vmlinux_name; - kernel = dso__new_guest_kernel(machine, vmlinux_name); + kernel = dso__new_guest_kernel(self, vmlinux_name); } if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel, machine); - dsos__add(&machine->kernel_dsos, kernel); + dso__read_running_kernel_build_id(kernel, self); + dsos__add(&self->kernel_dsos, kernel); } return kernel; } @@ -2026,6 +2026,23 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) return 0; } +int machine__create_kernel_maps(struct machine *self) +{ + struct dso *kernel = machine__create_kernel(self); + + if (kernel == NULL || + __machine__create_kernel_maps(self, kernel) < 0) + return -1; + + if (symbol_conf.use_modules && machine__create_modules(self) < 0) + pr_debug("Problems creating module maps, continuing anyway...\n"); + /* + * Now that we have all the maps created, just set the ->end of them: + */ + map_groups__fixup_end(&self->kmaps); + return 0; +} + static void vmlinux_path__exit(void) { while (--vmlinux_path__nr_entries >= 0) { @@ -2144,25 +2161,12 @@ out_free_comm_list: int machines__create_kernel_maps(struct rb_root *self, pid_t pid) { - struct dso *kernel; struct machine *machine = machines__findnew(self, pid); if (machine == NULL) return -1; - kernel = dsos__create_kernel(machine); - if (kernel == NULL) - return -1; - - if (__machine__create_kernel_maps(machine, kernel) < 0) - return -1; - if (symbol_conf.use_modules && machine__create_modules(machine) < 0) - pr_debug("Problems creating module maps, continuing anyway...\n"); - /* - * Now that we have all the maps created, just set the ->end of them: - */ - map_groups__fixup_end(&machine->kmaps); - return 0; + return machine__create_kernel_maps(machine); } static int hex(char ch) @@ -2248,3 +2252,36 @@ failure: return ret; } + +int machine__load_kallsyms(struct machine *self, const char *filename, + enum map_type type, symbol_filter_t filter) +{ + struct map *map = self->vmlinux_maps[type]; + int ret = dso__load_kallsyms(map->dso, filename, map, filter); + + if (ret > 0) { + dso__set_loaded(map->dso, type); + /* + * Since /proc/kallsyms will have multiple sessions for the + * kernel, with modules between them, fixup the end of all + * sections. + */ + __map_groups__fixup_end(&self->kmaps, type); + } + + return ret; +} + +int machine__load_vmlinux_path(struct machine *self, enum map_type type, + symbol_filter_t filter) +{ + struct map *map = self->vmlinux_maps[type]; + int ret = dso__load_vmlinux_path(map->dso, map, filter); + + if (ret > 0) { + dso__set_loaded(map->dso, type); + map__reloc_vmlinux(map); + } + + return ret; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2cec6a10716..a517c17407b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -162,6 +162,11 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); +int machine__load_kallsyms(struct machine *self, const char *filename, + enum map_type type, symbol_filter_t filter); +int machine__load_vmlinux_path(struct machine *self, enum map_type type, + symbol_filter_t filter); + size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); @@ -199,6 +204,8 @@ int kallsyms__parse(const char *filename, void *arg, char type, u64 start)); int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); +int machine__create_kernel_maps(struct machine *self); + int machines__create_kernel_maps(struct rb_root *self, pid_t pid); int machines__create_guest_kernel_maps(struct rb_root *self); -- cgit v1.2.3-70-g09d2 From 1c6a800cde3b818fd8320b5d402f2d77d2948c00 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Apr 2010 18:58:32 -0300 Subject: perf test: Initial regression testing command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First an example with the first internal test: [acme@doppio linux-2.6-tip]$ perf test 1: vmlinux symtab matches kallsyms: Ok So it run just one test, that is "vmlinux symtab matches kallsyms", and it was successful. If we run it in verbose mode, we'll see details about errors and extra warnings for non-fatal problems: [acme@doppio linux-2.6-tip]$ perf test -v 1: vmlinux symtab matches kallsyms: --- start --- Looking at the vmlinux_path (5 entries long) No build_id in vmlinux, ignoring it No build_id in /boot/vmlinux, ignoring it No build_id in /boot/vmlinux-2.6.34-rc4-tip+, ignoring it Using /lib/modules/2.6.34-rc4-tip+/build/vmlinux for symbols Maps only in vmlinux: ffffffff81cb81b1-ffffffff81e1149b 0 [kernel].init.text ffffffff81e1149c-ffffffff9fffffff 0 [kernel].exit.text ffffffffff600000-ffffffffff6000ff 0 [kernel].vsyscall_0 ffffffffff600100-ffffffffff6003ff 0 [kernel].vsyscall_fn ffffffffff600400-ffffffffff6007ff 0 [kernel].vsyscall_1 ffffffffff600800-ffffffffffffffff 0 [kernel].vsyscall_2 Maps in vmlinux with a different name in kallsyms: ffffffffff600000-ffffffffff6000ff 0 [kernel].vsyscall_0 in kallsyms as [kernel].0 ffffffffff600100-ffffffffff6003ff 0 [kernel].vsyscall_fn in kallsyms as: *ffffffffff600100-ffffffffff60012f 0 [kernel].2 ffffffffff600400-ffffffffff6007ff 0 [kernel].vsyscall_1 in kallsyms as [kernel].6 ffffffffff600800-ffffffffffffffff 0 [kernel].vsyscall_2 in kallsyms as [kernel].8 Maps only in kallsyms: ffffffffff600130-ffffffffff6003ff 0 [kernel].4 ---- end ---- vmlinux symtab matches kallsyms: Ok [acme@doppio linux-2.6-tip]$ In the above case we only know the name of the non contiguous kernel ranges in the address space when reading the symbol information from the ELF symtab in vmlinux. The /proc/kallsyms file lack this, we only notice they are separate because there are modules after the kernel and after that more kernel functions, so we need to have a module rbtree backed by the module .ko path to get symtabs in the vmlinux case. The tool uses it to match by address to emit appropriate warning, but don't considers this fatal. The .init.text and .exit.text ines, of course, aren't in kallsyms, so I left these cases just as extra info in verbose mode. The end of the sections also aren't in kallsyms, so we the symbols layer does another pass and sets the end addresses as the next map start minus one, which sometimes pads, causing harmless mismatches. But at least the symbols match, tested it by copying /proc/kallsyms to /tmp/kallsyms and doing changes to see if they were detected. This first test also should serve as a first stab at documenting the symbol library by providing a self contained example that exercises it together with comments about what is being done. More tests to check if actions done on a monitored app, like doing mmaps, etc, makes the kernel generate the expected events should be added next. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-test.txt | 22 +++ tools/perf/Makefile | 1 + tools/perf/builtin-test.c | 281 +++++++++++++++++++++++++++++++++ tools/perf/builtin.h | 1 + tools/perf/command-list.txt | 1 + tools/perf/perf.c | 1 + 6 files changed, 307 insertions(+) create mode 100644 tools/perf/Documentation/perf-test.txt create mode 100644 tools/perf/builtin-test.c diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt new file mode 100644 index 00000000000..1c4b5f5b7f7 --- /dev/null +++ b/tools/perf/Documentation/perf-test.txt @@ -0,0 +1,22 @@ +perf-test(1) +============ + +NAME +---- +perf-test - Runs sanity tests. + +SYNOPSIS +-------- +[verse] +'perf test ' + +DESCRIPTION +----------- +This command does assorted sanity tests, initially thru linked routines but +also will look for a directory with more tests in the form of scripts. + +OPTIONS +------- +-v:: +--verbose:: + Be more verbose. diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b86f2ad165a..739c4412b18 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -490,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o +BUILTIN_OBJS += $(OUTPUT)builtin-test.o PERFLIBS = $(LIB_FILE) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c new file mode 100644 index 00000000000..0339612e738 --- /dev/null +++ b/tools/perf/builtin-test.c @@ -0,0 +1,281 @@ +/* + * builtin-test.c + * + * Builtin regression testing command: ever growing number of sanity tests + */ +#include "builtin.h" + +#include "util/cache.h" +#include "util/debug.h" +#include "util/parse-options.h" +#include "util/session.h" +#include "util/symbol.h" +#include "util/thread.h" + +static long page_size; + +static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) +{ + bool *visited = symbol__priv(sym); + *visited = true; + return 0; +} + +static int test__vmlinux_matches_kallsyms(void) +{ + int err = -1; + struct rb_node *nd; + struct symbol *sym; + struct map *kallsyms_map, *vmlinux_map; + struct machine kallsyms, vmlinux; + enum map_type type = MAP__FUNCTION; + struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; + + /* + * Step 1: + * + * Init the machines that will hold kernel, modules obtained from + * both vmlinux + .ko files and from /proc/kallsyms split by modules. + */ + machine__init(&kallsyms, "", HOST_KERNEL_ID); + machine__init(&vmlinux, "", HOST_KERNEL_ID); + + /* + * Step 2: + * + * Create the kernel maps for kallsyms and the DSO where we will then + * load /proc/kallsyms. Also create the modules maps from /proc/modules + * and find the .ko files that match them in /lib/modules/`uname -r`/. + */ + if (machine__create_kernel_maps(&kallsyms) < 0) { + pr_debug("machine__create_kernel_maps "); + return -1; + } + + /* + * Step 3: + * + * Load and split /proc/kallsyms into multiple maps, one per module. + */ + if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { + pr_debug("dso__load_kallsyms "); + goto out; + } + + /* + * Step 4: + * + * kallsyms will be internally on demand sorted by name so that we can + * find the reference relocation * symbol, i.e. the symbol we will use + * to see if the running kernel was relocated by checking if it has the + * same value in the vmlinux file we load. + */ + kallsyms_map = machine__kernel_map(&kallsyms, type); + + sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); + if (sym == NULL) { + pr_debug("dso__find_symbol_by_name "); + goto out; + } + + ref_reloc_sym.addr = sym->start; + + /* + * Step 5: + * + * Now repeat step 2, this time for the vmlinux file we'll auto-locate. + */ + if (machine__create_kernel_maps(&vmlinux) < 0) { + pr_debug("machine__create_kernel_maps "); + goto out; + } + + vmlinux_map = machine__kernel_map(&vmlinux, type); + map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; + + /* + * Step 6: + * + * Locate a vmlinux file in the vmlinux path that has a buildid that + * matches the one of the running kernel. + * + * While doing that look if we find the ref reloc symbol, if we find it + * we'll have its ref_reloc_symbol.unrelocated_addr and then + * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines + * to fixup the symbols. + */ + if (machine__load_vmlinux_path(&vmlinux, type, + vmlinux_matches_kallsyms_filter) <= 0) { + pr_debug("machine__load_vmlinux_path "); + goto out; + } + + err = 0; + /* + * Step 7: + * + * Now look at the symbols in the vmlinux DSO and check if we find all of them + * in the kallsyms dso. For the ones that are in both, check its names and + * end addresses too. + */ + for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { + struct symbol *pair; + + sym = rb_entry(nd, struct symbol, rb_node); + pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); + + if (pair && pair->start == sym->start) { +next_pair: + if (strcmp(sym->name, pair->name) == 0) { + /* + * kallsyms don't have the symbol end, so we + * set that by using the next symbol start - 1, + * in some cases we get this up to a page + * wrong, trace_kmalloc when I was developing + * this code was one such example, 2106 bytes + * off the real size. More than that and we + * _really_ have a problem. + */ + s64 skew = sym->end - pair->end; + if (llabs(skew) < page_size) + continue; + + pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", + sym->start, sym->name, sym->end, pair->end); + } else { + struct rb_node *nnd = rb_prev(&pair->rb_node); + + if (nnd) { + struct symbol *next = rb_entry(nnd, struct symbol, rb_node); + + if (next->start == sym->start) { + pair = next; + goto next_pair; + } + } + pr_debug("%#Lx: diff name v: %s k: %s\n", + sym->start, sym->name, pair->name); + } + } else + pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name); + + err = -1; + } + + if (!verbose) + goto out; + + pr_info("Maps only in vmlinux:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + /* + * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while + * the kernel will have the path for the vmlinux file being used, + * so use the short name, less descriptive but the same ("[kernel]" in + * both cases. + */ + pair = map_groups__find_by_name(&kallsyms.kmaps, type, + (pos->dso->kernel ? + pos->dso->short_name : + pos->dso->name)); + if (pair) + pair->priv = 1; + else + map__fprintf(pos, stderr); + } + + pr_info("Maps in vmlinux with a different name in kallsyms:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + + pair = map_groups__find(&kallsyms.kmaps, type, pos->start); + if (pair == NULL || pair->priv) + continue; + + if (pair->start == pos->start) { + pair->priv = 1; + pr_info(" %Lx-%Lx %Lx %s in kallsyms as", + pos->start, pos->end, pos->pgoff, pos->dso->name); + if (pos->pgoff != pair->pgoff || pos->end != pair->end) + pr_info(": \n*%Lx-%Lx %Lx", + pair->start, pair->end, pair->pgoff); + pr_info(" %s\n", pair->dso->name); + pair->priv = 1; + } + } + + pr_info("Maps only in kallsyms:\n"); + + for (nd = rb_first(&kallsyms.kmaps.maps[type]); + nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node); + + if (!pos->priv) + map__fprintf(pos, stderr); + } +out: + return err; +} + +static struct test { + const char *desc; + int (*func)(void); +} tests[] = { + { + .desc = "vmlinux symtab matches kallsyms", + .func = test__vmlinux_matches_kallsyms, + }, + { + .func = NULL, + }, +}; + +static int __cmd_test(void) +{ + int i = 0; + + page_size = sysconf(_SC_PAGE_SIZE); + + while (tests[i].func) { + int err; + pr_info("%2d: %s:", i + 1, tests[i].desc); + pr_debug("\n--- start ---\n"); + err = tests[i].func(); + pr_debug("---- end ----\n%s:", tests[i].desc); + pr_info(" %s\n", err ? "FAILED!\n" : "Ok"); + ++i; + } + + return 0; +} + +static const char * const test_usage[] = { + "perf test []", + NULL, +}; + +static const struct option test_options[] = { + OPT_BOOLEAN('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_END() +}; + +int cmd_test(int argc, const char **argv, const char *prefix __used) +{ + argc = parse_options(argc, argv, test_options, test_usage, 0); + if (argc) + usage_with_options(test_usage, test_options); + + symbol_conf.priv_size = sizeof(int); + symbol_conf.sort_by_name = true; + symbol_conf.try_vmlinux_path = true; + + if (symbol__init() < 0) + return -1; + + setup_pager(); + + return __cmd_test(); +} diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index ab28bca92e5..34a8a9ab961 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h @@ -33,5 +33,6 @@ extern int cmd_probe(int argc, const char **argv, const char *prefix); extern int cmd_kmem(int argc, const char **argv, const char *prefix); extern int cmd_lock(int argc, const char **argv, const char *prefix); extern int cmd_kvm(int argc, const char **argv, const char *prefix); +extern int cmd_test(int argc, const char **argv, const char *prefix); #endif diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index 2a1162d413a..80a1a446ce3 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt @@ -20,3 +20,4 @@ perf-probe mainporcelain common perf-kmem mainporcelain common perf-lock mainporcelain common perf-kvm mainporcelain common +perf-test mainporcelain common diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 985cdb4bd00..5ff9b5b4697 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -308,6 +308,7 @@ static void handle_internal_command(int argc, const char **argv) { "kmem", cmd_kmem, 0 }, { "lock", cmd_lock, 0 }, { "kvm", cmd_kvm, 0 }, + { "test", cmd_test, 0 }, }; unsigned int i; static const char ext[] = STRIP_EXTENSION; -- cgit v1.2.3-70-g09d2