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

Commit 76c588f1 authored by He Kuang's avatar He Kuang Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Find right DSO taking into account if binary is 32 or 64-bit



There's a problem in machine__findnew_vdso(), vdso buildid generated by a
32-bit machine stores it with the name 'vdso', but when processing buildid on a
64-bit machine with the same 'perf.data', perf will search for vdso named as
'vdso32' and get failed.

This patch tries to find the existing dsos in machine->dsos by thread dso_type.
64-bit thread tries to find vdso with name 'vdso', because all 64-bit vdso is
named as that. 32-bit thread first tries to find vdso with name 'vdso32' if
this thread was run on 64-bit machine, if failed, then it tries 'vdso' which
indicates that the thread was run on 32-bit machine when recording.

Committer note:

Additional explanation by Adrian Hunter:

We match maps to builds ids using the file name - consider
machine__findnew_[v]dso() called in map__new().  So in the context of a perf
data file, we consider the file name to be unique.

A vdso map does not have a file name - all we know is that it is vdso.  We look
at the thread to tell if it is 32-bit, 64-bit or x32.  Then we need to get the
build id which has been recorded using short name "[vdso]" or "[vdso32]" or
"[vdsox32]".

The problem is that on a 32-bit machine, we use the name "[vdso]".  If you take
a 32-bit perf data file to a 64-bit machine, it gets hard to figure out if
"[vdso]" is 32-bit or 64-bit.

This patch solves that problem.

 ----

This also merges a followup patch fixing a problem introduced by the
original submission of this patch, that would crash 'perf record' when
recording samples for a 32-bit app on a 64-bit system.

Signed-off-by: default avatarHe Kuang <hekuang@huawei.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1463475894-163531-1-git-send-email-hekuang@huawei.com
Link: http://lkml.kernel.org/r/1466578626-92406-6-git-send-email-hekuang@huawei.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 41840d21
Loading
Loading
Loading
Loading
+37 −3
Original line number Diff line number Diff line
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
	return dso;
}

#if BITS_PER_LONG == 64

static enum dso_type machine__thread_dso_type(struct machine *machine,
					      struct thread *thread)
{
@@ -156,6 +154,8 @@ static enum dso_type machine__thread_dso_type(struct machine *machine,
	return dso_type;
}

#if BITS_PER_LONG == 64

static int vdso__do_copy_compat(FILE *f, int fd)
{
	char buf[4096];
@@ -283,8 +283,38 @@ static int __machine__findnew_vdso_compat(struct machine *machine,

#endif

static struct dso *machine__find_vdso(struct machine *machine,
				      struct thread *thread)
{
	struct dso *dso = NULL;
	enum dso_type dso_type;

	dso_type = machine__thread_dso_type(machine, thread);
	switch (dso_type) {
	case DSO__TYPE_32BIT:
		dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
		if (!dso) {
			dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO,
					   true);
			if (dso && dso_type != dso__type(dso, machine))
				dso = NULL;
		}
		break;
	case DSO__TYPE_X32BIT:
		dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
		break;
	case DSO__TYPE_64BIT:
	case DSO__TYPE_UNKNOWN:
	default:
		dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
		break;
	}

	return dso;
}

struct dso *machine__findnew_vdso(struct machine *machine,
				  struct thread *thread __maybe_unused)
				  struct thread *thread)
{
	struct vdso_info *vdso_info;
	struct dso *dso = NULL;
@@ -297,6 +327,10 @@ struct dso *machine__findnew_vdso(struct machine *machine,
	if (!vdso_info)
		goto out_unlock;

	dso = machine__find_vdso(machine, thread);
	if (dso)
		goto out_unlock;

#if BITS_PER_LONG == 64
	if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
		goto out_unlock;