Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7dbf4dcf authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Back [vdso] DSO with real data



Storing data for VDSO shared object, because we need it for the post
unwind processing.

The VDSO shared object is same for all process on a running system, so
it makes no difference when we store it inside the tracer - perf.

When [vdso] map memory is hit, we retrieve [vdso] DSO image and store it
into temporary file.

During the build-id processing phase, the [vdso] DSO image is stored in
build-id db, and build-id reference is made inside perf.data. The
build-id vdso file object is called '[vdso]'. We don't use temporary
file name which gets removed when record is finished.

During report phase the vdso build-id object is treated as any other
build-id DSO object.

Adding following API for vdso object:

  bool is_vdso_map(const char *filename)
    - returns true if the filename matches vdso map name

  struct dso *vdso__dso_findnew(struct list_head *head)
    - find/create proper vdso DSO object

  vdso__exit(void)
    - removes temporary VDSO image if there's any

This change makes backtrace dwarf post unwind possible from [vdso] maps.

Following output is current report of [vdso] sample dwarf backtrace:

  # Overhead  Command      Shared Object                         Symbol
  # ........  .......  .................  .............................
  #
      99.52%       ex  [vdso]             [.] 0x00007fff3ace89af
                   |
                   --- 0x7fff3ace89af

Following output is new report of [vdso] sample dwarf backtrace:

  # Overhead  Command      Shared Object                         Symbol
  # ........  .......  .................  .............................
  #
      99.52%       ex  [vdso]             [.] 0x00000000000009af
                   |
                   --- 0x7fff3ace89af
                       main
                       __libc_start_main
                       _start

Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1347295819-23177-5-git-send-email-jolsa@redhat.com


[ committer note: s/ALIGN/PERF_ALIGN/g to cope with the android build changes ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 1c4be9ff
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -337,6 +337,7 @@ LIB_H += util/intlist.h
LIB_H += util/perf_regs.h
LIB_H += util/unwind.h
LIB_H += ui/helpline.h
LIB_H += util/vdso.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -404,6 +405,7 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o

LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/hist.o
+2 −1
Original line number Diff line number Diff line
@@ -43,7 +43,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
	}

	build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
	err = build_id_cache__add_s(sbuild_id, debugdir, filename, false);
	err = build_id_cache__add_s(sbuild_id, debugdir, filename,
				    false, false);
	if (verbose)
		pr_info("Adding %s %s: %s\n", sbuild_id, filename,
			err ? "FAIL" : "Ok");
+49 −21
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "debug.h"
#include "cpumap.h"
#include "pmu.h"
#include "vdso.h"

static bool no_buildid_cache = false;

@@ -207,31 +208,53 @@ perf_header__set_cmdline(int argc, const char **argv)
			continue;		\
		else

static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
				u16 misc, int fd)
static int write_buildid(char *name, size_t name_len, u8 *build_id,
			 pid_t pid, u16 misc, int fd)
{
	struct dso *pos;

	dsos__for_each_with_build_id(pos, head) {
	int err;
	struct build_id_event b;
	size_t len;

		if (!pos->hit)
			continue;
		len = pos->long_name_len + 1;
	len = name_len + 1;
	len = PERF_ALIGN(len, NAME_ALIGN);

	memset(&b, 0, sizeof(b));
		memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
	memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
	b.pid = pid;
	b.header.misc = misc;
	b.header.size = sizeof(b) + len;

	err = do_write(fd, &b, sizeof(b));
	if (err < 0)
		return err;
		err = write_padded(fd, pos->long_name,
				   pos->long_name_len + 1, len);
		if (err < 0)

	return write_padded(fd, name, name_len + 1, len);
}

static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
				u16 misc, int fd)
{
	struct dso *pos;

	dsos__for_each_with_build_id(pos, head) {
		int err;
		char  *name;
		size_t name_len;

		if (!pos->hit)
			continue;

		if (is_vdso_map(pos->short_name)) {
			name = (char *) VDSO__MAP_NAME;
			name_len = sizeof(VDSO__MAP_NAME) + 1;
		} else {
			name = pos->long_name;
			name_len = pos->long_name_len + 1;
		}

		err = write_buildid(name, name_len, pos->build_id,
				    pid, misc, fd);
		if (err)
			return err;
	}

@@ -277,12 +300,13 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
}

int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
			  const char *name, bool is_kallsyms)
			  const char *name, bool is_kallsyms, bool is_vdso)
{
	const size_t size = PATH_MAX;
	char *realname, *filename = zalloc(size),
	     *linkname = zalloc(size), *targetname;
	int len, err = -1;
	bool slash = is_kallsyms || is_vdso;

	if (is_kallsyms) {
		if (symbol_conf.kptr_restrict) {
@@ -297,7 +321,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
		goto out_free;

	len = scnprintf(filename, size, "%s%s%s",
		       debugdir, is_kallsyms ? "/" : "", realname);
		       debugdir, slash ? "/" : "",
		       is_vdso ? VDSO__MAP_NAME : realname);
	if (mkdir_p(filename, 0755))
		goto out_free;

@@ -333,13 +358,14 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,

static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
				 const char *name, const char *debugdir,
				 bool is_kallsyms)
				 bool is_kallsyms, bool is_vdso)
{
	char sbuild_id[BUILD_ID_SIZE * 2 + 1];

	build_id__sprintf(build_id, build_id_size, sbuild_id);

	return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
	return build_id_cache__add_s(sbuild_id, debugdir, name,
				     is_kallsyms, is_vdso);
}

int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
@@ -383,9 +409,11 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
static int dso__cache_build_id(struct dso *dso, const char *debugdir)
{
	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
	bool is_vdso = is_vdso_map(dso->short_name);

	return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
				     dso->long_name, debugdir, is_kallsyms);
				     dso->long_name, debugdir,
				     is_kallsyms, is_vdso);
}

static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);

int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
			  const char *name, bool is_kallsyms);
			  const char *name, bool is_kallsyms, bool is_vdso);
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);

int perf_event__synthesize_attr(struct perf_tool *tool,
+9 −3
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include "map.h"
#include "thread.h"
#include "strlist.h"
#include "vdso.h"

const char *map_type__name[MAP__NR_TYPES] = {
	[MAP__FUNCTION] = "Functions",
@@ -23,7 +24,6 @@ static inline int is_anon_memory(const char *filename)
static inline int is_no_dso_memory(const char *filename)
{
	return !strcmp(filename, "[stack]") ||
	       !strcmp(filename, "[vdso]")  ||
	       !strcmp(filename, "[heap]");
}

@@ -52,9 +52,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
	if (self != NULL) {
		char newfilename[PATH_MAX];
		struct dso *dso;
		int anon, no_dso;
		int anon, no_dso, vdso;

		anon = is_anon_memory(filename);
		vdso = is_vdso_map(filename);
		no_dso = is_no_dso_memory(filename);

		if (anon) {
@@ -62,7 +63,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
			filename = newfilename;
		}

		if (vdso) {
			pgoff = 0;
			dso = vdso__dso_findnew(dsos__list);
		} else
			dso = __dsos__findnew(dsos__list, filename);

		if (dso == NULL)
			goto out_delete;

Loading