Commit 949d160b authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarJiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Benjamin Redelings <benjamin.redelings@nescent.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Ulrich Drepper <drepper@gmail.com>
Link: http://lkml.kernel.org/r/1342959280-5361-11-git-send-email-jolsa@redhat.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 44f24cb3
Loading
Loading
Loading
Loading
+109 −0
Original line number Diff line number Diff line
@@ -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);
}
+8 −0
Original line number Diff line number Diff line
@@ -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 */