diff options
author | Jiri Olsa <jolsa@redhat.com> | 2012-10-27 17:18:32 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-29 09:37:25 -0400 |
commit | cdd059d731eeb466f51a404ee6cbfafb0fc7c20b (patch) | |
tree | 36346ccb768ee0b8642b79bef6c7ad723a203a12 /tools/perf/util/symbol.c | |
parent | ea36c46be69c6e49c877971c4b3b3876b24b6082 (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>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 599 |
1 files changed, 2 insertions, 597 deletions
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 | ||
26 | static void dso_cache__free(struct rb_root *root); | ||
27 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, | 26 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, |
28 | symbol_filter_t filter); | 27 | symbol_filter_t filter); |
29 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | 28 | static 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 | ||
59 | static 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 | |||
67 | int 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 | |||
77 | bool dso__loaded(const struct dso *dso, enum map_type type) | ||
78 | { | ||
79 | return dso->loaded & (1 << type); | ||
80 | } | ||
81 | |||
82 | bool dso__sorted_by_name(const struct dso *dso, enum map_type type) | ||
83 | { | ||
84 | return dso->sorted_by_name & (1 << type); | ||
85 | } | ||
86 | |||
87 | static void dso__set_sorted_by_name(struct dso *dso, enum map_type type) | ||
88 | { | ||
89 | dso->sorted_by_name |= (1 << type); | ||
90 | } | ||
91 | |||
92 | bool symbol_type__is_a(char symbol_type, enum map_type map_type) | 58 | bool 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 | ||
273 | static size_t symbol__fprintf(struct symbol *sym, FILE *fp) | 239 | size_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 | ||
304 | void dso__set_long_name(struct dso *dso, char *name) | 270 | void 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 | |||
312 | static 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 | |||
320 | static void dso__set_basename(struct dso *dso) | ||
321 | { | ||
322 | dso__set_short_name(dso, basename(dso->long_name)); | ||
323 | } | ||
324 | |||
325 | struct 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 | |||
350 | static 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 | ||
363 | void 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 | |||
376 | void 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 | |||
382 | void symbols__insert(struct rb_root *symbols, struct symbol *sym) | 283 | void 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 | ||
507 | size_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 | |||
515 | size_t dso__fprintf_symbols_by_name(struct dso *dso, | 408 | size_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 | ||
530 | size_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 | |||
549 | int kallsyms__parse(const char *filename, void *arg, | 423 | int 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 | ||
880 | bool 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 | |||
885 | bool __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 | |||
907 | char 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 | |||
930 | int 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 | |||
1010 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | 754 | int 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 | ||
1145 | static 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 | |||
1166 | static int map_groups__set_modules_path_dir(struct map_groups *mg, | 889 | static 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 | ||
1579 | void dsos__add(struct list_head *head, struct dso *dso) | ||
1580 | { | ||
1581 | list_add_tail(&dso->node, head); | ||
1582 | } | ||
1583 | |||
1584 | struct 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 | |||
1594 | struct 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 | |||
1609 | size_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 | |||
1623 | size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) | 1302 | size_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 | ||
1637 | static 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 | |||
1652 | size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, | 1316 | size_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 | ||
1672 | static struct dso* | ||
1673 | dso__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 | |||
1693 | void 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 | |||
1705 | static struct dso *machine__get_kernel(struct machine *machine) | 1336 | static 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 | |||
2148 | struct 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 | |||
2159 | static 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 | |||
2183 | int 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 | |||
2204 | static void | ||
2205 | dso_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 | |||
2219 | static struct dso_cache* | ||
2220 | dso_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 | |||
2243 | static void | ||
2244 | dso_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 | |||
2268 | static ssize_t | ||
2269 | dso_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 | |||
2279 | static ssize_t | ||
2280 | dso_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 | |||
2325 | static 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 | |||
2337 | ssize_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 | |||
2366 | ssize_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 | } | ||