aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/builtin-annotate.c73
-rw-r--r--tools/perf/builtin-report.c79
-rw-r--r--tools/perf/builtin-top.c74
-rw-r--r--tools/perf/util/event.h6
-rw-r--r--tools/perf/util/module.c545
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/sort.c38
-rw-r--r--tools/perf/util/sort.h7
-rw-r--r--tools/perf/util/symbol.c447
-rw-r--r--tools/perf/util/symbol.h20
-rw-r--r--tools/perf/util/thread.c34
-rw-r--r--tools/perf/util/thread.h4
13 files changed, 453 insertions, 929 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 055290a5b835..8e7509f2d882 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -336,7 +336,6 @@ LIB_H += util/strlist.h
336LIB_H += util/run-command.h 336LIB_H += util/run-command.h
337LIB_H += util/sigchain.h 337LIB_H += util/sigchain.h
338LIB_H += util/symbol.h 338LIB_H += util/symbol.h
339LIB_H += util/module.h
340LIB_H += util/color.h 339LIB_H += util/color.h
341LIB_H += util/values.h 340LIB_H += util/values.h
342LIB_H += util/sort.h 341LIB_H += util/sort.h
@@ -364,7 +363,6 @@ LIB_OBJS += util/usage.o
364LIB_OBJS += util/wrapper.o 363LIB_OBJS += util/wrapper.o
365LIB_OBJS += util/sigchain.o 364LIB_OBJS += util/sigchain.o
366LIB_OBJS += util/symbol.o 365LIB_OBJS += util/symbol.o
367LIB_OBJS += util/module.o
368LIB_OBJS += util/color.o 366LIB_OBJS += util/color.o
369LIB_OBJS += util/pager.o 367LIB_OBJS += util/pager.o
370LIB_OBJS += util/header.o 368LIB_OBJS += util/header.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index df516dce9540..7d5a3b1bcda9 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -63,6 +63,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
63 return; 63 return;
64 64
65 sym_size = sym->end - sym->start; 65 sym_size = sym->end - sym->start;
66 ip = he->map->map_ip(he->map, ip);
66 offset = ip - sym->start; 67 offset = ip - sym->start;
67 68
68 if (offset >= sym_size) 69 if (offset >= sym_size)
@@ -80,7 +81,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
80} 81}
81 82
82static int 83static int
83hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 84hist_entry__add(struct thread *thread, struct map *map,
84 struct symbol *sym, u64 ip, char level) 85 struct symbol *sym, u64 ip, char level)
85{ 86{
86 struct rb_node **p = &hist.rb_node; 87 struct rb_node **p = &hist.rb_node;
@@ -89,7 +90,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
89 struct hist_entry entry = { 90 struct hist_entry entry = {
90 .thread = thread, 91 .thread = thread,
91 .map = map, 92 .map = map,
92 .dso = dso,
93 .sym = sym, 93 .sym = sym,
94 .ip = ip, 94 .ip = ip,
95 .level = level, 95 .level = level,
@@ -130,10 +130,10 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
130{ 130{
131 char level; 131 char level;
132 int show = 0; 132 int show = 0;
133 struct dso *dso = NULL;
134 struct thread *thread; 133 struct thread *thread;
135 u64 ip = event->ip.ip; 134 u64 ip = event->ip.ip;
136 struct map *map = NULL; 135 struct map *map = NULL;
136 struct symbol *sym = NULL;
137 137
138 thread = threads__findnew(event->ip.pid, &threads, &last_match); 138 thread = threads__findnew(event->ip.pid, &threads, &last_match);
139 139
@@ -155,32 +155,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
155 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 155 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
156 show = SHOW_KERNEL; 156 show = SHOW_KERNEL;
157 level = 'k'; 157 level = 'k';
158 158 sym = kernel_maps__find_symbol(ip, &map);
159 dso = kernel_dso; 159 dump_printf(" ...... dso: %s\n",
160 160 map ? map->dso->long_name : "<not found>");
161 dump_printf(" ...... dso: %s\n", dso->name);
162
163 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 161 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
164
165 show = SHOW_USER; 162 show = SHOW_USER;
166 level = '.'; 163 level = '.';
167
168 map = thread__find_map(thread, ip); 164 map = thread__find_map(thread, ip);
169 if (map != NULL) { 165 if (map != NULL) {
166got_map:
170 ip = map->map_ip(map, ip); 167 ip = map->map_ip(map, ip);
171 dso = map->dso; 168 sym = map->dso->find_symbol(map->dso, ip);
172 } else { 169 } else {
173 /* 170 /*
174 * If this is outside of all known maps, 171 * If this is outside of all known maps,
175 * and is a negative address, try to look it 172 * and is a negative address, try to look it
176 * up in the kernel dso, as it might be a 173 * up in the kernel dso, as it might be a
177 * vsyscall (which executes in user-mode): 174 * vsyscall or vdso (which executes in user-mode).
175 *
176 * XXX This is nasty, we should have a symbol list in
177 * the "[vdso]" dso, but for now lets use the old
178 * trick of looking in the whole kernel symbol list.
178 */ 179 */
179 if ((long long)ip < 0) 180 if ((long long)ip < 0) {
180 dso = kernel_dso; 181 map = kernel_map;
182 goto got_map;
183 }
181 } 184 }
182 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 185 dump_printf(" ...... dso: %s\n",
183 186 map ? map->dso->long_name : "<not found>");
184 } else { 187 } else {
185 show = SHOW_HV; 188 show = SHOW_HV;
186 level = 'H'; 189 level = 'H';
@@ -188,12 +191,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
188 } 191 }
189 192
190 if (show & show_mask) { 193 if (show & show_mask) {
191 struct symbol *sym = NULL; 194 if (hist_entry__add(thread, map, sym, ip, level)) {
192
193 if (dso)
194 sym = dso->find_symbol(dso, ip);
195
196 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
197 fprintf(stderr, 195 fprintf(stderr,
198 "problem incrementing symbol count, skipping event\n"); 196 "problem incrementing symbol count, skipping event\n");
199 return -1; 197 return -1;
@@ -313,7 +311,7 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
313} 311}
314 312
315static int 313static int
316parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 314parse_line(FILE *file, struct symbol *sym, u64 len)
317{ 315{
318 char *line = NULL, *tmp, *tmp2; 316 char *line = NULL, *tmp, *tmp2;
319 static const char *prev_line; 317 static const char *prev_line;
@@ -363,7 +361,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
363 const char *color; 361 const char *color;
364 struct sym_ext *sym_ext = sym->priv; 362 struct sym_ext *sym_ext = sym->priv;
365 363
366 offset = line_ip - start; 364 offset = line_ip - sym->start;
367 if (offset < len) 365 if (offset < len)
368 hits = sym->hist[offset]; 366 hits = sym->hist[offset];
369 367
@@ -442,7 +440,7 @@ static void free_source_line(struct symbol *sym, int len)
442 440
443/* Get the filename:line for the colored entries */ 441/* Get the filename:line for the colored entries */
444static void 442static void
445get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 443get_source_line(struct symbol *sym, int len, const char *filename)
446{ 444{
447 int i; 445 int i;
448 char cmd[PATH_MAX * 2]; 446 char cmd[PATH_MAX * 2];
@@ -467,7 +465,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
467 if (sym_ext[i].percent <= 0.5) 465 if (sym_ext[i].percent <= 0.5)
468 continue; 466 continue;
469 467
470 offset = start + i; 468 offset = sym->start + i;
471 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 469 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
472 fp = popen(cmd, "r"); 470 fp = popen(cmd, "r");
473 if (!fp) 471 if (!fp)
@@ -519,31 +517,23 @@ static void print_summary(const char *filename)
519 517
520static void annotate_sym(struct dso *dso, struct symbol *sym) 518static void annotate_sym(struct dso *dso, struct symbol *sym)
521{ 519{
522 const char *filename = dso->name, *d_filename; 520 const char *filename = dso->long_name, *d_filename;
523 u64 start, end, len; 521 u64 len;
524 char command[PATH_MAX*2]; 522 char command[PATH_MAX*2];
525 FILE *file; 523 FILE *file;
526 524
527 if (!filename) 525 if (!filename)
528 return; 526 return;
529 if (sym->module) 527
530 filename = sym->module->path;
531 else if (dso == kernel_dso)
532 filename = vmlinux_name;
533
534 start = sym->obj_start;
535 if (!start)
536 start = sym->start;
537 if (full_paths) 528 if (full_paths)
538 d_filename = filename; 529 d_filename = filename;
539 else 530 else
540 d_filename = basename(filename); 531 d_filename = basename(filename);
541 532
542 end = start + sym->end - sym->start + 1;
543 len = sym->end - sym->start; 533 len = sym->end - sym->start;
544 534
545 if (print_line) { 535 if (print_line) {
546 get_source_line(sym, start, len, filename); 536 get_source_line(sym, len, filename);
547 print_summary(filename); 537 print_summary(filename);
548 } 538 }
549 539
@@ -552,10 +542,11 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
552 printf("------------------------------------------------\n"); 542 printf("------------------------------------------------\n");
553 543
554 if (verbose >= 2) 544 if (verbose >= 2)
555 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 545 printf("annotating [%p] %30s : [%p] %30s\n",
546 dso, dso->long_name, sym, sym->name);
556 547
557 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 548 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
558 (u64)start, (u64)end, filename, filename); 549 sym->start, sym->end, filename, filename);
559 550
560 if (verbose >= 3) 551 if (verbose >= 3)
561 printf("doing: %s\n", command); 552 printf("doing: %s\n", command);
@@ -565,7 +556,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
565 return; 556 return;
566 557
567 while (!feof(file)) { 558 while (!feof(file)) {
568 if (parse_line(file, sym, start, len) < 0) 559 if (parse_line(file, sym, len) < 0)
569 break; 560 break;
570 } 561 }
571 562
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c1a54fc8527a..3ed3baf96ffb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -349,22 +349,17 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
349 349
350 350
351static struct symbol * 351static struct symbol *
352resolve_symbol(struct thread *thread, struct map **mapp, 352resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
353 struct dso **dsop, u64 *ipp)
354{ 353{
355 struct dso *dso = dsop ? *dsop : NULL;
356 struct map *map = mapp ? *mapp : NULL; 354 struct map *map = mapp ? *mapp : NULL;
357 u64 ip = *ipp; 355 u64 ip = *ipp;
358 356
359 if (!thread)
360 return NULL;
361
362 if (dso)
363 goto got_dso;
364
365 if (map) 357 if (map)
366 goto got_map; 358 goto got_map;
367 359
360 if (!thread)
361 return NULL;
362
368 map = thread__find_map(thread, ip); 363 map = thread__find_map(thread, ip);
369 if (map != NULL) { 364 if (map != NULL) {
370 /* 365 /*
@@ -379,29 +374,29 @@ resolve_symbol(struct thread *thread, struct map **mapp,
379 *mapp = map; 374 *mapp = map;
380got_map: 375got_map:
381 ip = map->map_ip(map, ip); 376 ip = map->map_ip(map, ip);
382
383 dso = map->dso;
384 } else { 377 } else {
385 /* 378 /*
386 * If this is outside of all known maps, 379 * If this is outside of all known maps,
387 * and is a negative address, try to look it 380 * and is a negative address, try to look it
388 * up in the kernel dso, as it might be a 381 * up in the kernel dso, as it might be a
389 * vsyscall (which executes in user-mode): 382 * vsyscall or vdso (which executes in user-mode).
383 *
384 * XXX This is nasty, we should have a symbol list in
385 * the "[vdso]" dso, but for now lets use the old
386 * trick of looking in the whole kernel symbol list.
390 */ 387 */
391 if ((long long)ip < 0) 388 if ((long long)ip < 0) {
392 dso = kernel_dso; 389 map = kernel_map;
390 if (mapp)
391 *mapp = map;
392 }
393 } 393 }
394 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 394 dump_printf(" ...... dso: %s\n",
395 map ? map->dso->long_name : "<not found>");
395 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 396 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
396 *ipp = ip; 397 *ipp = ip;
397 398
398 if (dsop) 399 return map ? map->dso->find_symbol(map->dso, ip) : NULL;
399 *dsop = dso;
400
401 if (!dso)
402 return NULL;
403got_dso:
404 return dso->find_symbol(dso, ip);
405} 400}
406 401
407static int call__match(struct symbol *sym) 402static int call__match(struct symbol *sym)
@@ -413,7 +408,7 @@ static int call__match(struct symbol *sym)
413} 408}
414 409
415static struct symbol ** 410static struct symbol **
416resolve_callchain(struct thread *thread, struct map *map __used, 411resolve_callchain(struct thread *thread, struct map *map,
417 struct ip_callchain *chain, struct hist_entry *entry) 412 struct ip_callchain *chain, struct hist_entry *entry)
418{ 413{
419 u64 context = PERF_CONTEXT_MAX; 414 u64 context = PERF_CONTEXT_MAX;
@@ -430,8 +425,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
430 425
431 for (i = 0; i < chain->nr; i++) { 426 for (i = 0; i < chain->nr; i++) {
432 u64 ip = chain->ips[i]; 427 u64 ip = chain->ips[i];
433 struct dso *dso = NULL; 428 struct symbol *sym = NULL;
434 struct symbol *sym;
435 429
436 if (ip >= PERF_CONTEXT_MAX) { 430 if (ip >= PERF_CONTEXT_MAX) {
437 context = ip; 431 context = ip;
@@ -440,17 +434,15 @@ resolve_callchain(struct thread *thread, struct map *map __used,
440 434
441 switch (context) { 435 switch (context) {
442 case PERF_CONTEXT_HV: 436 case PERF_CONTEXT_HV:
443 dso = hypervisor_dso;
444 break; 437 break;
445 case PERF_CONTEXT_KERNEL: 438 case PERF_CONTEXT_KERNEL:
446 dso = kernel_dso; 439 sym = kernel_maps__find_symbol(ip, &map);
447 break; 440 break;
448 default: 441 default:
442 sym = resolve_symbol(thread, &map, &ip);
449 break; 443 break;
450 } 444 }
451 445
452 sym = resolve_symbol(thread, NULL, &dso, &ip);
453
454 if (sym) { 446 if (sym) {
455 if (sort__has_parent && call__match(sym) && 447 if (sort__has_parent && call__match(sym) &&
456 !entry->parent) 448 !entry->parent)
@@ -469,7 +461,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
469 */ 461 */
470 462
471static int 463static int
472hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 464hist_entry__add(struct thread *thread, struct map *map,
473 struct symbol *sym, u64 ip, struct ip_callchain *chain, 465 struct symbol *sym, u64 ip, struct ip_callchain *chain,
474 char level, u64 count) 466 char level, u64 count)
475{ 467{
@@ -480,7 +472,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
480 struct hist_entry entry = { 472 struct hist_entry entry = {
481 .thread = thread, 473 .thread = thread,
482 .map = map, 474 .map = map,
483 .dso = dso,
484 .sym = sym, 475 .sym = sym,
485 .ip = ip, 476 .ip = ip,
486 .level = level, 477 .level = level,
@@ -641,7 +632,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
641{ 632{
642 char level; 633 char level;
643 int show = 0; 634 int show = 0;
644 struct dso *dso = NULL; 635 struct symbol *sym = NULL;
645 struct thread *thread; 636 struct thread *thread;
646 u64 ip = event->ip.ip; 637 u64 ip = event->ip.ip;
647 u64 period = 1; 638 u64 period = 1;
@@ -700,35 +691,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
700 show = SHOW_KERNEL; 691 show = SHOW_KERNEL;
701 level = 'k'; 692 level = 'k';
702 693
703 dso = kernel_dso; 694 sym = kernel_maps__find_symbol(ip, &map);
704 695 dump_printf(" ...... dso: %s\n",
705 dump_printf(" ...... dso: %s\n", dso->name); 696 map ? map->dso->long_name : "<not found>");
706
707 } else if (cpumode == PERF_RECORD_MISC_USER) { 697 } else if (cpumode == PERF_RECORD_MISC_USER) {
708 698
709 show = SHOW_USER; 699 show = SHOW_USER;
710 level = '.'; 700 level = '.';
701 sym = resolve_symbol(thread, &map, &ip);
711 702
712 } else { 703 } else {
713 show = SHOW_HV; 704 show = SHOW_HV;
714 level = 'H'; 705 level = 'H';
715 706
716 dso = hypervisor_dso;
717
718 dump_printf(" ...... dso: [hypervisor]\n"); 707 dump_printf(" ...... dso: [hypervisor]\n");
719 } 708 }
720 709
721 if (show & show_mask) { 710 if (show & show_mask) {
722 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 711 if (dso_list &&
723 712 (!map || !map->dso ||
724 if (dso_list && (!dso || !dso->name || 713 !(strlist__has_entry(dso_list, map->dso->short_name) ||
725 !strlist__has_entry(dso_list, dso->name))) 714 (map->dso->short_name != map->dso->long_name &&
715 strlist__has_entry(dso_list, map->dso->long_name)))))
726 return 0; 716 return 0;
727 717
728 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name))) 718 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
729 return 0; 719 return 0;
730 720
731 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 721 if (hist_entry__add(thread, map, sym, ip,
722 chain, level, period)) {
732 eprintf("problem incrementing symbol count, skipping event\n"); 723 eprintf("problem incrementing symbol count, skipping event\n");
733 return -1; 724 return -1;
734 } 725 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bf464ce7e3e2..befef842757e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -103,6 +104,7 @@ struct sym_entry {
103 unsigned long snap_count; 104 unsigned long snap_count;
104 double weight; 105 double weight;
105 int skip; 106 int skip;
107 struct map *map;
106 struct source_line *source; 108 struct source_line *source;
107 struct source_line *lines; 109 struct source_line *lines;
108 struct source_line **lines_tail; 110 struct source_line **lines_tail;
@@ -116,12 +118,11 @@ struct sym_entry {
116static void parse_source(struct sym_entry *syme) 118static void parse_source(struct sym_entry *syme)
117{ 119{
118 struct symbol *sym; 120 struct symbol *sym;
119 struct module *module; 121 struct map *map;
120 struct section *section = NULL;
121 FILE *file; 122 FILE *file;
122 char command[PATH_MAX*2]; 123 char command[PATH_MAX*2];
123 const char *path = vmlinux_name; 124 const char *path;
124 u64 start, end, len; 125 u64 len;
125 126
126 if (!syme) 127 if (!syme)
127 return; 128 return;
@@ -132,27 +133,15 @@ static void parse_source(struct sym_entry *syme)
132 } 133 }
133 134
134 sym = (struct symbol *)(syme + 1); 135 sym = (struct symbol *)(syme + 1);
135 module = sym->module; 136 map = syme->map;
137 path = map->dso->long_name;
136 138
137 if (module)
138 path = module->path;
139 if (!path)
140 return;
141
142 start = sym->obj_start;
143 if (!start)
144 start = sym->start;
145
146 if (module) {
147 section = module->sections->find_section(module->sections, ".text");
148 if (section)
149 start -= section->vma;
150 }
151
152 end = start + sym->end - sym->start + 1;
153 len = sym->end - sym->start; 139 len = sym->end - sym->start;
154 140
155 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 141 sprintf(command,
142 "objdump --start-address=0x%016Lx "
143 "--stop-address=0x%016Lx -dS %s",
144 sym->start, sym->end, path);
156 145
157 file = popen(command, "r"); 146 file = popen(command, "r");
158 if (!file) 147 if (!file)
@@ -184,13 +173,11 @@ static void parse_source(struct sym_entry *syme)
184 173
185 if (strlen(src->line)>8 && src->line[8] == ':') { 174 if (strlen(src->line)>8 && src->line[8] == ':') {
186 src->eip = strtoull(src->line, NULL, 16); 175 src->eip = strtoull(src->line, NULL, 16);
187 if (section) 176 src->eip += map->start;
188 src->eip += section->vma;
189 } 177 }
190 if (strlen(src->line)>8 && src->line[16] == ':') { 178 if (strlen(src->line)>8 && src->line[16] == ':') {
191 src->eip = strtoull(src->line, NULL, 16); 179 src->eip = strtoull(src->line, NULL, 16);
192 if (section) 180 src->eip += map->start;
193 src->eip += section->vma;
194 } 181 }
195 } 182 }
196 pclose(file); 183 pclose(file);
@@ -242,16 +229,9 @@ static void lookup_sym_source(struct sym_entry *syme)
242 struct symbol *symbol = (struct symbol *)(syme + 1); 229 struct symbol *symbol = (struct symbol *)(syme + 1);
243 struct source_line *line; 230 struct source_line *line;
244 char pattern[PATH_MAX]; 231 char pattern[PATH_MAX];
245 char *idx;
246 232
247 sprintf(pattern, "<%s>:", symbol->name); 233 sprintf(pattern, "<%s>:", symbol->name);
248 234
249 if (symbol->module) {
250 idx = strstr(pattern, "\t");
251 if (idx)
252 *idx = 0;
253 }
254
255 pthread_mutex_lock(&syme->source_lock); 235 pthread_mutex_lock(&syme->source_lock);
256 for (line = syme->lines; line; line = line->next) { 236 for (line = syme->lines; line; line = line->next) {
257 if (strstr(line->line, pattern)) { 237 if (strstr(line->line, pattern)) {
@@ -513,8 +493,8 @@ static void print_sym_table(void)
513 if (verbose) 493 if (verbose)
514 printf(" - %016llx", sym->start); 494 printf(" - %016llx", sym->start);
515 printf(" : %s", sym->name); 495 printf(" : %s", sym->name);
516 if (sym->module) 496 if (syme->map->dso->name[0] == '[')
517 printf("\t[%s]", sym->module->name); 497 printf(" \t%s", syme->map->dso->name);
518 printf("\n"); 498 printf("\n");
519 } 499 }
520} 500}
@@ -784,7 +764,7 @@ static const char *skip_symbols[] = {
784 NULL 764 NULL
785}; 765};
786 766
787static int symbol_filter(struct dso *self, struct symbol *sym) 767static int symbol_filter(struct map *map, struct symbol *sym)
788{ 768{
789 struct sym_entry *syme; 769 struct sym_entry *syme;
790 const char *name = sym->name; 770 const char *name = sym->name;
@@ -806,7 +786,8 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
806 strstr(name, "_text_end")) 786 strstr(name, "_text_end"))
807 return 1; 787 return 1;
808 788
809 syme = dso__sym_priv(self, sym); 789 syme = dso__sym_priv(map->dso, sym);
790 syme->map = map;
810 pthread_mutex_init(&syme->source_lock, NULL); 791 pthread_mutex_init(&syme->source_lock, NULL);
811 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 792 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
812 sym_filter_entry = syme; 793 sym_filter_entry = syme;
@@ -825,22 +806,14 @@ static int parse_symbols(void)
825{ 806{
826 int use_modules = vmlinux_name ? 1 : 0; 807 int use_modules = vmlinux_name ? 1 : 0;
827 808
828 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 809 if (dsos__load_kernel(vmlinux_name, sizeof(struct sym_entry),
829 if (kernel_dso == NULL) 810 symbol_filter, verbose, use_modules) <= 0)
830 return -1; 811 return -1;
831 812
832 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
833 goto out_delete_dso;
834
835 if (dump_symtab) 813 if (dump_symtab)
836 dso__fprintf(kernel_dso, stderr); 814 dsos__fprintf(stderr);
837 815
838 return 0; 816 return 0;
839
840out_delete_dso:
841 dso__delete(kernel_dso);
842 kernel_dso = NULL;
843 return -1;
844} 817}
845 818
846/* 819/*
@@ -848,10 +821,11 @@ out_delete_dso:
848 */ 821 */
849static void record_ip(u64 ip, int counter) 822static void record_ip(u64 ip, int counter)
850{ 823{
851 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 824 struct map *map;
825 struct symbol *sym = kernel_maps__find_symbol(ip, &map);
852 826
853 if (sym != NULL) { 827 if (sym != NULL) {
854 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 828 struct sym_entry *syme = dso__sym_priv(map->dso, sym);
855 829
856 if (!syme->skip) { 830 if (!syme->skip) {
857 syme->count[counter]++; 831 syme->count[counter]++;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 4c69eb553807..a39520e6ae8f 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -3,6 +3,7 @@
3 3
4#include "../perf.h" 4#include "../perf.h"
5#include "util.h" 5#include "util.h"
6#include <linux/list.h>
6#include <linux/rbtree.h> 7#include <linux/rbtree.h>
7 8
8enum { 9enum {
@@ -79,7 +80,10 @@ typedef union event_union {
79} event_t; 80} event_t;
80 81
81struct map { 82struct map {
82 struct rb_node rb_node; 83 union {
84 struct rb_node rb_node;
85 struct list_head node;
86 };
83 u64 start; 87 u64 start;
84 u64 end; 88 u64 end;
85 u64 pgoff; 89 u64 pgoff;
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
deleted file mode 100644
index 0d8c85defcd2..000000000000
--- a/tools/perf/util/module.c
+++ /dev/null
@@ -1,545 +0,0 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <libgen.h>
8#include <gelf.h>
9#include <elf.h>
10#include <dirent.h>
11#include <sys/utsname.h>
12
13static unsigned int crc32(const char *p, unsigned int len)
14{
15 int i;
16 unsigned int crc = 0;
17
18 while (len--) {
19 crc ^= *p++;
20 for (i = 0; i < 8; i++)
21 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
22 }
23 return crc;
24}
25
26/* module section methods */
27
28struct sec_dso *sec_dso__new_dso(const char *name)
29{
30 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
31
32 if (self != NULL) {
33 strcpy(self->name, name);
34 self->secs = RB_ROOT;
35 self->find_section = sec_dso__find_section;
36 }
37
38 return self;
39}
40
41static void sec_dso__delete_section(struct section *self)
42{
43 free(((void *)self));
44}
45
46void sec_dso__delete_sections(struct sec_dso *self)
47{
48 struct section *pos;
49 struct rb_node *next = rb_first(&self->secs);
50
51 while (next) {
52 pos = rb_entry(next, struct section, rb_node);
53 next = rb_next(&pos->rb_node);
54 rb_erase(&pos->rb_node, &self->secs);
55 sec_dso__delete_section(pos);
56 }
57}
58
59void sec_dso__delete_self(struct sec_dso *self)
60{
61 sec_dso__delete_sections(self);
62 free(self);
63}
64
65static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
66{
67 struct rb_node **p = &self->secs.rb_node;
68 struct rb_node *parent = NULL;
69 const u64 hash = sec->hash;
70 struct section *s;
71
72 while (*p != NULL) {
73 parent = *p;
74 s = rb_entry(parent, struct section, rb_node);
75 if (hash < s->hash)
76 p = &(*p)->rb_left;
77 else
78 p = &(*p)->rb_right;
79 }
80 rb_link_node(&sec->rb_node, parent, p);
81 rb_insert_color(&sec->rb_node, &self->secs);
82}
83
84struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
85{
86 struct rb_node *n;
87 u64 hash;
88 int len;
89
90 if (self == NULL)
91 return NULL;
92
93 len = strlen(name);
94 hash = crc32(name, len);
95
96 n = self->secs.rb_node;
97
98 while (n) {
99 struct section *s = rb_entry(n, struct section, rb_node);
100
101 if (hash < s->hash)
102 n = n->rb_left;
103 else if (hash > s->hash)
104 n = n->rb_right;
105 else {
106 if (!strcmp(name, s->name))
107 return s;
108 else
109 n = rb_next(&s->rb_node);
110 }
111 }
112
113 return NULL;
114}
115
116static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
117{
118 return fprintf(fp, "name:%s vma:%llx path:%s\n",
119 self->name, self->vma, self->path);
120}
121
122size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
123{
124 size_t ret = fprintf(fp, "dso: %s\n", self->name);
125
126 struct rb_node *nd;
127 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
128 struct section *pos = rb_entry(nd, struct section, rb_node);
129 ret += sec_dso__fprintf_section(pos, fp);
130 }
131
132 return ret;
133}
134
135static struct section *section__new(const char *name, const char *path)
136{
137 struct section *self = calloc(1, sizeof(*self));
138
139 if (!self)
140 goto out_failure;
141
142 self->name = calloc(1, strlen(name) + 1);
143 if (!self->name)
144 goto out_failure;
145
146 self->path = calloc(1, strlen(path) + 1);
147 if (!self->path)
148 goto out_failure;
149
150 strcpy(self->name, name);
151 strcpy(self->path, path);
152 self->hash = crc32(self->name, strlen(name));
153
154 return self;
155
156out_failure:
157 if (self) {
158 if (self->name)
159 free(self->name);
160 if (self->path)
161 free(self->path);
162 free(self);
163 }
164
165 return NULL;
166}
167
168/* module methods */
169
170struct mod_dso *mod_dso__new_dso(const char *name)
171{
172 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
173
174 if (self != NULL) {
175 strcpy(self->name, name);
176 self->mods = RB_ROOT;
177 self->find_module = mod_dso__find_module;
178 }
179
180 return self;
181}
182
183static void mod_dso__delete_module(struct module *self)
184{
185 free(((void *)self));
186}
187
188void mod_dso__delete_modules(struct mod_dso *self)
189{
190 struct module *pos;
191 struct rb_node *next = rb_first(&self->mods);
192
193 while (next) {
194 pos = rb_entry(next, struct module, rb_node);
195 next = rb_next(&pos->rb_node);
196 rb_erase(&pos->rb_node, &self->mods);
197 mod_dso__delete_module(pos);
198 }
199}
200
201void mod_dso__delete_self(struct mod_dso *self)
202{
203 mod_dso__delete_modules(self);
204 free(self);
205}
206
207static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
208{
209 struct rb_node **p = &self->mods.rb_node;
210 struct rb_node *parent = NULL;
211 const u64 hash = mod->hash;
212 struct module *m;
213
214 while (*p != NULL) {
215 parent = *p;
216 m = rb_entry(parent, struct module, rb_node);
217 if (hash < m->hash)
218 p = &(*p)->rb_left;
219 else
220 p = &(*p)->rb_right;
221 }
222 rb_link_node(&mod->rb_node, parent, p);
223 rb_insert_color(&mod->rb_node, &self->mods);
224}
225
226struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
227{
228 struct rb_node *n;
229 u64 hash;
230 int len;
231
232 if (self == NULL)
233 return NULL;
234
235 len = strlen(name);
236 hash = crc32(name, len);
237
238 n = self->mods.rb_node;
239
240 while (n) {
241 struct module *m = rb_entry(n, struct module, rb_node);
242
243 if (hash < m->hash)
244 n = n->rb_left;
245 else if (hash > m->hash)
246 n = n->rb_right;
247 else {
248 if (!strcmp(name, m->name))
249 return m;
250 else
251 n = rb_next(&m->rb_node);
252 }
253 }
254
255 return NULL;
256}
257
258static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
259{
260 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
261}
262
263size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
264{
265 struct rb_node *nd;
266 size_t ret;
267
268 ret = fprintf(fp, "dso: %s\n", self->name);
269
270 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
271 struct module *pos = rb_entry(nd, struct module, rb_node);
272
273 ret += mod_dso__fprintf_module(pos, fp);
274 }
275
276 return ret;
277}
278
279static struct module *module__new(const char *name, const char *path)
280{
281 struct module *self = calloc(1, sizeof(*self));
282
283 if (!self)
284 goto out_failure;
285
286 self->name = calloc(1, strlen(name) + 1);
287 if (!self->name)
288 goto out_failure;
289
290 self->path = calloc(1, strlen(path) + 1);
291 if (!self->path)
292 goto out_failure;
293
294 strcpy(self->name, name);
295 strcpy(self->path, path);
296 self->hash = crc32(self->name, strlen(name));
297
298 return self;
299
300out_failure:
301 if (self) {
302 if (self->name)
303 free(self->name);
304 if (self->path)
305 free(self->path);
306 free(self);
307 }
308
309 return NULL;
310}
311
312static int mod_dso__load_sections(struct module *mod)
313{
314 int count = 0, path_len;
315 struct dirent *entry;
316 char *line = NULL;
317 char *dir_path;
318 DIR *dir;
319 size_t n;
320
321 path_len = strlen("/sys/module/");
322 path_len += strlen(mod->name);
323 path_len += strlen("/sections/");
324
325 dir_path = calloc(1, path_len + 1);
326 if (dir_path == NULL)
327 goto out_failure;
328
329 strcat(dir_path, "/sys/module/");
330 strcat(dir_path, mod->name);
331 strcat(dir_path, "/sections/");
332
333 dir = opendir(dir_path);
334 if (dir == NULL)
335 goto out_free;
336
337 while ((entry = readdir(dir))) {
338 struct section *section;
339 char *path, *vma;
340 int line_len;
341 FILE *file;
342
343 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
344 continue;
345
346 path = calloc(1, path_len + strlen(entry->d_name) + 1);
347 if (path == NULL)
348 break;
349 strcat(path, dir_path);
350 strcat(path, entry->d_name);
351
352 file = fopen(path, "r");
353 if (file == NULL) {
354 free(path);
355 break;
356 }
357
358 line_len = getline(&line, &n, file);
359 if (line_len < 0) {
360 free(path);
361 fclose(file);
362 break;
363 }
364
365 if (!line) {
366 free(path);
367 fclose(file);
368 break;
369 }
370
371 line[--line_len] = '\0'; /* \n */
372
373 vma = strstr(line, "0x");
374 if (!vma) {
375 free(path);
376 fclose(file);
377 break;
378 }
379 vma += 2;
380
381 section = section__new(entry->d_name, path);
382 if (!section) {
383 fprintf(stderr, "load_sections: allocation error\n");
384 free(path);
385 fclose(file);
386 break;
387 }
388
389 hex2u64(vma, &section->vma);
390 sec_dso__insert_section(mod->sections, section);
391
392 free(path);
393 fclose(file);
394 count++;
395 }
396
397 closedir(dir);
398 free(line);
399 free(dir_path);
400
401 return count;
402
403out_free:
404 free(dir_path);
405
406out_failure:
407 return count;
408}
409
410static int mod_dso__load_module_paths(struct mod_dso *self)
411{
412 struct utsname uts;
413 int count = 0, len, err = -1;
414 char *line = NULL;
415 FILE *file;
416 char *dpath, *dir;
417 size_t n;
418
419 if (uname(&uts) < 0)
420 return err;
421
422 len = strlen("/lib/modules/");
423 len += strlen(uts.release);
424 len += strlen("/modules.dep");
425
426 dpath = calloc(1, len + 1);
427 if (dpath == NULL)
428 return err;
429
430 strcat(dpath, "/lib/modules/");
431 strcat(dpath, uts.release);
432 strcat(dpath, "/modules.dep");
433
434 file = fopen(dpath, "r");
435 if (file == NULL)
436 goto out_failure;
437
438 dir = dirname(dpath);
439 if (!dir)
440 goto out_failure;
441 strcat(dir, "/");
442
443 while (!feof(file)) {
444 struct module *module;
445 char *name, *path, *tmp;
446 FILE *modfile;
447 int line_len;
448
449 line_len = getline(&line, &n, file);
450 if (line_len < 0)
451 break;
452
453 if (!line)
454 break;
455
456 line[--line_len] = '\0'; /* \n */
457
458 path = strchr(line, ':');
459 if (!path)
460 break;
461 *path = '\0';
462
463 path = strdup(line);
464 if (!path)
465 break;
466
467 if (!strstr(path, dir)) {
468 if (strncmp(path, "kernel/", 7))
469 break;
470
471 free(path);
472 path = calloc(1, strlen(dir) + strlen(line) + 1);
473 if (!path)
474 break;
475 strcat(path, dir);
476 strcat(path, line);
477 }
478
479 modfile = fopen(path, "r");
480 if (modfile == NULL)
481 break;
482 fclose(modfile);
483
484 name = strdup(path);
485 if (!name)
486 break;
487
488 name = strtok(name, "/");
489 tmp = name;
490
491 while (tmp) {
492 tmp = strtok(NULL, "/");
493 if (tmp)
494 name = tmp;
495 }
496
497 name = strsep(&name, ".");
498 if (!name)
499 break;
500
501 /* Quirk: replace '-' with '_' in all modules */
502 for (len = strlen(name); len; len--) {
503 if (*(name+len) == '-')
504 *(name+len) = '_';
505 }
506
507 module = module__new(name, path);
508 if (!module)
509 break;
510 mod_dso__insert_module(self, module);
511
512 module->sections = sec_dso__new_dso("sections");
513 if (!module->sections)
514 break;
515
516 module->active = mod_dso__load_sections(module);
517
518 if (module->active > 0)
519 count++;
520 }
521
522 if (feof(file))
523 err = count;
524 else
525 fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n");
526
527out_failure:
528 if (dpath)
529 free(dpath);
530 if (file)
531 fclose(file);
532 if (line)
533 free(line);
534
535 return err;
536}
537
538int mod_dso__load_modules(struct mod_dso *dso)
539{
540 int err;
541
542 err = mod_dso__load_module_paths(dso);
543
544 return err;
545}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
deleted file mode 100644
index 098e0412bc22..000000000000
--- a/tools/perf/util/module.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef __PERF_MODULE_
2#define __PERF_MODULE_ 1
3
4#include <linux/types.h>
5#include "../types.h"
6#include <linux/list.h>
7#include <linux/rbtree.h>
8
9struct section {
10 struct rb_node rb_node;
11 u64 hash;
12 u64 vma;
13 char *name;
14 char *path;
15};
16
17struct sec_dso {
18 struct list_head node;
19 struct rb_root secs;
20 struct section *(*find_section)(struct sec_dso *, const char *name);
21 char name[0];
22};
23
24struct module {
25 struct rb_node rb_node;
26 u64 hash;
27 char *name;
28 char *path;
29 struct sec_dso *sections;
30 int active;
31};
32
33struct mod_dso {
34 struct list_head node;
35 struct rb_root mods;
36 struct module *(*find_module)(struct mod_dso *, const char *name);
37 char name[0];
38};
39
40struct sec_dso *sec_dso__new_dso(const char *name);
41void sec_dso__delete_sections(struct sec_dso *self);
42void sec_dso__delete_self(struct sec_dso *self);
43size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
44struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
45
46struct mod_dso *mod_dso__new_dso(const char *name);
47void mod_dso__delete_modules(struct mod_dso *self);
48void mod_dso__delete_self(struct mod_dso *self);
49size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
50struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
51int mod_dso__load_modules(struct mod_dso *dso);
52
53#endif /* __PERF_MODULE_ */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 50e75abb1fdd..40c9acd41cad 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -129,20 +129,32 @@ sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
129int64_t 129int64_t
130sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 130sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
131{ 131{
132 struct dso *dso_l = left->dso; 132 struct dso *dso_l = left->map ? left->map->dso : NULL;
133 struct dso *dso_r = right->dso; 133 struct dso *dso_r = right->map ? right->map->dso : NULL;
134 const char *dso_name_l, *dso_name_r;
134 135
135 if (!dso_l || !dso_r) 136 if (!dso_l || !dso_r)
136 return cmp_null(dso_l, dso_r); 137 return cmp_null(dso_l, dso_r);
137 138
138 return strcmp(dso_l->name, dso_r->name); 139 if (verbose) {
140 dso_name_l = dso_l->long_name;
141 dso_name_r = dso_r->long_name;
142 } else {
143 dso_name_l = dso_l->short_name;
144 dso_name_r = dso_r->short_name;
145 }
146
147 return strcmp(dso_name_l, dso_name_r);
139} 148}
140 149
141size_t 150size_t
142sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) 151sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
143{ 152{
144 if (self->dso) 153 if (self->map && self->map->dso) {
145 return repsep_fprintf(fp, "%-*s", width, self->dso->name); 154 const char *dso_name = !verbose ? self->map->dso->short_name :
155 self->map->dso->long_name;
156 return repsep_fprintf(fp, "%-*s", width, dso_name);
157 }
146 158
147 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip); 159 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
148} 160}
@@ -169,20 +181,16 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
169{ 181{
170 size_t ret = 0; 182 size_t ret = 0;
171 183
172 if (verbose) 184 if (verbose) {
173 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, 185 char o = self->map ? dso__symtab_origin(self->map->dso) : '!';
174 dso__symtab_origin(self->dso)); 186 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
187 }
175 188
176 ret += repsep_fprintf(fp, "[%c] ", self->level); 189 ret += repsep_fprintf(fp, "[%c] ", self->level);
177 if (self->sym) { 190 if (self->sym)
178 ret += repsep_fprintf(fp, "%s", self->sym->name); 191 ret += repsep_fprintf(fp, "%s", self->sym->name);
179 192 else
180 if (self->sym->module)
181 ret += repsep_fprintf(fp, "\t[%s]",
182 self->sym->module->name);
183 } else {
184 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); 193 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
185 }
186 194
187 return ret; 195 return ret;
188} 196}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 4684fd6d5c4a..13806d782af6 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -42,18 +42,15 @@ extern unsigned int threads__col_width;
42 42
43struct hist_entry { 43struct hist_entry {
44 struct rb_node rb_node; 44 struct rb_node rb_node;
45 45 u64 count;
46 struct thread *thread; 46 struct thread *thread;
47 struct map *map; 47 struct map *map;
48 struct dso *dso;
49 struct symbol *sym; 48 struct symbol *sym;
50 struct symbol *parent;
51 u64 ip; 49 u64 ip;
52 char level; 50 char level;
51 struct symbol *parent;
53 struct callchain_node callchain; 52 struct callchain_node callchain;
54 struct rb_root sorted_chain; 53 struct rb_root sorted_chain;
55
56 u64 count;
57}; 54};
58 55
59/* 56/*
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 559fb06210f5..e88296899470 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2,12 +2,14 @@
2#include "../perf.h" 2#include "../perf.h"
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5#include "thread.h"
5 6
6#include "debug.h" 7#include "debug.h"
7 8
8#include <libelf.h> 9#include <libelf.h>
9#include <gelf.h> 10#include <gelf.h>
10#include <elf.h> 11#include <elf.h>
12#include <sys/utsname.h>
11 13
12const char *sym_hist_filter; 14const char *sym_hist_filter;
13 15
@@ -18,12 +20,15 @@ enum dso_origin {
18 DSO__ORIG_UBUNTU, 20 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID, 21 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO, 22 DSO__ORIG_DSO,
23 DSO__ORIG_KMODULE,
21 DSO__ORIG_NOT_FOUND, 24 DSO__ORIG_NOT_FOUND,
22}; 25};
23 26
24static struct symbol *symbol__new(u64 start, u64 len, 27static void dsos__add(struct dso *dso);
25 const char *name, unsigned int priv_size, 28static struct dso *dsos__find(const char *name);
26 u64 obj_start, int v) 29
30static struct symbol *symbol__new(u64 start, u64 len, const char *name,
31 unsigned int priv_size, int v)
27{ 32{
28 size_t namelen = strlen(name) + 1; 33 size_t namelen = strlen(name) + 1;
29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 34 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -32,10 +37,9 @@ static struct symbol *symbol__new(u64 start, u64 len,
32 return NULL; 37 return NULL;
33 38
34 if (v >= 2) 39 if (v >= 2)
35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 40 printf("new symbol: %016Lx [%08lx]: %s, hist: %p\n",
36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 41 start, (unsigned long)len, name, self->hist);
37 42
38 self->obj_start= obj_start;
39 self->hist = NULL; 43 self->hist = NULL;
40 self->hist_sum = 0; 44 self->hist_sum = 0;
41 45
@@ -60,12 +64,8 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
60 64
61static size_t symbol__fprintf(struct symbol *self, FILE *fp) 65static size_t symbol__fprintf(struct symbol *self, FILE *fp)
62{ 66{
63 if (!self->module) 67 return fprintf(fp, " %llx-%llx %s\n",
64 return fprintf(fp, " %llx-%llx %s\n",
65 self->start, self->end, self->name); 68 self->start, self->end, self->name);
66 else
67 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
68 self->start, self->end, self->name, self->module->name);
69} 69}
70 70
71struct dso *dso__new(const char *name, unsigned int sym_priv_size) 71struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -74,6 +74,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
74 74
75 if (self != NULL) { 75 if (self != NULL) {
76 strcpy(self->name, name); 76 strcpy(self->name, name);
77 self->long_name = self->name;
78 self->short_name = self->name;
77 self->syms = RB_ROOT; 79 self->syms = RB_ROOT;
78 self->sym_priv_size = sym_priv_size; 80 self->sym_priv_size = sym_priv_size;
79 self->find_symbol = dso__find_symbol; 81 self->find_symbol = dso__find_symbol;
@@ -100,6 +102,8 @@ static void dso__delete_symbols(struct dso *self)
100void dso__delete(struct dso *self) 102void dso__delete(struct dso *self)
101{ 103{
102 dso__delete_symbols(self); 104 dso__delete_symbols(self);
105 if (self->long_name != self->name)
106 free(self->long_name);
103 free(self); 107 free(self);
104} 108}
105 109
@@ -147,7 +151,7 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
147 151
148size_t dso__fprintf(struct dso *self, FILE *fp) 152size_t dso__fprintf(struct dso *self, FILE *fp)
149{ 153{
150 size_t ret = fprintf(fp, "dso: %s\n", self->name); 154 size_t ret = fprintf(fp, "dso: %s\n", self->long_name);
151 155
152 struct rb_node *nd; 156 struct rb_node *nd;
153 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 157 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
@@ -158,7 +162,8 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
158 return ret; 162 return ret;
159} 163}
160 164
161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) 165static int dso__load_kallsyms(struct dso *self, struct map *map,
166 symbol_filter_t filter, int v)
162{ 167{
163 struct rb_node *nd, *prevnd; 168 struct rb_node *nd, *prevnd;
164 char *line = NULL; 169 char *line = NULL;
@@ -200,12 +205,12 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
200 * Well fix up the end later, when we have all sorted. 205 * Well fix up the end later, when we have all sorted.
201 */ 206 */
202 sym = symbol__new(start, 0xdead, line + len + 2, 207 sym = symbol__new(start, 0xdead, line + len + 2,
203 self->sym_priv_size, 0, v); 208 self->sym_priv_size, v);
204 209
205 if (sym == NULL) 210 if (sym == NULL)
206 goto out_delete_line; 211 goto out_delete_line;
207 212
208 if (filter && filter(self, sym)) 213 if (filter && filter(map, sym))
209 symbol__delete(sym, self->sym_priv_size); 214 symbol__delete(sym, self->sym_priv_size);
210 else { 215 else {
211 dso__insert_symbol(self, sym); 216 dso__insert_symbol(self, sym);
@@ -241,14 +246,15 @@ out_failure:
241 return -1; 246 return -1;
242} 247}
243 248
244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) 249static int dso__load_perf_map(struct dso *self, struct map *map,
250 symbol_filter_t filter, int v)
245{ 251{
246 char *line = NULL; 252 char *line = NULL;
247 size_t n; 253 size_t n;
248 FILE *file; 254 FILE *file;
249 int nr_syms = 0; 255 int nr_syms = 0;
250 256
251 file = fopen(self->name, "r"); 257 file = fopen(self->long_name, "r");
252 if (file == NULL) 258 if (file == NULL)
253 goto out_failure; 259 goto out_failure;
254 260
@@ -279,12 +285,12 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
279 continue; 285 continue;
280 286
281 sym = symbol__new(start, size, line + len, 287 sym = symbol__new(start, size, line + len,
282 self->sym_priv_size, start, v); 288 self->sym_priv_size, v);
283 289
284 if (sym == NULL) 290 if (sym == NULL)
285 goto out_delete_line; 291 goto out_delete_line;
286 292
287 if (filter && filter(self, sym)) 293 if (filter && filter(map, sym))
288 symbol__delete(sym, self->sym_priv_size); 294 symbol__delete(sym, self->sym_priv_size);
289 else { 295 else {
290 dso__insert_symbol(self, sym); 296 dso__insert_symbol(self, sym);
@@ -410,7 +416,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
410 Elf *elf; 416 Elf *elf;
411 int nr = 0, symidx, fd, err = 0; 417 int nr = 0, symidx, fd, err = 0;
412 418
413 fd = open(self->name, O_RDONLY); 419 fd = open(self->long_name, O_RDONLY);
414 if (fd < 0) 420 if (fd < 0)
415 goto out; 421 goto out;
416 422
@@ -478,7 +484,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
478 "%s@plt", elf_sym__name(&sym, symstrs)); 484 "%s@plt", elf_sym__name(&sym, symstrs));
479 485
480 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 486 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
481 sympltname, self->sym_priv_size, 0, v); 487 sympltname, self->sym_priv_size, v);
482 if (!f) 488 if (!f)
483 goto out_elf_end; 489 goto out_elf_end;
484 490
@@ -496,7 +502,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
496 "%s@plt", elf_sym__name(&sym, symstrs)); 502 "%s@plt", elf_sym__name(&sym, symstrs));
497 503
498 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 504 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
499 sympltname, self->sym_priv_size, 0, v); 505 sympltname, self->sym_priv_size, v);
500 if (!f) 506 if (!f)
501 goto out_elf_end; 507 goto out_elf_end;
502 508
@@ -515,12 +521,13 @@ out_close:
515 return nr; 521 return nr;
516out: 522out:
517 fprintf(stderr, "%s: problems reading %s PLT info.\n", 523 fprintf(stderr, "%s: problems reading %s PLT info.\n",
518 __func__, self->name); 524 __func__, self->long_name);
519 return 0; 525 return 0;
520} 526}
521 527
522static int dso__load_sym(struct dso *self, int fd, const char *name, 528static int dso__load_sym(struct dso *self, struct map *map, const char *name,
523 symbol_filter_t filter, int v, struct module *mod) 529 int fd, symbol_filter_t filter, int kernel,
530 int kmodule, int v)
524{ 531{
525 Elf_Data *symstrs, *secstrs; 532 Elf_Data *symstrs, *secstrs;
526 uint32_t nr_syms; 533 uint32_t nr_syms;
@@ -532,7 +539,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
532 GElf_Sym sym; 539 GElf_Sym sym;
533 Elf_Scn *sec, *sec_strndx; 540 Elf_Scn *sec, *sec_strndx;
534 Elf *elf; 541 Elf *elf;
535 int nr = 0, kernel = !strcmp("[kernel]", self->name); 542 int nr = 0;
536 543
537 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 544 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
538 if (elf == NULL) { 545 if (elf == NULL) {
@@ -589,8 +596,6 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
589 struct symbol *f; 596 struct symbol *f;
590 const char *elf_name; 597 const char *elf_name;
591 char *demangled; 598 char *demangled;
592 u64 obj_start;
593 struct section *section = NULL;
594 int is_label = elf_sym__is_label(&sym); 599 int is_label = elf_sym__is_label(&sym);
595 const char *section_name; 600 const char *section_name;
596 601
@@ -607,7 +612,6 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
607 continue; 612 continue;
608 613
609 section_name = elf_sec__name(&shdr, secstrs); 614 section_name = elf_sec__name(&shdr, secstrs);
610 obj_start = sym.st_value;
611 615
612 if (self->adjust_symbols) { 616 if (self->adjust_symbols) {
613 if (v >= 2) 617 if (v >= 2)
@@ -615,18 +619,8 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
615 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 619 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
616 620
617 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 621 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
618 } 622 } else if (kmodule)
619 623 sym.st_value += shdr.sh_offset;
620 if (mod) {
621 section = mod->sections->find_section(mod->sections, section_name);
622 if (section)
623 sym.st_value += section->vma;
624 else {
625 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
626 mod->name, section_name);
627 goto out_elf_end;
628 }
629 }
630 /* 624 /*
631 * We need to figure out if the object was created from C++ sources 625 * We need to figure out if the object was created from C++ sources
632 * DWARF DW_compile_unit has this, but we don't always have access 626 * DWARF DW_compile_unit has this, but we don't always have access
@@ -638,15 +632,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
638 elf_name = demangled; 632 elf_name = demangled;
639 633
640 f = symbol__new(sym.st_value, sym.st_size, elf_name, 634 f = symbol__new(sym.st_value, sym.st_size, elf_name,
641 self->sym_priv_size, obj_start, v); 635 self->sym_priv_size, v);
642 free(demangled); 636 free(demangled);
643 if (!f) 637 if (!f)
644 goto out_elf_end; 638 goto out_elf_end;
645 639
646 if (filter && filter(self, f)) 640 if (filter && filter(map, f))
647 symbol__delete(f, self->sym_priv_size); 641 symbol__delete(f, self->sym_priv_size);
648 else { 642 else {
649 f->module = mod;
650 dso__insert_symbol(self, f); 643 dso__insert_symbol(self, f);
651 nr++; 644 nr++;
652 } 645 }
@@ -671,7 +664,7 @@ static char *dso__read_build_id(struct dso *self, int v)
671 char *build_id = NULL, *bid; 664 char *build_id = NULL, *bid;
672 unsigned char *raw; 665 unsigned char *raw;
673 Elf *elf; 666 Elf *elf;
674 int fd = open(self->name, O_RDONLY); 667 int fd = open(self->long_name, O_RDONLY);
675 668
676 if (fd < 0) 669 if (fd < 0)
677 goto out; 670 goto out;
@@ -680,7 +673,7 @@ static char *dso__read_build_id(struct dso *self, int v)
680 if (elf == NULL) { 673 if (elf == NULL) {
681 if (v) 674 if (v)
682 fprintf(stderr, "%s: cannot read %s ELF file.\n", 675 fprintf(stderr, "%s: cannot read %s ELF file.\n",
683 __func__, self->name); 676 __func__, self->long_name);
684 goto out_close; 677 goto out_close;
685 } 678 }
686 679
@@ -709,7 +702,7 @@ static char *dso__read_build_id(struct dso *self, int v)
709 bid += 2; 702 bid += 2;
710 } 703 }
711 if (v >= 2) 704 if (v >= 2)
712 printf("%s(%s): %s\n", __func__, self->name, build_id); 705 printf("%s(%s): %s\n", __func__, self->long_name, build_id);
713out_elf_end: 706out_elf_end:
714 elf_end(elf); 707 elf_end(elf);
715out_close: 708out_close:
@@ -727,6 +720,7 @@ char dso__symtab_origin(const struct dso *self)
727 [DSO__ORIG_UBUNTU] = 'u', 720 [DSO__ORIG_UBUNTU] = 'u',
728 [DSO__ORIG_BUILDID] = 'b', 721 [DSO__ORIG_BUILDID] = 'b',
729 [DSO__ORIG_DSO] = 'd', 722 [DSO__ORIG_DSO] = 'd',
723 [DSO__ORIG_KMODULE] = 'K',
730 }; 724 };
731 725
732 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 726 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -734,7 +728,7 @@ char dso__symtab_origin(const struct dso *self)
734 return origin[self->origin]; 728 return origin[self->origin];
735} 729}
736 730
737int dso__load(struct dso *self, symbol_filter_t filter, int v) 731int dso__load(struct dso *self, struct map *map, symbol_filter_t filter, int v)
738{ 732{
739 int size = PATH_MAX; 733 int size = PATH_MAX;
740 char *name = malloc(size), *build_id = NULL; 734 char *name = malloc(size), *build_id = NULL;
@@ -747,7 +741,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v)
747 self->adjust_symbols = 0; 741 self->adjust_symbols = 0;
748 742
749 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 743 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
750 ret = dso__load_perf_map(self, filter, v); 744 ret = dso__load_perf_map(self, map, filter, v);
751 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 745 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
752 DSO__ORIG_NOT_FOUND; 746 DSO__ORIG_NOT_FOUND;
753 return ret; 747 return ret;
@@ -760,10 +754,12 @@ more:
760 self->origin++; 754 self->origin++;
761 switch (self->origin) { 755 switch (self->origin) {
762 case DSO__ORIG_FEDORA: 756 case DSO__ORIG_FEDORA:
763 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 757 snprintf(name, size, "/usr/lib/debug%s.debug",
758 self->long_name);
764 break; 759 break;
765 case DSO__ORIG_UBUNTU: 760 case DSO__ORIG_UBUNTU:
766 snprintf(name, size, "/usr/lib/debug%s", self->name); 761 snprintf(name, size, "/usr/lib/debug%s",
762 self->long_name);
767 break; 763 break;
768 case DSO__ORIG_BUILDID: 764 case DSO__ORIG_BUILDID:
769 build_id = dso__read_build_id(self, v); 765 build_id = dso__read_build_id(self, v);
@@ -777,7 +773,7 @@ more:
777 self->origin++; 773 self->origin++;
778 /* Fall thru */ 774 /* Fall thru */
779 case DSO__ORIG_DSO: 775 case DSO__ORIG_DSO:
780 snprintf(name, size, "%s", self->name); 776 snprintf(name, size, "%s", self->long_name);
781 break; 777 break;
782 778
783 default: 779 default:
@@ -787,7 +783,7 @@ more:
787 fd = open(name, O_RDONLY); 783 fd = open(name, O_RDONLY);
788 } while (fd < 0); 784 } while (fd < 0);
789 785
790 ret = dso__load_sym(self, fd, name, filter, v, NULL); 786 ret = dso__load_sym(self, map, name, fd, filter, 0, 0, v);
791 close(fd); 787 close(fd);
792 788
793 /* 789 /*
@@ -808,89 +804,247 @@ out:
808 return ret; 804 return ret;
809} 805}
810 806
811static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 807static struct rb_root kernel_maps;
812 symbol_filter_t filter, int v) 808struct map *kernel_map;
809
810static void kernel_maps__insert(struct map *map)
813{ 811{
814 struct module *mod = mod_dso__find_module(mods, name); 812 maps__insert(&kernel_maps, map);
815 int err = 0, fd; 813}
816 814
817 if (mod == NULL || !mod->active) 815struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
818 return err; 816{
817 /*
818 * We can't have kernel_map in kernel_maps because it spans an address
819 * space that includes the modules. The right way to fix this is to
820 * create several maps, so that we don't have overlapping ranges with
821 * modules. For now lets look first on the kernel dso.
822 */
823 struct map *map = maps__find(&kernel_maps, ip);
824 struct symbol *sym;
825
826 if (map) {
827 ip = map->map_ip(map, ip);
828 sym = map->dso->find_symbol(map->dso, ip);
829 } else {
830 map = kernel_map;
831 sym = map->dso->find_symbol(map->dso, ip);
832 }
819 833
820 fd = open(mod->path, O_RDONLY); 834 if (mapp)
835 *mapp = map;
821 836
822 if (fd < 0) 837 return sym;
838}
839
840struct map *kernel_maps__find_by_dso_name(const char *name)
841{
842 struct rb_node *nd;
843
844 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
845 struct map *map = rb_entry(nd, struct map, rb_node);
846
847 if (map->dso && strcmp(map->dso->name, name) == 0)
848 return map;
849 }
850
851 return NULL;
852}
853
854static int dso__load_module_sym(struct dso *self, struct map *map,
855 symbol_filter_t filter, int v)
856{
857 int err = 0, fd = open(self->long_name, O_RDONLY);
858
859 if (fd < 0) {
860 if (v)
861 fprintf(stderr, "%s: cannot open %s\n",
862 __func__, self->long_name);
823 return err; 863 return err;
864 }
824 865
825 err = dso__load_sym(self, fd, name, filter, v, mod); 866 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1, v);
826 close(fd); 867 close(fd);
827 868
828 return err; 869 return err;
829} 870}
830 871
831int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) 872static int dsos__load_modules_sym_dir(char *dirname,
873 symbol_filter_t filter, int v)
832{ 874{
833 struct mod_dso *mods = mod_dso__new_dso("modules"); 875 struct dirent *dent;
834 struct module *pos; 876 int nr_symbols = 0, err;
835 struct rb_node *next; 877 DIR *dir = opendir(dirname);
836 int err, count = 0;
837 878
838 err = mod_dso__load_modules(mods); 879 if (!dir) {
880 if (v)
881 fprintf(stderr, "%s: cannot open %s dir\n", __func__,
882 dirname);
883 return -1;
884 }
839 885
840 if (err <= 0) 886 while ((dent = readdir(dir)) != NULL) {
841 return err; 887 char path[PATH_MAX];
888
889 if (dent->d_type == DT_DIR) {
890 if (!strcmp(dent->d_name, ".") ||
891 !strcmp(dent->d_name, ".."))
892 continue;
893
894 snprintf(path, sizeof(path), "%s/%s",
895 dirname, dent->d_name);
896 err = dsos__load_modules_sym_dir(path, filter, v);
897 if (err < 0)
898 goto failure;
899 } else {
900 char *dot = strrchr(dent->d_name, '.'),
901 dso_name[PATH_MAX];
902 struct map *map;
903 struct rb_node *last;
904
905 if (dot == NULL || strcmp(dot, ".ko"))
906 continue;
907 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
908 (int)(dot - dent->d_name), dent->d_name);
909
910 map = kernel_maps__find_by_dso_name(dso_name);
911 if (map == NULL)
912 continue;
913
914 snprintf(path, sizeof(path), "%s/%s",
915 dirname, dent->d_name);
916
917 map->dso->long_name = strdup(path);
918 if (map->dso->long_name == NULL)
919 goto failure;
920
921 err = dso__load_module_sym(map->dso, map, filter, v);
922 if (err < 0)
923 goto failure;
924 last = rb_last(&map->dso->syms);
925 if (last) {
926 struct symbol *sym;
927 sym = rb_entry(last, struct symbol, rb_node);
928 map->end = map->start + sym->end;
929 }
930 }
931 nr_symbols += err;
932 }
842 933
843 /* 934 return nr_symbols;
844 * Iterate over modules, and load active symbols. 935failure:
845 */ 936 closedir(dir);
846 next = rb_first(&mods->mods); 937 return -1;
847 while (next) { 938}
848 pos = rb_entry(next, struct module, rb_node);
849 err = dso__load_module(self, mods, pos->name, filter, v);
850 939
851 if (err < 0) 940static int dsos__load_modules_sym(symbol_filter_t filter, int v)
852 break; 941{
942 struct utsname uts;
943 char modules_path[PATH_MAX];
853 944
854 next = rb_next(&pos->rb_node); 945 if (uname(&uts) < 0)
855 count += err; 946 return -1;
856 }
857 947
858 if (err < 0) { 948 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
859 mod_dso__delete_modules(mods); 949 uts.release);
860 mod_dso__delete_self(mods);
861 return err;
862 }
863 950
864 return count; 951 return dsos__load_modules_sym_dir(modules_path, filter, v);
865} 952}
866 953
867static inline void dso__fill_symbol_holes(struct dso *self) 954/*
955 * Constructor variant for modules (where we know from /proc/modules where
956 * they are loaded) and for vmlinux, where only after we load all the
957 * symbols we'll know where it starts and ends.
958 */
959static struct map *map__new2(u64 start, struct dso *dso)
868{ 960{
869 struct symbol *prev = NULL; 961 struct map *self = malloc(sizeof(*self));
870 struct rb_node *nd;
871 962
872 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 963 if (self != NULL) {
873 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 964 self->start = start;
965 /*
966 * Will be filled after we load all the symbols
967 */
968 self->end = 0;
969
970 self->pgoff = 0;
971 self->dso = dso;
972 self->map_ip = map__map_ip;
973 RB_CLEAR_NODE(&self->rb_node);
974 }
975 return self;
976}
977
978int dsos__load_modules(unsigned int sym_priv_size,
979 symbol_filter_t filter, int v)
980{
981 char *line = NULL;
982 size_t n;
983 FILE *file = fopen("/proc/modules", "r");
984 struct map *map;
874 985
875 if (prev) { 986 if (file == NULL)
876 u64 hole = 0; 987 return -1;
877 int alias = pos->start == prev->start;
878 988
879 if (!alias) 989 while (!feof(file)) {
880 hole = prev->start - pos->end - 1; 990 char name[PATH_MAX];
991 u64 start;
992 struct dso *dso;
993 char *sep;
994 int line_len;
881 995
882 if (hole || alias) { 996 line_len = getline(&line, &n, file);
883 if (alias) 997 if (line_len < 0)
884 pos->end = prev->end; 998 break;
885 else if (hole) 999
886 pos->end = prev->start - 1; 1000 if (!line)
887 } 1001 goto out_failure;
1002
1003 line[--line_len] = '\0'; /* \n */
1004
1005 sep = strrchr(line, 'x');
1006 if (sep == NULL)
1007 continue;
1008
1009 hex2u64(sep + 1, &start);
1010
1011 sep = strchr(line, ' ');
1012 if (sep == NULL)
1013 continue;
1014
1015 *sep = '\0';
1016
1017 snprintf(name, sizeof(name), "[%s]", line);
1018 dso = dso__new(name, sym_priv_size);
1019
1020 if (dso == NULL)
1021 goto out_delete_line;
1022
1023 map = map__new2(start, dso);
1024 if (map == NULL) {
1025 dso__delete(dso);
1026 goto out_delete_line;
888 } 1027 }
889 prev = pos; 1028
1029 dso->origin = DSO__ORIG_KMODULE;
1030 kernel_maps__insert(map);
1031 dsos__add(dso);
890 } 1032 }
1033
1034 free(line);
1035 fclose(file);
1036
1037 v = 1;
1038 return dsos__load_modules_sym(filter, v);
1039
1040out_delete_line:
1041 free(line);
1042out_failure:
1043 return -1;
891} 1044}
892 1045
893static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 1046static int dso__load_vmlinux(struct dso *self, struct map *map,
1047 const char *vmlinux,
894 symbol_filter_t filter, int v) 1048 symbol_filter_t filter, int v)
895{ 1049{
896 int err, fd = open(vmlinux, O_RDONLY); 1050 int err, fd = open(vmlinux, O_RDONLY);
@@ -898,28 +1052,36 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
898 if (fd < 0) 1052 if (fd < 0)
899 return -1; 1053 return -1;
900 1054
901 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); 1055 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0, v);
902
903 if (err > 0)
904 dso__fill_symbol_holes(self);
905 1056
906 close(fd); 1057 close(fd);
907 1058
908 return err; 1059 return err;
909} 1060}
910 1061
911int dso__load_kernel(struct dso *self, const char *vmlinux, 1062int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
912 symbol_filter_t filter, int v, int use_modules) 1063 symbol_filter_t filter, int v, int use_modules)
913{ 1064{
914 int err = -1; 1065 int err = -1;
1066 struct dso *dso = dso__new(vmlinux, sym_priv_size);
1067
1068 if (dso == NULL)
1069 return -1;
1070
1071 dso->short_name = "[kernel]";
1072 kernel_map = map__new2(0, dso);
1073 if (kernel_map == NULL)
1074 goto out_delete_dso;
1075
1076 kernel_map->map_ip = vdso__map_ip;
915 1077
916 if (vmlinux) { 1078 if (vmlinux) {
917 err = dso__load_vmlinux(self, vmlinux, filter, v); 1079 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter, v);
918 if (err > 0 && use_modules) { 1080 if (err > 0 && use_modules) {
919 int syms = dso__load_modules(self, filter, v); 1081 int syms = dsos__load_modules(sym_priv_size, filter, v);
920 1082
921 if (syms < 0) { 1083 if (syms < 0) {
922 fprintf(stderr, "dso__load_modules failed!\n"); 1084 fprintf(stderr, "dsos__load_modules failed!\n");
923 return syms; 1085 return syms;
924 } 1086 }
925 err += syms; 1087 err += syms;
@@ -927,18 +1089,34 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
927 } 1089 }
928 1090
929 if (err <= 0) 1091 if (err <= 0)
930 err = dso__load_kallsyms(self, filter, v); 1092 err = dso__load_kallsyms(dso, kernel_map, filter, v);
1093
1094 if (err > 0) {
1095 struct rb_node *node = rb_first(&dso->syms);
1096 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
931 1097
932 if (err > 0) 1098 kernel_map->start = sym->start;
933 self->origin = DSO__ORIG_KERNEL; 1099 node = rb_last(&dso->syms);
1100 sym = rb_entry(node, struct symbol, rb_node);
1101 kernel_map->end = sym->end;
1102
1103 dso->origin = DSO__ORIG_KERNEL;
1104 /*
1105 * XXX See kernel_maps__find_symbol comment
1106 * kernel_maps__insert(kernel_map)
1107 */
1108 dsos__add(dso);
1109 }
934 1110
935 return err; 1111 return err;
1112
1113out_delete_dso:
1114 dso__delete(dso);
1115 return -1;
936} 1116}
937 1117
938LIST_HEAD(dsos); 1118LIST_HEAD(dsos);
939struct dso *kernel_dso;
940struct dso *vdso; 1119struct dso *vdso;
941struct dso *hypervisor_dso;
942 1120
943const char *vmlinux_name = "vmlinux"; 1121const char *vmlinux_name = "vmlinux";
944int modules; 1122int modules;
@@ -970,7 +1148,7 @@ struct dso *dsos__findnew(const char *name)
970 if (!dso) 1148 if (!dso)
971 goto out_delete_dso; 1149 goto out_delete_dso;
972 1150
973 nr = dso__load(dso, NULL, verbose); 1151 nr = dso__load(dso, NULL, NULL, verbose);
974 if (nr < 0) { 1152 if (nr < 0) {
975 eprintf("Failed to open: %s\n", name); 1153 eprintf("Failed to open: %s\n", name);
976 goto out_delete_dso; 1154 goto out_delete_dso;
@@ -995,43 +1173,20 @@ void dsos__fprintf(FILE *fp)
995 dso__fprintf(pos, fp); 1173 dso__fprintf(pos, fp);
996} 1174}
997 1175
998static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
999{
1000 return dso__find_symbol(dso, ip);
1001}
1002
1003int load_kernel(void) 1176int load_kernel(void)
1004{ 1177{
1005 int err; 1178 if (dsos__load_kernel(vmlinux_name, 0, NULL, verbose, modules) <= 0)
1006
1007 kernel_dso = dso__new("[kernel]", 0);
1008 if (!kernel_dso)
1009 return -1; 1179 return -1;
1010 1180
1011 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1012 if (err <= 0) {
1013 dso__delete(kernel_dso);
1014 kernel_dso = NULL;
1015 } else
1016 dsos__add(kernel_dso);
1017
1018 vdso = dso__new("[vdso]", 0); 1181 vdso = dso__new("[vdso]", 0);
1019 if (!vdso) 1182 if (!vdso)
1020 return -1; 1183 return -1;
1021 1184
1022 vdso->find_symbol = vdso__find_symbol;
1023
1024 dsos__add(vdso); 1185 dsos__add(vdso);
1025 1186
1026 hypervisor_dso = dso__new("[hypervisor]", 0); 1187 return 0;
1027 if (!hypervisor_dso)
1028 return -1;
1029 dsos__add(hypervisor_dso);
1030
1031 return err;
1032} 1188}
1033 1189
1034
1035void symbol__init(void) 1190void symbol__init(void)
1036{ 1191{
1037 elf_version(EV_CURRENT); 1192 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index ee164f659ed3..5339fd82ec96 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -5,7 +5,6 @@
5#include "types.h" 5#include "types.h"
6#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include "module.h"
9#include "event.h" 8#include "event.h"
10 9
11#ifdef HAVE_CPLUS_DEMANGLE 10#ifdef HAVE_CPLUS_DEMANGLE
@@ -36,10 +35,8 @@ struct symbol {
36 struct rb_node rb_node; 35 struct rb_node rb_node;
37 u64 start; 36 u64 start;
38 u64 end; 37 u64 end;
39 u64 obj_start;
40 u64 hist_sum; 38 u64 hist_sum;
41 u64 *hist; 39 u64 *hist;
42 struct module *module;
43 void *priv; 40 void *priv;
44 char name[0]; 41 char name[0];
45}; 42};
@@ -52,12 +49,14 @@ struct dso {
52 unsigned char adjust_symbols; 49 unsigned char adjust_symbols;
53 unsigned char slen_calculated; 50 unsigned char slen_calculated;
54 unsigned char origin; 51 unsigned char origin;
52 const char *short_name;
53 char *long_name;
55 char name[0]; 54 char name[0];
56}; 55};
57 56
58extern const char *sym_hist_filter; 57extern const char *sym_hist_filter;
59 58
60typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym); 59typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
61 60
62struct dso *dso__new(const char *name, unsigned int sym_priv_size); 61struct dso *dso__new(const char *name, unsigned int sym_priv_size);
63void dso__delete(struct dso *self); 62void dso__delete(struct dso *self);
@@ -69,10 +68,12 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
69 68
70struct symbol *dso__find_symbol(struct dso *self, u64 ip); 69struct symbol *dso__find_symbol(struct dso *self, u64 ip);
71 70
72int dso__load_kernel(struct dso *self, const char *vmlinux, 71int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
73 symbol_filter_t filter, int verbose, int modules); 72 symbol_filter_t filter, int verbose, int modules);
74int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); 73int dsos__load_modules(unsigned int sym_priv_size, symbol_filter_t filter,
75int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 74 int verbose);
75int dso__load(struct dso *self, struct map *map, symbol_filter_t filter,
76 int verbose);
76struct dso *dsos__findnew(const char *name); 77struct dso *dsos__findnew(const char *name);
77void dsos__fprintf(FILE *fp); 78void dsos__fprintf(FILE *fp);
78 79
@@ -84,9 +85,8 @@ int load_kernel(void);
84void symbol__init(void); 85void symbol__init(void);
85 86
86extern struct list_head dsos; 87extern struct list_head dsos;
87extern struct dso *kernel_dso; 88extern struct map *kernel_map;
88extern struct dso *vdso; 89extern struct dso *vdso;
89extern struct dso *hypervisor_dso;
90extern const char *vmlinux_name; 90extern const char *vmlinux_name;
91extern int modules; 91extern int modules;
92#endif /* __PERF_SYMBOL */ 92#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9d0945cc66d1..3b56aebb1f4b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -16,6 +16,7 @@ static struct thread *thread__new(pid_t pid)
16 if (self->comm) 16 if (self->comm)
17 snprintf(self->comm, 32, ":%d", self->pid); 17 snprintf(self->comm, 32, ":%d", self->pid);
18 self->maps = RB_ROOT; 18 self->maps = RB_ROOT;
19 INIT_LIST_HEAD(&self->removed_maps);
19 } 20 }
20 21
21 return self; 22 return self;
@@ -32,13 +33,20 @@ int thread__set_comm(struct thread *self, const char *comm)
32static size_t thread__fprintf(struct thread *self, FILE *fp) 33static size_t thread__fprintf(struct thread *self, FILE *fp)
33{ 34{
34 struct rb_node *nd; 35 struct rb_node *nd;
35 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 36 struct map *pos;
37 size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
38 self->pid, self->comm);
36 39
37 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) { 40 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) {
38 struct map *pos = rb_entry(nd, struct map, rb_node); 41 pos = rb_entry(nd, struct map, rb_node);
39 ret += map__fprintf(pos, fp); 42 ret += map__fprintf(pos, fp);
40 } 43 }
41 44
45 ret = fprintf(fp, "Removed maps:\n");
46
47 list_for_each_entry(pos, &self->removed_maps, node)
48 ret += map__fprintf(pos, fp);
49
42 return ret; 50 return ret;
43} 51}
44 52
@@ -112,21 +120,13 @@ static void thread__remove_overlappings(struct thread *self, struct map *map)
112 map__fprintf(pos, stdout); 120 map__fprintf(pos, stdout);
113 } 121 }
114 122
115 if (map->start <= pos->start && map->end > pos->start) 123 rb_erase(&pos->rb_node, &self->maps);
116 pos->start = map->end; 124 /*
117 125 * We may have references to this map, for instance in some
118 if (map->end >= pos->end && map->start < pos->end) 126 * hist_entry instances, so just move them to a separate
119 pos->end = map->start; 127 * list.
120 128 */
121 if (verbose >= 2) { 129 list_add_tail(&pos->node, &self->removed_maps);
122 printf("after collision:\n");
123 map__fprintf(pos, stdout);
124 }
125
126 if (pos->start >= pos->end) {
127 rb_erase(&pos->rb_node, &self->maps);
128 free(pos);
129 }
130 } 130 }
131} 131}
132 132
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index bbb37c1a52ee..845d9b62f96f 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -8,6 +8,7 @@
8struct thread { 8struct thread {
9 struct rb_node rb_node; 9 struct rb_node rb_node;
10 struct rb_root maps; 10 struct rb_root maps;
11 struct list_head removed_maps;
11 pid_t pid; 12 pid_t pid;
12 char shortname[3]; 13 char shortname[3];
13 char *comm; 14 char *comm;
@@ -25,6 +26,9 @@ size_t threads__fprintf(FILE *fp, struct rb_root *threads);
25void maps__insert(struct rb_root *maps, struct map *map); 26void maps__insert(struct rb_root *maps, struct map *map);
26struct map *maps__find(struct rb_root *maps, u64 ip); 27struct map *maps__find(struct rb_root *maps, u64 ip);
27 28
29struct symbol *kernel_maps__find_symbol(const u64 ip, struct map **mapp);
30struct map *kernel_maps__find_by_dso_name(const char *name);
31
28static inline struct map *thread__find_map(struct thread *self, u64 ip) 32static inline struct map *thread__find_map(struct thread *self, u64 ip)
29{ 33{
30 return self ? maps__find(&self->maps, ip) : NULL; 34 return self ? maps__find(&self->maps, ip) : NULL;