diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-12-13 16:50:29 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-14 10:57:17 -0500 |
commit | 4aa65636411ccb12f006a6ad593930655c445ff6 (patch) | |
tree | 0f494705a2a7631070a5372bb53f873684b001c2 /tools/perf/util | |
parent | b3165f414416a717f72a376720564012af5a2e01 (diff) |
perf session: Move kmaps to perf_session
There is still some more work to do to disentangle map creation
from DSO loading, but this happens only for the kernel, and for
the early adopters of perf diff, where this disentanglement
matters most, we'll be testing different kernels, so no problem
here.
Further clarification: right now we create the kernel maps for
the various modules and discontiguous kernel text maps when
loading the DSO, we should do it as a two step process, first
creating the maps, for multiple mappings with the same DSO
store, then doing the dso load just once, for the first hit on
one of the maps sharing this DSO backing store.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260741029-4430-6-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/event.c | 13 | ||||
-rw-r--r-- | tools/perf/util/event.h | 10 | ||||
-rw-r--r-- | tools/perf/util/map.c | 14 | ||||
-rw-r--r-- | tools/perf/util/session.c | 19 | ||||
-rw-r--r-- | tools/perf/util/session.h | 6 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 89 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 11 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 3 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 11 |
9 files changed, 96 insertions, 80 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2d09c29b3a6c..222efb1fc3bd 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -256,7 +256,8 @@ int event__process_task(event_t *self, struct perf_session *session) | |||
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | void thread__find_addr_location(struct thread *self, u8 cpumode, | 259 | void thread__find_addr_location(struct thread *self, |
260 | struct perf_session *session, u8 cpumode, | ||
260 | enum map_type type, u64 addr, | 261 | enum map_type type, u64 addr, |
261 | struct addr_location *al, | 262 | struct addr_location *al, |
262 | symbol_filter_t filter) | 263 | symbol_filter_t filter) |
@@ -268,7 +269,7 @@ void thread__find_addr_location(struct thread *self, u8 cpumode, | |||
268 | 269 | ||
269 | if (cpumode & PERF_RECORD_MISC_KERNEL) { | 270 | if (cpumode & PERF_RECORD_MISC_KERNEL) { |
270 | al->level = 'k'; | 271 | al->level = 'k'; |
271 | mg = kmaps; | 272 | mg = &session->kmaps; |
272 | } else if (cpumode & PERF_RECORD_MISC_USER) | 273 | } else if (cpumode & PERF_RECORD_MISC_USER) |
273 | al->level = '.'; | 274 | al->level = '.'; |
274 | else { | 275 | else { |
@@ -289,14 +290,14 @@ try_again: | |||
289 | * "[vdso]" dso, but for now lets use the old trick of looking | 290 | * "[vdso]" dso, but for now lets use the old trick of looking |
290 | * in the whole kernel symbol list. | 291 | * in the whole kernel symbol list. |
291 | */ | 292 | */ |
292 | if ((long long)al->addr < 0 && mg != kmaps) { | 293 | if ((long long)al->addr < 0 && mg != &session->kmaps) { |
293 | mg = kmaps; | 294 | mg = &session->kmaps; |
294 | goto try_again; | 295 | goto try_again; |
295 | } | 296 | } |
296 | al->sym = NULL; | 297 | al->sym = NULL; |
297 | } else { | 298 | } else { |
298 | al->addr = al->map->map_ip(al->map, al->addr); | 299 | al->addr = al->map->map_ip(al->map, al->addr); |
299 | al->sym = map__find_symbol(al->map, al->addr, filter); | 300 | al->sym = map__find_symbol(al->map, session, al->addr, filter); |
300 | } | 301 | } |
301 | } | 302 | } |
302 | 303 | ||
@@ -311,7 +312,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
311 | 312 | ||
312 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 313 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); |
313 | 314 | ||
314 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | 315 | thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION, |
315 | self->ip.ip, al, filter); | 316 | self->ip.ip, al, filter); |
316 | dump_printf(" ...... dso: %s\n", | 317 | dump_printf(" ...... dso: %s\n", |
317 | al->map ? al->map->dso->long_name : | 318 | al->map ? al->map->dso->long_name : |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index bb090257570e..035ecf3c25cc 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -149,15 +149,17 @@ void map__delete(struct map *self); | |||
149 | struct map *map__clone(struct map *self); | 149 | struct map *map__clone(struct map *self); |
150 | int map__overlap(struct map *l, struct map *r); | 150 | int map__overlap(struct map *l, struct map *r); |
151 | size_t map__fprintf(struct map *self, FILE *fp); | 151 | size_t map__fprintf(struct map *self, FILE *fp); |
152 | struct symbol *map__find_symbol(struct map *self, u64 addr, | 152 | |
153 | symbol_filter_t filter); | 153 | struct perf_session; |
154 | |||
155 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, | ||
156 | u64 addr, symbol_filter_t filter); | ||
154 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, | 157 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, |
158 | struct perf_session *session, | ||
155 | symbol_filter_t filter); | 159 | symbol_filter_t filter); |
156 | void map__fixup_start(struct map *self); | 160 | void map__fixup_start(struct map *self); |
157 | void map__fixup_end(struct map *self); | 161 | void map__fixup_end(struct map *self); |
158 | 162 | ||
159 | struct perf_session; | ||
160 | |||
161 | int event__synthesize_thread(pid_t pid, | 163 | int event__synthesize_thread(pid_t pid, |
162 | int (*process)(event_t *event, | 164 | int (*process)(event_t *event, |
163 | struct perf_session *session), | 165 | struct perf_session *session), |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 76bdca640a9b..8b3dd467adb5 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -104,10 +104,11 @@ void map__fixup_end(struct map *self) | |||
104 | 104 | ||
105 | #define DSO__DELETED "(deleted)" | 105 | #define DSO__DELETED "(deleted)" |
106 | 106 | ||
107 | static int map__load(struct map *self, symbol_filter_t filter) | 107 | static int map__load(struct map *self, struct perf_session *session, |
108 | symbol_filter_t filter) | ||
108 | { | 109 | { |
109 | const char *name = self->dso->long_name; | 110 | const char *name = self->dso->long_name; |
110 | int nr = dso__load(self->dso, self, filter); | 111 | int nr = dso__load(self->dso, self, session, filter); |
111 | 112 | ||
112 | if (nr < 0) { | 113 | if (nr < 0) { |
113 | if (self->dso->has_build_id) { | 114 | if (self->dso->has_build_id) { |
@@ -143,19 +144,20 @@ static int map__load(struct map *self, symbol_filter_t filter) | |||
143 | return 0; | 144 | return 0; |
144 | } | 145 | } |
145 | 146 | ||
146 | struct symbol *map__find_symbol(struct map *self, u64 addr, | 147 | struct symbol *map__find_symbol(struct map *self, struct perf_session *session, |
147 | symbol_filter_t filter) | 148 | u64 addr, symbol_filter_t filter) |
148 | { | 149 | { |
149 | if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0) | 150 | if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0) |
150 | return NULL; | 151 | return NULL; |
151 | 152 | ||
152 | return dso__find_symbol(self->dso, self->type, addr); | 153 | return dso__find_symbol(self->dso, self->type, addr); |
153 | } | 154 | } |
154 | 155 | ||
155 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, | 156 | struct symbol *map__find_symbol_by_name(struct map *self, const char *name, |
157 | struct perf_session *session, | ||
156 | symbol_filter_t filter) | 158 | symbol_filter_t filter) |
157 | { | 159 | { |
158 | if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0) | 160 | if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0) |
159 | return NULL; | 161 | return NULL; |
160 | 162 | ||
161 | if (!dso__sorted_by_name(self->dso, self->type)) | 163 | if (!dso__sorted_by_name(self->dso, self->type)) |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 09836a537fc5..fe87a2f2e5a5 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -49,7 +49,7 @@ out_close: | |||
49 | } | 49 | } |
50 | 50 | ||
51 | struct perf_session *perf_session__new(const char *filename, int mode, | 51 | struct perf_session *perf_session__new(const char *filename, int mode, |
52 | bool force) | 52 | bool force, struct symbol_conf *conf) |
53 | { | 53 | { |
54 | size_t len = filename ? strlen(filename) + 1 : 0; | 54 | size_t len = filename ? strlen(filename) + 1 : 0; |
55 | struct perf_session *self = zalloc(sizeof(*self) + len); | 55 | struct perf_session *self = zalloc(sizeof(*self) + len); |
@@ -58,7 +58,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, | |||
58 | goto out; | 58 | goto out; |
59 | 59 | ||
60 | if (perf_header__init(&self->header) < 0) | 60 | if (perf_header__init(&self->header) < 0) |
61 | goto out_delete; | 61 | goto out_free; |
62 | 62 | ||
63 | memcpy(self->filename, filename, len); | 63 | memcpy(self->filename, filename, len); |
64 | self->threads = RB_ROOT; | 64 | self->threads = RB_ROOT; |
@@ -66,16 +66,21 @@ struct perf_session *perf_session__new(const char *filename, int mode, | |||
66 | self->mmap_window = 32; | 66 | self->mmap_window = 32; |
67 | self->cwd = NULL; | 67 | self->cwd = NULL; |
68 | self->cwdlen = 0; | 68 | self->cwdlen = 0; |
69 | map_groups__init(&self->kmaps); | ||
69 | 70 | ||
70 | if (mode == O_RDONLY && perf_session__open(self, force) < 0) { | 71 | if (perf_session__create_kernel_maps(self, conf) < 0) |
71 | perf_session__delete(self); | 72 | goto out_delete; |
72 | self = NULL; | 73 | |
73 | } | 74 | if (mode == O_RDONLY && perf_session__open(self, force) < 0) |
75 | goto out_delete; | ||
74 | out: | 76 | out: |
75 | return self; | 77 | return self; |
76 | out_delete: | 78 | out_free: |
77 | free(self); | 79 | free(self); |
78 | return NULL; | 80 | return NULL; |
81 | out_delete: | ||
82 | perf_session__delete(self); | ||
83 | return NULL; | ||
79 | } | 84 | } |
80 | 85 | ||
81 | void perf_session__delete(struct perf_session *self) | 86 | void perf_session__delete(struct perf_session *self) |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 1dbef7cdd489..20b2c9cc834b 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -3,19 +3,23 @@ | |||
3 | 3 | ||
4 | #include "event.h" | 4 | #include "event.h" |
5 | #include "header.h" | 5 | #include "header.h" |
6 | #include "thread.h" | ||
6 | #include <linux/rbtree.h> | 7 | #include <linux/rbtree.h> |
7 | 8 | ||
8 | struct thread; | 9 | struct thread; |
10 | struct symbol_conf; | ||
9 | 11 | ||
10 | struct perf_session { | 12 | struct perf_session { |
11 | struct perf_header header; | 13 | struct perf_header header; |
12 | unsigned long size; | 14 | unsigned long size; |
13 | unsigned long mmap_window; | 15 | unsigned long mmap_window; |
16 | struct map_groups kmaps; | ||
14 | struct rb_root threads; | 17 | struct rb_root threads; |
15 | struct thread *last_match; | 18 | struct thread *last_match; |
16 | int fd; | 19 | int fd; |
17 | int cwdlen; | 20 | int cwdlen; |
18 | char *cwd; | 21 | char *cwd; |
22 | bool use_modules; | ||
19 | char filename[0]; | 23 | char filename[0]; |
20 | }; | 24 | }; |
21 | 25 | ||
@@ -37,7 +41,7 @@ struct perf_event_ops { | |||
37 | }; | 41 | }; |
38 | 42 | ||
39 | struct perf_session *perf_session__new(const char *filename, int mode, | 43 | struct perf_session *perf_session__new(const char *filename, int mode, |
40 | bool force); | 44 | bool force, struct symbol_conf *conf); |
41 | void perf_session__delete(struct perf_session *self); | 45 | void perf_session__delete(struct perf_session *self); |
42 | 46 | ||
43 | int perf_session__process_events(struct perf_session *self, | 47 | int perf_session__process_events(struct perf_session *self, |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index d3d9fed74f1d..185b9eec192b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "util.h" | 1 | #include "util.h" |
2 | #include "../perf.h" | 2 | #include "../perf.h" |
3 | #include "session.h" | ||
3 | #include "string.h" | 4 | #include "string.h" |
4 | #include "symbol.h" | 5 | #include "symbol.h" |
5 | #include "thread.h" | 6 | #include "thread.h" |
@@ -31,7 +32,7 @@ enum dso_origin { | |||
31 | static void dsos__add(struct list_head *head, struct dso *dso); | 32 | static void dsos__add(struct list_head *head, struct dso *dso); |
32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 33 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
33 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
34 | struct map_groups *mg, symbol_filter_t filter); | 35 | struct perf_session *session, symbol_filter_t filter); |
35 | unsigned int symbol__priv_size; | 36 | unsigned int symbol__priv_size; |
36 | static int vmlinux_path__nr_entries; | 37 | static int vmlinux_path__nr_entries; |
37 | static char **vmlinux_path; | 38 | static char **vmlinux_path; |
@@ -41,9 +42,6 @@ static struct symbol_conf symbol_conf__defaults = { | |||
41 | .try_vmlinux_path = true, | 42 | .try_vmlinux_path = true, |
42 | }; | 43 | }; |
43 | 44 | ||
44 | static struct map_groups kmaps_mem; | ||
45 | struct map_groups *kmaps = &kmaps_mem; | ||
46 | |||
47 | bool dso__loaded(const struct dso *self, enum map_type type) | 45 | bool dso__loaded(const struct dso *self, enum map_type type) |
48 | { | 46 | { |
49 | return self->loaded & (1 << type); | 47 | return self->loaded & (1 << type); |
@@ -456,7 +454,7 @@ out_failure: | |||
456 | * the original ELF section names vmlinux have. | 454 | * the original ELF section names vmlinux have. |
457 | */ | 455 | */ |
458 | static int dso__split_kallsyms(struct dso *self, struct map *map, | 456 | static int dso__split_kallsyms(struct dso *self, struct map *map, |
459 | struct map_groups *mg, symbol_filter_t filter) | 457 | struct perf_session *session, symbol_filter_t filter) |
460 | { | 458 | { |
461 | struct map *curr_map = map; | 459 | struct map *curr_map = map; |
462 | struct symbol *pos; | 460 | struct symbol *pos; |
@@ -473,13 +471,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
473 | 471 | ||
474 | module = strchr(pos->name, '\t'); | 472 | module = strchr(pos->name, '\t'); |
475 | if (module) { | 473 | if (module) { |
476 | if (!mg->use_modules) | 474 | if (!session->use_modules) |
477 | goto discard_symbol; | 475 | goto discard_symbol; |
478 | 476 | ||
479 | *module++ = '\0'; | 477 | *module++ = '\0'; |
480 | 478 | ||
481 | if (strcmp(self->name, module)) { | 479 | if (strcmp(self->name, module)) { |
482 | curr_map = map_groups__find_by_name(mg, map->type, module); | 480 | curr_map = map_groups__find_by_name(&session->kmaps, map->type, module); |
483 | if (curr_map == NULL) { | 481 | if (curr_map == NULL) { |
484 | pr_debug("/proc/{kallsyms,modules} " | 482 | pr_debug("/proc/{kallsyms,modules} " |
485 | "inconsistency!\n"); | 483 | "inconsistency!\n"); |
@@ -510,7 +508,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
510 | } | 508 | } |
511 | 509 | ||
512 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; | 510 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
513 | map_groups__insert(mg, curr_map); | 511 | map_groups__insert(&session->kmaps, curr_map); |
514 | ++kernel_range; | 512 | ++kernel_range; |
515 | } | 513 | } |
516 | 514 | ||
@@ -531,7 +529,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
531 | 529 | ||
532 | 530 | ||
533 | static int dso__load_kallsyms(struct dso *self, struct map *map, | 531 | static int dso__load_kallsyms(struct dso *self, struct map *map, |
534 | struct map_groups *mg, symbol_filter_t filter) | 532 | struct perf_session *session, symbol_filter_t filter) |
535 | { | 533 | { |
536 | if (dso__load_all_kallsyms(self, map) < 0) | 534 | if (dso__load_all_kallsyms(self, map) < 0) |
537 | return -1; | 535 | return -1; |
@@ -539,14 +537,7 @@ static int dso__load_kallsyms(struct dso *self, struct map *map, | |||
539 | symbols__fixup_end(&self->symbols[map->type]); | 537 | symbols__fixup_end(&self->symbols[map->type]); |
540 | self->origin = DSO__ORIG_KERNEL; | 538 | self->origin = DSO__ORIG_KERNEL; |
541 | 539 | ||
542 | return dso__split_kallsyms(self, map, mg, filter); | 540 | return dso__split_kallsyms(self, map, session, filter); |
543 | } | ||
544 | |||
545 | size_t kernel_maps__fprintf(FILE *fp) | ||
546 | { | ||
547 | size_t printed = fprintf(fp, "Kernel maps:\n"); | ||
548 | printed += map_groups__fprintf_maps(kmaps, fp); | ||
549 | return printed + fprintf(fp, "END kernel maps\n"); | ||
550 | } | 541 | } |
551 | 542 | ||
552 | static int dso__load_perf_map(struct dso *self, struct map *map, | 543 | static int dso__load_perf_map(struct dso *self, struct map *map, |
@@ -873,7 +864,7 @@ static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type | |||
873 | } | 864 | } |
874 | 865 | ||
875 | static int dso__load_sym(struct dso *self, struct map *map, | 866 | static int dso__load_sym(struct dso *self, struct map *map, |
876 | struct map_groups *mg, const char *name, int fd, | 867 | struct perf_session *session, const char *name, int fd, |
877 | symbol_filter_t filter, int kernel, int kmodule) | 868 | symbol_filter_t filter, int kernel, int kmodule) |
878 | { | 869 | { |
879 | struct map *curr_map = map; | 870 | struct map *curr_map = map; |
@@ -977,7 +968,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
977 | snprintf(dso_name, sizeof(dso_name), | 968 | snprintf(dso_name, sizeof(dso_name), |
978 | "%s%s", self->short_name, section_name); | 969 | "%s%s", self->short_name, section_name); |
979 | 970 | ||
980 | curr_map = map_groups__find_by_name(mg, map->type, dso_name); | 971 | curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name); |
981 | if (curr_map == NULL) { | 972 | if (curr_map == NULL) { |
982 | u64 start = sym.st_value; | 973 | u64 start = sym.st_value; |
983 | 974 | ||
@@ -996,7 +987,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
996 | curr_map->map_ip = identity__map_ip; | 987 | curr_map->map_ip = identity__map_ip; |
997 | curr_map->unmap_ip = identity__map_ip; | 988 | curr_map->unmap_ip = identity__map_ip; |
998 | curr_dso->origin = DSO__ORIG_KERNEL; | 989 | curr_dso->origin = DSO__ORIG_KERNEL; |
999 | map_groups__insert(kmaps, curr_map); | 990 | map_groups__insert(&session->kmaps, curr_map); |
1000 | dsos__add(&dsos__kernel, curr_dso); | 991 | dsos__add(&dsos__kernel, curr_dso); |
1001 | } else | 992 | } else |
1002 | curr_dso = curr_map->dso; | 993 | curr_dso = curr_map->dso; |
@@ -1211,7 +1202,8 @@ char dso__symtab_origin(const struct dso *self) | |||
1211 | return origin[self->origin]; | 1202 | return origin[self->origin]; |
1212 | } | 1203 | } |
1213 | 1204 | ||
1214 | int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | 1205 | int dso__load(struct dso *self, struct map *map, struct perf_session *session, |
1206 | symbol_filter_t filter) | ||
1215 | { | 1207 | { |
1216 | int size = PATH_MAX; | 1208 | int size = PATH_MAX; |
1217 | char *name; | 1209 | char *name; |
@@ -1222,7 +1214,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1222 | dso__set_loaded(self, map->type); | 1214 | dso__set_loaded(self, map->type); |
1223 | 1215 | ||
1224 | if (self->kernel) | 1216 | if (self->kernel) |
1225 | return dso__load_kernel_sym(self, map, kmaps, filter); | 1217 | return dso__load_kernel_sym(self, map, session, filter); |
1226 | 1218 | ||
1227 | name = malloc(size); | 1219 | name = malloc(size); |
1228 | if (!name) | 1220 | if (!name) |
@@ -1323,7 +1315,7 @@ struct map *map_groups__find_by_name(struct map_groups *self, | |||
1323 | return NULL; | 1315 | return NULL; |
1324 | } | 1316 | } |
1325 | 1317 | ||
1326 | static int dsos__set_modules_path_dir(char *dirname) | 1318 | static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname) |
1327 | { | 1319 | { |
1328 | struct dirent *dent; | 1320 | struct dirent *dent; |
1329 | DIR *dir = opendir(dirname); | 1321 | DIR *dir = opendir(dirname); |
@@ -1343,7 +1335,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1343 | 1335 | ||
1344 | snprintf(path, sizeof(path), "%s/%s", | 1336 | snprintf(path, sizeof(path), "%s/%s", |
1345 | dirname, dent->d_name); | 1337 | dirname, dent->d_name); |
1346 | if (dsos__set_modules_path_dir(path) < 0) | 1338 | if (perf_session__set_modules_path_dir(self, path) < 0) |
1347 | goto failure; | 1339 | goto failure; |
1348 | } else { | 1340 | } else { |
1349 | char *dot = strrchr(dent->d_name, '.'), | 1341 | char *dot = strrchr(dent->d_name, '.'), |
@@ -1357,7 +1349,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1357 | (int)(dot - dent->d_name), dent->d_name); | 1349 | (int)(dot - dent->d_name), dent->d_name); |
1358 | 1350 | ||
1359 | strxfrchar(dso_name, '-', '_'); | 1351 | strxfrchar(dso_name, '-', '_'); |
1360 | map = map_groups__find_by_name(kmaps, MAP__FUNCTION, dso_name); | 1352 | map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name); |
1361 | if (map == NULL) | 1353 | if (map == NULL) |
1362 | continue; | 1354 | continue; |
1363 | 1355 | ||
@@ -1377,7 +1369,7 @@ failure: | |||
1377 | return -1; | 1369 | return -1; |
1378 | } | 1370 | } |
1379 | 1371 | ||
1380 | static int dsos__set_modules_path(void) | 1372 | static int perf_session__set_modules_path(struct perf_session *self) |
1381 | { | 1373 | { |
1382 | struct utsname uts; | 1374 | struct utsname uts; |
1383 | char modules_path[PATH_MAX]; | 1375 | char modules_path[PATH_MAX]; |
@@ -1388,7 +1380,7 @@ static int dsos__set_modules_path(void) | |||
1388 | snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", | 1380 | snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", |
1389 | uts.release); | 1381 | uts.release); |
1390 | 1382 | ||
1391 | return dsos__set_modules_path_dir(modules_path); | 1383 | return perf_session__set_modules_path_dir(self, modules_path); |
1392 | } | 1384 | } |
1393 | 1385 | ||
1394 | /* | 1386 | /* |
@@ -1410,7 +1402,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
1410 | return self; | 1402 | return self; |
1411 | } | 1403 | } |
1412 | 1404 | ||
1413 | static int map_groups__create_module_maps(struct map_groups *self) | 1405 | static int perf_session__create_module_maps(struct perf_session *self) |
1414 | { | 1406 | { |
1415 | char *line = NULL; | 1407 | char *line = NULL; |
1416 | size_t n; | 1408 | size_t n; |
@@ -1467,14 +1459,14 @@ static int map_groups__create_module_maps(struct map_groups *self) | |||
1467 | dso->has_build_id = true; | 1459 | dso->has_build_id = true; |
1468 | 1460 | ||
1469 | dso->origin = DSO__ORIG_KMODULE; | 1461 | dso->origin = DSO__ORIG_KMODULE; |
1470 | map_groups__insert(self, map); | 1462 | map_groups__insert(&self->kmaps, map); |
1471 | dsos__add(&dsos__kernel, dso); | 1463 | dsos__add(&dsos__kernel, dso); |
1472 | } | 1464 | } |
1473 | 1465 | ||
1474 | free(line); | 1466 | free(line); |
1475 | fclose(file); | 1467 | fclose(file); |
1476 | 1468 | ||
1477 | return dsos__set_modules_path(); | 1469 | return perf_session__set_modules_path(self); |
1478 | 1470 | ||
1479 | out_delete_line: | 1471 | out_delete_line: |
1480 | free(line); | 1472 | free(line); |
@@ -1483,7 +1475,7 @@ out_failure: | |||
1483 | } | 1475 | } |
1484 | 1476 | ||
1485 | static int dso__load_vmlinux(struct dso *self, struct map *map, | 1477 | static int dso__load_vmlinux(struct dso *self, struct map *map, |
1486 | struct map_groups *mg, | 1478 | struct perf_session *session, |
1487 | const char *vmlinux, symbol_filter_t filter) | 1479 | const char *vmlinux, symbol_filter_t filter) |
1488 | { | 1480 | { |
1489 | int err = -1, fd; | 1481 | int err = -1, fd; |
@@ -1517,14 +1509,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1517 | return -1; | 1509 | return -1; |
1518 | 1510 | ||
1519 | dso__set_loaded(self, map->type); | 1511 | dso__set_loaded(self, map->type); |
1520 | err = dso__load_sym(self, map, mg, self->long_name, fd, filter, 1, 0); | 1512 | err = dso__load_sym(self, map, session, self->long_name, fd, filter, 1, 0); |
1521 | close(fd); | 1513 | close(fd); |
1522 | 1514 | ||
1523 | return err; | 1515 | return err; |
1524 | } | 1516 | } |
1525 | 1517 | ||
1526 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 1518 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
1527 | struct map_groups *mg, symbol_filter_t filter) | 1519 | struct perf_session *session, symbol_filter_t filter) |
1528 | { | 1520 | { |
1529 | int err; | 1521 | int err; |
1530 | bool is_kallsyms; | 1522 | bool is_kallsyms; |
@@ -1534,7 +1526,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1534 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | 1526 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", |
1535 | vmlinux_path__nr_entries); | 1527 | vmlinux_path__nr_entries); |
1536 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1528 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
1537 | err = dso__load_vmlinux(self, map, mg, | 1529 | err = dso__load_vmlinux(self, map, session, |
1538 | vmlinux_path[i], filter); | 1530 | vmlinux_path[i], filter); |
1539 | if (err > 0) { | 1531 | if (err > 0) { |
1540 | pr_debug("Using %s for symbols\n", | 1532 | pr_debug("Using %s for symbols\n", |
@@ -1550,12 +1542,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1550 | if (is_kallsyms) | 1542 | if (is_kallsyms) |
1551 | goto do_kallsyms; | 1543 | goto do_kallsyms; |
1552 | 1544 | ||
1553 | err = dso__load_vmlinux(self, map, mg, self->long_name, filter); | 1545 | err = dso__load_vmlinux(self, map, session, self->long_name, filter); |
1554 | if (err <= 0) { | 1546 | if (err <= 0) { |
1555 | pr_info("The file %s cannot be used, " | 1547 | pr_info("The file %s cannot be used, " |
1556 | "trying to use /proc/kallsyms...", self->long_name); | 1548 | "trying to use /proc/kallsyms...", self->long_name); |
1557 | do_kallsyms: | 1549 | do_kallsyms: |
1558 | err = dso__load_kallsyms(self, map, mg, filter); | 1550 | err = dso__load_kallsyms(self, map, session, filter); |
1559 | if (err > 0 && !is_kallsyms) | 1551 | if (err > 0 && !is_kallsyms) |
1560 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); | 1552 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); |
1561 | } | 1553 | } |
@@ -1757,23 +1749,30 @@ int symbol__init(struct symbol_conf *conf) | |||
1757 | if (pconf->sort_by_name) | 1749 | if (pconf->sort_by_name) |
1758 | symbol__priv_size += (sizeof(struct symbol_name_rb_node) - | 1750 | symbol__priv_size += (sizeof(struct symbol_name_rb_node) - |
1759 | sizeof(struct symbol)); | 1751 | sizeof(struct symbol)); |
1760 | map_groups__init(kmaps); | ||
1761 | 1752 | ||
1762 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) | 1753 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) |
1763 | return -1; | 1754 | return -1; |
1764 | 1755 | ||
1765 | if (map_groups__create_kernel_maps(kmaps, pconf->vmlinux_name) < 0) { | 1756 | return 0; |
1766 | vmlinux_path__exit(); | 1757 | } |
1758 | |||
1759 | int perf_session__create_kernel_maps(struct perf_session *self, | ||
1760 | struct symbol_conf *conf) | ||
1761 | { | ||
1762 | const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; | ||
1763 | |||
1764 | if (map_groups__create_kernel_maps(&self->kmaps, | ||
1765 | pconf->vmlinux_name) < 0) | ||
1767 | return -1; | 1766 | return -1; |
1768 | } | ||
1769 | 1767 | ||
1770 | kmaps->use_modules = pconf->use_modules; | 1768 | self->use_modules = pconf->use_modules; |
1771 | if (pconf->use_modules && map_groups__create_module_maps(kmaps) < 0) | 1769 | |
1772 | pr_debug("Failed to load list of modules in use, " | 1770 | if (pconf->use_modules && perf_session__create_module_maps(self) < 0) |
1773 | "continuing...\n"); | 1771 | pr_debug("Failed to load list of modules for session %s, " |
1772 | "continuing...\n", self->filename); | ||
1774 | /* | 1773 | /* |
1775 | * Now that we have all the maps created, just set the ->end of them: | 1774 | * Now that we have all the maps created, just set the ->end of them: |
1776 | */ | 1775 | */ |
1777 | map_groups__fixup_end(kmaps); | 1776 | map_groups__fixup_end(&self->kmaps); |
1778 | return 0; | 1777 | return 0; |
1779 | } | 1778 | } |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index cf99f88adf39..941ef331790e 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -98,8 +98,11 @@ bool dso__sorted_by_name(const struct dso *self, enum map_type type); | |||
98 | 98 | ||
99 | void dso__sort_by_name(struct dso *self, enum map_type type); | 99 | void dso__sort_by_name(struct dso *self, enum map_type type); |
100 | 100 | ||
101 | struct perf_session; | ||
102 | |||
101 | struct dso *dsos__findnew(const char *name); | 103 | struct dso *dsos__findnew(const char *name); |
102 | int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); | 104 | int dso__load(struct dso *self, struct map *map, struct perf_session *session, |
105 | symbol_filter_t filter); | ||
103 | void dsos__fprintf(FILE *fp); | 106 | void dsos__fprintf(FILE *fp); |
104 | size_t dsos__fprintf_buildid(FILE *fp); | 107 | size_t dsos__fprintf_buildid(FILE *fp); |
105 | 108 | ||
@@ -116,12 +119,10 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size); | |||
116 | bool dsos__read_build_ids(void); | 119 | bool dsos__read_build_ids(void); |
117 | int build_id__sprintf(u8 *self, int len, char *bf); | 120 | int build_id__sprintf(u8 *self, int len, char *bf); |
118 | 121 | ||
119 | size_t kernel_maps__fprintf(FILE *fp); | ||
120 | |||
121 | int symbol__init(struct symbol_conf *conf); | 122 | int symbol__init(struct symbol_conf *conf); |
123 | int perf_session__create_kernel_maps(struct perf_session *self, | ||
124 | struct symbol_conf *conf); | ||
122 | 125 | ||
123 | struct map_groups; | ||
124 | struct map_groups *kmaps; | ||
125 | extern struct list_head dsos__user, dsos__kernel; | 126 | extern struct list_head dsos__user, dsos__kernel; |
126 | extern struct dso *vdso; | 127 | extern struct dso *vdso; |
127 | #endif /* __PERF_SYMBOL */ | 128 | #endif /* __PERF_SYMBOL */ |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 634b7f7140d5..4a08dcf50b68 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -282,13 +282,14 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp) | |||
282 | } | 282 | } |
283 | 283 | ||
284 | struct symbol *map_groups__find_symbol(struct map_groups *self, | 284 | struct symbol *map_groups__find_symbol(struct map_groups *self, |
285 | struct perf_session *session, | ||
285 | enum map_type type, u64 addr, | 286 | enum map_type type, u64 addr, |
286 | symbol_filter_t filter) | 287 | symbol_filter_t filter) |
287 | { | 288 | { |
288 | struct map *map = map_groups__find(self, type, addr); | 289 | struct map *map = map_groups__find(self, type, addr); |
289 | 290 | ||
290 | if (map != NULL) | 291 | if (map != NULL) |
291 | return map__find_symbol(map, map->map_ip(map, addr), filter); | 292 | return map__find_symbol(map, session, map->map_ip(map, addr), filter); |
292 | 293 | ||
293 | return NULL; | 294 | return NULL; |
294 | } | 295 | } |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index e93abf2d9cb6..c206f72c8881 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -8,7 +8,6 @@ | |||
8 | struct map_groups { | 8 | struct map_groups { |
9 | struct rb_root maps[MAP__NR_TYPES]; | 9 | struct rb_root maps[MAP__NR_TYPES]; |
10 | struct list_head removed_maps[MAP__NR_TYPES]; | 10 | struct list_head removed_maps[MAP__NR_TYPES]; |
11 | bool use_modules; | ||
12 | }; | 11 | }; |
13 | 12 | ||
14 | struct thread { | 13 | struct thread { |
@@ -49,19 +48,21 @@ static inline struct map *thread__find_map(struct thread *self, | |||
49 | return self ? map_groups__find(&self->mg, type, addr) : NULL; | 48 | return self ? map_groups__find(&self->mg, type, addr) : NULL; |
50 | } | 49 | } |
51 | 50 | ||
52 | void thread__find_addr_location(struct thread *self, u8 cpumode, | 51 | void thread__find_addr_location(struct thread *self, |
52 | struct perf_session *session, u8 cpumode, | ||
53 | enum map_type type, u64 addr, | 53 | enum map_type type, u64 addr, |
54 | struct addr_location *al, | 54 | struct addr_location *al, |
55 | symbol_filter_t filter); | 55 | symbol_filter_t filter); |
56 | struct symbol *map_groups__find_symbol(struct map_groups *self, | 56 | struct symbol *map_groups__find_symbol(struct map_groups *self, |
57 | struct perf_session *session, | ||
57 | enum map_type type, u64 addr, | 58 | enum map_type type, u64 addr, |
58 | symbol_filter_t filter); | 59 | symbol_filter_t filter); |
59 | 60 | ||
60 | static inline struct symbol * | 61 | static inline struct symbol * |
61 | map_groups__find_function(struct map_groups *self, u64 addr, | 62 | map_groups__find_function(struct map_groups *self, struct perf_session *session, |
62 | symbol_filter_t filter) | 63 | u64 addr, symbol_filter_t filter) |
63 | { | 64 | { |
64 | return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); | 65 | return map_groups__find_symbol(self, session, MAP__FUNCTION, addr, filter); |
65 | } | 66 | } |
66 | 67 | ||
67 | struct map *map_groups__find_by_name(struct map_groups *self, | 68 | struct map *map_groups__find_by_name(struct map_groups *self, |