Commit-ID:  949d160b6962c13fc071afefa22997780fcc94a5
Gitweb:     http://git.kernel.org/tip/949d160b6962c13fc071afefa22997780fcc94a5
Author:     Jiri Olsa <jo...@redhat.com>
AuthorDate: Sun, 22 Jul 2012 14:14:33 +0200
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Wed, 25 Jul 2012 11:32:49 -0300

perf symbols: Add interface to read DSO image data

Adding following interface for DSO object to allow
reading of DSO image data:

  dso__data_fd
    - opens DSO and returns file descriptor
      Binary types are used to locate/open DSO in following order:
        DSO_BINARY_TYPE__BUILD_ID_CACHE
        DSO_BINARY_TYPE__SYSTEM_PATH_DSO
      In other word we first try to open DSO build-id path,
      and if that fails we try to open DSO system path.

  dso__data_read_offset
    - reads DSO data from specified offset

  dso__data_read_addr
    - reads DSO data from specified address/map.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Arun Sharma <asha...@fb.com>
Cc: Benjamin Redelings <benjamin.redeli...@nescent.org>
Cc: Corey Ashford <cjash...@linux.vnet.ibm.com>
Cc: Cyrill Gorcunov <gorcu...@openvz.org>
Cc: Frank Ch. Eigler <f...@redhat.com>
Cc: Frederic Weisbecker <fweis...@gmail.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu...@hitachi.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zijls...@chello.nl>
Cc: Robert Richter <robert.rich...@amd.com>
Cc: Stephane Eranian <eran...@google.com>
Cc: Tom Zanussi <tzanu...@gmail.com>
Cc: Ulrich Drepper <drep...@gmail.com>
Link: 
http://lkml.kernel.org/r/1342959280-5361-11-git-send-email-jo...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/util/symbol.c |  109 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/symbol.h |    8 +++
 2 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 60677a6..8131949 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -65,6 +65,14 @@ static enum dso_binary_type binary_type_symtab[] = {
 
 #define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab)
 
+static enum dso_binary_type binary_type_data[] = {
+       DSO_BINARY_TYPE__BUILD_ID_CACHE,
+       DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
+       DSO_BINARY_TYPE__NOT_FOUND,
+};
+
+#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data)
+
 int dso__name_len(const struct dso *dso)
 {
        if (!dso)
@@ -336,6 +344,7 @@ struct dso *dso__new(const char *name)
                for (i = 0; i < MAP__NR_TYPES; ++i)
                        dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
                dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
+               dso->data_type   = DSO_BINARY_TYPE__NOT_FOUND;
                dso->loaded = 0;
                dso->sorted_by_name = 0;
                dso->has_build_id = 0;
@@ -2953,3 +2962,103 @@ struct map *dso__new_map(const char *name)
 
        return map;
 }
+
+static int open_dso(struct dso *dso, struct machine *machine)
+{
+       char *root_dir = (char *) "";
+       char *name;
+       int fd;
+
+       name = malloc(PATH_MAX);
+       if (!name)
+               return -ENOMEM;
+
+       if (machine)
+               root_dir = machine->root_dir;
+
+       if (dso__binary_type_file(dso, dso->data_type,
+                                 root_dir, name, PATH_MAX)) {
+               free(name);
+               return -EINVAL;
+       }
+
+       fd = open(name, O_RDONLY);
+       free(name);
+       return fd;
+}
+
+int dso__data_fd(struct dso *dso, struct machine *machine)
+{
+       int i = 0;
+
+       if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
+               return open_dso(dso, machine);
+
+       do {
+               int fd;
+
+               dso->data_type = binary_type_data[i++];
+
+               fd = open_dso(dso, machine);
+               if (fd >= 0)
+                       return fd;
+
+       } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
+
+       return -EINVAL;
+}
+
+static ssize_t dso_cache_read(struct dso *dso __used, u64 offset __used,
+                             u8 *data __used, ssize_t size __used)
+{
+       return -EINVAL;
+}
+
+static int dso_cache_add(struct dso *dso __used, u64 offset __used,
+                        u8 *data __used, ssize_t size __used)
+{
+       return 0;
+}
+
+static ssize_t read_dso_data(struct dso *dso, struct machine *machine,
+                    u64 offset, u8 *data, ssize_t size)
+{
+       ssize_t rsize = -1;
+       int fd;
+
+       fd = dso__data_fd(dso, machine);
+       if (fd < 0)
+               return -1;
+
+       do {
+               if (-1 == lseek(fd, offset, SEEK_SET))
+                       break;
+
+               rsize = read(fd, data, size);
+               if (-1 == rsize)
+                       break;
+
+               if (dso_cache_add(dso, offset, data, size))
+                       pr_err("Failed to add data int dso cache.");
+
+       } while (0);
+
+       close(fd);
+       return rsize;
+}
+
+ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
+                             u64 offset, u8 *data, ssize_t size)
+{
+       if (dso_cache_read(dso, offset, data, size))
+               return read_dso_data(dso, machine, offset, data, size);
+       return 0;
+}
+
+ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
+                           struct machine *machine, u64 addr,
+                           u8 *data, ssize_t size)
+{
+       u64 offset = map->map_ip(map, addr);
+       return dso__data_read_offset(dso, machine, offset, data, size);
+}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index dc474f0..9b9ea00 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -189,6 +189,7 @@ struct dso {
        enum dso_kernel_type    kernel;
        enum dso_swap_type      needs_swap;
        enum dso_binary_type    symtab_type;
+       enum dso_binary_type    data_type;
        u8               adjust_symbols:1;
        u8               has_build_id:1;
        u8               hit:1;
@@ -306,4 +307,11 @@ size_t machine__fprintf_vmlinux_path(struct machine 
*machine, FILE *fp);
 
 int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
                          char *root_dir, char *file, size_t size);
+
+int dso__data_fd(struct dso *dso, struct machine *machine);
+ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
+                             u64 offset, u8 *data, ssize_t size);
+ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
+                           struct machine *machine, u64 addr,
+                           u8 *data, ssize_t size);
 #endif /* __PERF_SYMBOL */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to