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: He Kuang <hekuang@huawei.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Arnaldo 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: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
He Kuang 2016-05-17 09:04:54 +00:00 committed by Arnaldo Carvalho de Melo
parent 41840d211c
commit 76c588f1f6
1 changed files with 37 additions and 3 deletions

View File

@ -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;