aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-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
9 files changed, 362 insertions, 792 deletions
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;