aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-12-13 16:50:29 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-14 10:57:17 -0500
commit4aa65636411ccb12f006a6ad593930655c445ff6 (patch)
tree0f494705a2a7631070a5372bb53f873684b001c2
parentb3165f414416a717f72a376720564012af5a2e01 (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>
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-kmem.c41
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c14
-rw-r--r--tools/perf/builtin-sched.c4
-rw-r--r--tools/perf/builtin-timechart.c3
-rw-r--r--tools/perf/builtin-top.c4
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/util/event.c13
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/map.c14
-rw-r--r--tools/perf/util/session.c19
-rw-r--r--tools/perf/util/session.h6
-rw-r--r--tools/perf/util/symbol.c89
-rw-r--r--tools/perf/util/symbol.h11
-rw-r--r--tools/perf/util/thread.c3
-rw-r--r--tools/perf/util/thread.h11
18 files changed, 134 insertions, 118 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 795f865c1366..e44c54c79be4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -463,7 +463,7 @@ static struct perf_event_ops event_ops = {
463static int __cmd_annotate(void) 463static int __cmd_annotate(void)
464{ 464{
465 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 465 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
466 force); 466 force, &symbol_conf);
467 int ret; 467 int ret;
468 468
469 if (session == NULL) 469 if (session == NULL)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 2629f76d95fe..7c36e4b2eccf 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -54,8 +54,8 @@ static int perf_file_section__process_buildids(struct perf_file_section *self,
54static int __cmd_buildid_list(void) 54static int __cmd_buildid_list(void)
55{ 55{
56 int err = -1; 56 int err = -1;
57 struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); 57 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
58 58 force, NULL);
59 if (session == NULL) 59 if (session == NULL)
60 return -1; 60 return -1;
61 61
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index de194958fe6e..e79ecbc17181 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -364,19 +364,6 @@ static struct perf_event_ops event_ops = {
364 .sample_type_check = sample_type_check, 364 .sample_type_check = sample_type_check,
365}; 365};
366 366
367static int read_events(void)
368{
369 int err;
370 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
371
372 if (session == NULL)
373 return -ENOMEM;
374
375 err = perf_session__process_events(session, &event_ops);
376 perf_session__delete(session);
377 return err;
378}
379
380static double fragmentation(unsigned long n_req, unsigned long n_alloc) 367static double fragmentation(unsigned long n_req, unsigned long n_alloc)
381{ 368{
382 if (n_alloc == 0) 369 if (n_alloc == 0)
@@ -385,7 +372,8 @@ static double fragmentation(unsigned long n_req, unsigned long n_alloc)
385 return 100.0 - (100.0 * n_req / n_alloc); 372 return 100.0 - (100.0 * n_req / n_alloc);
386} 373}
387 374
388static void __print_result(struct rb_root *root, int n_lines, int is_caller) 375static void __print_result(struct rb_root *root, struct perf_session *session,
376 int n_lines, int is_caller)
389{ 377{
390 struct rb_node *next; 378 struct rb_node *next;
391 379
@@ -406,7 +394,7 @@ static void __print_result(struct rb_root *root, int n_lines, int is_caller)
406 if (is_caller) { 394 if (is_caller) {
407 addr = data->call_site; 395 addr = data->call_site;
408 if (!raw_ip) 396 if (!raw_ip)
409 sym = map_groups__find_function(kmaps, addr, NULL); 397 sym = map_groups__find_function(&session->kmaps, session, addr, NULL);
410 } else 398 } else
411 addr = data->ptr; 399 addr = data->ptr;
412 400
@@ -447,12 +435,12 @@ static void print_summary(void)
447 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 435 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
448} 436}
449 437
450static void print_result(void) 438static void print_result(struct perf_session *session)
451{ 439{
452 if (caller_flag) 440 if (caller_flag)
453 __print_result(&root_caller_sorted, caller_lines, 1); 441 __print_result(&root_caller_sorted, session, caller_lines, 1);
454 if (alloc_flag) 442 if (alloc_flag)
455 __print_result(&root_alloc_sorted, alloc_lines, 0); 443 __print_result(&root_alloc_sorted, session, alloc_lines, 0);
456 print_summary(); 444 print_summary();
457} 445}
458 446
@@ -520,12 +508,21 @@ static void sort_result(void)
520 508
521static int __cmd_kmem(void) 509static int __cmd_kmem(void)
522{ 510{
511 int err;
512 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
513 0, NULL);
514 if (session == NULL)
515 return -ENOMEM;
516
523 setup_pager(); 517 setup_pager();
524 read_events(); 518 err = perf_session__process_events(session, &event_ops);
519 if (err != 0)
520 goto out_delete;
525 sort_result(); 521 sort_result();
526 print_result(); 522 print_result(session);
527 523out_delete:
528 return 0; 524 perf_session__delete(session);
525 return err;
529} 526}
530 527
531static const char * const kmem_usage[] = { 528static const char * const kmem_usage[] = {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b7e15a1b1ec2..a66a58d52818 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -442,7 +442,7 @@ static int __cmd_record(int argc, const char **argv)
442 exit(-1); 442 exit(-1);
443 } 443 }
444 444
445 session = perf_session__new(output_name, O_WRONLY, force); 445 session = perf_session__new(output_name, O_WRONLY, force, NULL);
446 if (session == NULL) { 446 if (session == NULL) {
447 pr_err("Not enough memory for reading perf file header\n"); 447 pr_err("Not enough memory for reading perf file header\n");
448 return -1; 448 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index efa8147b8991..3487224670a8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -414,6 +414,7 @@ static int call__match(struct symbol *sym)
414} 414}
415 415
416static struct symbol **resolve_callchain(struct thread *thread, 416static struct symbol **resolve_callchain(struct thread *thread,
417 struct perf_session *session,
417 struct ip_callchain *chain, 418 struct ip_callchain *chain,
418 struct symbol **parent) 419 struct symbol **parent)
419{ 420{
@@ -447,8 +448,8 @@ static struct symbol **resolve_callchain(struct thread *thread,
447 continue; 448 continue;
448 } 449 }
449 450
450 thread__find_addr_location(thread, cpumode, MAP__FUNCTION, 451 thread__find_addr_location(thread, session, cpumode,
451 ip, &al, NULL); 452 MAP__FUNCTION, ip, &al, NULL);
452 if (al.sym != NULL) { 453 if (al.sym != NULL) {
453 if (sort__has_parent && !*parent && 454 if (sort__has_parent && !*parent &&
454 call__match(al.sym)) 455 call__match(al.sym))
@@ -467,6 +468,7 @@ static struct symbol **resolve_callchain(struct thread *thread,
467 */ 468 */
468 469
469static int hist_entry__add(struct addr_location *al, 470static int hist_entry__add(struct addr_location *al,
471 struct perf_session *session,
470 struct ip_callchain *chain, u64 count) 472 struct ip_callchain *chain, u64 count)
471{ 473{
472 struct symbol **syms = NULL, *parent = NULL; 474 struct symbol **syms = NULL, *parent = NULL;
@@ -474,7 +476,7 @@ static int hist_entry__add(struct addr_location *al,
474 struct hist_entry *he; 476 struct hist_entry *he;
475 477
476 if ((sort__has_parent || callchain) && chain) 478 if ((sort__has_parent || callchain) && chain)
477 syms = resolve_callchain(al->thread, chain, &parent); 479 syms = resolve_callchain(al->thread, session, chain, &parent);
478 480
479 he = __hist_entry__add(al, parent, count, &hit); 481 he = __hist_entry__add(al, parent, count, &hit);
480 if (he == NULL) 482 if (he == NULL)
@@ -650,7 +652,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
650 652
651 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 653 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
652 654
653 thread__find_addr_location(thread, cpumode, 655 thread__find_addr_location(thread, session, cpumode,
654 MAP__FUNCTION, data.ip, &al, NULL); 656 MAP__FUNCTION, data.ip, &al, NULL);
655 /* 657 /*
656 * We have to do this here as we may have a dso with no symbol hit that 658 * We have to do this here as we may have a dso with no symbol hit that
@@ -669,7 +671,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
669 if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name)) 671 if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
670 return 0; 672 return 0;
671 673
672 if (hist_entry__add(&al, data.callchain, data.period)) { 674 if (hist_entry__add(&al, session, data.callchain, data.period)) {
673 pr_debug("problem incrementing symbol count, skipping event\n"); 675 pr_debug("problem incrementing symbol count, skipping event\n");
674 return -1; 676 return -1;
675 } 677 }
@@ -763,7 +765,7 @@ static int __cmd_report(void)
763 int ret; 765 int ret;
764 struct perf_session *session; 766 struct perf_session *session;
765 767
766 session = perf_session__new(input_name, O_RDONLY, force); 768 session = perf_session__new(input_name, O_RDONLY, force, &symbol_conf);
767 if (session == NULL) 769 if (session == NULL)
768 return -ENOMEM; 770 return -ENOMEM;
769 771
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 8d58d9e07a7b..bce05dff6dfe 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1679,8 +1679,8 @@ static struct perf_event_ops event_ops = {
1679static int read_events(void) 1679static int read_events(void)
1680{ 1680{
1681 int err; 1681 int err;
1682 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); 1682 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1683 1683 0, NULL);
1684 if (session == NULL) 1684 if (session == NULL)
1685 return -ENOMEM; 1685 return -ENOMEM;
1686 1686
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index b5211facddc6..27018531404b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1056,7 +1056,8 @@ static struct perf_event_ops event_ops = {
1056 1056
1057static int __cmd_timechart(void) 1057static int __cmd_timechart(void)
1058{ 1058{
1059 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); 1059 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1060 0, NULL);
1060 int ret; 1061 int ret;
1061 1062
1062 if (session == NULL) 1063 if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0f7a4da2924c..3b212bb2e4df 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1162,8 +1162,8 @@ static int __cmd_top(void)
1162 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1162 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1163 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1163 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1164 */ 1164 */
1165 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false); 1165 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false,
1166 1166 &symbol_conf);
1167 if (session == NULL) 1167 if (session == NULL)
1168 return -ENOMEM; 1168 return -ENOMEM;
1169 1169
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d76532375054..9d89ae423ca5 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -318,7 +318,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
318 318
319 setup_pager(); 319 setup_pager();
320 320
321 session = perf_session__new(input_name, O_RDONLY, 0); 321 session = perf_session__new(input_name, O_RDONLY, 0, NULL);
322 if (session == NULL) 322 if (session == NULL)
323 return -ENOMEM; 323 return -ENOMEM;
324 324
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
259void thread__find_addr_location(struct thread *self, u8 cpumode, 259void 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);
149struct map *map__clone(struct map *self); 149struct map *map__clone(struct map *self);
150int map__overlap(struct map *l, struct map *r); 150int map__overlap(struct map *l, struct map *r);
151size_t map__fprintf(struct map *self, FILE *fp); 151size_t map__fprintf(struct map *self, FILE *fp);
152struct symbol *map__find_symbol(struct map *self, u64 addr, 152
153 symbol_filter_t filter); 153struct perf_session;
154
155struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
156 u64 addr, symbol_filter_t filter);
154struct symbol *map__find_symbol_by_name(struct map *self, const char *name, 157struct 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);
156void map__fixup_start(struct map *self); 160void map__fixup_start(struct map *self);
157void map__fixup_end(struct map *self); 161void map__fixup_end(struct map *self);
158 162
159struct perf_session;
160
161int event__synthesize_thread(pid_t pid, 163int 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
107static int map__load(struct map *self, symbol_filter_t filter) 107static 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
146struct symbol *map__find_symbol(struct map *self, u64 addr, 147struct 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
155struct symbol *map__find_symbol_by_name(struct map *self, const char *name, 156struct 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
51struct perf_session *perf_session__new(const char *filename, int mode, 51struct 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;
74out: 76out:
75 return self; 77 return self;
76out_delete: 78out_free:
77 free(self); 79 free(self);
78 return NULL; 80 return NULL;
81out_delete:
82 perf_session__delete(self);
83 return NULL;
79} 84}
80 85
81void perf_session__delete(struct perf_session *self) 86void 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
8struct thread; 9struct thread;
10struct symbol_conf;
9 11
10struct perf_session { 12struct 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
39struct perf_session *perf_session__new(const char *filename, int mode, 43struct perf_session *perf_session__new(const char *filename, int mode,
40 bool force); 44 bool force, struct symbol_conf *conf);
41void perf_session__delete(struct perf_session *self); 45void perf_session__delete(struct perf_session *self);
42 46
43int perf_session__process_events(struct perf_session *self, 47int 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 {
31static void dsos__add(struct list_head *head, struct dso *dso); 32static void dsos__add(struct list_head *head, struct dso *dso);
32static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
33static int dso__load_kernel_sym(struct dso *self, struct map *map, 34static 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);
35unsigned int symbol__priv_size; 36unsigned int symbol__priv_size;
36static int vmlinux_path__nr_entries; 37static int vmlinux_path__nr_entries;
37static char **vmlinux_path; 38static 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
44static struct map_groups kmaps_mem;
45struct map_groups *kmaps = &kmaps_mem;
46
47bool dso__loaded(const struct dso *self, enum map_type type) 45bool 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 */
458static int dso__split_kallsyms(struct dso *self, struct map *map, 456static 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
533static int dso__load_kallsyms(struct dso *self, struct map *map, 531static 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
545size_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
552static int dso__load_perf_map(struct dso *self, struct map *map, 543static 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
875static int dso__load_sym(struct dso *self, struct map *map, 866static 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
1214int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 1205int 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
1326static int dsos__set_modules_path_dir(char *dirname) 1318static 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
1380static int dsos__set_modules_path(void) 1372static 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
1413static int map_groups__create_module_maps(struct map_groups *self) 1405static 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
1479out_delete_line: 1471out_delete_line:
1480 free(line); 1472 free(line);
@@ -1483,7 +1475,7 @@ out_failure:
1483} 1475}
1484 1476
1485static int dso__load_vmlinux(struct dso *self, struct map *map, 1477static 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
1526static int dso__load_kernel_sym(struct dso *self, struct map *map, 1518static 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);
1557do_kallsyms: 1549do_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
1759int 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
99void dso__sort_by_name(struct dso *self, enum map_type type); 99void dso__sort_by_name(struct dso *self, enum map_type type);
100 100
101struct perf_session;
102
101struct dso *dsos__findnew(const char *name); 103struct dso *dsos__findnew(const char *name);
102int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 104int dso__load(struct dso *self, struct map *map, struct perf_session *session,
105 symbol_filter_t filter);
103void dsos__fprintf(FILE *fp); 106void dsos__fprintf(FILE *fp);
104size_t dsos__fprintf_buildid(FILE *fp); 107size_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);
116bool dsos__read_build_ids(void); 119bool dsos__read_build_ids(void);
117int build_id__sprintf(u8 *self, int len, char *bf); 120int build_id__sprintf(u8 *self, int len, char *bf);
118 121
119size_t kernel_maps__fprintf(FILE *fp);
120
121int symbol__init(struct symbol_conf *conf); 122int symbol__init(struct symbol_conf *conf);
123int perf_session__create_kernel_maps(struct perf_session *self,
124 struct symbol_conf *conf);
122 125
123struct map_groups;
124struct map_groups *kmaps;
125extern struct list_head dsos__user, dsos__kernel; 126extern struct list_head dsos__user, dsos__kernel;
126extern struct dso *vdso; 127extern 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
284struct symbol *map_groups__find_symbol(struct map_groups *self, 284struct 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 @@
8struct map_groups { 8struct 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
14struct thread { 13struct 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
52void thread__find_addr_location(struct thread *self, u8 cpumode, 51void 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);
56struct symbol *map_groups__find_symbol(struct map_groups *self, 56struct 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
60static inline struct symbol * 61static inline struct symbol *
61map_groups__find_function(struct map_groups *self, u64 addr, 62map_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
67struct map *map_groups__find_by_name(struct map_groups *self, 68struct map *map_groups__find_by_name(struct map_groups *self,