aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-10-27 17:18:32 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-29 09:37:25 -0400
commitcdd059d731eeb466f51a404ee6cbfafb0fc7c20b (patch)
tree36346ccb768ee0b8642b79bef6c7ad723a203a12
parentea36c46be69c6e49c877971c4b3b3876b24b6082 (diff)
perf tools: Move dso_* related functions into dso object
Moving dso_* related functions into dso object. Keeping symbol loading related functions still in the symbol object as it seems more convenient. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Reviewed-by: Namhyung Kim <namhyung@kernel.org> Tested-by: Namhyung Kim <namhyung@kernel.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1351372712-21104-6-git-send-email-jolsa@redhat.com [ committer note: Use "symbol.h" instead of <symbol.h> to make it build with O= ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/util/dso.c594
-rw-r--r--tools/perf/util/dso.h148
-rw-r--r--tools/perf/util/symbol.c599
-rw-r--r--tools/perf/util/symbol.h134
5 files changed, 751 insertions, 726 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 629fc6a4b0df..ec63d53cd87f 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -327,6 +327,7 @@ LIB_H += util/svghelper.h
327LIB_H += util/tool.h 327LIB_H += util/tool.h
328LIB_H += util/run-command.h 328LIB_H += util/run-command.h
329LIB_H += util/sigchain.h 329LIB_H += util/sigchain.h
330LIB_H += util/dso.h
330LIB_H += util/symbol.h 331LIB_H += util/symbol.h
331LIB_H += util/color.h 332LIB_H += util/color.h
332LIB_H += util/values.h 333LIB_H += util/values.h
@@ -385,6 +386,7 @@ LIB_OBJS += $(OUTPUT)util/top.o
385LIB_OBJS += $(OUTPUT)util/usage.o 386LIB_OBJS += $(OUTPUT)util/usage.o
386LIB_OBJS += $(OUTPUT)util/wrapper.o 387LIB_OBJS += $(OUTPUT)util/wrapper.o
387LIB_OBJS += $(OUTPUT)util/sigchain.o 388LIB_OBJS += $(OUTPUT)util/sigchain.o
389LIB_OBJS += $(OUTPUT)util/dso.o
388LIB_OBJS += $(OUTPUT)util/symbol.o 390LIB_OBJS += $(OUTPUT)util/symbol.o
389LIB_OBJS += $(OUTPUT)util/symbol-elf.o 391LIB_OBJS += $(OUTPUT)util/symbol-elf.o
390LIB_OBJS += $(OUTPUT)util/dso-test-data.o 392LIB_OBJS += $(OUTPUT)util/dso-test-data.o
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
new file mode 100644
index 000000000000..db24a3f0c820
--- /dev/null
+++ b/tools/perf/util/dso.c
@@ -0,0 +1,594 @@
1#include "symbol.h"
2#include "dso.h"
3#include "util.h"
4#include "debug.h"
5
6char dso__symtab_origin(const struct dso *dso)
7{
8 static const char origin[] = {
9 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
10 [DSO_BINARY_TYPE__VMLINUX] = 'v',
11 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
12 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
13 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
14 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
15 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
16 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
17 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
19 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
20 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
21 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
22 };
23
24 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
25 return '!';
26 return origin[dso->symtab_type];
27}
28
29int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
30 char *root_dir, char *file, size_t size)
31{
32 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
33 int ret = 0;
34
35 switch (type) {
36 case DSO_BINARY_TYPE__DEBUGLINK: {
37 char *debuglink;
38
39 strncpy(file, dso->long_name, size);
40 debuglink = file + dso->long_name_len;
41 while (debuglink != file && *debuglink != '/')
42 debuglink--;
43 if (*debuglink == '/')
44 debuglink++;
45 filename__read_debuglink(dso->long_name, debuglink,
46 size - (debuglink - file));
47 }
48 break;
49 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
50 /* skip the locally configured cache if a symfs is given */
51 if (symbol_conf.symfs[0] ||
52 (dso__build_id_filename(dso, file, size) == NULL))
53 ret = -1;
54 break;
55
56 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
57 snprintf(file, size, "%s/usr/lib/debug%s.debug",
58 symbol_conf.symfs, dso->long_name);
59 break;
60
61 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
62 snprintf(file, size, "%s/usr/lib/debug%s",
63 symbol_conf.symfs, dso->long_name);
64 break;
65
66 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
67 if (!dso->has_build_id) {
68 ret = -1;
69 break;
70 }
71
72 build_id__sprintf(dso->build_id,
73 sizeof(dso->build_id),
74 build_id_hex);
75 snprintf(file, size,
76 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
77 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
78 break;
79
80 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
81 snprintf(file, size, "%s%s",
82 symbol_conf.symfs, dso->long_name);
83 break;
84
85 case DSO_BINARY_TYPE__GUEST_KMODULE:
86 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
87 root_dir, dso->long_name);
88 break;
89
90 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
91 snprintf(file, size, "%s%s", symbol_conf.symfs,
92 dso->long_name);
93 break;
94
95 default:
96 case DSO_BINARY_TYPE__KALLSYMS:
97 case DSO_BINARY_TYPE__VMLINUX:
98 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
99 case DSO_BINARY_TYPE__GUEST_VMLINUX:
100 case DSO_BINARY_TYPE__JAVA_JIT:
101 case DSO_BINARY_TYPE__NOT_FOUND:
102 ret = -1;
103 break;
104 }
105
106 return ret;
107}
108
109static int open_dso(struct dso *dso, struct machine *machine)
110{
111 char *root_dir = (char *) "";
112 char *name;
113 int fd;
114
115 name = malloc(PATH_MAX);
116 if (!name)
117 return -ENOMEM;
118
119 if (machine)
120 root_dir = machine->root_dir;
121
122 if (dso__binary_type_file(dso, dso->data_type,
123 root_dir, name, PATH_MAX)) {
124 free(name);
125 return -EINVAL;
126 }
127
128 fd = open(name, O_RDONLY);
129 free(name);
130 return fd;
131}
132
133int dso__data_fd(struct dso *dso, struct machine *machine)
134{
135 static enum dso_binary_type binary_type_data[] = {
136 DSO_BINARY_TYPE__BUILD_ID_CACHE,
137 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
138 DSO_BINARY_TYPE__NOT_FOUND,
139 };
140 int i = 0;
141
142 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
143 return open_dso(dso, machine);
144
145 do {
146 int fd;
147
148 dso->data_type = binary_type_data[i++];
149
150 fd = open_dso(dso, machine);
151 if (fd >= 0)
152 return fd;
153
154 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
155
156 return -EINVAL;
157}
158
159static void
160dso_cache__free(struct rb_root *root)
161{
162 struct rb_node *next = rb_first(root);
163
164 while (next) {
165 struct dso_cache *cache;
166
167 cache = rb_entry(next, struct dso_cache, rb_node);
168 next = rb_next(&cache->rb_node);
169 rb_erase(&cache->rb_node, root);
170 free(cache);
171 }
172}
173
174static struct dso_cache*
175dso_cache__find(struct rb_root *root, u64 offset)
176{
177 struct rb_node **p = &root->rb_node;
178 struct rb_node *parent = NULL;
179 struct dso_cache *cache;
180
181 while (*p != NULL) {
182 u64 end;
183
184 parent = *p;
185 cache = rb_entry(parent, struct dso_cache, rb_node);
186 end = cache->offset + DSO__DATA_CACHE_SIZE;
187
188 if (offset < cache->offset)
189 p = &(*p)->rb_left;
190 else if (offset >= end)
191 p = &(*p)->rb_right;
192 else
193 return cache;
194 }
195 return NULL;
196}
197
198static void
199dso_cache__insert(struct rb_root *root, struct dso_cache *new)
200{
201 struct rb_node **p = &root->rb_node;
202 struct rb_node *parent = NULL;
203 struct dso_cache *cache;
204 u64 offset = new->offset;
205
206 while (*p != NULL) {
207 u64 end;
208
209 parent = *p;
210 cache = rb_entry(parent, struct dso_cache, rb_node);
211 end = cache->offset + DSO__DATA_CACHE_SIZE;
212
213 if (offset < cache->offset)
214 p = &(*p)->rb_left;
215 else if (offset >= end)
216 p = &(*p)->rb_right;
217 }
218
219 rb_link_node(&new->rb_node, parent, p);
220 rb_insert_color(&new->rb_node, root);
221}
222
223static ssize_t
224dso_cache__memcpy(struct dso_cache *cache, u64 offset,
225 u8 *data, u64 size)
226{
227 u64 cache_offset = offset - cache->offset;
228 u64 cache_size = min(cache->size - cache_offset, size);
229
230 memcpy(data, cache->data + cache_offset, cache_size);
231 return cache_size;
232}
233
234static ssize_t
235dso_cache__read(struct dso *dso, struct machine *machine,
236 u64 offset, u8 *data, ssize_t size)
237{
238 struct dso_cache *cache;
239 ssize_t ret;
240 int fd;
241
242 fd = dso__data_fd(dso, machine);
243 if (fd < 0)
244 return -1;
245
246 do {
247 u64 cache_offset;
248
249 ret = -ENOMEM;
250
251 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
252 if (!cache)
253 break;
254
255 cache_offset = offset & DSO__DATA_CACHE_MASK;
256 ret = -EINVAL;
257
258 if (-1 == lseek(fd, cache_offset, SEEK_SET))
259 break;
260
261 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
262 if (ret <= 0)
263 break;
264
265 cache->offset = cache_offset;
266 cache->size = ret;
267 dso_cache__insert(&dso->cache, cache);
268
269 ret = dso_cache__memcpy(cache, offset, data, size);
270
271 } while (0);
272
273 if (ret <= 0)
274 free(cache);
275
276 close(fd);
277 return ret;
278}
279
280static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
281 u64 offset, u8 *data, ssize_t size)
282{
283 struct dso_cache *cache;
284
285 cache = dso_cache__find(&dso->cache, offset);
286 if (cache)
287 return dso_cache__memcpy(cache, offset, data, size);
288 else
289 return dso_cache__read(dso, machine, offset, data, size);
290}
291
292ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
293 u64 offset, u8 *data, ssize_t size)
294{
295 ssize_t r = 0;
296 u8 *p = data;
297
298 do {
299 ssize_t ret;
300
301 ret = dso_cache_read(dso, machine, offset, p, size);
302 if (ret < 0)
303 return ret;
304
305 /* Reached EOF, return what we have. */
306 if (!ret)
307 break;
308
309 BUG_ON(ret > size);
310
311 r += ret;
312 p += ret;
313 offset += ret;
314 size -= ret;
315
316 } while (size);
317
318 return r;
319}
320
321ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
322 struct machine *machine, u64 addr,
323 u8 *data, ssize_t size)
324{
325 u64 offset = map->map_ip(map, addr);
326 return dso__data_read_offset(dso, machine, offset, data, size);
327}
328
329struct map *dso__new_map(const char *name)
330{
331 struct map *map = NULL;
332 struct dso *dso = dso__new(name);
333
334 if (dso)
335 map = map__new2(0, dso, MAP__FUNCTION);
336
337 return map;
338}
339
340struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
341 const char *short_name, int dso_type)
342{
343 /*
344 * The kernel dso could be created by build_id processing.
345 */
346 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
347
348 /*
349 * We need to run this in all cases, since during the build_id
350 * processing we had no idea this was the kernel dso.
351 */
352 if (dso != NULL) {
353 dso__set_short_name(dso, short_name);
354 dso->kernel = dso_type;
355 }
356
357 return dso;
358}
359
360void dso__set_long_name(struct dso *dso, char *name)
361{
362 if (name == NULL)
363 return;
364 dso->long_name = name;
365 dso->long_name_len = strlen(name);
366}
367
368void dso__set_short_name(struct dso *dso, const char *name)
369{
370 if (name == NULL)
371 return;
372 dso->short_name = name;
373 dso->short_name_len = strlen(name);
374}
375
376static void dso__set_basename(struct dso *dso)
377{
378 dso__set_short_name(dso, basename(dso->long_name));
379}
380
381int dso__name_len(const struct dso *dso)
382{
383 if (!dso)
384 return strlen("[unknown]");
385 if (verbose)
386 return dso->long_name_len;
387
388 return dso->short_name_len;
389}
390
391bool dso__loaded(const struct dso *dso, enum map_type type)
392{
393 return dso->loaded & (1 << type);
394}
395
396bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
397{
398 return dso->sorted_by_name & (1 << type);
399}
400
401void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
402{
403 dso->sorted_by_name |= (1 << type);
404}
405
406struct dso *dso__new(const char *name)
407{
408 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
409
410 if (dso != NULL) {
411 int i;
412 strcpy(dso->name, name);
413 dso__set_long_name(dso, dso->name);
414 dso__set_short_name(dso, dso->name);
415 for (i = 0; i < MAP__NR_TYPES; ++i)
416 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
417 dso->cache = RB_ROOT;
418 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
419 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
420 dso->loaded = 0;
421 dso->sorted_by_name = 0;
422 dso->has_build_id = 0;
423 dso->kernel = DSO_TYPE_USER;
424 dso->needs_swap = DSO_SWAP__UNSET;
425 INIT_LIST_HEAD(&dso->node);
426 }
427
428 return dso;
429}
430
431void dso__delete(struct dso *dso)
432{
433 int i;
434 for (i = 0; i < MAP__NR_TYPES; ++i)
435 symbols__delete(&dso->symbols[i]);
436 if (dso->sname_alloc)
437 free((char *)dso->short_name);
438 if (dso->lname_alloc)
439 free(dso->long_name);
440 dso_cache__free(&dso->cache);
441 free(dso);
442}
443
444void dso__set_build_id(struct dso *dso, void *build_id)
445{
446 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
447 dso->has_build_id = 1;
448}
449
450bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
451{
452 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
453}
454
455void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
456{
457 char path[PATH_MAX];
458
459 if (machine__is_default_guest(machine))
460 return;
461 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
462 if (sysfs__read_build_id(path, dso->build_id,
463 sizeof(dso->build_id)) == 0)
464 dso->has_build_id = true;
465}
466
467int dso__kernel_module_get_build_id(struct dso *dso,
468 const char *root_dir)
469{
470 char filename[PATH_MAX];
471 /*
472 * kernel module short names are of the form "[module]" and
473 * we need just "module" here.
474 */
475 const char *name = dso->short_name + 1;
476
477 snprintf(filename, sizeof(filename),
478 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
479 root_dir, (int)strlen(name) - 1, name);
480
481 if (sysfs__read_build_id(filename, dso->build_id,
482 sizeof(dso->build_id)) == 0)
483 dso->has_build_id = true;
484
485 return 0;
486}
487
488bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
489{
490 bool have_build_id = false;
491 struct dso *pos;
492
493 list_for_each_entry(pos, head, node) {
494 if (with_hits && !pos->hit)
495 continue;
496 if (pos->has_build_id) {
497 have_build_id = true;
498 continue;
499 }
500 if (filename__read_build_id(pos->long_name, pos->build_id,
501 sizeof(pos->build_id)) > 0) {
502 have_build_id = true;
503 pos->has_build_id = true;
504 }
505 }
506
507 return have_build_id;
508}
509
510void dsos__add(struct list_head *head, struct dso *dso)
511{
512 list_add_tail(&dso->node, head);
513}
514
515struct dso *dsos__find(struct list_head *head, const char *name)
516{
517 struct dso *pos;
518
519 list_for_each_entry(pos, head, node)
520 if (strcmp(pos->long_name, name) == 0)
521 return pos;
522 return NULL;
523}
524
525struct dso *__dsos__findnew(struct list_head *head, const char *name)
526{
527 struct dso *dso = dsos__find(head, name);
528
529 if (!dso) {
530 dso = dso__new(name);
531 if (dso != NULL) {
532 dsos__add(head, dso);
533 dso__set_basename(dso);
534 }
535 }
536
537 return dso;
538}
539
540size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
541 bool with_hits)
542{
543 struct dso *pos;
544 size_t ret = 0;
545
546 list_for_each_entry(pos, head, node) {
547 if (with_hits && !pos->hit)
548 continue;
549 ret += dso__fprintf_buildid(pos, fp);
550 ret += fprintf(fp, " %s\n", pos->long_name);
551 }
552 return ret;
553}
554
555size_t __dsos__fprintf(struct list_head *head, FILE *fp)
556{
557 struct dso *pos;
558 size_t ret = 0;
559
560 list_for_each_entry(pos, head, node) {
561 int i;
562 for (i = 0; i < MAP__NR_TYPES; ++i)
563 ret += dso__fprintf(pos, i, fp);
564 }
565
566 return ret;
567}
568
569size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
570{
571 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
572
573 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
574 return fprintf(fp, "%s", sbuild_id);
575}
576
577size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
578{
579 struct rb_node *nd;
580 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
581
582 if (dso->short_name != dso->long_name)
583 ret += fprintf(fp, "%s, ", dso->long_name);
584 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
585 dso->loaded ? "" : "NOT ");
586 ret += dso__fprintf_buildid(dso, fp);
587 ret += fprintf(fp, ")\n");
588 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
589 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
590 ret += symbol__fprintf(pos, fp);
591 }
592
593 return ret;
594}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
new file mode 100644
index 000000000000..e03276940b99
--- /dev/null
+++ b/tools/perf/util/dso.h
@@ -0,0 +1,148 @@
1#ifndef __PERF_DSO
2#define __PERF_DSO
3
4#include <linux/types.h>
5#include <linux/rbtree.h>
6#include "types.h"
7#include "map.h"
8
9enum dso_binary_type {
10 DSO_BINARY_TYPE__KALLSYMS = 0,
11 DSO_BINARY_TYPE__GUEST_KALLSYMS,
12 DSO_BINARY_TYPE__VMLINUX,
13 DSO_BINARY_TYPE__GUEST_VMLINUX,
14 DSO_BINARY_TYPE__JAVA_JIT,
15 DSO_BINARY_TYPE__DEBUGLINK,
16 DSO_BINARY_TYPE__BUILD_ID_CACHE,
17 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
18 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
19 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
20 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
21 DSO_BINARY_TYPE__GUEST_KMODULE,
22 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
23 DSO_BINARY_TYPE__NOT_FOUND,
24};
25
26enum dso_kernel_type {
27 DSO_TYPE_USER = 0,
28 DSO_TYPE_KERNEL,
29 DSO_TYPE_GUEST_KERNEL
30};
31
32enum dso_swap_type {
33 DSO_SWAP__UNSET,
34 DSO_SWAP__NO,
35 DSO_SWAP__YES,
36};
37
38#define DSO__SWAP(dso, type, val) \
39({ \
40 type ____r = val; \
41 BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
42 if (dso->needs_swap == DSO_SWAP__YES) { \
43 switch (sizeof(____r)) { \
44 case 2: \
45 ____r = bswap_16(val); \
46 break; \
47 case 4: \
48 ____r = bswap_32(val); \
49 break; \
50 case 8: \
51 ____r = bswap_64(val); \
52 break; \
53 default: \
54 BUG_ON(1); \
55 } \
56 } \
57 ____r; \
58})
59
60#define DSO__DATA_CACHE_SIZE 4096
61#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
62
63struct dso_cache {
64 struct rb_node rb_node;
65 u64 offset;
66 u64 size;
67 char data[0];
68};
69
70struct dso {
71 struct list_head node;
72 struct rb_root symbols[MAP__NR_TYPES];
73 struct rb_root symbol_names[MAP__NR_TYPES];
74 struct rb_root cache;
75 enum dso_kernel_type kernel;
76 enum dso_swap_type needs_swap;
77 enum dso_binary_type symtab_type;
78 enum dso_binary_type data_type;
79 u8 adjust_symbols:1;
80 u8 has_build_id:1;
81 u8 hit:1;
82 u8 annotate_warned:1;
83 u8 sname_alloc:1;
84 u8 lname_alloc:1;
85 u8 sorted_by_name;
86 u8 loaded;
87 u8 build_id[BUILD_ID_SIZE];
88 const char *short_name;
89 char *long_name;
90 u16 long_name_len;
91 u16 short_name_len;
92 char name[0];
93};
94
95static inline void dso__set_loaded(struct dso *dso, enum map_type type)
96{
97 dso->loaded |= (1 << type);
98}
99
100struct dso *dso__new(const char *name);
101void dso__delete(struct dso *dso);
102
103void dso__set_short_name(struct dso *dso, const char *name);
104void dso__set_long_name(struct dso *dso, char *name);
105
106int dso__name_len(const struct dso *dso);
107
108bool dso__loaded(const struct dso *dso, enum map_type type);
109
110bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
111void dso__set_sorted_by_name(struct dso *dso, enum map_type type);
112void dso__sort_by_name(struct dso *dso, enum map_type type);
113
114void dso__set_build_id(struct dso *dso, void *build_id);
115bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
116void dso__read_running_kernel_build_id(struct dso *dso,
117 struct machine *machine);
118int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
119
120char dso__symtab_origin(const struct dso *dso);
121int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
122 char *root_dir, char *file, size_t size);
123
124int dso__data_fd(struct dso *dso, struct machine *machine);
125ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
126 u64 offset, u8 *data, ssize_t size);
127ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
128 struct machine *machine, u64 addr,
129 u8 *data, ssize_t size);
130
131struct map *dso__new_map(const char *name);
132struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
133 const char *short_name, int dso_type);
134
135void dsos__add(struct list_head *head, struct dso *dso);
136struct dso *dsos__find(struct list_head *head, const char *name);
137struct dso *__dsos__findnew(struct list_head *head, const char *name);
138bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
139
140size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
141 bool with_hits);
142size_t __dsos__fprintf(struct list_head *head, FILE *fp);
143
144size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
145size_t dso__fprintf_symbols_by_name(struct dso *dso,
146 enum map_type type, FILE *fp);
147size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
148#endif /* __PERF_DSO */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d3b1ecc00cbc..624c65e6ab98 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -23,7 +23,6 @@
23#define KSYM_NAME_LEN 256 23#define KSYM_NAME_LEN 256
24#endif 24#endif
25 25
26static void dso_cache__free(struct rb_root *root);
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 26static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 27 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -56,39 +55,6 @@ static enum dso_binary_type binary_type_symtab[] = {
56 55
57#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) 56#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
58 57
59static enum dso_binary_type binary_type_data[] = {
60 DSO_BINARY_TYPE__BUILD_ID_CACHE,
61 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
62 DSO_BINARY_TYPE__NOT_FOUND,
63};
64
65#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data)
66
67int dso__name_len(const struct dso *dso)
68{
69 if (!dso)
70 return strlen("[unknown]");
71 if (verbose)
72 return dso->long_name_len;
73
74 return dso->short_name_len;
75}
76
77bool dso__loaded(const struct dso *dso, enum map_type type)
78{
79 return dso->loaded & (1 << type);
80}
81
82bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
83{
84 return dso->sorted_by_name & (1 << type);
85}
86
87static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
88{
89 dso->sorted_by_name |= (1 << type);
90}
91
92bool symbol_type__is_a(char symbol_type, enum map_type map_type) 58bool symbol_type__is_a(char symbol_type, enum map_type map_type)
93{ 59{
94 symbol_type = toupper(symbol_type); 60 symbol_type = toupper(symbol_type);
@@ -270,7 +236,7 @@ void symbol__delete(struct symbol *sym)
270 free(((void *)sym) - symbol_conf.priv_size); 236 free(((void *)sym) - symbol_conf.priv_size);
271} 237}
272 238
273static size_t symbol__fprintf(struct symbol *sym, FILE *fp) 239size_t symbol__fprintf(struct symbol *sym, FILE *fp)
274{ 240{
275 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", 241 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
276 sym->start, sym->end, 242 sym->start, sym->end,
@@ -301,53 +267,7 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
301 return symbol__fprintf_symname_offs(sym, NULL, fp); 267 return symbol__fprintf_symname_offs(sym, NULL, fp);
302} 268}
303 269
304void dso__set_long_name(struct dso *dso, char *name) 270void symbols__delete(struct rb_root *symbols)
305{
306 if (name == NULL)
307 return;
308 dso->long_name = name;
309 dso->long_name_len = strlen(name);
310}
311
312static void dso__set_short_name(struct dso *dso, const char *name)
313{
314 if (name == NULL)
315 return;
316 dso->short_name = name;
317 dso->short_name_len = strlen(name);
318}
319
320static void dso__set_basename(struct dso *dso)
321{
322 dso__set_short_name(dso, basename(dso->long_name));
323}
324
325struct dso *dso__new(const char *name)
326{
327 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
328
329 if (dso != NULL) {
330 int i;
331 strcpy(dso->name, name);
332 dso__set_long_name(dso, dso->name);
333 dso__set_short_name(dso, dso->name);
334 for (i = 0; i < MAP__NR_TYPES; ++i)
335 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
336 dso->cache = RB_ROOT;
337 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
338 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
339 dso->loaded = 0;
340 dso->sorted_by_name = 0;
341 dso->has_build_id = 0;
342 dso->kernel = DSO_TYPE_USER;
343 dso->needs_swap = DSO_SWAP__UNSET;
344 INIT_LIST_HEAD(&dso->node);
345 }
346
347 return dso;
348}
349
350static void symbols__delete(struct rb_root *symbols)
351{ 271{
352 struct symbol *pos; 272 struct symbol *pos;
353 struct rb_node *next = rb_first(symbols); 273 struct rb_node *next = rb_first(symbols);
@@ -360,25 +280,6 @@ static void symbols__delete(struct rb_root *symbols)
360 } 280 }
361} 281}
362 282
363void dso__delete(struct dso *dso)
364{
365 int i;
366 for (i = 0; i < MAP__NR_TYPES; ++i)
367 symbols__delete(&dso->symbols[i]);
368 if (dso->sname_alloc)
369 free((char *)dso->short_name);
370 if (dso->lname_alloc)
371 free(dso->long_name);
372 dso_cache__free(&dso->cache);
373 free(dso);
374}
375
376void dso__set_build_id(struct dso *dso, void *build_id)
377{
378 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
379 dso->has_build_id = 1;
380}
381
382void symbols__insert(struct rb_root *symbols, struct symbol *sym) 283void symbols__insert(struct rb_root *symbols, struct symbol *sym)
383{ 284{
384 struct rb_node **p = &symbols->rb_node; 285 struct rb_node **p = &symbols->rb_node;
@@ -504,14 +405,6 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
504 &dso->symbols[type]); 405 &dso->symbols[type]);
505} 406}
506 407
507size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
508{
509 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
510
511 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
512 return fprintf(fp, "%s", sbuild_id);
513}
514
515size_t dso__fprintf_symbols_by_name(struct dso *dso, 408size_t dso__fprintf_symbols_by_name(struct dso *dso,
516 enum map_type type, FILE *fp) 409 enum map_type type, FILE *fp)
517{ 410{
@@ -527,25 +420,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
527 return ret; 420 return ret;
528} 421}
529 422
530size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
531{
532 struct rb_node *nd;
533 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
534
535 if (dso->short_name != dso->long_name)
536 ret += fprintf(fp, "%s, ", dso->long_name);
537 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
538 dso->loaded ? "" : "NOT ");
539 ret += dso__fprintf_buildid(dso, fp);
540 ret += fprintf(fp, ")\n");
541 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
542 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
543 ret += symbol__fprintf(pos, fp);
544 }
545
546 return ret;
547}
548
549int kallsyms__parse(const char *filename, void *arg, 423int kallsyms__parse(const char *filename, void *arg,
550 int (*process_symbol)(void *arg, const char *name, 424 int (*process_symbol)(void *arg, const char *name,
551 char type, u64 start)) 425 char type, u64 start))
@@ -877,136 +751,6 @@ out_failure:
877 return -1; 751 return -1;
878} 752}
879 753
880bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
881{
882 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
883}
884
885bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
886{
887 bool have_build_id = false;
888 struct dso *pos;
889
890 list_for_each_entry(pos, head, node) {
891 if (with_hits && !pos->hit)
892 continue;
893 if (pos->has_build_id) {
894 have_build_id = true;
895 continue;
896 }
897 if (filename__read_build_id(pos->long_name, pos->build_id,
898 sizeof(pos->build_id)) > 0) {
899 have_build_id = true;
900 pos->has_build_id = true;
901 }
902 }
903
904 return have_build_id;
905}
906
907char dso__symtab_origin(const struct dso *dso)
908{
909 static const char origin[] = {
910 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
911 [DSO_BINARY_TYPE__VMLINUX] = 'v',
912 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
913 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
914 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
915 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
916 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
917 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
918 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
919 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
920 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
921 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
922 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
923 };
924
925 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
926 return '!';
927 return origin[dso->symtab_type];
928}
929
930int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
931 char *root_dir, char *file, size_t size)
932{
933 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
934 int ret = 0;
935
936 switch (type) {
937 case DSO_BINARY_TYPE__DEBUGLINK: {
938 char *debuglink;
939
940 strncpy(file, dso->long_name, size);
941 debuglink = file + dso->long_name_len;
942 while (debuglink != file && *debuglink != '/')
943 debuglink--;
944 if (*debuglink == '/')
945 debuglink++;
946 filename__read_debuglink(dso->long_name, debuglink,
947 size - (debuglink - file));
948 }
949 break;
950 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
951 /* skip the locally configured cache if a symfs is given */
952 if (symbol_conf.symfs[0] ||
953 (dso__build_id_filename(dso, file, size) == NULL))
954 ret = -1;
955 break;
956
957 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
958 snprintf(file, size, "%s/usr/lib/debug%s.debug",
959 symbol_conf.symfs, dso->long_name);
960 break;
961
962 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
963 snprintf(file, size, "%s/usr/lib/debug%s",
964 symbol_conf.symfs, dso->long_name);
965 break;
966
967 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
968 if (!dso->has_build_id) {
969 ret = -1;
970 break;
971 }
972
973 build_id__sprintf(dso->build_id,
974 sizeof(dso->build_id),
975 build_id_hex);
976 snprintf(file, size,
977 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
978 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
979 break;
980
981 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
982 snprintf(file, size, "%s%s",
983 symbol_conf.symfs, dso->long_name);
984 break;
985
986 case DSO_BINARY_TYPE__GUEST_KMODULE:
987 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
988 root_dir, dso->long_name);
989 break;
990
991 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
992 snprintf(file, size, "%s%s", symbol_conf.symfs,
993 dso->long_name);
994 break;
995
996 default:
997 case DSO_BINARY_TYPE__KALLSYMS:
998 case DSO_BINARY_TYPE__VMLINUX:
999 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1000 case DSO_BINARY_TYPE__GUEST_VMLINUX:
1001 case DSO_BINARY_TYPE__JAVA_JIT:
1002 case DSO_BINARY_TYPE__NOT_FOUND:
1003 ret = -1;
1004 break;
1005 }
1006
1007 return ret;
1008}
1009
1010int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 754int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1011{ 755{
1012 char *name; 756 char *name;
@@ -1142,27 +886,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1142 return NULL; 886 return NULL;
1143} 887}
1144 888
1145static int dso__kernel_module_get_build_id(struct dso *dso,
1146 const char *root_dir)
1147{
1148 char filename[PATH_MAX];
1149 /*
1150 * kernel module short names are of the form "[module]" and
1151 * we need just "module" here.
1152 */
1153 const char *name = dso->short_name + 1;
1154
1155 snprintf(filename, sizeof(filename),
1156 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
1157 root_dir, (int)strlen(name) - 1, name);
1158
1159 if (sysfs__read_build_id(filename, dso->build_id,
1160 sizeof(dso->build_id)) == 0)
1161 dso->has_build_id = true;
1162
1163 return 0;
1164}
1165
1166static int map_groups__set_modules_path_dir(struct map_groups *mg, 889static int map_groups__set_modules_path_dir(struct map_groups *mg,
1167 const char *dir_name) 890 const char *dir_name)
1168{ 891{
@@ -1576,50 +1299,6 @@ out_try_fixup:
1576 return err; 1299 return err;
1577} 1300}
1578 1301
1579void dsos__add(struct list_head *head, struct dso *dso)
1580{
1581 list_add_tail(&dso->node, head);
1582}
1583
1584struct dso *dsos__find(struct list_head *head, const char *name)
1585{
1586 struct dso *pos;
1587
1588 list_for_each_entry(pos, head, node)
1589 if (strcmp(pos->long_name, name) == 0)
1590 return pos;
1591 return NULL;
1592}
1593
1594struct dso *__dsos__findnew(struct list_head *head, const char *name)
1595{
1596 struct dso *dso = dsos__find(head, name);
1597
1598 if (!dso) {
1599 dso = dso__new(name);
1600 if (dso != NULL) {
1601 dsos__add(head, dso);
1602 dso__set_basename(dso);
1603 }
1604 }
1605
1606 return dso;
1607}
1608
1609size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1610{
1611 struct dso *pos;
1612 size_t ret = 0;
1613
1614 list_for_each_entry(pos, head, node) {
1615 int i;
1616 for (i = 0; i < MAP__NR_TYPES; ++i)
1617 ret += dso__fprintf(pos, i, fp);
1618 }
1619
1620 return ret;
1621}
1622
1623size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) 1302size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
1624{ 1303{
1625 struct rb_node *nd; 1304 struct rb_node *nd;
@@ -1634,21 +1313,6 @@ size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
1634 return ret; 1313 return ret;
1635} 1314}
1636 1315
1637static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1638 bool with_hits)
1639{
1640 struct dso *pos;
1641 size_t ret = 0;
1642
1643 list_for_each_entry(pos, head, node) {
1644 if (with_hits && !pos->hit)
1645 continue;
1646 ret += dso__fprintf_buildid(pos, fp);
1647 ret += fprintf(fp, " %s\n", pos->long_name);
1648 }
1649 return ret;
1650}
1651
1652size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 1316size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
1653 bool with_hits) 1317 bool with_hits)
1654{ 1318{
@@ -1669,39 +1333,6 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
1669 return ret; 1333 return ret;
1670} 1334}
1671 1335
1672static struct dso*
1673dso__kernel_findnew(struct machine *machine, const char *name,
1674 const char *short_name, int dso_type)
1675{
1676 /*
1677 * The kernel dso could be created by build_id processing.
1678 */
1679 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
1680
1681 /*
1682 * We need to run this in all cases, since during the build_id
1683 * processing we had no idea this was the kernel dso.
1684 */
1685 if (dso != NULL) {
1686 dso__set_short_name(dso, short_name);
1687 dso->kernel = dso_type;
1688 }
1689
1690 return dso;
1691}
1692
1693void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
1694{
1695 char path[PATH_MAX];
1696
1697 if (machine__is_default_guest(machine))
1698 return;
1699 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
1700 if (sysfs__read_build_id(path, dso->build_id,
1701 sizeof(dso->build_id)) == 0)
1702 dso->has_build_id = true;
1703}
1704
1705static struct dso *machine__get_kernel(struct machine *machine) 1336static struct dso *machine__get_kernel(struct machine *machine)
1706{ 1337{
1707 const char *vmlinux_name = NULL; 1338 const char *vmlinux_name = NULL;
@@ -2144,229 +1775,3 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
2144 1775
2145 return ret; 1776 return ret;
2146} 1777}
2147
2148struct map *dso__new_map(const char *name)
2149{
2150 struct map *map = NULL;
2151 struct dso *dso = dso__new(name);
2152
2153 if (dso)
2154 map = map__new2(0, dso, MAP__FUNCTION);
2155
2156 return map;
2157}
2158
2159static int open_dso(struct dso *dso, struct machine *machine)
2160{
2161 char *root_dir = (char *) "";
2162 char *name;
2163 int fd;
2164
2165 name = malloc(PATH_MAX);
2166 if (!name)
2167 return -ENOMEM;
2168
2169 if (machine)
2170 root_dir = machine->root_dir;
2171
2172 if (dso__binary_type_file(dso, dso->data_type,
2173 root_dir, name, PATH_MAX)) {
2174 free(name);
2175 return -EINVAL;
2176 }
2177
2178 fd = open(name, O_RDONLY);
2179 free(name);
2180 return fd;
2181}
2182
2183int dso__data_fd(struct dso *dso, struct machine *machine)
2184{
2185 int i = 0;
2186
2187 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
2188 return open_dso(dso, machine);
2189
2190 do {
2191 int fd;
2192
2193 dso->data_type = binary_type_data[i++];
2194
2195 fd = open_dso(dso, machine);
2196 if (fd >= 0)
2197 return fd;
2198
2199 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
2200
2201 return -EINVAL;
2202}
2203
2204static void
2205dso_cache__free(struct rb_root *root)
2206{
2207 struct rb_node *next = rb_first(root);
2208
2209 while (next) {
2210 struct dso_cache *cache;
2211
2212 cache = rb_entry(next, struct dso_cache, rb_node);
2213 next = rb_next(&cache->rb_node);
2214 rb_erase(&cache->rb_node, root);
2215 free(cache);
2216 }
2217}
2218
2219static struct dso_cache*
2220dso_cache__find(struct rb_root *root, u64 offset)
2221{
2222 struct rb_node **p = &root->rb_node;
2223 struct rb_node *parent = NULL;
2224 struct dso_cache *cache;
2225
2226 while (*p != NULL) {
2227 u64 end;
2228
2229 parent = *p;
2230 cache = rb_entry(parent, struct dso_cache, rb_node);
2231 end = cache->offset + DSO__DATA_CACHE_SIZE;
2232
2233 if (offset < cache->offset)
2234 p = &(*p)->rb_left;
2235 else if (offset >= end)
2236 p = &(*p)->rb_right;
2237 else
2238 return cache;
2239 }
2240 return NULL;
2241}
2242
2243static void
2244dso_cache__insert(struct rb_root *root, struct dso_cache *new)
2245{
2246 struct rb_node **p = &root->rb_node;
2247 struct rb_node *parent = NULL;
2248 struct dso_cache *cache;
2249 u64 offset = new->offset;
2250
2251 while (*p != NULL) {
2252 u64 end;
2253
2254 parent = *p;
2255 cache = rb_entry(parent, struct dso_cache, rb_node);
2256 end = cache->offset + DSO__DATA_CACHE_SIZE;
2257
2258 if (offset < cache->offset)
2259 p = &(*p)->rb_left;
2260 else if (offset >= end)
2261 p = &(*p)->rb_right;
2262 }
2263
2264 rb_link_node(&new->rb_node, parent, p);
2265 rb_insert_color(&new->rb_node, root);
2266}
2267
2268static ssize_t
2269dso_cache__memcpy(struct dso_cache *cache, u64 offset,
2270 u8 *data, u64 size)
2271{
2272 u64 cache_offset = offset - cache->offset;
2273 u64 cache_size = min(cache->size - cache_offset, size);
2274
2275 memcpy(data, cache->data + cache_offset, cache_size);
2276 return cache_size;
2277}
2278
2279static ssize_t
2280dso_cache__read(struct dso *dso, struct machine *machine,
2281 u64 offset, u8 *data, ssize_t size)
2282{
2283 struct dso_cache *cache;
2284 ssize_t ret;
2285 int fd;
2286
2287 fd = dso__data_fd(dso, machine);
2288 if (fd < 0)
2289 return -1;
2290
2291 do {
2292 u64 cache_offset;
2293
2294 ret = -ENOMEM;
2295
2296 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
2297 if (!cache)
2298 break;
2299
2300 cache_offset = offset & DSO__DATA_CACHE_MASK;
2301 ret = -EINVAL;
2302
2303 if (-1 == lseek(fd, cache_offset, SEEK_SET))
2304 break;
2305
2306 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
2307 if (ret <= 0)
2308 break;
2309
2310 cache->offset = cache_offset;
2311 cache->size = ret;
2312 dso_cache__insert(&dso->cache, cache);
2313
2314 ret = dso_cache__memcpy(cache, offset, data, size);
2315
2316 } while (0);
2317
2318 if (ret <= 0)
2319 free(cache);
2320
2321 close(fd);
2322 return ret;
2323}
2324
2325static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
2326 u64 offset, u8 *data, ssize_t size)
2327{
2328 struct dso_cache *cache;
2329
2330 cache = dso_cache__find(&dso->cache, offset);
2331 if (cache)
2332 return dso_cache__memcpy(cache, offset, data, size);
2333 else
2334 return dso_cache__read(dso, machine, offset, data, size);
2335}
2336
2337ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
2338 u64 offset, u8 *data, ssize_t size)
2339{
2340 ssize_t r = 0;
2341 u8 *p = data;
2342
2343 do {
2344 ssize_t ret;
2345
2346 ret = dso_cache_read(dso, machine, offset, p, size);
2347 if (ret < 0)
2348 return ret;
2349
2350 /* Reached EOF, return what we have. */
2351 if (!ret)
2352 break;
2353
2354 BUG_ON(ret > size);
2355
2356 r += ret;
2357 p += ret;
2358 offset += ret;
2359 size -= ret;
2360
2361 } while (size);
2362
2363 return r;
2364}
2365
2366ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
2367 struct machine *machine, u64 addr,
2368 u8 *data, ssize_t size)
2369{
2370 u64 offset = map->map_ip(map, addr);
2371 return dso__data_read_offset(dso, machine, offset, data, size);
2372}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 45d3df8d36d0..863b05bea5ff 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -19,6 +19,8 @@
19#include <elf.h> 19#include <elf.h>
20#endif 20#endif
21 21
22#include "dso.h"
23
22#ifdef HAVE_CPLUS_DEMANGLE 24#ifdef HAVE_CPLUS_DEMANGLE
23extern char *cplus_demangle(const char *, int); 25extern char *cplus_demangle(const char *, int);
24 26
@@ -70,6 +72,7 @@ struct symbol {
70}; 72};
71 73
72void symbol__delete(struct symbol *sym); 74void symbol__delete(struct symbol *sym);
75void symbols__delete(struct rb_root *symbols);
73 76
74static inline size_t symbol__size(const struct symbol *sym) 77static inline size_t symbol__size(const struct symbol *sym)
75{ 78{
@@ -160,70 +163,6 @@ struct addr_location {
160 s32 cpu; 163 s32 cpu;
161}; 164};
162 165
163enum dso_binary_type {
164 DSO_BINARY_TYPE__KALLSYMS = 0,
165 DSO_BINARY_TYPE__GUEST_KALLSYMS,
166 DSO_BINARY_TYPE__VMLINUX,
167 DSO_BINARY_TYPE__GUEST_VMLINUX,
168 DSO_BINARY_TYPE__JAVA_JIT,
169 DSO_BINARY_TYPE__DEBUGLINK,
170 DSO_BINARY_TYPE__BUILD_ID_CACHE,
171 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
172 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
173 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
174 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
175 DSO_BINARY_TYPE__GUEST_KMODULE,
176 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
177 DSO_BINARY_TYPE__NOT_FOUND,
178};
179
180enum dso_kernel_type {
181 DSO_TYPE_USER = 0,
182 DSO_TYPE_KERNEL,
183 DSO_TYPE_GUEST_KERNEL
184};
185
186enum dso_swap_type {
187 DSO_SWAP__UNSET,
188 DSO_SWAP__NO,
189 DSO_SWAP__YES,
190};
191
192#define DSO__DATA_CACHE_SIZE 4096
193#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
194
195struct dso_cache {
196 struct rb_node rb_node;
197 u64 offset;
198 u64 size;
199 char data[0];
200};
201
202struct dso {
203 struct list_head node;
204 struct rb_root symbols[MAP__NR_TYPES];
205 struct rb_root symbol_names[MAP__NR_TYPES];
206 struct rb_root cache;
207 enum dso_kernel_type kernel;
208 enum dso_swap_type needs_swap;
209 enum dso_binary_type symtab_type;
210 enum dso_binary_type data_type;
211 u8 adjust_symbols:1;
212 u8 has_build_id:1;
213 u8 hit:1;
214 u8 annotate_warned:1;
215 u8 sname_alloc:1;
216 u8 lname_alloc:1;
217 u8 sorted_by_name;
218 u8 loaded;
219 u8 build_id[BUILD_ID_SIZE];
220 const char *short_name;
221 char *long_name;
222 u16 long_name_len;
223 u16 short_name_len;
224 char name[0];
225};
226
227struct symsrc { 166struct symsrc {
228 char *name; 167 char *name;
229 int fd; 168 int fd;
@@ -254,47 +193,6 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
254bool symsrc__has_symtab(struct symsrc *ss); 193bool symsrc__has_symtab(struct symsrc *ss);
255bool symsrc__possibly_runtime(struct symsrc *ss); 194bool symsrc__possibly_runtime(struct symsrc *ss);
256 195
257#define DSO__SWAP(dso, type, val) \
258({ \
259 type ____r = val; \
260 BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
261 if (dso->needs_swap == DSO_SWAP__YES) { \
262 switch (sizeof(____r)) { \
263 case 2: \
264 ____r = bswap_16(val); \
265 break; \
266 case 4: \
267 ____r = bswap_32(val); \
268 break; \
269 case 8: \
270 ____r = bswap_64(val); \
271 break; \
272 default: \
273 BUG_ON(1); \
274 } \
275 } \
276 ____r; \
277})
278
279struct dso *dso__new(const char *name);
280void dso__delete(struct dso *dso);
281
282int dso__name_len(const struct dso *dso);
283
284bool dso__loaded(const struct dso *dso, enum map_type type);
285bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
286
287static inline void dso__set_loaded(struct dso *dso, enum map_type type)
288{
289 dso->loaded |= (1 << type);
290}
291
292void dso__sort_by_name(struct dso *dso, enum map_type type);
293
294void dsos__add(struct list_head *head, struct dso *dso);
295struct dso *dsos__find(struct list_head *head, const char *name);
296struct dso *__dsos__findnew(struct list_head *head, const char *name);
297
298int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 196int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
299int dso__load_vmlinux(struct dso *dso, struct map *map, 197int dso__load_vmlinux(struct dso *dso, struct map *map,
300 const char *vmlinux, symbol_filter_t filter); 198 const char *vmlinux, symbol_filter_t filter);
@@ -307,25 +205,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
307int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 205int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
308 symbol_filter_t filter); 206 symbol_filter_t filter);
309 207
310size_t __dsos__fprintf(struct list_head *head, FILE *fp);
311
312size_t machine__fprintf_dsos_buildid(struct machine *machine, 208size_t machine__fprintf_dsos_buildid(struct machine *machine,
313 FILE *fp, bool with_hits); 209 FILE *fp, bool with_hits);
314size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); 210size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
315size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 211size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
316 FILE *fp, bool with_hits); 212 FILE *fp, bool with_hits);
317size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 213
318size_t dso__fprintf_symbols_by_name(struct dso *dso,
319 enum map_type type, FILE *fp);
320size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
321
322char dso__symtab_origin(const struct dso *dso);
323void dso__set_long_name(struct dso *dso, char *name);
324void dso__set_build_id(struct dso *dso, void *build_id);
325bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
326void dso__read_running_kernel_build_id(struct dso *dso,
327 struct machine *machine);
328struct map *dso__new_map(const char *name);
329struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 214struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
330 u64 addr); 215 u64 addr);
331struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 216struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -333,7 +218,6 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
333 218
334int filename__read_build_id(const char *filename, void *bf, size_t size); 219int filename__read_build_id(const char *filename, void *bf, size_t size);
335int sysfs__read_build_id(const char *filename, void *bf, size_t size); 220int sysfs__read_build_id(const char *filename, void *bf, size_t size);
336bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
337int kallsyms__parse(const char *filename, void *arg, 221int kallsyms__parse(const char *filename, void *arg,
338 int (*process_symbol)(void *arg, const char *name, 222 int (*process_symbol)(void *arg, const char *name,
339 char type, u64 start)); 223 char type, u64 start));
@@ -355,19 +239,11 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
355size_t symbol__fprintf_symname_offs(const struct symbol *sym, 239size_t symbol__fprintf_symname_offs(const struct symbol *sym,
356 const struct addr_location *al, FILE *fp); 240 const struct addr_location *al, FILE *fp);
357size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 241size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
242size_t symbol__fprintf(struct symbol *sym, FILE *fp);
358bool symbol_type__is_a(char symbol_type, enum map_type map_type); 243bool symbol_type__is_a(char symbol_type, enum map_type map_type);
359 244
360size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 245size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
361 246
362int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
363 char *root_dir, char *file, size_t size);
364
365int dso__data_fd(struct dso *dso, struct machine *machine);
366ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
367 u64 offset, u8 *data, ssize_t size);
368ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
369 struct machine *machine, u64 addr,
370 u8 *data, ssize_t size);
371int dso__test_data(void); 247int dso__test_data(void);
372int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 248int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
373 struct symsrc *runtime_ss, symbol_filter_t filter, 249 struct symsrc *runtime_ss, symbol_filter_t filter,