diff options
| author | Ingo Molnar <mingo@elte.hu> | 2010-04-30 03:58:05 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-04-30 03:58:05 -0400 |
| commit | bc4b473f1aa2ef785ccfd890a24a1de5a6660f98 (patch) | |
| tree | 77bbea692517ae4723b575631222bf715b4a1eb1 /tools | |
| parent | 3ca50496c2677a2b3fdd3ede86660fd1433beac6 (diff) | |
| parent | 1c6a800cde3b818fd8320b5d402f2d77d2948c00 (diff) | |
Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/Documentation/perf-test.txt | 22 | ||||
| -rw-r--r-- | tools/perf/Makefile | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-buildid-list.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-kmem.c | 10 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 36 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-test.c | 281 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 15 | ||||
| -rw-r--r-- | tools/perf/builtin.h | 1 | ||||
| -rw-r--r-- | tools/perf/command-list.txt | 1 | ||||
| -rw-r--r-- | tools/perf/perf.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 89 | ||||
| -rw-r--r-- | tools/perf/util/event.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 70 | ||||
| -rw-r--r-- | tools/perf/util/header.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 121 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 86 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 40 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 236 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 23 |
23 files changed, 725 insertions, 351 deletions
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt new file mode 100644 index 000000000000..1c4b5f5b7f71 --- /dev/null +++ b/tools/perf/Documentation/perf-test.txt | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | perf-test(1) | ||
| 2 | ============ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | perf-test - Runs sanity tests. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | 'perf test <options>' | ||
| 12 | |||
| 13 | DESCRIPTION | ||
| 14 | ----------- | ||
| 15 | This command does assorted sanity tests, initially thru linked routines but | ||
| 16 | also will look for a directory with more tests in the form of scripts. | ||
| 17 | |||
| 18 | OPTIONS | ||
| 19 | ------- | ||
| 20 | -v:: | ||
| 21 | --verbose:: | ||
| 22 | Be more verbose. | ||
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3ac6b677becd..739c4412b183 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -187,6 +187,8 @@ ifeq ($(ARCH),x86_64) | |||
| 187 | ARCH := x86 | 187 | ARCH := x86 |
| 188 | endif | 188 | endif |
| 189 | 189 | ||
| 190 | $(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null) | ||
| 191 | |||
| 190 | # CFLAGS and LDFLAGS are for the users to override from the command line. | 192 | # CFLAGS and LDFLAGS are for the users to override from the command line. |
| 191 | 193 | ||
| 192 | # | 194 | # |
| @@ -488,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o | |||
| 488 | BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o | 490 | BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o |
| 489 | BUILTIN_OBJS += $(OUTPUT)builtin-lock.o | 491 | BUILTIN_OBJS += $(OUTPUT)builtin-lock.o |
| 490 | BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o | 492 | BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o |
| 493 | BUILTIN_OBJS += $(OUTPUT)builtin-test.o | ||
| 491 | 494 | ||
| 492 | PERFLIBS = $(LIB_FILE) | 495 | PERFLIBS = $(LIB_FILE) |
| 493 | 496 | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f924b4332be6..b57dbcf62af3 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -571,7 +571,7 @@ static int __cmd_annotate(void) | |||
| 571 | perf_session__fprintf(session, stdout); | 571 | perf_session__fprintf(session, stdout); |
| 572 | 572 | ||
| 573 | if (verbose > 2) | 573 | if (verbose > 2) |
| 574 | dsos__fprintf(&session->kerninfo_root, stdout); | 574 | perf_session__fprintf_dsos(session, stdout); |
| 575 | 575 | ||
| 576 | perf_session__collapse_resort(&session->hists); | 576 | perf_session__collapse_resort(&session->hists); |
| 577 | perf_session__output_resort(&session->hists, session->event_total[0]); | 577 | 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 623afe3fdcb8..7dc3b2e7a5e4 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) | |||
| 46 | if (with_hits) | 46 | if (with_hits) |
| 47 | perf_session__process_events(session, &build_id__mark_dso_hit_ops); | 47 | perf_session__process_events(session, &build_id__mark_dso_hit_ops); |
| 48 | 48 | ||
| 49 | dsos__fprintf_buildid(&session->kerninfo_root, stdout, with_hits); | 49 | perf_session__fprintf_dsos_buildid(session, stdout, with_hits); |
| 50 | 50 | ||
| 51 | perf_session__delete(session); | 51 | perf_session__delete(session); |
| 52 | return err; | 52 | return err; |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ab906cbd5c79..ee05dba9609a 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, | |||
| 352 | int n_lines, int is_caller) | 352 | int n_lines, int is_caller) |
| 353 | { | 353 | { |
| 354 | struct rb_node *next; | 354 | struct rb_node *next; |
| 355 | struct kernel_info *kerninfo; | 355 | struct machine *machine; |
| 356 | 356 | ||
| 357 | printf("%.102s\n", graph_dotted_line); | 357 | printf("%.102s\n", graph_dotted_line); |
| 358 | printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); | 358 | printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); |
| @@ -361,8 +361,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session, | |||
| 361 | 361 | ||
| 362 | next = rb_first(root); | 362 | next = rb_first(root); |
| 363 | 363 | ||
| 364 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 364 | machine = perf_session__find_host_machine(session); |
| 365 | if (!kerninfo) { | 365 | if (!machine) { |
| 366 | pr_err("__print_result: couldn't find kernel information\n"); | 366 | pr_err("__print_result: couldn't find kernel information\n"); |
| 367 | return; | 367 | return; |
| 368 | } | 368 | } |
| @@ -370,7 +370,6 @@ static void __print_result(struct rb_root *root, struct perf_session *session, | |||
| 370 | struct alloc_stat *data = rb_entry(next, struct alloc_stat, | 370 | struct alloc_stat *data = rb_entry(next, struct alloc_stat, |
| 371 | node); | 371 | node); |
| 372 | struct symbol *sym = NULL; | 372 | struct symbol *sym = NULL; |
| 373 | struct map_groups *kmaps = &kerninfo->kmaps; | ||
| 374 | struct map *map; | 373 | struct map *map; |
| 375 | char buf[BUFSIZ]; | 374 | char buf[BUFSIZ]; |
| 376 | u64 addr; | 375 | u64 addr; |
| @@ -378,8 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, | |||
| 378 | if (is_caller) { | 377 | if (is_caller) { |
| 379 | addr = data->call_site; | 378 | addr = data->call_site; |
| 380 | if (!raw_ip) | 379 | if (!raw_ip) |
| 381 | sym = map_groups__find_function(kmaps, addr, | 380 | sym = machine__find_kernel_function(machine, addr, &map, NULL); |
| 382 | &map, NULL); | ||
| 383 | } else | 381 | } else |
| 384 | addr = data->ptr; | 382 | addr = data->ptr; |
| 385 | 383 | ||
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 27f992aca8b5..83b308a035c2 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -456,14 +456,14 @@ static void atexit_header(void) | |||
| 456 | } | 456 | } |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static void event__synthesize_guest_os(struct kernel_info *kerninfo, | 459 | static void event__synthesize_guest_os(struct machine *machine, void *data) |
| 460 | void *data __attribute__((unused))) | ||
| 461 | { | 460 | { |
| 462 | int err; | 461 | int err; |
| 463 | char *guest_kallsyms; | 462 | char *guest_kallsyms; |
| 464 | char path[PATH_MAX]; | 463 | char path[PATH_MAX]; |
| 464 | struct perf_session *psession = data; | ||
| 465 | 465 | ||
| 466 | if (is_host_kernel(kerninfo)) | 466 | if (machine__is_host(machine)) |
| 467 | return; | 467 | return; |
| 468 | 468 | ||
| 469 | /* | 469 | /* |
| @@ -475,16 +475,15 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, | |||
| 475 | *in module instead of in guest kernel. | 475 | *in module instead of in guest kernel. |
| 476 | */ | 476 | */ |
| 477 | err = event__synthesize_modules(process_synthesized_event, | 477 | err = event__synthesize_modules(process_synthesized_event, |
| 478 | session, | 478 | psession, machine); |
| 479 | kerninfo); | ||
| 480 | if (err < 0) | 479 | if (err < 0) |
| 481 | pr_err("Couldn't record guest kernel [%d]'s reference" | 480 | pr_err("Couldn't record guest kernel [%d]'s reference" |
| 482 | " relocation symbol.\n", kerninfo->pid); | 481 | " relocation symbol.\n", machine->pid); |
| 483 | 482 | ||
| 484 | if (is_default_guest(kerninfo)) | 483 | if (machine__is_default_guest(machine)) |
| 485 | guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; | 484 | guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; |
| 486 | else { | 485 | else { |
| 487 | sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); | 486 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); |
| 488 | guest_kallsyms = path; | 487 | guest_kallsyms = path; |
| 489 | } | 488 | } |
| 490 | 489 | ||
| @@ -493,13 +492,13 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, | |||
| 493 | * have no _text sometimes. | 492 | * have no _text sometimes. |
| 494 | */ | 493 | */ |
| 495 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 494 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
| 496 | session, kerninfo, "_text"); | 495 | psession, machine, "_text"); |
| 497 | if (err < 0) | 496 | if (err < 0) |
| 498 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 497 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
| 499 | session, kerninfo, "_stext"); | 498 | psession, machine, "_stext"); |
| 500 | if (err < 0) | 499 | if (err < 0) |
| 501 | pr_err("Couldn't record guest kernel [%d]'s reference" | 500 | pr_err("Couldn't record guest kernel [%d]'s reference" |
| 502 | " relocation symbol.\n", kerninfo->pid); | 501 | " relocation symbol.\n", machine->pid); |
| 503 | } | 502 | } |
| 504 | 503 | ||
| 505 | static int __cmd_record(int argc, const char **argv) | 504 | static int __cmd_record(int argc, const char **argv) |
| @@ -513,7 +512,7 @@ static int __cmd_record(int argc, const char **argv) | |||
| 513 | int child_ready_pipe[2], go_pipe[2]; | 512 | int child_ready_pipe[2], go_pipe[2]; |
| 514 | const bool forks = argc > 0; | 513 | const bool forks = argc > 0; |
| 515 | char buf; | 514 | char buf; |
| 516 | struct kernel_info *kerninfo; | 515 | struct machine *machine; |
| 517 | 516 | ||
| 518 | page_size = sysconf(_SC_PAGE_SIZE); | 517 | page_size = sysconf(_SC_PAGE_SIZE); |
| 519 | 518 | ||
| @@ -682,31 +681,30 @@ static int __cmd_record(int argc, const char **argv) | |||
| 682 | advance_output(err); | 681 | advance_output(err); |
| 683 | } | 682 | } |
| 684 | 683 | ||
| 685 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 684 | machine = perf_session__find_host_machine(session); |
| 686 | if (!kerninfo) { | 685 | if (!machine) { |
| 687 | pr_err("Couldn't find native kernel information.\n"); | 686 | pr_err("Couldn't find native kernel information.\n"); |
| 688 | return -1; | 687 | return -1; |
| 689 | } | 688 | } |
| 690 | 689 | ||
| 691 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 690 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
| 692 | session, kerninfo, "_text"); | 691 | session, machine, "_text"); |
| 693 | if (err < 0) | 692 | if (err < 0) |
| 694 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 693 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
| 695 | session, kerninfo, "_stext"); | 694 | session, machine, "_stext"); |
| 696 | if (err < 0) { | 695 | if (err < 0) { |
| 697 | pr_err("Couldn't record kernel reference relocation symbol.\n"); | 696 | pr_err("Couldn't record kernel reference relocation symbol.\n"); |
| 698 | return err; | 697 | return err; |
| 699 | } | 698 | } |
| 700 | 699 | ||
| 701 | err = event__synthesize_modules(process_synthesized_event, | 700 | err = event__synthesize_modules(process_synthesized_event, |
| 702 | session, kerninfo); | 701 | session, machine); |
| 703 | if (err < 0) { | 702 | if (err < 0) { |
| 704 | pr_err("Couldn't record kernel reference relocation symbol.\n"); | 703 | pr_err("Couldn't record kernel reference relocation symbol.\n"); |
| 705 | return err; | 704 | return err; |
| 706 | } | 705 | } |
| 707 | if (perf_guest) | 706 | if (perf_guest) |
| 708 | kerninfo__process_allkernels(&session->kerninfo_root, | 707 | perf_session__process_machines(session, event__synthesize_guest_os); |
| 709 | event__synthesize_guest_os, session); | ||
| 710 | 708 | ||
| 711 | if (!system_wide && profile_cpu == -1) | 709 | if (!system_wide && profile_cpu == -1) |
| 712 | event__synthesize_thread(target_tid, process_synthesized_event, | 710 | event__synthesize_thread(target_tid, process_synthesized_event, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 816edae7c5b2..f1b46eb7ef9a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -313,7 +313,7 @@ static int __cmd_report(void) | |||
| 313 | perf_session__fprintf(session, stdout); | 313 | perf_session__fprintf(session, stdout); |
| 314 | 314 | ||
| 315 | if (verbose > 2) | 315 | if (verbose > 2) |
| 316 | dsos__fprintf(&session->kerninfo_root, stdout); | 316 | perf_session__fprintf_dsos(session, stdout); |
| 317 | 317 | ||
| 318 | next = rb_first(&session->stats_by_id); | 318 | next = rb_first(&session->stats_by_id); |
| 319 | while (next) { | 319 | while (next) { |
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c new file mode 100644 index 000000000000..0339612e7385 --- /dev/null +++ b/tools/perf/builtin-test.c | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | /* | ||
| 2 | * builtin-test.c | ||
| 3 | * | ||
| 4 | * Builtin regression testing command: ever growing number of sanity tests | ||
| 5 | */ | ||
| 6 | #include "builtin.h" | ||
| 7 | |||
| 8 | #include "util/cache.h" | ||
| 9 | #include "util/debug.h" | ||
| 10 | #include "util/parse-options.h" | ||
| 11 | #include "util/session.h" | ||
| 12 | #include "util/symbol.h" | ||
| 13 | #include "util/thread.h" | ||
| 14 | |||
| 15 | static long page_size; | ||
| 16 | |||
| 17 | static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) | ||
| 18 | { | ||
| 19 | bool *visited = symbol__priv(sym); | ||
| 20 | *visited = true; | ||
| 21 | return 0; | ||
| 22 | } | ||
| 23 | |||
| 24 | static int test__vmlinux_matches_kallsyms(void) | ||
| 25 | { | ||
| 26 | int err = -1; | ||
| 27 | struct rb_node *nd; | ||
| 28 | struct symbol *sym; | ||
| 29 | struct map *kallsyms_map, *vmlinux_map; | ||
| 30 | struct machine kallsyms, vmlinux; | ||
| 31 | enum map_type type = MAP__FUNCTION; | ||
| 32 | struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Step 1: | ||
| 36 | * | ||
| 37 | * Init the machines that will hold kernel, modules obtained from | ||
| 38 | * both vmlinux + .ko files and from /proc/kallsyms split by modules. | ||
| 39 | */ | ||
| 40 | machine__init(&kallsyms, "", HOST_KERNEL_ID); | ||
| 41 | machine__init(&vmlinux, "", HOST_KERNEL_ID); | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Step 2: | ||
| 45 | * | ||
| 46 | * Create the kernel maps for kallsyms and the DSO where we will then | ||
| 47 | * load /proc/kallsyms. Also create the modules maps from /proc/modules | ||
| 48 | * and find the .ko files that match them in /lib/modules/`uname -r`/. | ||
| 49 | */ | ||
| 50 | if (machine__create_kernel_maps(&kallsyms) < 0) { | ||
| 51 | pr_debug("machine__create_kernel_maps "); | ||
| 52 | return -1; | ||
| 53 | } | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Step 3: | ||
| 57 | * | ||
| 58 | * Load and split /proc/kallsyms into multiple maps, one per module. | ||
| 59 | */ | ||
| 60 | if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { | ||
| 61 | pr_debug("dso__load_kallsyms "); | ||
| 62 | goto out; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Step 4: | ||
| 67 | * | ||
| 68 | * kallsyms will be internally on demand sorted by name so that we can | ||
| 69 | * find the reference relocation * symbol, i.e. the symbol we will use | ||
| 70 | * to see if the running kernel was relocated by checking if it has the | ||
| 71 | * same value in the vmlinux file we load. | ||
| 72 | */ | ||
| 73 | kallsyms_map = machine__kernel_map(&kallsyms, type); | ||
| 74 | |||
| 75 | sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); | ||
| 76 | if (sym == NULL) { | ||
| 77 | pr_debug("dso__find_symbol_by_name "); | ||
| 78 | goto out; | ||
| 79 | } | ||
| 80 | |||
| 81 | ref_reloc_sym.addr = sym->start; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Step 5: | ||
| 85 | * | ||
| 86 | * Now repeat step 2, this time for the vmlinux file we'll auto-locate. | ||
| 87 | */ | ||
| 88 | if (machine__create_kernel_maps(&vmlinux) < 0) { | ||
| 89 | pr_debug("machine__create_kernel_maps "); | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | |||
| 93 | vmlinux_map = machine__kernel_map(&vmlinux, type); | ||
| 94 | map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Step 6: | ||
| 98 | * | ||
| 99 | * Locate a vmlinux file in the vmlinux path that has a buildid that | ||
| 100 | * matches the one of the running kernel. | ||
| 101 | * | ||
| 102 | * While doing that look if we find the ref reloc symbol, if we find it | ||
| 103 | * we'll have its ref_reloc_symbol.unrelocated_addr and then | ||
| 104 | * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines | ||
| 105 | * to fixup the symbols. | ||
| 106 | */ | ||
| 107 | if (machine__load_vmlinux_path(&vmlinux, type, | ||
| 108 | vmlinux_matches_kallsyms_filter) <= 0) { | ||
| 109 | pr_debug("machine__load_vmlinux_path "); | ||
| 110 | goto out; | ||
| 111 | } | ||
| 112 | |||
| 113 | err = 0; | ||
| 114 | /* | ||
| 115 | * Step 7: | ||
| 116 | * | ||
| 117 | * Now look at the symbols in the vmlinux DSO and check if we find all of them | ||
| 118 | * in the kallsyms dso. For the ones that are in both, check its names and | ||
| 119 | * end addresses too. | ||
| 120 | */ | ||
| 121 | for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { | ||
| 122 | struct symbol *pair; | ||
| 123 | |||
| 124 | sym = rb_entry(nd, struct symbol, rb_node); | ||
| 125 | pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); | ||
| 126 | |||
| 127 | if (pair && pair->start == sym->start) { | ||
| 128 | next_pair: | ||
| 129 | if (strcmp(sym->name, pair->name) == 0) { | ||
| 130 | /* | ||
| 131 | * kallsyms don't have the symbol end, so we | ||
| 132 | * set that by using the next symbol start - 1, | ||
| 133 | * in some cases we get this up to a page | ||
| 134 | * wrong, trace_kmalloc when I was developing | ||
| 135 | * this code was one such example, 2106 bytes | ||
| 136 | * off the real size. More than that and we | ||
| 137 | * _really_ have a problem. | ||
| 138 | */ | ||
| 139 | s64 skew = sym->end - pair->end; | ||
| 140 | if (llabs(skew) < page_size) | ||
| 141 | continue; | ||
| 142 | |||
| 143 | pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", | ||
| 144 | sym->start, sym->name, sym->end, pair->end); | ||
| 145 | } else { | ||
| 146 | struct rb_node *nnd = rb_prev(&pair->rb_node); | ||
| 147 | |||
| 148 | if (nnd) { | ||
| 149 | struct symbol *next = rb_entry(nnd, struct symbol, rb_node); | ||
| 150 | |||
| 151 | if (next->start == sym->start) { | ||
| 152 | pair = next; | ||
| 153 | goto next_pair; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | pr_debug("%#Lx: diff name v: %s k: %s\n", | ||
| 157 | sym->start, sym->name, pair->name); | ||
| 158 | } | ||
| 159 | } else | ||
| 160 | pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name); | ||
| 161 | |||
| 162 | err = -1; | ||
| 163 | } | ||
| 164 | |||
| 165 | if (!verbose) | ||
| 166 | goto out; | ||
| 167 | |||
| 168 | pr_info("Maps only in vmlinux:\n"); | ||
| 169 | |||
| 170 | for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { | ||
| 171 | struct map *pos = rb_entry(nd, struct map, rb_node), *pair; | ||
| 172 | /* | ||
| 173 | * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while | ||
| 174 | * the kernel will have the path for the vmlinux file being used, | ||
| 175 | * so use the short name, less descriptive but the same ("[kernel]" in | ||
| 176 | * both cases. | ||
| 177 | */ | ||
| 178 | pair = map_groups__find_by_name(&kallsyms.kmaps, type, | ||
| 179 | (pos->dso->kernel ? | ||
| 180 | pos->dso->short_name : | ||
| 181 | pos->dso->name)); | ||
| 182 | if (pair) | ||
| 183 | pair->priv = 1; | ||
| 184 | else | ||
| 185 | map__fprintf(pos, stderr); | ||
| 186 | } | ||
| 187 | |||
| 188 | pr_info("Maps in vmlinux with a different name in kallsyms:\n"); | ||
| 189 | |||
| 190 | for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { | ||
| 191 | struct map *pos = rb_entry(nd, struct map, rb_node), *pair; | ||
| 192 | |||
| 193 | pair = map_groups__find(&kallsyms.kmaps, type, pos->start); | ||
| 194 | if (pair == NULL || pair->priv) | ||
| 195 | continue; | ||
| 196 | |||
| 197 | if (pair->start == pos->start) { | ||
| 198 | pair->priv = 1; | ||
| 199 | pr_info(" %Lx-%Lx %Lx %s in kallsyms as", | ||
| 200 | pos->start, pos->end, pos->pgoff, pos->dso->name); | ||
| 201 | if (pos->pgoff != pair->pgoff || pos->end != pair->end) | ||
| 202 | pr_info(": \n*%Lx-%Lx %Lx", | ||
| 203 | pair->start, pair->end, pair->pgoff); | ||
| 204 | pr_info(" %s\n", pair->dso->name); | ||
| 205 | pair->priv = 1; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | pr_info("Maps only in kallsyms:\n"); | ||
| 210 | |||
| 211 | for (nd = rb_first(&kallsyms.kmaps.maps[type]); | ||
| 212 | nd; nd = rb_next(nd)) { | ||
| 213 | struct map *pos = rb_entry(nd, struct map, rb_node); | ||
| 214 | |||
| 215 | if (!pos->priv) | ||
| 216 | map__fprintf(pos, stderr); | ||
| 217 | } | ||
| 218 | out: | ||
| 219 | return err; | ||
| 220 | } | ||
| 221 | |||
| 222 | static struct test { | ||
| 223 | const char *desc; | ||
| 224 | int (*func)(void); | ||
| 225 | } tests[] = { | ||
| 226 | { | ||
| 227 | .desc = "vmlinux symtab matches kallsyms", | ||
| 228 | .func = test__vmlinux_matches_kallsyms, | ||
| 229 | }, | ||
| 230 | { | ||
| 231 | .func = NULL, | ||
| 232 | }, | ||
| 233 | }; | ||
| 234 | |||
| 235 | static int __cmd_test(void) | ||
| 236 | { | ||
| 237 | int i = 0; | ||
| 238 | |||
| 239 | page_size = sysconf(_SC_PAGE_SIZE); | ||
| 240 | |||
| 241 | while (tests[i].func) { | ||
| 242 | int err; | ||
| 243 | pr_info("%2d: %s:", i + 1, tests[i].desc); | ||
| 244 | pr_debug("\n--- start ---\n"); | ||
| 245 | err = tests[i].func(); | ||
| 246 | pr_debug("---- end ----\n%s:", tests[i].desc); | ||
| 247 | pr_info(" %s\n", err ? "FAILED!\n" : "Ok"); | ||
| 248 | ++i; | ||
| 249 | } | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static const char * const test_usage[] = { | ||
| 255 | "perf test [<options>]", | ||
| 256 | NULL, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static const struct option test_options[] = { | ||
| 260 | OPT_BOOLEAN('v', "verbose", &verbose, | ||
| 261 | "be more verbose (show symbol address, etc)"), | ||
| 262 | OPT_END() | ||
| 263 | }; | ||
| 264 | |||
| 265 | int cmd_test(int argc, const char **argv, const char *prefix __used) | ||
| 266 | { | ||
| 267 | argc = parse_options(argc, argv, test_options, test_usage, 0); | ||
| 268 | if (argc) | ||
| 269 | usage_with_options(test_usage, test_options); | ||
| 270 | |||
| 271 | symbol_conf.priv_size = sizeof(int); | ||
| 272 | symbol_conf.sort_by_name = true; | ||
| 273 | symbol_conf.try_vmlinux_path = true; | ||
| 274 | |||
| 275 | if (symbol__init() < 0) | ||
| 276 | return -1; | ||
| 277 | |||
| 278 | setup_pager(); | ||
| 279 | |||
| 280 | return __cmd_test(); | ||
| 281 | } | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index dfd7ea7dabdd..d95281f588d2 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) | |||
| 854 | case 'Q': | 854 | case 'Q': |
| 855 | printf("exiting.\n"); | 855 | printf("exiting.\n"); |
| 856 | if (dump_symtab) | 856 | if (dump_symtab) |
| 857 | dsos__fprintf(&session->kerninfo_root, stderr); | 857 | perf_session__fprintf_dsos(session, stderr); |
| 858 | exit(0); | 858 | exit(0); |
| 859 | case 's': | 859 | case 's': |
| 860 | prompt_symbol(&sym_filter_entry, "Enter details symbol"); | 860 | prompt_symbol(&sym_filter_entry, "Enter details symbol"); |
| @@ -982,7 +982,7 @@ static void event__process_sample(const event_t *self, | |||
| 982 | u64 ip = self->ip.ip; | 982 | u64 ip = self->ip.ip; |
| 983 | struct sym_entry *syme; | 983 | struct sym_entry *syme; |
| 984 | struct addr_location al; | 984 | struct addr_location al; |
| 985 | struct kernel_info *kerninfo; | 985 | struct machine *machine; |
| 986 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 986 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
| 987 | 987 | ||
| 988 | ++samples; | 988 | ++samples; |
| @@ -992,18 +992,17 @@ static void event__process_sample(const event_t *self, | |||
| 992 | ++us_samples; | 992 | ++us_samples; |
| 993 | if (hide_user_symbols) | 993 | if (hide_user_symbols) |
| 994 | return; | 994 | return; |
| 995 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 995 | machine = perf_session__find_host_machine(session); |
| 996 | break; | 996 | break; |
| 997 | case PERF_RECORD_MISC_KERNEL: | 997 | case PERF_RECORD_MISC_KERNEL: |
| 998 | ++kernel_samples; | 998 | ++kernel_samples; |
| 999 | if (hide_kernel_symbols) | 999 | if (hide_kernel_symbols) |
| 1000 | return; | 1000 | return; |
| 1001 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 1001 | machine = perf_session__find_host_machine(session); |
| 1002 | break; | 1002 | break; |
| 1003 | case PERF_RECORD_MISC_GUEST_KERNEL: | 1003 | case PERF_RECORD_MISC_GUEST_KERNEL: |
| 1004 | ++guest_kernel_samples; | 1004 | ++guest_kernel_samples; |
| 1005 | kerninfo = kerninfo__find(&session->kerninfo_root, | 1005 | machine = perf_session__find_machine(session, self->ip.pid); |
| 1006 | self->ip.pid); | ||
| 1007 | break; | 1006 | break; |
| 1008 | case PERF_RECORD_MISC_GUEST_USER: | 1007 | case PERF_RECORD_MISC_GUEST_USER: |
| 1009 | ++guest_us_samples; | 1008 | ++guest_us_samples; |
| @@ -1016,7 +1015,7 @@ static void event__process_sample(const event_t *self, | |||
| 1016 | return; | 1015 | return; |
| 1017 | } | 1016 | } |
| 1018 | 1017 | ||
| 1019 | if (!kerninfo && perf_guest) { | 1018 | if (!machine && perf_guest) { |
| 1020 | pr_err("Can't find guest [%d]'s kernel information\n", | 1019 | pr_err("Can't find guest [%d]'s kernel information\n", |
| 1021 | self->ip.pid); | 1020 | self->ip.pid); |
| 1022 | return; | 1021 | return; |
| @@ -1041,7 +1040,7 @@ static void event__process_sample(const event_t *self, | |||
| 1041 | * --hide-kernel-symbols, even if the user specifies an | 1040 | * --hide-kernel-symbols, even if the user specifies an |
| 1042 | * invalid --vmlinux ;-) | 1041 | * invalid --vmlinux ;-) |
| 1043 | */ | 1042 | */ |
| 1044 | if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] && | 1043 | if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && |
| 1045 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { | 1044 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { |
| 1046 | pr_err("The %s file can't be used\n", | 1045 | pr_err("The %s file can't be used\n", |
| 1047 | symbol_conf.vmlinux_name); | 1046 | symbol_conf.vmlinux_name); |
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index ab28bca92e52..34a8a9ab9617 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); | |||
| 33 | extern int cmd_kmem(int argc, const char **argv, const char *prefix); | 33 | extern int cmd_kmem(int argc, const char **argv, const char *prefix); |
| 34 | extern int cmd_lock(int argc, const char **argv, const char *prefix); | 34 | extern int cmd_lock(int argc, const char **argv, const char *prefix); |
| 35 | extern int cmd_kvm(int argc, const char **argv, const char *prefix); | 35 | extern int cmd_kvm(int argc, const char **argv, const char *prefix); |
| 36 | extern int cmd_test(int argc, const char **argv, const char *prefix); | ||
| 36 | 37 | ||
| 37 | #endif | 38 | #endif |
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index 2a1162d413a8..80a1a446ce35 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt | |||
| @@ -20,3 +20,4 @@ perf-probe mainporcelain common | |||
| 20 | perf-kmem mainporcelain common | 20 | perf-kmem mainporcelain common |
| 21 | perf-lock mainporcelain common | 21 | perf-lock mainporcelain common |
| 22 | perf-kvm mainporcelain common | 22 | perf-kvm mainporcelain common |
| 23 | perf-test mainporcelain common | ||
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 985cdb4bd005..5ff9b5b46970 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) | |||
| 308 | { "kmem", cmd_kmem, 0 }, | 308 | { "kmem", cmd_kmem, 0 }, |
| 309 | { "lock", cmd_lock, 0 }, | 309 | { "lock", cmd_lock, 0 }, |
| 310 | { "kvm", cmd_kvm, 0 }, | 310 | { "kvm", cmd_kvm, 0 }, |
| 311 | { "test", cmd_test, 0 }, | ||
| 311 | }; | 312 | }; |
| 312 | unsigned int i; | 313 | unsigned int i; |
| 313 | static const char ext[] = STRIP_EXTENSION; | 314 | static const char ext[] = STRIP_EXTENSION; |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e3fa8d3d11b4..1757b0ffeaa9 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, | |||
| 172 | 172 | ||
| 173 | int event__synthesize_modules(event__handler_t process, | 173 | int event__synthesize_modules(event__handler_t process, |
| 174 | struct perf_session *session, | 174 | struct perf_session *session, |
| 175 | struct kernel_info *kerninfo) | 175 | struct machine *machine) |
| 176 | { | 176 | { |
| 177 | struct rb_node *nd; | 177 | struct rb_node *nd; |
| 178 | struct map_groups *kmaps = &kerninfo->kmaps; | 178 | struct map_groups *kmaps = &machine->kmaps; |
| 179 | u16 misc; | 179 | u16 misc; |
| 180 | 180 | ||
| 181 | /* | 181 | /* |
| 182 | * kernel uses 0 for user space maps, see kernel/perf_event.c | 182 | * kernel uses 0 for user space maps, see kernel/perf_event.c |
| 183 | * __perf_event_mmap | 183 | * __perf_event_mmap |
| 184 | */ | 184 | */ |
| 185 | if (is_host_kernel(kerninfo)) | 185 | if (machine__is_host(machine)) |
| 186 | misc = PERF_RECORD_MISC_KERNEL; | 186 | misc = PERF_RECORD_MISC_KERNEL; |
| 187 | else | 187 | else |
| 188 | misc = PERF_RECORD_MISC_GUEST_KERNEL; | 188 | misc = PERF_RECORD_MISC_GUEST_KERNEL; |
| @@ -204,7 +204,7 @@ int event__synthesize_modules(event__handler_t process, | |||
| 204 | (sizeof(ev.mmap.filename) - size)); | 204 | (sizeof(ev.mmap.filename) - size)); |
| 205 | ev.mmap.start = pos->start; | 205 | ev.mmap.start = pos->start; |
| 206 | ev.mmap.len = pos->end - pos->start; | 206 | ev.mmap.len = pos->end - pos->start; |
| 207 | ev.mmap.pid = kerninfo->pid; | 207 | ev.mmap.pid = machine->pid; |
| 208 | 208 | ||
| 209 | memcpy(ev.mmap.filename, pos->dso->long_name, | 209 | memcpy(ev.mmap.filename, pos->dso->long_name, |
| 210 | pos->dso->long_name_len + 1); | 210 | pos->dso->long_name_len + 1); |
| @@ -267,7 +267,7 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start) | |||
| 267 | 267 | ||
| 268 | int event__synthesize_kernel_mmap(event__handler_t process, | 268 | int event__synthesize_kernel_mmap(event__handler_t process, |
| 269 | struct perf_session *session, | 269 | struct perf_session *session, |
| 270 | struct kernel_info *kerninfo, | 270 | struct machine *machine, |
| 271 | const char *symbol_name) | 271 | const char *symbol_name) |
| 272 | { | 272 | { |
| 273 | size_t size; | 273 | size_t size; |
| @@ -288,8 +288,8 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
| 288 | */ | 288 | */ |
| 289 | struct process_symbol_args args = { .name = symbol_name, }; | 289 | struct process_symbol_args args = { .name = symbol_name, }; |
| 290 | 290 | ||
| 291 | mmap_name = kern_mmap_name(kerninfo, name_buff); | 291 | mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); |
| 292 | if (is_host_kernel(kerninfo)) { | 292 | if (machine__is_host(machine)) { |
| 293 | /* | 293 | /* |
| 294 | * kernel uses PERF_RECORD_MISC_USER for user space maps, | 294 | * kernel uses PERF_RECORD_MISC_USER for user space maps, |
| 295 | * see kernel/perf_event.c __perf_event_mmap | 295 | * see kernel/perf_event.c __perf_event_mmap |
| @@ -298,10 +298,10 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
| 298 | filename = "/proc/kallsyms"; | 298 | filename = "/proc/kallsyms"; |
| 299 | } else { | 299 | } else { |
| 300 | ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; | 300 | ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
| 301 | if (is_default_guest(kerninfo)) | 301 | if (machine__is_default_guest(machine)) |
| 302 | filename = (char *) symbol_conf.default_guest_kallsyms; | 302 | filename = (char *) symbol_conf.default_guest_kallsyms; |
| 303 | else { | 303 | else { |
| 304 | sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); | 304 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); |
| 305 | filename = path; | 305 | filename = path; |
| 306 | } | 306 | } |
| 307 | } | 307 | } |
| @@ -309,7 +309,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
| 309 | if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) | 309 | if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) |
| 310 | return -ENOENT; | 310 | return -ENOENT; |
| 311 | 311 | ||
| 312 | map = kerninfo->vmlinux_maps[MAP__FUNCTION]; | 312 | map = machine->vmlinux_maps[MAP__FUNCTION]; |
| 313 | size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), | 313 | size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), |
| 314 | "%s%s", mmap_name, symbol_name) + 1; | 314 | "%s%s", mmap_name, symbol_name) + 1; |
| 315 | size = ALIGN(size, sizeof(u64)); | 315 | size = ALIGN(size, sizeof(u64)); |
| @@ -318,7 +318,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
| 318 | ev.mmap.pgoff = args.start; | 318 | ev.mmap.pgoff = args.start; |
| 319 | ev.mmap.start = map->start; | 319 | ev.mmap.start = map->start; |
| 320 | ev.mmap.len = map->end - ev.mmap.start; | 320 | ev.mmap.len = map->end - ev.mmap.start; |
| 321 | ev.mmap.pid = kerninfo->pid; | 321 | ev.mmap.pid = machine->pid; |
| 322 | 322 | ||
| 323 | return process(&ev, session); | 323 | return process(&ev, session); |
| 324 | } | 324 | } |
| @@ -389,18 +389,18 @@ static int event__process_kernel_mmap(event_t *self, | |||
| 389 | { | 389 | { |
| 390 | struct map *map; | 390 | struct map *map; |
| 391 | char kmmap_prefix[PATH_MAX]; | 391 | char kmmap_prefix[PATH_MAX]; |
| 392 | struct kernel_info *kerninfo; | 392 | struct machine *machine; |
| 393 | enum dso_kernel_type kernel_type; | 393 | enum dso_kernel_type kernel_type; |
| 394 | bool is_kernel_mmap; | 394 | bool is_kernel_mmap; |
| 395 | 395 | ||
| 396 | kerninfo = kerninfo__findnew(&session->kerninfo_root, self->mmap.pid); | 396 | machine = perf_session__findnew_machine(session, self->mmap.pid); |
| 397 | if (!kerninfo) { | 397 | if (!machine) { |
| 398 | pr_err("Can't find id %d's kerninfo\n", self->mmap.pid); | 398 | pr_err("Can't find id %d's machine\n", self->mmap.pid); |
| 399 | goto out_problem; | 399 | goto out_problem; |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | kern_mmap_name(kerninfo, kmmap_prefix); | 402 | machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); |
| 403 | if (is_host_kernel(kerninfo)) | 403 | if (machine__is_host(machine)) |
| 404 | kernel_type = DSO_TYPE_KERNEL; | 404 | kernel_type = DSO_TYPE_KERNEL; |
| 405 | else | 405 | else |
| 406 | kernel_type = DSO_TYPE_GUEST_KERNEL; | 406 | kernel_type = DSO_TYPE_GUEST_KERNEL; |
| @@ -429,10 +429,8 @@ static int event__process_kernel_mmap(event_t *self, | |||
| 429 | } else | 429 | } else |
| 430 | strcpy(short_module_name, self->mmap.filename); | 430 | strcpy(short_module_name, self->mmap.filename); |
| 431 | 431 | ||
| 432 | map = map_groups__new_module(&kerninfo->kmaps, | 432 | map = machine__new_module(machine, self->mmap.start, |
| 433 | self->mmap.start, | 433 | self->mmap.filename); |
| 434 | self->mmap.filename, | ||
| 435 | kerninfo); | ||
| 436 | if (map == NULL) | 434 | if (map == NULL) |
| 437 | goto out_problem; | 435 | goto out_problem; |
| 438 | 436 | ||
| @@ -449,27 +447,25 @@ static int event__process_kernel_mmap(event_t *self, | |||
| 449 | * Should be there already, from the build-id table in | 447 | * Should be there already, from the build-id table in |
| 450 | * the header. | 448 | * the header. |
| 451 | */ | 449 | */ |
| 452 | struct dso *kernel = __dsos__findnew(&kerninfo->dsos__kernel, | 450 | struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, |
| 453 | kmmap_prefix); | 451 | kmmap_prefix); |
| 454 | if (kernel == NULL) | 452 | if (kernel == NULL) |
| 455 | goto out_problem; | 453 | goto out_problem; |
| 456 | 454 | ||
| 457 | kernel->kernel = kernel_type; | 455 | kernel->kernel = kernel_type; |
| 458 | if (__map_groups__create_kernel_maps(&kerninfo->kmaps, | 456 | if (__machine__create_kernel_maps(machine, kernel) < 0) |
| 459 | kerninfo->vmlinux_maps, kernel) < 0) | ||
| 460 | goto out_problem; | 457 | goto out_problem; |
| 461 | 458 | ||
| 462 | event_set_kernel_mmap_len(kerninfo->vmlinux_maps, self); | 459 | event_set_kernel_mmap_len(machine->vmlinux_maps, self); |
| 463 | perf_session__set_kallsyms_ref_reloc_sym(kerninfo->vmlinux_maps, | 460 | perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, |
| 464 | symbol_name, | 461 | symbol_name, |
| 465 | self->mmap.pgoff); | 462 | self->mmap.pgoff); |
| 466 | if (is_default_guest(kerninfo)) { | 463 | if (machine__is_default_guest(machine)) { |
| 467 | /* | 464 | /* |
| 468 | * preload dso of guest kernel and modules | 465 | * preload dso of guest kernel and modules |
| 469 | */ | 466 | */ |
| 470 | dso__load(kernel, | 467 | dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], |
| 471 | kerninfo->vmlinux_maps[MAP__FUNCTION], | 468 | NULL); |
| 472 | NULL); | ||
| 473 | } | 469 | } |
| 474 | } | 470 | } |
| 475 | return 0; | 471 | return 0; |
| @@ -479,7 +475,7 @@ out_problem: | |||
| 479 | 475 | ||
| 480 | int event__process_mmap(event_t *self, struct perf_session *session) | 476 | int event__process_mmap(event_t *self, struct perf_session *session) |
| 481 | { | 477 | { |
| 482 | struct kernel_info *kerninfo; | 478 | struct machine *machine; |
| 483 | struct thread *thread; | 479 | struct thread *thread; |
| 484 | struct map *map; | 480 | struct map *map; |
| 485 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 481 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
| @@ -498,8 +494,8 @@ int event__process_mmap(event_t *self, struct perf_session *session) | |||
| 498 | } | 494 | } |
| 499 | 495 | ||
| 500 | thread = perf_session__findnew(session, self->mmap.pid); | 496 | thread = perf_session__findnew(session, self->mmap.pid); |
| 501 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 497 | machine = perf_session__find_host_machine(session); |
| 502 | map = map__new(&kerninfo->dsos__user, self->mmap.start, | 498 | map = map__new(&machine->user_dsos, self->mmap.start, |
| 503 | self->mmap.len, self->mmap.pgoff, | 499 | self->mmap.len, self->mmap.pgoff, |
| 504 | self->mmap.pid, self->mmap.filename, | 500 | self->mmap.pid, self->mmap.filename, |
| 505 | MAP__FUNCTION, session->cwd, session->cwdlen); | 501 | MAP__FUNCTION, session->cwd, session->cwdlen); |
| @@ -546,7 +542,7 @@ void thread__find_addr_map(struct thread *self, | |||
| 546 | struct addr_location *al) | 542 | struct addr_location *al) |
| 547 | { | 543 | { |
| 548 | struct map_groups *mg = &self->mg; | 544 | struct map_groups *mg = &self->mg; |
| 549 | struct kernel_info *kerninfo = NULL; | 545 | struct machine *machine = NULL; |
| 550 | 546 | ||
| 551 | al->thread = self; | 547 | al->thread = self; |
| 552 | al->addr = addr; | 548 | al->addr = addr; |
| @@ -555,19 +551,19 @@ void thread__find_addr_map(struct thread *self, | |||
| 555 | 551 | ||
| 556 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { | 552 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { |
| 557 | al->level = 'k'; | 553 | al->level = 'k'; |
| 558 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 554 | machine = perf_session__find_host_machine(session); |
| 559 | mg = &kerninfo->kmaps; | 555 | mg = &machine->kmaps; |
| 560 | } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { | 556 | } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { |
| 561 | al->level = '.'; | 557 | al->level = '.'; |
| 562 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | 558 | machine = perf_session__find_host_machine(session); |
| 563 | } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { | 559 | } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { |
| 564 | al->level = 'g'; | 560 | al->level = 'g'; |
| 565 | kerninfo = kerninfo__find(&session->kerninfo_root, pid); | 561 | machine = perf_session__find_machine(session, pid); |
| 566 | if (!kerninfo) { | 562 | if (!machine) { |
| 567 | al->map = NULL; | 563 | al->map = NULL; |
| 568 | return; | 564 | return; |
| 569 | } | 565 | } |
| 570 | mg = &kerninfo->kmaps; | 566 | mg = &machine->kmaps; |
| 571 | } else { | 567 | } else { |
| 572 | /* | 568 | /* |
| 573 | * 'u' means guest os user space. | 569 | * 'u' means guest os user space. |
| @@ -603,10 +599,9 @@ try_again: | |||
| 603 | * in the whole kernel symbol list. | 599 | * in the whole kernel symbol list. |
| 604 | */ | 600 | */ |
| 605 | if ((long long)al->addr < 0 && | 601 | if ((long long)al->addr < 0 && |
| 606 | cpumode == PERF_RECORD_MISC_KERNEL && | 602 | cpumode == PERF_RECORD_MISC_KERNEL && |
| 607 | kerninfo && | 603 | machine && mg != &machine->kmaps) { |
| 608 | mg != &kerninfo->kmaps) { | 604 | mg = &machine->kmaps; |
| 609 | mg = &kerninfo->kmaps; | ||
| 610 | goto try_again; | 605 | goto try_again; |
| 611 | } | 606 | } |
| 612 | } else | 607 | } else |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 4af2ed5d48ad..b364da5b0cbf 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, | |||
| 156 | struct perf_session *session); | 156 | struct perf_session *session); |
| 157 | int event__synthesize_kernel_mmap(event__handler_t process, | 157 | int event__synthesize_kernel_mmap(event__handler_t process, |
| 158 | struct perf_session *session, | 158 | struct perf_session *session, |
| 159 | struct kernel_info *kerninfo, | 159 | struct machine *machine, |
| 160 | const char *symbol_name); | 160 | const char *symbol_name); |
| 161 | 161 | ||
| 162 | int event__synthesize_modules(event__handler_t process, | 162 | int event__synthesize_modules(event__handler_t process, |
| 163 | struct perf_session *session, | 163 | struct perf_session *session, |
| 164 | struct kernel_info *kerninfo); | 164 | struct machine *machine); |
| 165 | 165 | ||
| 166 | int event__process_comm(event_t *self, struct perf_session *session); | 166 | int event__process_comm(event_t *self, struct perf_session *session); |
| 167 | int event__process_lost(event_t *self, struct perf_session *session); | 167 | 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 75d016768021..6227dc4cb2cf 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) | |||
| 229 | int err = 0; | 229 | int err = 0; |
| 230 | u16 kmisc, umisc; | 230 | u16 kmisc, umisc; |
| 231 | 231 | ||
| 232 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | 232 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
| 233 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 233 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 234 | rb_node); | 234 | if (machine__is_host(pos)) { |
| 235 | if (is_host_kernel(pos)) { | ||
| 236 | kmisc = PERF_RECORD_MISC_KERNEL; | 235 | kmisc = PERF_RECORD_MISC_KERNEL; |
| 237 | umisc = PERF_RECORD_MISC_USER; | 236 | umisc = PERF_RECORD_MISC_USER; |
| 238 | } else { | 237 | } else { |
| @@ -240,11 +239,11 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) | |||
| 240 | umisc = PERF_RECORD_MISC_GUEST_USER; | 239 | umisc = PERF_RECORD_MISC_GUEST_USER; |
| 241 | } | 240 | } |
| 242 | 241 | ||
| 243 | err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, | 242 | err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid, |
| 244 | kmisc, fd); | 243 | kmisc, fd); |
| 245 | if (err == 0) | 244 | if (err == 0) |
| 246 | err = __dsos__write_buildid_table(&pos->dsos__user, | 245 | err = __dsos__write_buildid_table(&pos->user_dsos, |
| 247 | pos->pid, umisc, fd); | 246 | pos->pid, umisc, fd); |
| 248 | if (err) | 247 | if (err) |
| 249 | break; | 248 | break; |
| 250 | } | 249 | } |
| @@ -378,11 +377,10 @@ static int dsos__cache_build_ids(struct perf_header *self) | |||
| 378 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 377 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
| 379 | return -1; | 378 | return -1; |
| 380 | 379 | ||
| 381 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | 380 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
| 382 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 381 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 383 | rb_node); | 382 | ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir); |
| 384 | ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); | 383 | ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir); |
| 385 | ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); | ||
| 386 | } | 384 | } |
| 387 | return ret ? -1 : 0; | 385 | return ret ? -1 : 0; |
| 388 | } | 386 | } |
| @@ -394,11 +392,10 @@ static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) | |||
| 394 | struct perf_session, header); | 392 | struct perf_session, header); |
| 395 | struct rb_node *nd; | 393 | struct rb_node *nd; |
| 396 | 394 | ||
| 397 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | 395 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
| 398 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 396 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 399 | rb_node); | 397 | ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits); |
| 400 | ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); | 398 | ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits); |
| 401 | ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); | ||
| 402 | } | 399 | } |
| 403 | 400 | ||
| 404 | return ret; | 401 | return ret; |
| @@ -685,13 +682,13 @@ static int __event_process_build_id(struct build_id_event *bev, | |||
| 685 | { | 682 | { |
| 686 | int err = -1; | 683 | int err = -1; |
| 687 | struct list_head *head; | 684 | struct list_head *head; |
| 688 | struct kernel_info *kerninfo; | 685 | struct machine *machine; |
| 689 | u16 misc; | 686 | u16 misc; |
| 690 | struct dso *dso; | 687 | struct dso *dso; |
| 691 | enum dso_kernel_type dso_type; | 688 | enum dso_kernel_type dso_type; |
| 692 | 689 | ||
| 693 | kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); | 690 | machine = perf_session__findnew_machine(session, bev->pid); |
| 694 | if (!kerninfo) | 691 | if (!machine) |
| 695 | goto out; | 692 | goto out; |
| 696 | 693 | ||
| 697 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 694 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
| @@ -699,16 +696,16 @@ static int __event_process_build_id(struct build_id_event *bev, | |||
| 699 | switch (misc) { | 696 | switch (misc) { |
| 700 | case PERF_RECORD_MISC_KERNEL: | 697 | case PERF_RECORD_MISC_KERNEL: |
| 701 | dso_type = DSO_TYPE_KERNEL; | 698 | dso_type = DSO_TYPE_KERNEL; |
| 702 | head = &kerninfo->dsos__kernel; | 699 | head = &machine->kernel_dsos; |
| 703 | break; | 700 | break; |
| 704 | case PERF_RECORD_MISC_GUEST_KERNEL: | 701 | case PERF_RECORD_MISC_GUEST_KERNEL: |
| 705 | dso_type = DSO_TYPE_GUEST_KERNEL; | 702 | dso_type = DSO_TYPE_GUEST_KERNEL; |
| 706 | head = &kerninfo->dsos__kernel; | 703 | head = &machine->kernel_dsos; |
| 707 | break; | 704 | break; |
| 708 | case PERF_RECORD_MISC_USER: | 705 | case PERF_RECORD_MISC_USER: |
| 709 | case PERF_RECORD_MISC_GUEST_USER: | 706 | case PERF_RECORD_MISC_GUEST_USER: |
| 710 | dso_type = DSO_TYPE_USER; | 707 | dso_type = DSO_TYPE_USER; |
| 711 | head = &kerninfo->dsos__user; | 708 | head = &machine->user_dsos; |
| 712 | break; | 709 | break; |
| 713 | default: | 710 | default: |
| 714 | goto out; | 711 | goto out; |
| @@ -1113,8 +1110,7 @@ int event__process_tracing_data(event_t *self, | |||
| 1113 | } | 1110 | } |
| 1114 | 1111 | ||
| 1115 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 1112 | int event__synthesize_build_id(struct dso *pos, u16 misc, |
| 1116 | event__handler_t process, | 1113 | event__handler_t process, struct machine *machine, |
| 1117 | struct kernel_info *kerninfo, | ||
| 1118 | struct perf_session *session) | 1114 | struct perf_session *session) |
| 1119 | { | 1115 | { |
| 1120 | event_t ev; | 1116 | event_t ev; |
| @@ -1131,7 +1127,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
| 1131 | memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); | 1127 | memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); |
| 1132 | ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; | 1128 | ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; |
| 1133 | ev.build_id.header.misc = misc; | 1129 | ev.build_id.header.misc = misc; |
| 1134 | ev.build_id.pid = kerninfo->pid; | 1130 | ev.build_id.pid = machine->pid; |
| 1135 | ev.build_id.header.size = sizeof(ev.build_id) + len; | 1131 | ev.build_id.header.size = sizeof(ev.build_id) + len; |
| 1136 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); | 1132 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); |
| 1137 | 1133 | ||
| @@ -1142,7 +1138,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
| 1142 | 1138 | ||
| 1143 | static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | 1139 | static int __event_synthesize_build_ids(struct list_head *head, u16 misc, |
| 1144 | event__handler_t process, | 1140 | event__handler_t process, |
| 1145 | struct kernel_info *kerninfo, | 1141 | struct machine *machine, |
| 1146 | struct perf_session *session) | 1142 | struct perf_session *session) |
| 1147 | { | 1143 | { |
| 1148 | struct dso *pos; | 1144 | struct dso *pos; |
| @@ -1153,7 +1149,7 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | |||
| 1153 | continue; | 1149 | continue; |
| 1154 | 1150 | ||
| 1155 | err = event__synthesize_build_id(pos, misc, process, | 1151 | err = event__synthesize_build_id(pos, misc, process, |
| 1156 | kerninfo, session); | 1152 | machine, session); |
| 1157 | if (err < 0) | 1153 | if (err < 0) |
| 1158 | return err; | 1154 | return err; |
| 1159 | } | 1155 | } |
| @@ -1166,15 +1162,15 @@ int event__synthesize_build_ids(event__handler_t process, | |||
| 1166 | { | 1162 | { |
| 1167 | int err = 0; | 1163 | int err = 0; |
| 1168 | u16 kmisc, umisc; | 1164 | u16 kmisc, umisc; |
| 1169 | struct kernel_info *pos; | 1165 | struct machine *pos; |
| 1170 | struct rb_node *nd; | 1166 | struct rb_node *nd; |
| 1171 | 1167 | ||
| 1172 | if (!dsos__read_build_ids(&session->header, true)) | 1168 | if (!dsos__read_build_ids(&session->header, true)) |
| 1173 | return 0; | 1169 | return 0; |
| 1174 | 1170 | ||
| 1175 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | 1171 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
| 1176 | pos = rb_entry(nd, struct kernel_info, rb_node); | 1172 | pos = rb_entry(nd, struct machine, rb_node); |
| 1177 | if (is_host_kernel(pos)) { | 1173 | if (machine__is_host(pos)) { |
| 1178 | kmisc = PERF_RECORD_MISC_KERNEL; | 1174 | kmisc = PERF_RECORD_MISC_KERNEL; |
| 1179 | umisc = PERF_RECORD_MISC_USER; | 1175 | umisc = PERF_RECORD_MISC_USER; |
| 1180 | } else { | 1176 | } else { |
| @@ -1182,11 +1178,11 @@ int event__synthesize_build_ids(event__handler_t process, | |||
| 1182 | umisc = PERF_RECORD_MISC_GUEST_USER; | 1178 | umisc = PERF_RECORD_MISC_GUEST_USER; |
| 1183 | } | 1179 | } |
| 1184 | 1180 | ||
| 1185 | err = __event_synthesize_build_ids(&pos->dsos__kernel, | 1181 | err = __event_synthesize_build_ids(&pos->kernel_dsos, kmisc, |
| 1186 | kmisc, process, pos, session); | 1182 | process, pos, session); |
| 1187 | if (err == 0) | 1183 | if (err == 0) |
| 1188 | err = __event_synthesize_build_ids(&pos->dsos__user, | 1184 | err = __event_synthesize_build_ids(&pos->user_dsos, umisc, |
| 1189 | umisc, process, pos, session); | 1185 | process, pos, session); |
| 1190 | if (err) | 1186 | if (err) |
| 1191 | break; | 1187 | break; |
| 1192 | } | 1188 | } |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 275915458148..f39443db0706 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, | |||
| 120 | 120 | ||
| 121 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 121 | int event__synthesize_build_id(struct dso *pos, u16 misc, |
| 122 | event__handler_t process, | 122 | event__handler_t process, |
| 123 | struct kernel_info *kerninfo, | 123 | struct machine *machine, |
| 124 | struct perf_session *session); | 124 | struct perf_session *session); |
| 125 | int event__synthesize_build_ids(event__handler_t process, | 125 | int event__synthesize_build_ids(event__handler_t process, |
| 126 | struct perf_session *session); | 126 | struct perf_session *session); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 7facd016ec97..44a4df68b3cf 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) | |||
| 245 | self->maps[i] = RB_ROOT; | 245 | self->maps[i] = RB_ROOT; |
| 246 | INIT_LIST_HEAD(&self->removed_maps[i]); | 246 | INIT_LIST_HEAD(&self->removed_maps[i]); |
| 247 | } | 247 | } |
| 248 | self->this_kerninfo = NULL; | 248 | self->machine = NULL; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | void map_groups__flush(struct map_groups *self) | 251 | void map_groups__flush(struct map_groups *self) |
| @@ -513,133 +513,140 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
| 513 | return NULL; | 513 | return NULL; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, | 516 | int machine__init(struct machine *self, const char *root_dir, pid_t pid) |
| 517 | pid_t pid, const char *root_dir) | ||
| 518 | { | 517 | { |
| 519 | struct rb_node **p = &kerninfo_root->rb_node; | 518 | map_groups__init(&self->kmaps); |
| 519 | RB_CLEAR_NODE(&self->rb_node); | ||
| 520 | INIT_LIST_HEAD(&self->user_dsos); | ||
| 521 | INIT_LIST_HEAD(&self->kernel_dsos); | ||
| 522 | |||
| 523 | self->kmaps.machine = self; | ||
| 524 | self->pid = pid; | ||
| 525 | self->root_dir = strdup(root_dir); | ||
| 526 | return self->root_dir == NULL ? -ENOMEM : 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | struct machine *machines__add(struct rb_root *self, pid_t pid, | ||
| 530 | const char *root_dir) | ||
| 531 | { | ||
| 532 | struct rb_node **p = &self->rb_node; | ||
| 520 | struct rb_node *parent = NULL; | 533 | struct rb_node *parent = NULL; |
| 521 | struct kernel_info *kerninfo, *pos; | 534 | struct machine *pos, *machine = malloc(sizeof(*machine)); |
| 522 | 535 | ||
| 523 | kerninfo = malloc(sizeof(struct kernel_info)); | 536 | if (!machine) |
| 524 | if (!kerninfo) | ||
| 525 | return NULL; | 537 | return NULL; |
| 526 | 538 | ||
| 527 | kerninfo->pid = pid; | 539 | if (machine__init(machine, root_dir, pid) != 0) { |
| 528 | map_groups__init(&kerninfo->kmaps); | 540 | free(machine); |
| 529 | kerninfo->root_dir = strdup(root_dir); | 541 | return NULL; |
| 530 | RB_CLEAR_NODE(&kerninfo->rb_node); | 542 | } |
| 531 | INIT_LIST_HEAD(&kerninfo->dsos__user); | ||
| 532 | INIT_LIST_HEAD(&kerninfo->dsos__kernel); | ||
| 533 | kerninfo->kmaps.this_kerninfo = kerninfo; | ||
| 534 | 543 | ||
| 535 | while (*p != NULL) { | 544 | while (*p != NULL) { |
| 536 | parent = *p; | 545 | parent = *p; |
| 537 | pos = rb_entry(parent, struct kernel_info, rb_node); | 546 | pos = rb_entry(parent, struct machine, rb_node); |
| 538 | if (pid < pos->pid) | 547 | if (pid < pos->pid) |
| 539 | p = &(*p)->rb_left; | 548 | p = &(*p)->rb_left; |
| 540 | else | 549 | else |
| 541 | p = &(*p)->rb_right; | 550 | p = &(*p)->rb_right; |
| 542 | } | 551 | } |
| 543 | 552 | ||
| 544 | rb_link_node(&kerninfo->rb_node, parent, p); | 553 | rb_link_node(&machine->rb_node, parent, p); |
| 545 | rb_insert_color(&kerninfo->rb_node, kerninfo_root); | 554 | rb_insert_color(&machine->rb_node, self); |
| 546 | 555 | ||
| 547 | return kerninfo; | 556 | return machine; |
| 548 | } | 557 | } |
| 549 | 558 | ||
| 550 | struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid) | 559 | struct machine *machines__find(struct rb_root *self, pid_t pid) |
| 551 | { | 560 | { |
| 552 | struct rb_node **p = &kerninfo_root->rb_node; | 561 | struct rb_node **p = &self->rb_node; |
| 553 | struct rb_node *parent = NULL; | 562 | struct rb_node *parent = NULL; |
| 554 | struct kernel_info *kerninfo; | 563 | struct machine *machine; |
| 555 | struct kernel_info *default_kerninfo = NULL; | 564 | struct machine *default_machine = NULL; |
| 556 | 565 | ||
| 557 | while (*p != NULL) { | 566 | while (*p != NULL) { |
| 558 | parent = *p; | 567 | parent = *p; |
| 559 | kerninfo = rb_entry(parent, struct kernel_info, rb_node); | 568 | machine = rb_entry(parent, struct machine, rb_node); |
| 560 | if (pid < kerninfo->pid) | 569 | if (pid < machine->pid) |
| 561 | p = &(*p)->rb_left; | 570 | p = &(*p)->rb_left; |
| 562 | else if (pid > kerninfo->pid) | 571 | else if (pid > machine->pid) |
| 563 | p = &(*p)->rb_right; | 572 | p = &(*p)->rb_right; |
| 564 | else | 573 | else |
| 565 | return kerninfo; | 574 | return machine; |
| 566 | if (!kerninfo->pid) | 575 | if (!machine->pid) |
| 567 | default_kerninfo = kerninfo; | 576 | default_machine = machine; |
| 568 | } | 577 | } |
| 569 | 578 | ||
| 570 | return default_kerninfo; | 579 | return default_machine; |
| 571 | } | 580 | } |
| 572 | 581 | ||
| 573 | struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root) | 582 | /* |
| 583 | * FIXME: Why repeatedly search for this? | ||
| 584 | */ | ||
| 585 | struct machine *machines__find_host(struct rb_root *self) | ||
| 574 | { | 586 | { |
| 575 | struct rb_node **p = &kerninfo_root->rb_node; | 587 | struct rb_node **p = &self->rb_node; |
| 576 | struct rb_node *parent = NULL; | 588 | struct rb_node *parent = NULL; |
| 577 | struct kernel_info *kerninfo; | 589 | struct machine *machine; |
| 578 | pid_t pid = HOST_KERNEL_ID; | 590 | pid_t pid = HOST_KERNEL_ID; |
| 579 | 591 | ||
| 580 | while (*p != NULL) { | 592 | while (*p != NULL) { |
| 581 | parent = *p; | 593 | parent = *p; |
| 582 | kerninfo = rb_entry(parent, struct kernel_info, rb_node); | 594 | machine = rb_entry(parent, struct machine, rb_node); |
| 583 | if (pid < kerninfo->pid) | 595 | if (pid < machine->pid) |
| 584 | p = &(*p)->rb_left; | 596 | p = &(*p)->rb_left; |
| 585 | else if (pid > kerninfo->pid) | 597 | else if (pid > machine->pid) |
| 586 | p = &(*p)->rb_right; | 598 | p = &(*p)->rb_right; |
| 587 | else | 599 | else |
| 588 | return kerninfo; | 600 | return machine; |
| 589 | } | 601 | } |
| 590 | 602 | ||
| 591 | return NULL; | 603 | return NULL; |
| 592 | } | 604 | } |
| 593 | 605 | ||
| 594 | struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid) | 606 | struct machine *machines__findnew(struct rb_root *self, pid_t pid) |
| 595 | { | 607 | { |
| 596 | char path[PATH_MAX]; | 608 | char path[PATH_MAX]; |
| 597 | const char *root_dir; | 609 | const char *root_dir; |
| 598 | int ret; | 610 | struct machine *machine = machines__find(self, pid); |
| 599 | struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid); | ||
| 600 | 611 | ||
| 601 | if (!kerninfo || kerninfo->pid != pid) { | 612 | if (!machine || machine->pid != pid) { |
| 602 | if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) | 613 | if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) |
| 603 | root_dir = ""; | 614 | root_dir = ""; |
| 604 | else { | 615 | else { |
| 605 | if (!symbol_conf.guestmount) | 616 | if (!symbol_conf.guestmount) |
| 606 | goto out; | 617 | goto out; |
| 607 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | 618 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); |
| 608 | ret = access(path, R_OK); | 619 | if (access(path, R_OK)) { |
| 609 | if (ret) { | ||
| 610 | pr_err("Can't access file %s\n", path); | 620 | pr_err("Can't access file %s\n", path); |
| 611 | goto out; | 621 | goto out; |
| 612 | } | 622 | } |
| 613 | root_dir = path; | 623 | root_dir = path; |
| 614 | } | 624 | } |
| 615 | kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir); | 625 | machine = machines__add(self, pid, root_dir); |
| 616 | } | 626 | } |
| 617 | 627 | ||
| 618 | out: | 628 | out: |
| 619 | return kerninfo; | 629 | return machine; |
| 620 | } | 630 | } |
| 621 | 631 | ||
| 622 | void kerninfo__process_allkernels(struct rb_root *kerninfo_root, | 632 | void machines__process(struct rb_root *self, machine__process_t process, void *data) |
| 623 | process_kernel_info process, | ||
| 624 | void *data) | ||
| 625 | { | 633 | { |
| 626 | struct rb_node *nd; | 634 | struct rb_node *nd; |
| 627 | 635 | ||
| 628 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | 636 | for (nd = rb_first(self); nd; nd = rb_next(nd)) { |
| 629 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 637 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 630 | rb_node); | ||
| 631 | process(pos, data); | 638 | process(pos, data); |
| 632 | } | 639 | } |
| 633 | } | 640 | } |
| 634 | 641 | ||
| 635 | char *kern_mmap_name(struct kernel_info *kerninfo, char *buff) | 642 | char *machine__mmap_name(struct machine *self, char *bf, size_t size) |
| 636 | { | 643 | { |
| 637 | if (is_host_kernel(kerninfo)) | 644 | if (machine__is_host(self)) |
| 638 | sprintf(buff, "[%s]", "kernel.kallsyms"); | 645 | snprintf(bf, size, "[%s]", "kernel.kallsyms"); |
| 639 | else if (is_default_guest(kerninfo)) | 646 | else if (machine__is_default_guest(self)) |
| 640 | sprintf(buff, "[%s]", "guest.kernel.kallsyms"); | 647 | snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); |
| 641 | else | 648 | else |
| 642 | sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid); | 649 | snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid); |
| 643 | 650 | ||
| 644 | return buff; | 651 | return bf; |
| 645 | } | 652 | } |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 30d38d634e09..f39134512829 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
| 6 | #include <linux/rbtree.h> | 6 | #include <linux/rbtree.h> |
| 7 | #include <stdio.h> | 7 | #include <stdio.h> |
| 8 | #include <stdbool.h> | ||
| 8 | #include "types.h" | 9 | #include "types.h" |
| 9 | 10 | ||
| 10 | enum map_type { | 11 | enum map_type { |
| @@ -19,7 +20,7 @@ extern const char *map_type__name[MAP__NR_TYPES]; | |||
| 19 | struct dso; | 20 | struct dso; |
| 20 | struct ref_reloc_sym; | 21 | struct ref_reloc_sym; |
| 21 | struct map_groups; | 22 | struct map_groups; |
| 22 | struct kernel_info; | 23 | struct machine; |
| 23 | 24 | ||
| 24 | struct map { | 25 | struct map { |
| 25 | union { | 26 | union { |
| @@ -29,6 +30,7 @@ struct map { | |||
| 29 | u64 start; | 30 | u64 start; |
| 30 | u64 end; | 31 | u64 end; |
| 31 | enum map_type type; | 32 | enum map_type type; |
| 33 | u32 priv; | ||
| 32 | u64 pgoff; | 34 | u64 pgoff; |
| 33 | 35 | ||
| 34 | /* ip -> dso rip */ | 36 | /* ip -> dso rip */ |
| @@ -46,25 +48,31 @@ struct kmap { | |||
| 46 | }; | 48 | }; |
| 47 | 49 | ||
| 48 | struct map_groups { | 50 | struct map_groups { |
| 49 | struct rb_root maps[MAP__NR_TYPES]; | 51 | struct rb_root maps[MAP__NR_TYPES]; |
| 50 | struct list_head removed_maps[MAP__NR_TYPES]; | 52 | struct list_head removed_maps[MAP__NR_TYPES]; |
| 51 | struct kernel_info *this_kerninfo; | 53 | struct machine *machine; |
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | /* Native host kernel uses -1 as pid index in kernel_info */ | 56 | /* Native host kernel uses -1 as pid index in machine */ |
| 55 | #define HOST_KERNEL_ID (-1) | 57 | #define HOST_KERNEL_ID (-1) |
| 56 | #define DEFAULT_GUEST_KERNEL_ID (0) | 58 | #define DEFAULT_GUEST_KERNEL_ID (0) |
| 57 | 59 | ||
| 58 | struct kernel_info { | 60 | struct machine { |
| 59 | struct rb_node rb_node; | 61 | struct rb_node rb_node; |
| 60 | pid_t pid; | 62 | pid_t pid; |
| 61 | char *root_dir; | 63 | char *root_dir; |
| 62 | struct list_head dsos__user; | 64 | struct list_head user_dsos; |
| 63 | struct list_head dsos__kernel; | 65 | struct list_head kernel_dsos; |
| 64 | struct map_groups kmaps; | 66 | struct map_groups kmaps; |
| 65 | struct map *vmlinux_maps[MAP__NR_TYPES]; | 67 | struct map *vmlinux_maps[MAP__NR_TYPES]; |
| 66 | }; | 68 | }; |
| 67 | 69 | ||
| 70 | static inline | ||
| 71 | struct map *machine__kernel_map(struct machine *self, enum map_type type) | ||
| 72 | { | ||
| 73 | return self->vmlinux_maps[type]; | ||
| 74 | } | ||
| 75 | |||
| 68 | static inline struct kmap *map__kmap(struct map *self) | 76 | static inline struct kmap *map__kmap(struct map *self) |
| 69 | { | 77 | { |
| 70 | return (struct kmap *)(self + 1); | 78 | return (struct kmap *)(self + 1); |
| @@ -124,36 +132,31 @@ int map_groups__clone(struct map_groups *self, | |||
| 124 | size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); | 132 | size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); |
| 125 | size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); | 133 | size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); |
| 126 | 134 | ||
| 127 | struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, | 135 | typedef void (*machine__process_t)(struct machine *self, void *data); |
| 128 | pid_t pid, const char *root_dir); | 136 | |
| 129 | struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid); | 137 | void machines__process(struct rb_root *self, machine__process_t process, void *data); |
| 130 | struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid); | 138 | struct machine *machines__add(struct rb_root *self, pid_t pid, |
| 131 | struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root); | 139 | const char *root_dir); |
| 132 | char *kern_mmap_name(struct kernel_info *kerninfo, char *buff); | 140 | struct machine *machines__find_host(struct rb_root *self); |
| 141 | struct machine *machines__find(struct rb_root *self, pid_t pid); | ||
| 142 | struct machine *machines__findnew(struct rb_root *self, pid_t pid); | ||
| 143 | char *machine__mmap_name(struct machine *self, char *bf, size_t size); | ||
| 144 | int machine__init(struct machine *self, const char *root_dir, pid_t pid); | ||
| 133 | 145 | ||
| 134 | /* | 146 | /* |
| 135 | * Default guest kernel is defined by parameter --guestkallsyms | 147 | * Default guest kernel is defined by parameter --guestkallsyms |
| 136 | * and --guestmodules | 148 | * and --guestmodules |
| 137 | */ | 149 | */ |
| 138 | static inline int is_default_guest(struct kernel_info *kerninfo) | 150 | static inline bool machine__is_default_guest(struct machine *self) |
| 139 | { | 151 | { |
| 140 | if (!kerninfo) | 152 | return self ? self->pid == DEFAULT_GUEST_KERNEL_ID : false; |
| 141 | return 0; | ||
| 142 | return kerninfo->pid == DEFAULT_GUEST_KERNEL_ID; | ||
| 143 | } | 153 | } |
| 144 | 154 | ||
| 145 | static inline int is_host_kernel(struct kernel_info *kerninfo) | 155 | static inline bool machine__is_host(struct machine *self) |
| 146 | { | 156 | { |
| 147 | if (!kerninfo) | 157 | return self ? self->pid == HOST_KERNEL_ID : false; |
| 148 | return 0; | ||
| 149 | return kerninfo->pid == HOST_KERNEL_ID; | ||
| 150 | } | 158 | } |
| 151 | 159 | ||
| 152 | typedef void (*process_kernel_info)(struct kernel_info *kerninfo, void *data); | ||
| 153 | void kerninfo__process_allkernels(struct rb_root *kerninfo_root, | ||
| 154 | process_kernel_info process, | ||
| 155 | void *data); | ||
| 156 | |||
| 157 | static inline void map_groups__insert(struct map_groups *self, struct map *map) | 160 | static inline void map_groups__insert(struct map_groups *self, struct map *map) |
| 158 | { | 161 | { |
| 159 | maps__insert(&self->maps[map->type], map); | 162 | maps__insert(&self->maps[map->type], map); |
| @@ -178,10 +181,20 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, | |||
| 178 | symbol_filter_t filter); | 181 | symbol_filter_t filter); |
| 179 | 182 | ||
| 180 | static inline | 183 | static inline |
| 181 | struct symbol *map_groups__find_function(struct map_groups *self, u64 addr, | 184 | struct symbol *machine__find_kernel_symbol(struct machine *self, |
| 182 | struct map **mapp, symbol_filter_t filter) | 185 | enum map_type type, u64 addr, |
| 186 | struct map **mapp, | ||
| 187 | symbol_filter_t filter) | ||
| 188 | { | ||
| 189 | return map_groups__find_symbol(&self->kmaps, type, addr, mapp, filter); | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline | ||
| 193 | struct symbol *machine__find_kernel_function(struct machine *self, u64 addr, | ||
| 194 | struct map **mapp, | ||
| 195 | symbol_filter_t filter) | ||
| 183 | { | 196 | { |
| 184 | return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter); | 197 | return machine__find_kernel_symbol(self, MAP__FUNCTION, addr, mapp, filter); |
| 185 | } | 198 | } |
| 186 | 199 | ||
| 187 | static inline | 200 | static inline |
| @@ -197,10 +210,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
| 197 | 210 | ||
| 198 | struct map *map_groups__find_by_name(struct map_groups *self, | 211 | struct map *map_groups__find_by_name(struct map_groups *self, |
| 199 | enum map_type type, const char *name); | 212 | enum map_type type, const char *name); |
| 200 | struct map *map_groups__new_module(struct map_groups *self, | 213 | struct map *machine__new_module(struct machine *self, u64 start, const char *filename); |
| 201 | u64 start, | ||
| 202 | const char *filename, | ||
| 203 | struct kernel_info *kerninfo); | ||
| 204 | 214 | ||
| 205 | void map_groups__flush(struct map_groups *self); | 215 | void map_groups__flush(struct map_groups *self); |
| 206 | 216 | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9ded38ced234..914c67095d96 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, ...) | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | 74 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); |
| 75 | static struct map_groups kmap_groups; | 75 | static struct machine machine; |
| 76 | static struct map *kmaps[MAP__NR_TYPES]; | ||
| 77 | 76 | ||
| 78 | /* Initialize symbol maps and path of vmlinux */ | 77 | /* Initialize symbol maps and path of vmlinux */ |
| 79 | static int init_vmlinux(void) | 78 | static int init_vmlinux(void) |
| @@ -92,12 +91,15 @@ static int init_vmlinux(void) | |||
| 92 | goto out; | 91 | goto out; |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 94 | ret = machine__init(&machine, "/", 0); | ||
| 95 | if (ret < 0) | ||
| 96 | goto out; | ||
| 97 | |||
| 95 | kernel = dso__new_kernel(symbol_conf.vmlinux_name); | 98 | kernel = dso__new_kernel(symbol_conf.vmlinux_name); |
| 96 | if (kernel == NULL) | 99 | if (kernel == NULL) |
| 97 | die("Failed to create kernel dso."); | 100 | die("Failed to create kernel dso."); |
| 98 | 101 | ||
| 99 | map_groups__init(&kmap_groups); | 102 | ret = __machine__create_kernel_maps(&machine, kernel); |
| 100 | ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel); | ||
| 101 | if (ret < 0) | 103 | if (ret < 0) |
| 102 | pr_debug("Failed to create kernel maps.\n"); | 104 | pr_debug("Failed to create kernel maps.\n"); |
| 103 | 105 | ||
| @@ -110,12 +112,12 @@ out: | |||
| 110 | #ifdef DWARF_SUPPORT | 112 | #ifdef DWARF_SUPPORT |
| 111 | static int open_vmlinux(void) | 113 | static int open_vmlinux(void) |
| 112 | { | 114 | { |
| 113 | if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { | 115 | if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { |
| 114 | pr_debug("Failed to load kernel map.\n"); | 116 | pr_debug("Failed to load kernel map.\n"); |
| 115 | return -EINVAL; | 117 | return -EINVAL; |
| 116 | } | 118 | } |
| 117 | pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); | 119 | pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name); |
| 118 | return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); | 120 | return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY); |
| 119 | } | 121 | } |
| 120 | 122 | ||
| 121 | /* Convert trace point to probe point with debuginfo */ | 123 | /* Convert trace point to probe point with debuginfo */ |
| @@ -125,7 +127,7 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, | |||
| 125 | struct symbol *sym; | 127 | struct symbol *sym; |
| 126 | int fd, ret = -ENOENT; | 128 | int fd, ret = -ENOENT; |
| 127 | 129 | ||
| 128 | sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], | 130 | sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], |
| 129 | tp->symbol, NULL); | 131 | tp->symbol, NULL); |
| 130 | if (sym) { | 132 | if (sym) { |
| 131 | fd = open_vmlinux(); | 133 | fd = open_vmlinux(); |
| @@ -1466,7 +1468,7 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, | |||
| 1466 | } | 1468 | } |
| 1467 | 1469 | ||
| 1468 | /* Currently just checking function name from symbol map */ | 1470 | /* Currently just checking function name from symbol map */ |
| 1469 | sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], | 1471 | sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], |
| 1470 | tev->point.symbol, NULL); | 1472 | tev->point.symbol, NULL); |
| 1471 | if (!sym) { | 1473 | if (!sym) { |
| 1472 | pr_warning("Kernel symbol \'%s\' not found.\n", | 1474 | pr_warning("Kernel symbol \'%s\' not found.\n", |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b7aade2184b2..a8dd73ed1581 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) | |||
| 69 | 69 | ||
| 70 | int perf_session__create_kernel_maps(struct perf_session *self) | 70 | int perf_session__create_kernel_maps(struct perf_session *self) |
| 71 | { | 71 | { |
| 72 | int ret; | 72 | struct rb_root *machines = &self->machines; |
| 73 | struct rb_root *root = &self->kerninfo_root; | 73 | int ret = machines__create_kernel_maps(machines, HOST_KERNEL_ID); |
| 74 | 74 | ||
| 75 | ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); | ||
| 76 | if (ret >= 0) | 75 | if (ret >= 0) |
| 77 | ret = map_groups__create_guest_kernel_maps(root); | 76 | ret = machines__create_guest_kernel_maps(machines); |
| 78 | return ret; | 77 | return ret; |
| 79 | } | 78 | } |
| 80 | 79 | ||
| @@ -97,7 +96,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
| 97 | self->cwd = NULL; | 96 | self->cwd = NULL; |
| 98 | self->cwdlen = 0; | 97 | self->cwdlen = 0; |
| 99 | self->unknown_events = 0; | 98 | self->unknown_events = 0; |
| 100 | self->kerninfo_root = RB_ROOT; | 99 | self->machines = RB_ROOT; |
| 101 | self->ordered_samples.flush_limit = ULLONG_MAX; | 100 | self->ordered_samples.flush_limit = ULLONG_MAX; |
| 102 | INIT_LIST_HEAD(&self->ordered_samples.samples_head); | 101 | INIT_LIST_HEAD(&self->ordered_samples.samples_head); |
| 103 | 102 | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 796e2291ebd7..61ca92e58ad4 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -25,7 +25,7 @@ struct perf_session { | |||
| 25 | unsigned long mmap_window; | 25 | unsigned long mmap_window; |
| 26 | struct rb_root threads; | 26 | struct rb_root threads; |
| 27 | struct thread *last_match; | 27 | struct thread *last_match; |
| 28 | struct rb_root kerninfo_root; | 28 | struct rb_root machines; |
| 29 | struct events_stats events_stats; | 29 | struct events_stats events_stats; |
| 30 | struct rb_root stats_by_id; | 30 | struct rb_root stats_by_id; |
| 31 | unsigned long event_total[PERF_RECORD_MAX]; | 31 | unsigned long event_total[PERF_RECORD_MAX]; |
| @@ -102,4 +102,42 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | |||
| 102 | u64 session_total, const char *helpline, | 102 | u64 session_total, const char *helpline, |
| 103 | const char *input_name); | 103 | const char *input_name); |
| 104 | #endif | 104 | #endif |
| 105 | |||
| 106 | static inline | ||
| 107 | struct machine *perf_session__find_host_machine(struct perf_session *self) | ||
| 108 | { | ||
| 109 | return machines__find_host(&self->machines); | ||
| 110 | } | ||
| 111 | |||
| 112 | static inline | ||
| 113 | struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) | ||
| 114 | { | ||
| 115 | return machines__find(&self->machines, pid); | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline | ||
| 119 | struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) | ||
| 120 | { | ||
| 121 | return machines__findnew(&self->machines, pid); | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline | ||
| 125 | void perf_session__process_machines(struct perf_session *self, | ||
| 126 | machine__process_t process) | ||
| 127 | { | ||
| 128 | return machines__process(&self->machines, process, self); | ||
| 129 | } | ||
| 130 | |||
| 131 | static inline | ||
| 132 | size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) | ||
| 133 | { | ||
| 134 | return machines__fprintf_dsos(&self->machines, fp); | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline | ||
| 138 | size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, | ||
| 139 | bool with_hits) | ||
| 140 | { | ||
| 141 | return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); | ||
| 142 | } | ||
| 105 | #endif /* __PERF_SESSION_H */ | 143 | #endif /* __PERF_SESSION_H */ |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e77c33a11de3..4c0146a49063 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, | |||
| 485 | symbol_filter_t filter) | 485 | symbol_filter_t filter) |
| 486 | { | 486 | { |
| 487 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 487 | struct map_groups *kmaps = map__kmap(map)->kmaps; |
| 488 | struct kernel_info *kerninfo = kmaps->this_kerninfo; | 488 | struct machine *machine = kmaps->machine; |
| 489 | struct map *curr_map = map; | 489 | struct map *curr_map = map; |
| 490 | struct symbol *pos; | 490 | struct symbol *pos; |
| 491 | int count = 0; | 491 | int count = 0; |
| @@ -508,8 +508,8 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
| 508 | 508 | ||
| 509 | if (strcmp(curr_map->dso->short_name, module)) { | 509 | if (strcmp(curr_map->dso->short_name, module)) { |
| 510 | if (curr_map != map && | 510 | if (curr_map != map && |
| 511 | self->kernel == DSO_TYPE_GUEST_KERNEL && | 511 | self->kernel == DSO_TYPE_GUEST_KERNEL && |
| 512 | is_default_guest(kerninfo)) { | 512 | machine__is_default_guest(machine)) { |
| 513 | /* | 513 | /* |
| 514 | * We assume all symbols of a module are | 514 | * We assume all symbols of a module are |
| 515 | * continuous in * kallsyms, so curr_map | 515 | * continuous in * kallsyms, so curr_map |
| @@ -527,13 +527,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
| 527 | pr_err("%s/proc/{kallsyms,modules} " | 527 | pr_err("%s/proc/{kallsyms,modules} " |
| 528 | "inconsistency while looking " | 528 | "inconsistency while looking " |
| 529 | "for \"%s\" module!\n", | 529 | "for \"%s\" module!\n", |
| 530 | kerninfo->root_dir, module); | 530 | machine->root_dir, module); |
| 531 | curr_map = map; | 531 | curr_map = map; |
| 532 | goto discard_symbol; | 532 | goto discard_symbol; |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | if (curr_map->dso->loaded && | 535 | if (curr_map->dso->loaded && |
| 536 | !is_default_guest(kmaps->this_kerninfo)) | 536 | !machine__is_default_guest(machine)) |
| 537 | goto discard_symbol; | 537 | goto discard_symbol; |
| 538 | } | 538 | } |
| 539 | /* | 539 | /* |
| @@ -586,7 +586,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
| 586 | 586 | ||
| 587 | if (curr_map != map && | 587 | if (curr_map != map && |
| 588 | self->kernel == DSO_TYPE_GUEST_KERNEL && | 588 | self->kernel == DSO_TYPE_GUEST_KERNEL && |
| 589 | is_default_guest(kmaps->this_kerninfo)) { | 589 | machine__is_default_guest(kmaps->machine)) { |
| 590 | dso__set_loaded(curr_map->dso, curr_map->type); | 590 | dso__set_loaded(curr_map->dso, curr_map->type); |
| 591 | } | 591 | } |
| 592 | 592 | ||
| @@ -1291,7 +1291,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1291 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1291 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
| 1292 | int ret = -1; | 1292 | int ret = -1; |
| 1293 | int fd; | 1293 | int fd; |
| 1294 | struct kernel_info *kerninfo; | 1294 | struct machine *machine; |
| 1295 | const char *root_dir; | 1295 | const char *root_dir; |
| 1296 | 1296 | ||
| 1297 | dso__set_loaded(self, map->type); | 1297 | dso__set_loaded(self, map->type); |
| @@ -1301,10 +1301,10 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1301 | else if (self->kernel == DSO_TYPE_GUEST_KERNEL) | 1301 | else if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
| 1302 | return dso__load_guest_kernel_sym(self, map, filter); | 1302 | return dso__load_guest_kernel_sym(self, map, filter); |
| 1303 | 1303 | ||
| 1304 | if (map->groups && map->groups->this_kerninfo) | 1304 | if (map->groups && map->groups->machine) |
| 1305 | kerninfo = map->groups->this_kerninfo; | 1305 | machine = map->groups->machine; |
| 1306 | else | 1306 | else |
| 1307 | kerninfo = NULL; | 1307 | machine = NULL; |
| 1308 | 1308 | ||
| 1309 | name = malloc(size); | 1309 | name = malloc(size); |
| 1310 | if (!name) | 1310 | if (!name) |
| @@ -1359,8 +1359,8 @@ more: | |||
| 1359 | snprintf(name, size, "%s", self->long_name); | 1359 | snprintf(name, size, "%s", self->long_name); |
| 1360 | break; | 1360 | break; |
| 1361 | case DSO__ORIG_GUEST_KMODULE: | 1361 | case DSO__ORIG_GUEST_KMODULE: |
| 1362 | if (map->groups && map->groups->this_kerninfo) | 1362 | if (map->groups && map->groups->machine) |
| 1363 | root_dir = map->groups->this_kerninfo->root_dir; | 1363 | root_dir = map->groups->machine->root_dir; |
| 1364 | else | 1364 | else |
| 1365 | root_dir = ""; | 1365 | root_dir = ""; |
| 1366 | snprintf(name, size, "%s%s", root_dir, self->long_name); | 1366 | snprintf(name, size, "%s%s", root_dir, self->long_name); |
| @@ -1528,21 +1528,20 @@ static char *get_kernel_version(const char *root_dir) | |||
| 1528 | return strdup(name); | 1528 | return strdup(name); |
| 1529 | } | 1529 | } |
| 1530 | 1530 | ||
| 1531 | static int map_groups__set_modules_path(struct map_groups *self, | 1531 | static int machine__set_modules_path(struct machine *self) |
| 1532 | const char *root_dir) | ||
| 1533 | { | 1532 | { |
| 1534 | char *version; | 1533 | char *version; |
| 1535 | char modules_path[PATH_MAX]; | 1534 | char modules_path[PATH_MAX]; |
| 1536 | 1535 | ||
| 1537 | version = get_kernel_version(root_dir); | 1536 | version = get_kernel_version(self->root_dir); |
| 1538 | if (!version) | 1537 | if (!version) |
| 1539 | return -1; | 1538 | return -1; |
| 1540 | 1539 | ||
| 1541 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", | 1540 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", |
| 1542 | root_dir, version); | 1541 | self->root_dir, version); |
| 1543 | free(version); | 1542 | free(version); |
| 1544 | 1543 | ||
| 1545 | return map_groups__set_modules_path_dir(self, modules_path); | 1544 | return map_groups__set_modules_path_dir(&self->kmaps, modules_path); |
| 1546 | } | 1545 | } |
| 1547 | 1546 | ||
| 1548 | /* | 1547 | /* |
| @@ -1564,14 +1563,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
| 1564 | return self; | 1563 | return self; |
| 1565 | } | 1564 | } |
| 1566 | 1565 | ||
| 1567 | struct map *map_groups__new_module(struct map_groups *self, u64 start, | 1566 | struct map *machine__new_module(struct machine *self, u64 start, |
| 1568 | const char *filename, | 1567 | const char *filename) |
| 1569 | struct kernel_info *kerninfo) | ||
| 1570 | { | 1568 | { |
| 1571 | struct map *map; | 1569 | struct map *map; |
| 1572 | struct dso *dso; | 1570 | struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename); |
| 1573 | 1571 | ||
| 1574 | dso = __dsos__findnew(&kerninfo->dsos__kernel, filename); | ||
| 1575 | if (dso == NULL) | 1572 | if (dso == NULL) |
| 1576 | return NULL; | 1573 | return NULL; |
| 1577 | 1574 | ||
| @@ -1579,28 +1576,27 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, | |||
| 1579 | if (map == NULL) | 1576 | if (map == NULL) |
| 1580 | return NULL; | 1577 | return NULL; |
| 1581 | 1578 | ||
| 1582 | if (is_host_kernel(kerninfo)) | 1579 | if (machine__is_host(self)) |
| 1583 | dso->origin = DSO__ORIG_KMODULE; | 1580 | dso->origin = DSO__ORIG_KMODULE; |
| 1584 | else | 1581 | else |
| 1585 | dso->origin = DSO__ORIG_GUEST_KMODULE; | 1582 | dso->origin = DSO__ORIG_GUEST_KMODULE; |
| 1586 | map_groups__insert(self, map); | 1583 | map_groups__insert(&self->kmaps, map); |
| 1587 | return map; | 1584 | return map; |
| 1588 | } | 1585 | } |
| 1589 | 1586 | ||
| 1590 | static int map_groups__create_modules(struct kernel_info *kerninfo) | 1587 | static int machine__create_modules(struct machine *self) |
| 1591 | { | 1588 | { |
| 1592 | char *line = NULL; | 1589 | char *line = NULL; |
| 1593 | size_t n; | 1590 | size_t n; |
| 1594 | FILE *file; | 1591 | FILE *file; |
| 1595 | struct map *map; | 1592 | struct map *map; |
| 1596 | const char *root_dir; | ||
| 1597 | const char *modules; | 1593 | const char *modules; |
| 1598 | char path[PATH_MAX]; | 1594 | char path[PATH_MAX]; |
| 1599 | 1595 | ||
| 1600 | if (is_default_guest(kerninfo)) | 1596 | if (machine__is_default_guest(self)) |
| 1601 | modules = symbol_conf.default_guest_modules; | 1597 | modules = symbol_conf.default_guest_modules; |
| 1602 | else { | 1598 | else { |
| 1603 | sprintf(path, "%s/proc/modules", kerninfo->root_dir); | 1599 | sprintf(path, "%s/proc/modules", self->root_dir); |
| 1604 | modules = path; | 1600 | modules = path; |
| 1605 | } | 1601 | } |
| 1606 | 1602 | ||
| @@ -1608,8 +1604,6 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) | |||
| 1608 | if (file == NULL) | 1604 | if (file == NULL) |
| 1609 | return -1; | 1605 | return -1; |
| 1610 | 1606 | ||
| 1611 | root_dir = kerninfo->root_dir; | ||
| 1612 | |||
| 1613 | while (!feof(file)) { | 1607 | while (!feof(file)) { |
| 1614 | char name[PATH_MAX]; | 1608 | char name[PATH_MAX]; |
| 1615 | u64 start; | 1609 | u64 start; |
| @@ -1638,17 +1632,16 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) | |||
| 1638 | *sep = '\0'; | 1632 | *sep = '\0'; |
| 1639 | 1633 | ||
| 1640 | snprintf(name, sizeof(name), "[%s]", line); | 1634 | snprintf(name, sizeof(name), "[%s]", line); |
| 1641 | map = map_groups__new_module(&kerninfo->kmaps, | 1635 | map = machine__new_module(self, start, name); |
| 1642 | start, name, kerninfo); | ||
| 1643 | if (map == NULL) | 1636 | if (map == NULL) |
| 1644 | goto out_delete_line; | 1637 | goto out_delete_line; |
| 1645 | dso__kernel_module_get_build_id(map->dso, root_dir); | 1638 | dso__kernel_module_get_build_id(map->dso, self->root_dir); |
| 1646 | } | 1639 | } |
| 1647 | 1640 | ||
| 1648 | free(line); | 1641 | free(line); |
| 1649 | fclose(file); | 1642 | fclose(file); |
| 1650 | 1643 | ||
| 1651 | return map_groups__set_modules_path(&kerninfo->kmaps, root_dir); | 1644 | return machine__set_modules_path(self); |
| 1652 | 1645 | ||
| 1653 | out_delete_line: | 1646 | out_delete_line: |
| 1654 | free(line); | 1647 | free(line); |
| @@ -1820,16 +1813,16 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, | |||
| 1820 | { | 1813 | { |
| 1821 | int err; | 1814 | int err; |
| 1822 | const char *kallsyms_filename = NULL; | 1815 | const char *kallsyms_filename = NULL; |
| 1823 | struct kernel_info *kerninfo; | 1816 | struct machine *machine; |
| 1824 | char path[PATH_MAX]; | 1817 | char path[PATH_MAX]; |
| 1825 | 1818 | ||
| 1826 | if (!map->groups) { | 1819 | if (!map->groups) { |
| 1827 | pr_debug("Guest kernel map hasn't the point to groups\n"); | 1820 | pr_debug("Guest kernel map hasn't the point to groups\n"); |
| 1828 | return -1; | 1821 | return -1; |
| 1829 | } | 1822 | } |
| 1830 | kerninfo = map->groups->this_kerninfo; | 1823 | machine = map->groups->machine; |
| 1831 | 1824 | ||
| 1832 | if (is_default_guest(kerninfo)) { | 1825 | if (machine__is_default_guest(machine)) { |
| 1833 | /* | 1826 | /* |
| 1834 | * if the user specified a vmlinux filename, use it and only | 1827 | * if the user specified a vmlinux filename, use it and only |
| 1835 | * it, reporting errors to the user if it cannot be used. | 1828 | * it, reporting errors to the user if it cannot be used. |
| @@ -1845,7 +1838,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, | |||
| 1845 | if (!kallsyms_filename) | 1838 | if (!kallsyms_filename) |
| 1846 | return -1; | 1839 | return -1; |
| 1847 | } else { | 1840 | } else { |
| 1848 | sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); | 1841 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); |
| 1849 | kallsyms_filename = path; | 1842 | kallsyms_filename = path; |
| 1850 | } | 1843 | } |
| 1851 | 1844 | ||
| @@ -1856,9 +1849,8 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, | |||
| 1856 | out_try_fixup: | 1849 | out_try_fixup: |
| 1857 | if (err > 0) { | 1850 | if (err > 0) { |
| 1858 | if (kallsyms_filename != NULL) { | 1851 | if (kallsyms_filename != NULL) { |
| 1859 | kern_mmap_name(kerninfo, path); | 1852 | machine__mmap_name(machine, path, sizeof(path)); |
| 1860 | dso__set_long_name(self, | 1853 | dso__set_long_name(self, strdup(path)); |
| 1861 | strdup(path)); | ||
| 1862 | } | 1854 | } |
| 1863 | map__fixup_start(map); | 1855 | map__fixup_start(map); |
| 1864 | map__fixup_end(map); | 1856 | map__fixup_end(map); |
| @@ -1897,27 +1889,32 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) | |||
| 1897 | return dso; | 1889 | return dso; |
| 1898 | } | 1890 | } |
| 1899 | 1891 | ||
| 1900 | static void __dsos__fprintf(struct list_head *head, FILE *fp) | 1892 | static size_t __dsos__fprintf(struct list_head *head, FILE *fp) |
| 1901 | { | 1893 | { |
| 1902 | struct dso *pos; | 1894 | struct dso *pos; |
| 1895 | size_t ret = 0; | ||
| 1903 | 1896 | ||
| 1904 | list_for_each_entry(pos, head, node) { | 1897 | list_for_each_entry(pos, head, node) { |
| 1905 | int i; | 1898 | int i; |
| 1906 | for (i = 0; i < MAP__NR_TYPES; ++i) | 1899 | for (i = 0; i < MAP__NR_TYPES; ++i) |
| 1907 | dso__fprintf(pos, i, fp); | 1900 | ret += dso__fprintf(pos, i, fp); |
| 1908 | } | 1901 | } |
| 1902 | |||
| 1903 | return ret; | ||
| 1909 | } | 1904 | } |
| 1910 | 1905 | ||
| 1911 | void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp) | 1906 | size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp) |
| 1912 | { | 1907 | { |
| 1913 | struct rb_node *nd; | 1908 | struct rb_node *nd; |
| 1909 | size_t ret = 0; | ||
| 1914 | 1910 | ||
| 1915 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | 1911 | for (nd = rb_first(self); nd; nd = rb_next(nd)) { |
| 1916 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 1912 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 1917 | rb_node); | 1913 | ret += __dsos__fprintf(&pos->kernel_dsos, fp); |
| 1918 | __dsos__fprintf(&pos->dsos__kernel, fp); | 1914 | ret += __dsos__fprintf(&pos->user_dsos, fp); |
| 1919 | __dsos__fprintf(&pos->dsos__user, fp); | ||
| 1920 | } | 1915 | } |
| 1916 | |||
| 1917 | return ret; | ||
| 1921 | } | 1918 | } |
| 1922 | 1919 | ||
| 1923 | static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | 1920 | static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, |
| @@ -1935,19 +1932,15 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | |||
| 1935 | return ret; | 1932 | return ret; |
| 1936 | } | 1933 | } |
| 1937 | 1934 | ||
| 1938 | size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, | 1935 | size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) |
| 1939 | FILE *fp, bool with_hits) | ||
| 1940 | { | 1936 | { |
| 1941 | struct rb_node *nd; | 1937 | struct rb_node *nd; |
| 1942 | size_t ret = 0; | 1938 | size_t ret = 0; |
| 1943 | 1939 | ||
| 1944 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | 1940 | for (nd = rb_first(self); nd; nd = rb_next(nd)) { |
| 1945 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | 1941 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 1946 | rb_node); | 1942 | ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); |
| 1947 | ret += __dsos__fprintf_buildid(&pos->dsos__kernel, | 1943 | ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); |
| 1948 | fp, with_hits); | ||
| 1949 | ret += __dsos__fprintf_buildid(&pos->dsos__user, | ||
| 1950 | fp, with_hits); | ||
| 1951 | } | 1944 | } |
| 1952 | return ret; | 1945 | return ret; |
| 1953 | } | 1946 | } |
| @@ -1964,14 +1957,12 @@ struct dso *dso__new_kernel(const char *name) | |||
| 1964 | return self; | 1957 | return self; |
| 1965 | } | 1958 | } |
| 1966 | 1959 | ||
| 1967 | static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, | 1960 | static struct dso *dso__new_guest_kernel(struct machine *machine, |
| 1968 | const char *name) | 1961 | const char *name) |
| 1969 | { | 1962 | { |
| 1970 | char buff[PATH_MAX]; | 1963 | char bf[PATH_MAX]; |
| 1971 | struct dso *self; | 1964 | struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf))); |
| 1972 | 1965 | ||
| 1973 | kern_mmap_name(kerninfo, buff); | ||
| 1974 | self = dso__new(name ?: buff); | ||
| 1975 | if (self != NULL) { | 1966 | if (self != NULL) { |
| 1976 | dso__set_short_name(self, "[guest.kernel]"); | 1967 | dso__set_short_name(self, "[guest.kernel]"); |
| 1977 | self->kernel = DSO_TYPE_GUEST_KERNEL; | 1968 | self->kernel = DSO_TYPE_GUEST_KERNEL; |
| @@ -1980,64 +1971,78 @@ static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, | |||
| 1980 | return self; | 1971 | return self; |
| 1981 | } | 1972 | } |
| 1982 | 1973 | ||
| 1983 | void dso__read_running_kernel_build_id(struct dso *self, | 1974 | void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine) |
| 1984 | struct kernel_info *kerninfo) | ||
| 1985 | { | 1975 | { |
| 1986 | char path[PATH_MAX]; | 1976 | char path[PATH_MAX]; |
| 1987 | 1977 | ||
| 1988 | if (is_default_guest(kerninfo)) | 1978 | if (machine__is_default_guest(machine)) |
| 1989 | return; | 1979 | return; |
| 1990 | sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir); | 1980 | sprintf(path, "%s/sys/kernel/notes", machine->root_dir); |
| 1991 | if (sysfs__read_build_id(path, self->build_id, | 1981 | if (sysfs__read_build_id(path, self->build_id, |
| 1992 | sizeof(self->build_id)) == 0) | 1982 | sizeof(self->build_id)) == 0) |
| 1993 | self->has_build_id = true; | 1983 | self->has_build_id = true; |
| 1994 | } | 1984 | } |
| 1995 | 1985 | ||
| 1996 | static struct dso *dsos__create_kernel(struct kernel_info *kerninfo) | 1986 | static struct dso *machine__create_kernel(struct machine *self) |
| 1997 | { | 1987 | { |
| 1998 | const char *vmlinux_name = NULL; | 1988 | const char *vmlinux_name = NULL; |
| 1999 | struct dso *kernel; | 1989 | struct dso *kernel; |
| 2000 | 1990 | ||
| 2001 | if (is_host_kernel(kerninfo)) { | 1991 | if (machine__is_host(self)) { |
| 2002 | vmlinux_name = symbol_conf.vmlinux_name; | 1992 | vmlinux_name = symbol_conf.vmlinux_name; |
| 2003 | kernel = dso__new_kernel(vmlinux_name); | 1993 | kernel = dso__new_kernel(vmlinux_name); |
| 2004 | } else { | 1994 | } else { |
| 2005 | if (is_default_guest(kerninfo)) | 1995 | if (machine__is_default_guest(self)) |
| 2006 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; | 1996 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; |
| 2007 | kernel = dso__new_guest_kernel(kerninfo, vmlinux_name); | 1997 | kernel = dso__new_guest_kernel(self, vmlinux_name); |
| 2008 | } | 1998 | } |
| 2009 | 1999 | ||
| 2010 | if (kernel != NULL) { | 2000 | if (kernel != NULL) { |
| 2011 | dso__read_running_kernel_build_id(kernel, kerninfo); | 2001 | dso__read_running_kernel_build_id(kernel, self); |
| 2012 | dsos__add(&kerninfo->dsos__kernel, kernel); | 2002 | dsos__add(&self->kernel_dsos, kernel); |
| 2013 | } | 2003 | } |
| 2014 | return kernel; | 2004 | return kernel; |
| 2015 | } | 2005 | } |
| 2016 | 2006 | ||
| 2017 | int __map_groups__create_kernel_maps(struct map_groups *self, | 2007 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) |
| 2018 | struct map *vmlinux_maps[MAP__NR_TYPES], | ||
| 2019 | struct dso *kernel) | ||
| 2020 | { | 2008 | { |
| 2021 | enum map_type type; | 2009 | enum map_type type; |
| 2022 | 2010 | ||
| 2023 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 2011 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
| 2024 | struct kmap *kmap; | 2012 | struct kmap *kmap; |
| 2025 | 2013 | ||
| 2026 | vmlinux_maps[type] = map__new2(0, kernel, type); | 2014 | self->vmlinux_maps[type] = map__new2(0, kernel, type); |
| 2027 | if (vmlinux_maps[type] == NULL) | 2015 | if (self->vmlinux_maps[type] == NULL) |
| 2028 | return -1; | 2016 | return -1; |
| 2029 | 2017 | ||
| 2030 | vmlinux_maps[type]->map_ip = | 2018 | self->vmlinux_maps[type]->map_ip = |
| 2031 | vmlinux_maps[type]->unmap_ip = identity__map_ip; | 2019 | self->vmlinux_maps[type]->unmap_ip = identity__map_ip; |
| 2032 | 2020 | ||
| 2033 | kmap = map__kmap(vmlinux_maps[type]); | 2021 | kmap = map__kmap(self->vmlinux_maps[type]); |
| 2034 | kmap->kmaps = self; | 2022 | kmap->kmaps = &self->kmaps; |
| 2035 | map_groups__insert(self, vmlinux_maps[type]); | 2023 | map_groups__insert(&self->kmaps, self->vmlinux_maps[type]); |
| 2036 | } | 2024 | } |
| 2037 | 2025 | ||
| 2038 | return 0; | 2026 | return 0; |
| 2039 | } | 2027 | } |
| 2040 | 2028 | ||
| 2029 | int machine__create_kernel_maps(struct machine *self) | ||
| 2030 | { | ||
| 2031 | struct dso *kernel = machine__create_kernel(self); | ||
| 2032 | |||
| 2033 | if (kernel == NULL || | ||
| 2034 | __machine__create_kernel_maps(self, kernel) < 0) | ||
| 2035 | return -1; | ||
| 2036 | |||
| 2037 | if (symbol_conf.use_modules && machine__create_modules(self) < 0) | ||
| 2038 | pr_debug("Problems creating module maps, continuing anyway...\n"); | ||
| 2039 | /* | ||
| 2040 | * Now that we have all the maps created, just set the ->end of them: | ||
| 2041 | */ | ||
| 2042 | map_groups__fixup_end(&self->kmaps); | ||
| 2043 | return 0; | ||
| 2044 | } | ||
| 2045 | |||
| 2041 | static void vmlinux_path__exit(void) | 2046 | static void vmlinux_path__exit(void) |
| 2042 | { | 2047 | { |
| 2043 | while (--vmlinux_path__nr_entries >= 0) { | 2048 | while (--vmlinux_path__nr_entries >= 0) { |
| @@ -2154,30 +2159,14 @@ out_free_comm_list: | |||
| 2154 | return -1; | 2159 | return -1; |
| 2155 | } | 2160 | } |
| 2156 | 2161 | ||
| 2157 | int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid) | 2162 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid) |
| 2158 | { | 2163 | { |
| 2159 | struct kernel_info *kerninfo; | 2164 | struct machine *machine = machines__findnew(self, pid); |
| 2160 | struct dso *kernel; | ||
| 2161 | |||
| 2162 | kerninfo = kerninfo__findnew(kerninfo_root, pid); | ||
| 2163 | if (kerninfo == NULL) | ||
| 2164 | return -1; | ||
| 2165 | kernel = dsos__create_kernel(kerninfo); | ||
| 2166 | if (kernel == NULL) | ||
| 2167 | return -1; | ||
| 2168 | 2165 | ||
| 2169 | if (__map_groups__create_kernel_maps(&kerninfo->kmaps, | 2166 | if (machine == NULL) |
| 2170 | kerninfo->vmlinux_maps, kernel) < 0) | ||
| 2171 | return -1; | 2167 | return -1; |
| 2172 | 2168 | ||
| 2173 | if (symbol_conf.use_modules && | 2169 | return machine__create_kernel_maps(machine); |
| 2174 | map_groups__create_modules(kerninfo) < 0) | ||
| 2175 | pr_debug("Problems creating module maps, continuing anyway...\n"); | ||
| 2176 | /* | ||
| 2177 | * Now that we have all the maps created, just set the ->end of them: | ||
| 2178 | */ | ||
| 2179 | map_groups__fixup_end(&kerninfo->kmaps); | ||
| 2180 | return 0; | ||
| 2181 | } | 2170 | } |
| 2182 | 2171 | ||
| 2183 | static int hex(char ch) | 2172 | static int hex(char ch) |
| @@ -2223,7 +2212,7 @@ char *strxfrchar(char *s, char from, char to) | |||
| 2223 | return s; | 2212 | return s; |
| 2224 | } | 2213 | } |
| 2225 | 2214 | ||
| 2226 | int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) | 2215 | int machines__create_guest_kernel_maps(struct rb_root *self) |
| 2227 | { | 2216 | { |
| 2228 | int ret = 0; | 2217 | int ret = 0; |
| 2229 | struct dirent **namelist = NULL; | 2218 | struct dirent **namelist = NULL; |
| @@ -2234,8 +2223,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) | |||
| 2234 | if (symbol_conf.default_guest_vmlinux_name || | 2223 | if (symbol_conf.default_guest_vmlinux_name || |
| 2235 | symbol_conf.default_guest_modules || | 2224 | symbol_conf.default_guest_modules || |
| 2236 | symbol_conf.default_guest_kallsyms) { | 2225 | symbol_conf.default_guest_kallsyms) { |
| 2237 | map_groups__create_kernel_maps(kerninfo_root, | 2226 | machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID); |
| 2238 | DEFAULT_GUEST_KERNEL_ID); | ||
| 2239 | } | 2227 | } |
| 2240 | 2228 | ||
| 2241 | if (symbol_conf.guestmount) { | 2229 | if (symbol_conf.guestmount) { |
| @@ -2256,8 +2244,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) | |||
| 2256 | pr_debug("Can't access file %s\n", path); | 2244 | pr_debug("Can't access file %s\n", path); |
| 2257 | goto failure; | 2245 | goto failure; |
| 2258 | } | 2246 | } |
| 2259 | map_groups__create_kernel_maps(kerninfo_root, | 2247 | machines__create_kernel_maps(self, pid); |
| 2260 | pid); | ||
| 2261 | } | 2248 | } |
| 2262 | failure: | 2249 | failure: |
| 2263 | free(namelist); | 2250 | free(namelist); |
| @@ -2265,3 +2252,36 @@ failure: | |||
| 2265 | 2252 | ||
| 2266 | return ret; | 2253 | return ret; |
| 2267 | } | 2254 | } |
| 2255 | |||
| 2256 | int machine__load_kallsyms(struct machine *self, const char *filename, | ||
| 2257 | enum map_type type, symbol_filter_t filter) | ||
| 2258 | { | ||
| 2259 | struct map *map = self->vmlinux_maps[type]; | ||
| 2260 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); | ||
| 2261 | |||
| 2262 | if (ret > 0) { | ||
| 2263 | dso__set_loaded(map->dso, type); | ||
| 2264 | /* | ||
| 2265 | * Since /proc/kallsyms will have multiple sessions for the | ||
| 2266 | * kernel, with modules between them, fixup the end of all | ||
| 2267 | * sections. | ||
| 2268 | */ | ||
| 2269 | __map_groups__fixup_end(&self->kmaps, type); | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | return ret; | ||
| 2273 | } | ||
| 2274 | |||
| 2275 | int machine__load_vmlinux_path(struct machine *self, enum map_type type, | ||
| 2276 | symbol_filter_t filter) | ||
| 2277 | { | ||
| 2278 | struct map *map = self->vmlinux_maps[type]; | ||
| 2279 | int ret = dso__load_vmlinux_path(map->dso, map, filter); | ||
| 2280 | |||
| 2281 | if (ret > 0) { | ||
| 2282 | dso__set_loaded(map->dso, type); | ||
| 2283 | map__reloc_vmlinux(map); | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | return ret; | ||
| 2287 | } | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 478f5ab37787..a517c17407b7 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -162,9 +162,13 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map, | |||
| 162 | symbol_filter_t filter); | 162 | symbol_filter_t filter); |
| 163 | int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, | 163 | int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, |
| 164 | symbol_filter_t filter); | 164 | symbol_filter_t filter); |
| 165 | void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp); | 165 | int machine__load_kallsyms(struct machine *self, const char *filename, |
| 166 | size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, | 166 | enum map_type type, symbol_filter_t filter); |
| 167 | FILE *fp, bool with_hits); | 167 | int machine__load_vmlinux_path(struct machine *self, enum map_type type, |
| 168 | symbol_filter_t filter); | ||
| 169 | |||
| 170 | size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); | ||
| 171 | size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); | ||
| 168 | 172 | ||
| 169 | size_t dso__fprintf_buildid(struct dso *self, FILE *fp); | 173 | size_t dso__fprintf_buildid(struct dso *self, FILE *fp); |
| 170 | size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); | 174 | size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); |
| @@ -186,8 +190,7 @@ enum dso_origin { | |||
| 186 | char dso__symtab_origin(const struct dso *self); | 190 | char dso__symtab_origin(const struct dso *self); |
| 187 | void dso__set_long_name(struct dso *self, char *name); | 191 | void dso__set_long_name(struct dso *self, char *name); |
| 188 | void dso__set_build_id(struct dso *self, void *build_id); | 192 | void dso__set_build_id(struct dso *self, void *build_id); |
| 189 | void dso__read_running_kernel_build_id(struct dso *self, | 193 | void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); |
| 190 | struct kernel_info *kerninfo); | ||
| 191 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); | 194 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); |
| 192 | struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, | 195 | struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, |
| 193 | const char *name); | 196 | const char *name); |
| @@ -200,11 +203,11 @@ int kallsyms__parse(const char *filename, void *arg, | |||
| 200 | int (*process_symbol)(void *arg, const char *name, | 203 | int (*process_symbol)(void *arg, const char *name, |
| 201 | char type, u64 start)); | 204 | char type, u64 start)); |
| 202 | 205 | ||
| 203 | int __map_groups__create_kernel_maps(struct map_groups *self, | 206 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); |
| 204 | struct map *vmlinux_maps[MAP__NR_TYPES], | 207 | int machine__create_kernel_maps(struct machine *self); |
| 205 | struct dso *kernel); | 208 | |
| 206 | int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid); | 209 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid); |
| 207 | int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root); | 210 | int machines__create_guest_kernel_maps(struct rb_root *self); |
| 208 | 211 | ||
| 209 | int symbol__init(void); | 212 | int symbol__init(void); |
| 210 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 213 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
