aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
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 /tools/perf/util/symbol.c
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>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c599
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
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}