Add support for remote unwind
Subsystems (2)
v3 cover Add support for remote unwind
v2 url:
http://thread.gmane.org/gmane.linux.kernel/2218373
Currently, perf script uses host unwind methods(local unwind) to parse perf.data callchain info regardless of the target architecture. So we get wrong result and no promotion when do remote unwind on other platforms/machines.
This patchset adds build tests for the supported platforms for remote unwinding, and checks whether a dso is 32-bit or 64-bit according to elf class info for each thread to let perf use the correct remote unwind methods instead.
Only x86 and aarch64 is added in this patchset to show the work flow, other platforms can be added easily.
We can see the right result for unwind info on different machines, for
example: perf.data recorded on i686 qemu with '-g' option and parsed on x86_64 machine.
before this patchset:
hello 1219 [001] 72190.667975: probe:sys_close: (c1169d60)
c1169d61 sys_close ([kernel.kallsyms])
c189c0d7 sysenter_past_esp ([kernel.kallsyms])
b777aba9 [unknown] ([vdso32])after:
(Add vdso into buildid-cache first by 'perf buildid-cache -a' and libraries are provided in symfs dir)
hello 1219 [001] 72190.667975: probe:sys_close: (c1169d60)
c1169d61 sys_close ([kernel.kallsyms])
c189c0d7 sysenter_past_esp ([kernel.kallsyms])
b777aba9 __kernel_vsyscall ([vdso32])
b76971cc close (/lib/libc-2.22.so)
804842e fib (/tmp/hello)
804849d main (/tmp/hello)
b75d746e __libc_start_main (/lib/libc-2.22.so)
8048341 _start (/tmp/hello)v3:
- Remove --vdso option, store vdso buildid in perf.data and let perf fetch it automatically.
- Use existing dso__type() function to test if dso is 32-bit or 64-bit.
v2:
- Explain the reason why we can omit dwarf judgement when recording in commit message.
- Elaborate on why we need to add a custom vdso path option, and change the type name to DSO_BINARY_TYPE__VDSO.
- Hide the build tests status for cross platform unwind.
- Keep generic version of libunwind-debug-frame test.
- Put 32/64-bit test functions into separate patch.
- Extract unwind related functions to unwind-libunwind.c and add new file for common parts used by both local and remote unwind.
- Eliminate most of the ifdefs in .c file.
Thanks.
He Kuang (7):
perf tools: Set vdso name to vdso[64,32] depending on platform perf tools: Store vdso buildid unconditionally
perf tools: Remove the logical that skip buildid cache if symfs is
given
perf tools: Promote proper messages for cross-platform unwind perf callchain: Add support for cross-platform unwind perf callchain: Support x86 target platform
perf callchain: Support aarch64 cross-platform
.../arch/arm64/include/libunwind/libunwind-arch.h | 18 ++++ tools/perf/arch/arm64/util/unwind-libunwind.c | 5 +- .../arch/x86/include/libunwind/libunwind-arch.h | 18 ++++ tools/perf/arch/x86/util/unwind-libunwind.c | 42 ++++++++ tools/perf/config/Makefile | 35 ++++++- tools/perf/util/Build | 13 ++- tools/perf/util/build-id.c | 2 +- tools/perf/util/dso.c | 6 +- tools/perf/util/thread.c | 7 +- tools/perf/util/thread.h | 14 ++- tools/perf/util/unwind-libunwind.c | 49 +++++++-- tools/perf/util/unwind-libunwind_common.c | 114 +++++++++++++++++++++ tools/perf/util/unwind.h | 48 +++++++-- tools/perf/util/vdso.h | 7 +- 14 files changed, 348 insertions(+), 30 deletions(-) create mode 100644 tools/perf/arch/arm64/include/libunwind/libunwind-arch.h create mode 100644 tools/perf/arch/x86/include/libunwind/libunwind-arch.h create mode 100644 tools/perf/util/unwind-libunwind_common.c
Signature · 1 line
1.8.5.2
PATCH v3 1/7 perf tools: Set vdso name to vdso[64,32] depending on platform
This is a preparation for cross-platform vdso lookup.
There is a naming confusion about vdso name, 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 uses different names when storing the buildid, i.e. vdso64 for 64-bit machine and vdso32 for 32-bit machine, and eliminates this naming confusion.
--- tools/perf/util/vdso.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
tools/perf/util/vdso.h +6 -1
@@ -4,10 +4,15 @@#include <linux/types.h> #include <string.h> #include <stdbool.h> +#include "util.h" #define VDSO__MAP_NAME "[vdso]" -#define DSO__NAME_VDSO "[vdso]" +#if BITS_PER_LONG ==64 +#define DSO__NAME_VDSO "[vdso64]" +#else +#define DSO__NAME_VDSO "[vdso32]" +#endif #define DSO__NAME_VDSO32 "[vdso32]"#define DSO__NAME_VDSOX32 "[vdsox32]"
Signature · 1 line
1.8.5.2
Adrian Hunter
reviewerRe: [PATCH v3 1/7] perf tools: Set vdso name to vdso[64,32] depending on platform
Quoted 10 lines · He Kuang
This is a preparation for cross-platform vdso lookup.
There is a naming confusion about vdso name, 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 uses different names when storing the buildid, i.e. vdso64 for 64-bit machine and vdso32 for 32-bit machine, and eliminates this naming confusion.
That looks like it will break existing perf.data files because they will have a different name recorded in the buildid section.
Also it doesn't look like it would work the other way around i.e. recording on a 64-bit machine and processing on a 32-bit machine.
Quoted 28 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)tools/perf/util/vdso.h +6
-1@@ -4,10 +4,15 @@#include <linux/types.h> #include <string.h> #include <stdbool.h> +#include "util.h" #define VDSO__MAP_NAME "[vdso]" -#define DSO__NAME_VDSO "[vdso]" +#if BITS_PER_LONG ==64 +#define DSO__NAME_VDSO "[vdso64]" +#else +#define DSO__NAME_VDSO "[vdso32]" +#endif #define DSO__NAME_VDSO32 "[vdso32]"#define DSO__NAME_VDSOX32 "[vdsox32]"
PATCH v3 1/7 perf tools: Find vdso with the consider of cross-platform
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 exsiting 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.
--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)
tools/perf/util/vdso.c +37 -3
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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); +break ; +case DSO__TYPE_X32BIT : + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSOX32 , true); +if (!dso) + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , + 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;
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 1/7 UPDATE] perf tools: Find vdso with the consider of cross-platform
Em Fri, May 13, 2016 at 08:51:49AM +0000, He Kuang escreveu:
Quoted 11 lines
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 exsiting dsos in
machine->dsosby threaddso_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.
Adrian, are you ok now?
- Arnaldo
Quoted 80 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +37
-3@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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); +break ; +case DSO__TYPE_X32BIT : + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSOX32 , true); +if (!dso) + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , + 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;Signature · 1 line
1.8.5.2
Adrian Hunter
reviewerRe: [PATCH v3 1/7 UPDATE] perf tools: Find vdso with the consider of cross-platform
Quoted 6 lines · Arnaldo Carvalho de Melo
Em Fri, May 13, 2016 at 08:51:49AM +0000, He Kuang escreveu:
Quoted 5 lines
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.
Quoted 8 lines
Quoted 6 lines
This patch tries to find the exsiting dsos in
machine->dsosby threaddso_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.Adrian, are you ok now?
I sent a couple more comments.
Adrian Hunter
reviewerRe: [PATCH v3 1/7 UPDATE] perf tools: Find vdso with the consider of cross-platform
In reply to He KuangQuoted 46 lines · He Kuang
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 exsiting dsos in
machine->dsosby threaddso_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.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +5
-2@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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) +{
tools/perf/util/vdso.c static int __machine__findnew_vdso_compat(struct machine *machine, · line 298
Quoted 10 lines
tools/perf/util/vdso.c +10
-0+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);
So if we have not yet added the 32-bit vdso but have added the 64-bit vdso, we will return the wrong one.
Can we check it? e.g.
if (!dso) dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true); if (dso_type != dso__type(dso, machine)) dso = NULL;
tools/perf/util/vdso.c static int __machine__findnew_vdso_compat(struct machine *machine, · line 304
Quoted 6 lines
tools/perf/util/vdso.c +6
-0+break ; +case DSO__TYPE_X32BIT : + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSOX32 , true); +if (!dso) + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , + true);
The x32 vdso is never called DSO__NAME_VDSO so this is not correct, but for the same reason we don't need this __dsos__find() anyway.
Quoted 29 lines
tools/perf/util/vdso.c +16
-1+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;
PATCH v3 1/7 perf tools: Find vdso with the consider of cross-platform
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 exsiting 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.
--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)
tools/perf/util/vdso.c +37 -3
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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_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;
Signature · 1 line
1.8.5.2
Re: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
Quoted 5 lines · He Kuang
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.
Quoted 8 lines
This patch tries to find the exsiting dsos in
machine->dsosby threaddso_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.Signed-off-by He Kuang <[email protected]>
Looks OK.
Quoted 78 lines
--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +37
-3@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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_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;
Re: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
Em Tue, May 17, 2016 at 12:17:29PM +0300, Adrian Hunter escreveu:
Quoted 13 lines · He Kuang
Quoted 11 lines
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 exsiting dsos in
machine->dsosby threaddso_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.
Quoted 5 lines
Quoted 1 line
Signed-off-by He Kuang <[email protected]>Looks OK.
Acked-by Adrian Hunter <[email protected]>
Thanks, applied.
- Arnaldo
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
In reply to He KuangEm Tue, May 17, 2016 at 09:04:54AM +0000, He Kuang escreveu:
Quoted 4 lines
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.
Without looking at the code, just trying to understand your patch by reading your description: Why would we look for names if we have build-ids? All this type and name comparasions seems wrong if we have a build-id, no?
Adrian?
- Arnaldo
Quoted 87 lines
This patch tries to find the exsiting dsos in
machine->dsosby threaddso_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.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +37
-3@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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_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;Signature · 1 line
1.8.5.2
Re: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
hi
Quoted 5 lines · Arnaldo Carvalho de Melo
Em Tue, May 17, 2016 at 09:04:54AM +0000, He Kuang escreveu:
Quoted 4 lines
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.
Quoted 9 lines
Without looking at the code, just trying to understand your patch by reading your description: Why would we look for names if we have build-ids? All this type and name comparasions seems wrong if we have a build-id, no?
Adrian?
- Arnaldo
We should find a binary with the {name, buildid} pair, the key is name not buildid.
There're more than one vdso binaries in system, we store parts/all of them when recording and should find out which one to use for unwinding in the 'perf script' stage, by comparing the name and the thread's dso_type.
Thank you.
Quoted 87 lines
Quoted 87 lines
This patch tries to find the exsiting dsos in
machine->dsosby threaddso_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.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +37
-3@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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_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;Signature · 1 line
1.8.5.2
Adrian Hunter
reviewerRe: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
In reply to Arnaldo Carvalho de MeloQuoted 6 lines · Arnaldo Carvalho de Melo
Em Tue, May 17, 2016 at 09:04:54AM +0000, He Kuang escreveu:
Quoted 4 lines
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.
Quoted 6 lines
Without looking at the code, just trying to understand your patch by reading your description: Why would we look for names if we have build-ids? All this type and name comparasions seems wrong if we have a build-id, no?
Adrian?
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.
I acked it in another email.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 1/7 UPDATE2] perf tools: Find vdso with the consider of cross-platform
Em Thu, Jun 16, 2016 at 04:00:12PM +0300, Adrian Hunter escreveu:
Quoted 23 lines · Arnaldo Carvalho de Melo
Quoted 6 lines
Em Tue, May 17, 2016 at 09:04:54AM +0000, He Kuang escreveu:
Quoted 4 lines
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.Quoted 6 lines
Without looking at the code, just trying to understand your patch by reading your description: Why would we look for names if we have build-ids? All this type and name comparasions seems wrong if we have a build-id, no?
Adrian?
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]".
Quoted 7 lines
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.
I acked it in another email.
Ok, somehow this got lost, I thought to have applied it already, but re-reading the changeset comment, I got confused, thanks for providing this explanation, that I will stick to the changeset log for this message, to help understanding this when scratching our heads in the future.
- Arnaldo
Re: [PATCH v3 1/7 UPDATE] perf tools: Find vdso with the consider of cross-platform
In reply to Adrian HunterQuoted 68 lines · Adrian Hunter
Quoted 46 lines · He Kuang
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 exsiting dsos in
machine->dsosby threaddso_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.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)tools/perf/util/vdso.c +5
-2@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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) +{tools/perf/util/vdso.c static int __machine__findnew_vdso_compat(struct machine *machine, · line 298
Quoted 10 lines
tools/perf/util/vdso.c +10
-0+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);So if we have not yet added the 32-bit vdso but have added the 64-bit vdso, we will return the wrong one.
Can we check it? e.g.
if (!dso) dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true); if (dso_type != dso__type(dso, machine)) dso = NULL;
Quoted 8 lines
tools/perf/util/vdso.c static int __machine__findnew_vdso_compat(struct machine *machine, · line 304
Quoted 6 lines
tools/perf/util/vdso.c +6
-0+break ; +case DSO__TYPE_X32BIT : + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSOX32 , true); +if (!dso) + dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , + true);The x32 vdso is never called
DSO__NAME_VDSOso this is not correct, but for the same reason we don't need this__dsos__find()anyway.
Thanks, update
Quoted 30 lines
Quoted 29 lines
tools/perf/util/vdso.c +16
-1+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;
Re: [PATCH v3 1/7] perf tools: Set vdso name to vdso[64,32] depending on platform
In reply to Adrian HunterQuoted 8 lines · Adrian Hunter
Quoted 7 lines · He Kuang
This is a preparation for cross-platform vdso lookup.
There is a naming confusion about vdso name, 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.
Quoted 8 lines
Quoted 3 lines
This patch uses different names when storing the buildid, i.e. vdso64 for 64-bit machine and vdso32 for 32-bit machine, and eliminates this naming confusion.
That looks like it will break existing perf.data files because they will have a different name recorded in the buildid section.
Also it doesn't look like it would work the other way around i.e. recording on a 64-bit machine and processing on a 32-bit machine.
Yes, please have a look at the new patch.
Thanks
Quoted 28 lines
Quoted 27 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)tools/perf/util/vdso.h +6
-1@@ -4,10 +4,15 @@#include <linux/types.h> #include <string.h> #include <stdbool.h> +#include "util.h" #define VDSO__MAP_NAME "[vdso]" -#define DSO__NAME_VDSO "[vdso]" +#if BITS_PER_LONG ==64 +#define DSO__NAME_VDSO "[vdso64]" +#else +#define DSO__NAME_VDSO "[vdso32]" +#endif #define DSO__NAME_VDSO32 "[vdso32]"#define DSO__NAME_VDSOX32 "[vdsox32]"
PATCH v3 2/7 perf tools: Store vdso buildid unconditionally
In reply to He KuangWhen unwinding callchains on a different machine, vdso info should be provided so the unwind process won't be interrupted if address falls into vdso region. But in most cases, the addresses of sample events are not in vdso range, the buildid of a zero hit vdso won't be stored into perf.data.
This patch stores vdso buildid regardless of whether the vdso is hit or not.
--- tools/perf/util/build-id.c | 2 +- tools/perf/util/dso.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +1 -1
@@ -256,7 +256,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)size_t name_len;bool in_kernel = false; -if (!pos->hit) +if (!pos->hit && !dso__is_vdso (pos))continue ;if (dso__is_vdso (pos)) {
tools/perf/util/dso.c +2 -1
@@ -7,6 +7,7 @@#include "auxtrace.h" #include "util.h" #include "debug.h" +#include "vdso.h" char dso__symtab_origin (const struct dso *dso) {
@@ -1169,7 +1170,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)struct dso *pos;list_for_each_entry (pos, head, node) { -if (with_hits && !pos->hit) +if (with_hits && !pos->hit && !dso__is_vdso (pos))continue ;if (pos->has_build_id) { have_build_id = true;
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 2/7] perf tools: Store vdso buildid unconditionally
Em Thu, May 12, 2016 at 08:43:11AM +0000, He Kuang escreveu:
Quoted 8 lines
When unwinding callchains on a different machine, vdso info should be provided so the unwind process won't be interrupted if address falls into vdso region. But in most cases, the addresses of sample events are not in vdso range, the buildid of a zero hit vdso won't be stored into perf.data.
This patch stores vdso buildid regardless of whether the vdso is hit or not.
Looks ok, applied.
Quoted 42 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/build-id.c | 2 +- tools/perf/util/dso.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)tools/perf/util/build-id.c +1
-1@@ -256,7 +256,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)size_t name_len;bool in_kernel = false; -if (!pos->hit) +if (!pos->hit && !dso__is_vdso (pos))continue ;if (dso__is_vdso (pos)) {tools/perf/util/dso.c +2
-1@@ -7,6 +7,7 @@#include "auxtrace.h" #include "util.h" #include "debug.h" +#include "vdso.h" char dso__symtab_origin (const struct dso *dso) {@@ -1169,7 +1170,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)struct dso *pos;list_for_each_entry (pos, head, node) { -if (with_hits && !pos->hit) +if (with_hits && !pos->hit && !dso__is_vdso (pos))continue ;if (pos->has_build_id) { have_build_id = true;Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/urgent] perf symbols: Store vdso buildid unconditionally
In reply to He Kuangperf symbols: Store vdso buildid unconditionally
Commit-ID: 6ae98ba611ed1c11ddc5645475bc03b46a3c04e7 Gitweb: http://git.kernel.org/tip/6ae98ba611ed1c11ddc5645475bc03b46a3c04e7 Author: He Kuang <[email protected]> AuthorDate: Thu, 12 May 2016 08:43:11 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 16 May 2016 23:11:45 -0300
perf symbols: Store vdso buildid unconditionally
When unwinding callchains on a different machine, vdso info should be available so the unwind process won't be interrupted if address falls into vdso region. But in most cases, the addresses of sample events are not in vdso range, the buildid of a zero hit vdso won't be stored into perf.data.
This patch stores vdso buildid regardless of whether the vdso is hit or not.
--- tools/perf/util/build-id.c | 2 +- tools/perf/util/dso.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +1 -1
@@ -256,7 +256,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)size_t name_len;bool in_kernel = false; -if (!pos->hit) +if (!pos->hit && !dso__is_vdso (pos))continue ;if (dso__is_vdso (pos)) {
tools/perf/util/dso.c +2 -1
@@ -7,6 +7,7 @@#include "auxtrace.h" #include "util.h" #include "debug.h" +#include "vdso.h" char dso__symtab_origin (const struct dso *dso) {
@@ -1169,7 +1170,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)struct dso *pos;list_for_each_entry (pos, head, node) { -if (with_hits && !pos->hit) +if (with_hits && !pos->hit && !dso__is_vdso (pos))continue ;if (pos->has_build_id) { have_build_id = true;
PATCH v3 3/7 perf tools: Remove the logical that skip buildid cache if symfs is given
In reply to He KuangSymfs dir and buildid dir are two places that perf looks into for symbols, currently, if symfs dir is given, buildid-cache is skipped.
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. And consider that the binaries indexed by buildid do not cause ambiguity, this patch simply removes that logical.
--- tools/perf/util/dso.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/util/dso.c +1 -2
@@ -64,8 +64,7 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__BUILD_ID_CACHE :/* skip the locally configured cache if a symfs is given */ -if (symbol_conf.symfs[0 ] || - (dso__build_id_filename (dso, filename, size) ==NULL )) +if (dso__build_id_filename (dso, filename, size) ==NULL ) ret =-1 ;break ;
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
Em Thu, May 12, 2016 at 08:43:12AM +0000, He Kuang escreveu:
Quoted 7 lines
Symfs dir and buildid dir are two places that perf looks into for symbols, currently, if symfs dir is given, buildid-cache is skipped.
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. And consider that the binaries indexed by buildid do not cause ambiguity, this patch simply removes that logical.
Makes perfect sense, David, do you have any concern? Can I have your Acked-by?
- Arnaldo
Quoted 21 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/dso.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)tools/perf/util/dso.c +1
-2@@ -64,8 +64,7 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__BUILD_ID_CACHE :/* skip the locally configured cache if a symfs is given */ -if (symbol_conf.symfs[0 ] || - (dso__build_id_filename (dso, filename, size) ==NULL )) +if (dso__build_id_filename (dso, filename, size) ==NULL ) ret =-1 ;break ;Signature · 1 line
1.8.5.2
Re: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Thu, May 12, 2016 at 08:43:12AM +0000, He Kuang escreveu:
Quoted 7 lines
Symfs dir and buildid dir are two places that perf looks into for symbols, currently, if symfs dir is given, buildid-cache is skipped.
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. And consider that the binaries indexed by buildid do not cause ambiguity, this patch simply removes that logical.
Makes perfect sense, David, do you have any concern? Can I have your Acked-by?
seems odd to me you want to look in the buildid-cache when a symfs is given. The point of symfs was "go look for everything under here."
I believe dso__load is going to hit DSO_BINARY_TYPE__BUILD_ID_CACHE before any of the others and there are probably cases where a stale cache entry would be hit before a build tree entry (e.g., symfs).
What about putting the build id cache under the symfs? so instead of dropping the symfs check and it to the path for the build id cache.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
Em Thu, May 12, 2016 at 02:23:37PM -0600, David Ahern escreveu:
Quoted 13 lines · Arnaldo Carvalho de Melo
Quoted 11 lines
Em Thu, May 12, 2016 at 08:43:12AM +0000, He Kuang escreveu:
Quoted 7 lines
Symfs dir and buildid dir are two places that perf looks into for symbols, currently, if symfs dir is given, buildid-cache is skipped.
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. And consider that the binaries indexed by buildid do not cause ambiguity, this patch simply removes that logical.
Makes perfect sense, David, do you have any concern? Can I have your Acked-by?
Quoted 6 lines
seems odd to me you want to look in the buildid-cache when a symfs is given. The point of symfs was "go look for everything under here."
I believe
dso__loadis going to hitDSO_BINARY_TYPE__BUILD_ID_CACHEbefore any of the others and there are probably cases where a stale cache entry would be hit before a build tree entry (e.g., symfs).
Stale cache entry? How'd that be? Its content based, i.e. if there is an entry for a given build id _anywhere_ why wouldn't we want to use it?
Quoted 2 lines
What about putting the build id cache under the symfs? so instead of dropping the symfs check and it to the path for the build id cache.
Well, the use case of look at both still looks sane to me, but maybe the way you suggest works for He, He?
- Arnaldo
Re: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
In reply to David Ahernhi
Quoted 10 lines · David Ahern
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Thu, May 12, 2016 at 08:43:12AM +0000, He Kuang escreveu:
Quoted 7 lines
Symfs dir and buildid dir are two places that perf looks into for symbols, currently, if symfs dir is given, buildid-cache is skipped.
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. And consider that the binaries indexed by buildid do not cause ambiguity, this patch simply removes that logical.
Quoted 6 lines
Quoted 2 lines
Makes perfect sense, David, do you have any concern? Can I have your Acked-by?
seems odd to me you want to look in the buildid-cache when a symfs is given. The point of symfs was "go look for everything under here."
I believe
dso__loadis going to hitDSO_BINARY_TYPE__BUILD_ID_CACHEbefore any of the others and there are probably cases where a stale cache entry would be hit before a build tree entry (e.g., symfs).
Build id entries recorded in perf.data reflect the current dso, so if buildid is matched , how can it be a stale one?
Quoted 4 lines
What about putting the build id cache under the symfs? so instead of dropping the symfs check and it to the path for the build id cache.
I think your intention is to reference symbol files in one place instead of two. So there're two possible approaches, one is all in buildid-cache, but in practice, I found lots of binaries in symfs even not contains valid buildid, so this way is not work.
The other one is all in symfs. It seems ok, but one problem I should point out, with my test environment as an example, the symfsdir is $(TARGET_ROOTFS),and by default buildid_dir is $(TARGET_ROOTFS)/$(HOME)/.debug/, host perf does not know $(HOME) folder in target and we should copy the debug folder
to $(TARGET_ROOTFS), which is readonly in the target. For me, it's
easier to use 'buildid-cache -a vdso-xxxx' to add that into host buildid-cache than copy debug folder from $(HOME) to readonly $(TARGET_ROOTFS).
Without the stale concern, I prefer the two places(buildid-dir in host and target symfs) way.
Thanks.
Re: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
Quoted 19 lines · Hekuang
Quoted 4 lines
What about putting the build id cache under the symfs? so instead of dropping the symfs check and it to the path for the build id cache.
I think your intention is to reference symbol files in one place instead of two. So there're two possible approaches, one is all in buildid-cache, but in practice, I found lots of binaries in symfs even not contains valid buildid, so this way is not work.
The other one is all in symfs. It seems ok, but one problem I should point out, with my test environment as an example, the symfsdir is $(TARGET_ROOTFS),and by default
buildid_diris $(TARGET_ROOTFS)/$(HOME)/.debug/, host perf does not know $(HOME) folder in target and we should copy the debug folder
to $(TARGET_ROOTFS), which is readonly in the target. For me, it's
easier to use 'buildid-cache -a vdso-xxxx' to add that into host buildid-cache than copy debug folder from $(HOME) to readonly $(TARGET_ROOTFS).
Quoted 2 lines
Without the stale concern, I prefer the two places(buildid-dir in host and target symfs) way.
The intention of symfs is every single file opened by perf is relative to that directory. As I recall when I added that option in early 2011 I made sure that statement is true. I think it is best to maintain that design.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH v3 3/7] perf tools: Remove the logical that skip buildid cache if symfs is given
Em Fri, May 13, 2016 at 08:27:29AM -0600, David Ahern escreveu:
Quoted 19 lines · Hekuang
Quoted 17 lines
Quoted 2 lines
What about putting the build id cache under the symfs? so instead of dropping the symfs check and it to the path for the build id cache.
I think your intention is to reference symbol files in one place instead of two. So there're two possible approaches, one is all in buildid-cache, but in practice, I found lots of binaries in symfs even not contains valid buildid, so this way is not work.
The other one is all in symfs. It seems ok, but one problem I should point out, with my test environment as an example, the symfsdir is $(TARGET_ROOTFS),and by default
buildid_diris $(TARGET_ROOTFS)/$(HOME)/.debug/, host perf does not know $(HOME) folder in target and we should copy the debug folder
to $(TARGET_ROOTFS), which is readonly in the target. For me, it's
easier to use 'buildid-cache -a vdso-xxxx' to add that into host buildid-cache than copy debug folder from $(HOME) to readonly $(TARGET_ROOTFS).
Quoted 6 lines
Quoted 2 lines
Without the stale concern, I prefer the two places(buildid-dir in host and target symfs) way.
The intention of symfs is every single file opened by perf is relative to that directory. As I recall when I added that option in early 2011 I made sure that statement is true. I think it is best to maintain that design.
Ok, so we can introduce --dso-prefix for Hekuang's use case, i.e. be able to lookup by build-id, fallbacking to a (possibly read-only) directory.
This way the existing --symfs semantic remains written in stone.
- Arnaldo
PATCH v3 3/7 perf tools: Add option for the path of buildid dsos under symfs
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. For the reason that to have every single file opened by perf is relative to symfs dirctory, perf skips the buildid dir if symfs is given.
This patch references the buildid dir under symfs if '--symfs' is used, and adds new option '--dso-prefix' to specify the subdir path in symfs which contains the buildid dsos.
--- tools/perf/builtin-script.c | 2 ++ tools/perf/util/config.c | 10 ++++++++++ tools/perf/util/dso.c | 6 ++++-- tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 1 + tools/perf/util/util.h | 1 + 6 files changed, 19 insertions(+), 2 deletions(-)
tools/perf/builtin-script.c +2 -0
@@ -2043,6 +2043,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "Enable symbol demangling"),OPT_BOOLEAN (0 ,"demangle-kernel" , &symbol_conf.demangle_kernel,"Enable kernel symbol demangling" ), +OPT_STRING (0 ,"dso-prefix" , &symbol_conf.dso_prefix,"direcotry" , +"Look for dsos relative to this directory under symfs" ), OPT_END() };
tools/perf/util/config.c +10 -0
@@ -553,3 +553,13 @@ void set_buildid_dir(const char *dir)/* for communicating with external commands */ setenv ("PERF_BUILDID_DIR" , buildid_dir,1 ); } + +static bool buildid_dir_under_symfs_flag; +void set_buildid_dir_under_symfs (void ) +{ +if (!buildid_dir_under_symfs_flag && symbol_conf.symfs[0 ]) { +__symbol__join_symfs (buildid_dir,MAXPATHLEN -1 , + symbol_conf.dso_prefix); + buildid_dir_under_symfs_flag = true; + } +}
tools/perf/util/dso.c +4 -2
@@ -64,8 +64,10 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__BUILD_ID_CACHE :/* skip the locally configured cache if a symfs is given */ -if (symbol_conf.symfs[0 ] || - (dso__build_id_filename (dso, filename, size) ==NULL )) +if (symbol_conf.symfs[0 ]) +set_buildid_dir_under_symfs (); + +if (dso__build_id_filename (dso, filename, size) ==NULL ) ret =-1 ;break ;
tools/perf/util/symbol.c +1 -0
@@ -40,6 +40,7 @@ struct symbol_conf symbol_conf = { .show_hist_headers = true, .symfs = "", .event_group = true, + .dso_prefix = "", };static enum dso_binary_type binary_type_symtab[] = {
tools/perf/util/symbol.h +1 -0
@@ -136,6 +136,7 @@ struct symbol_conf {struct intlist *pid_list, *tid_list;const char *symfs; +const char *dso_prefix; };extern struct symbol_conf symbol_conf;
tools/perf/util/util.h +1 -0
@@ -142,6 +142,7 @@ void set_warning_routine(void (*routine)(const char *err, va_list params));int prefixcmp (const char *str,const char *prefix);void set_buildid_dir (const char *dir); +void set_buildid_dir_under_symfs (void );#ifdef __GLIBC_PREREQ#if __GLIBC_PREREQ (2 ,1 )
Signature · 1 line
1.8.5.2
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 8 lines · He Kuang
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. For the reason that to have every single file opened by perf is relative to symfs dirctory, perf skips the buildid dir if symfs is given.
This patch references the buildid dir under symfs if '--symfs' is used, and adds new option '--dso-prefix' to specify the subdir path in symfs which contains the buildid dsos.
In the previous version of this patch you just wanted to drop the symfs check. That means there is a path that perf searches for buildid files and reading it worked for you. Why is adding symsfs to that path not enough? ie., Why do you need to specify a different location under the symfs?
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 6 lines · David Ahern
Quoted 5 lines · He Kuang
In the cross-platform perf record/script scenario, we need vdsos in buildid-cache dir and other libs in symfs dir at the same time. For the reason that to have every single file opened by perf is relative to symfs dirctory, perf skips the buildid dir if symfs is given.
Quoted 6 lines
Quoted 3 lines
This patch references the buildid dir under symfs if '--symfs' is used, and adds new option '--dso-prefix' to specify the subdir path in symfs which contains the buildid dsos.
In the previous version of this patch you just wanted to drop the symfs check. That means there is a path that perf searches for buildid files and reading it worked for you. Why is adding symsfs to that path not enough? ie., Why do you need to specify a different location under the symfs?
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
Currently, $(BUILDID_ROOT)/.debug/.buildid has a directory structure organized by the buildid value, like this:
.build-id
- 3a
| e5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd
- 84
dbd75729adba57cc42f5544b25de571c0c8731
perf searchs for buildid binaries by the buildid value.
And symfs is a normal file tree and perf searchs for binaryies by the file name.
lib
- libc.so
- ld.so
Tt's inappropriate to add symfs to .build-id dir becuase they have different dirctory structure and perf searchs for them by differnt ways.
So in this patch I add .buildid to symfs and got dirctory tree like this:
symfs
- $(DSO_PREFIX)
- .build-id
- 3a
- 84
- libc.so
- ld.so
Thanks
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 2 lines · Hekuang
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
So 'perf buildid-cache' needs the symfs option?
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 7 lines · David Ahern
Quoted 2 lines · Hekuang
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
So 'perf buildid-cache' needs the symfs option?
No, for the host, we don't reference any files in buildid-cache if symfs is givin.
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
In reply to David AhernQuoted 7 lines · David Ahern
Quoted 2 lines · Hekuang
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
So 'perf buildid-cache' needs the symfs option?
With this patch 'PATCH v3 3/7 UPDATE', the tree of symfs dir is like this:
├── debug($(dso-prefix)) │ ├── .build-id │ │ ├── 3a │ │ │ └── e5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd -> ../../[kernel.kallsyms]/3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ │ └── 84 │ │ └── dbd75729adba57cc42f5544b25de571c0c8731 -> ../../[vdso32]/84dbd75729adba57cc42f5544b25de571c0c8731 │ ├── [kernel.kallsyms] │ │ └── 3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ ├── [vdso] │ │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 │ └── [vdso32] │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 ├── lib │ ├── ld-2.22.so │ └── libc-2.22.so ├── tmp │ └── hello └── xxx
So all binaries we need are included in the symfs dir. I think this is consistent with your idea explained in previous mails.
With this symfs, we do not need buildid dir anymore and what's your idea on 'perf buildid-cache' needs symfs option? after all, that only effects on buildid dir.
Thanks.
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 34 lines · Hekuang
Quoted 7 lines · David Ahern
Quoted 2 lines · Hekuang
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
So 'perf buildid-cache' needs the symfs option?
With this patch 'PATCH v3 3/7 UPDATE', the tree of symfs dir is like this:
├── debug($(dso-prefix)) │ ├── .build-id │ │ ├── 3a │ │ │ └── e5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd -> ../../[kernel.kallsyms]/3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ │ └── 84 │ │ └── dbd75729adba57cc42f5544b25de571c0c8731 -> ../../[vdso32]/84dbd75729adba57cc42f5544b25de571c0c8731 │ ├── [kernel.kallsyms] │ │ └── 3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ ├── [vdso] │ │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 │ └── [vdso32] │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 ├── lib │ ├── ld-2.22.so │ └── libc-2.22.so ├── tmp │ └── hello └── xxx
Quoted 6 lines
So all binaries we need are included in the symfs dir. I think this is consistent with your idea explained in previous mails.
With this symfs, we do not need buildid dir anymore and what's your idea on 'perf buildid-cache' needs symfs option? after all, that only effects on buildid dir.
I don't understand why dso-prefix option is needed? Why make me type yet more options to the analysis command? Why can't the directory be located under the symfs tree in a known location and populated the same way it is without symfs?
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 35 lines · David Ahern
Quoted 34 lines · Hekuang
Quoted 7 lines · David Ahern
Quoted 2 lines · Hekuang
In previous patch, I use 'perf buildid-cache -a' to add vdso binary into the HOST buildid dir.
So 'perf buildid-cache' needs the symfs option?
With this patch 'PATCH v3 3/7 UPDATE', the tree of symfs dir is like this:
├── debug($(dso-prefix)) │ ├── .build-id │ │ ├── 3a │ │ │ └── e5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd -> ../../[kernel.kallsyms]/3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ │ └── 84 │ │ └── dbd75729adba57cc42f5544b25de571c0c8731 -> ../../[vdso32]/84dbd75729adba57cc42f5544b25de571c0c8731 │ ├── [kernel.kallsyms] │ │ └── 3ae5ba6d4e532ad529e43ccf1ce1ddf8a64a4fdd │ ├── [vdso] │ │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 │ └── [vdso32] │ └── 84dbd75729adba57cc42f5544b25de571c0c8731 ├── lib │ ├── ld-2.22.so │ └── libc-2.22.so ├── tmp │ └── hello └── xxx
Quoted 10 lines
Quoted 6 lines
So all binaries we need are included in the symfs dir. I think this is consistent with your idea explained in previous mails.
With this symfs, we do not need buildid dir anymore and what's your idea on 'perf buildid-cache' needs symfs option? after all, that only effects on buildid dir.
I don't understand why dso-prefix option is needed? Why make me type yet more options to the analysis command? Why can't the directory be located under the symfs tree in a known location and populated the same way it is without symfs?
Because the default buidid folder path is $HOME/.debug/.buildid, and this $HOME is on the target machine, not the same as $HOME on the host. Without that option, we need to copy $HOME/.debug/.buildid to the 'known location in symfs', that's also an extra work.
Re: [PATCH v3 3/7 UPDATE] perf tools: Add option for the path of buildid dsos under symfs
Quoted 11 lines · Hekuang
Quoted 6 lines
I don't understand why dso-prefix option is needed? Why make me type yet more options to the analysis command? Why can't the directory be located under the symfs tree in a known location and populated the same way it is without symfs?
Because the default buidid folder path is $HOME/.debug/.buildid, and this $HOME is on the target machine, not the same as $HOME on the host. Without that option, we need to copy $HOME/.debug/.buildid to the 'known location in symfs', that's also an extra work.
My argument for symfs is that $HOME is not relevant or if it is the path is symfs/$HOME. The use case is dealing with countless images -- some development, some production. I should be able to nuke the symfs when the analysis is done and everything related to it is gone. With the $HOME/.debug path it just grows on and on with no real means of pruning it.
If the vdsos are for a particular symfs then why aren't the vdso's under it in a known location?
PATCH v3 4/7 perf tools: Promote proper messages for cross-platform unwind
In reply to He KuangCurrently, perf script uses host unwind methods to parse perf.data callchain info regardless of the target architecture. So we get wrong result and no promotion when unwinding callchains of x86(32-bit) on x86(64-bit) machine.
This patch shows proper error messages when we do remote unwind x86(32-bit) on other machines.
Same thing for other platforms will be added in next patches.
--- tools/perf/config/Makefile | 6 ++++++ tools/perf/util/thread.c | 2 ++ tools/perf/util/unwind-libunwind.c | 33 +++++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 5 +++++ 4 files changed, 46 insertions(+)
tools/perf/config/Makefile +6 -0
@@ -345,6 +345,12 @@ ifeq ($(ARCH),powerpc) endif ifndef NO_LIBUNWIND + ifeq ($(feature-libunwind-x86), 1) + LIBUNWIND_LIBS += -lunwind-x86 + $(call detected,CONFIG_LIBUNWIND_X86) + CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT + endif + ifneq ($(feature-libunwind), 1) msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); NO_LIBUNWIND := 1
tools/perf/util/thread.c +2 -0
@@ -186,6 +186,8 @@ void thread__insert_map(struct thread *thread, struct map *map) {map_groups__fixup_overlappings (thread->mg, map, stderr);map_groups__insert (thread->mg, map); + +unwind__get_arch (thread, map); } static int thread__clone_map_groups(struct thread *thread,
tools/perf/util/unwind-libunwind.c +33 -0
@@ -680,3 +680,36 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,return get_entries (&ui, cb, arg, max_stack); } + +void unwind__get_arch (struct thread *thread,struct map *map) +{ +char *arch; +enum dso_type dso_type; + +if (!thread->mg->machine->env) +return ; + + dso_type =dso__type (map->dso, thread->mg->machine); +if (dso_type ==DSO__TYPE_UNKNOWN ) +return ; + +if (thread->addr_space) +pr_debug ("Thread map already set, 64bit is %d, dso=%s\n" , + dso_type ==DSO__TYPE_64BIT , map->dso->name); + + arch = thread->mg->machine->env->arch; + +if (!strcmp (arch,"x86_64" ) + || !strcmp (arch,"x86" ) + || !strcmp (arch,"i686" )) { +pr_debug ("Thread map is X86, 64bit is %d\n" , + dso_type ==DSO__TYPE_64BIT ); + if (dso_type != DSO__TYPE_64BIT) +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +pr_err ("target platform=%s is not implemented!\n" , + arch); +#else +pr_err ("target platform=%s is not supported!\n" , arch); +#endif + } +}
tools/perf/util/unwind.h +5 -0
@@ -24,6 +24,7 @@ int libunwind__arch_reg_id(int regnum);int unwind__prepare_access (struct thread *thread);void unwind__flush_access (struct thread *thread);void unwind__finish_access (struct thread *thread); +void unwind__get_arch (struct thread *thread,struct map *map);#else static inline int unwind__prepare_access (struct thread *thread__maybe_unused ) {
@@ -32,6 +33,8 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused)static inline void unwind__flush_access (struct thread *thread__maybe_unused ) {}static inline void unwind__finish_access (struct thread *thread__maybe_unused ) {} +static inline void unwind__get_arch (struct thread *thread__maybe_unused , +struct map *map__maybe_unused ) {}#endif #else static inline int
@@ -51,5 +54,7 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused)static inline void unwind__flush_access (struct thread *thread__maybe_unused ) {}static inline void unwind__finish_access (struct thread *thread__maybe_unused ) {} +static inline void unwind__get_arch (struct thread *thread__maybe_unused , +struct map *map__maybe_unused ) {}#endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* __UNWIND_H */
Signature · 1 line
1.8.5.2
PATCH v3 5/7 perf callchain: Add support for cross-platform unwind
In reply to He KuangUse thread specific unwind ops to unwind cross-platform callchains.
Before this patch, unwind methods is suitable for local unwind, this patch changes the fixed methods to thread/map related. Each time a map is inserted, we find the target arch and see if this platform can be remote unwind. In this patch, we test for x86 platform and only show proper messages. The real unwind methods are not implemented, will be introduced in next patch.
Common function used by both local unwind and remote unwind are separated into new file 'unwind-libunwind_common.c'.
--- tools/perf/config/Makefile | 19 +++++- tools/perf/util/Build | 3 +- tools/perf/util/thread.c | 5 +- tools/perf/util/thread.h | 14 ++++- tools/perf/util/unwind-libunwind.c | 74 +++++++++++----------- tools/perf/util/unwind-libunwind_common.c | 101 ++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 35 ++++++++--- 7 files changed, 197 insertions(+), 54 deletions(-) create mode 100644 tools/perf/util/unwind-libunwind_common.c
tools/perf/config/Makefile +16 -3
@@ -345,14 +345,24 @@ ifeq ($(ARCH),powerpc) endif ifndef NO_LIBUNWIND + have_libunwind = ifeq ($(feature-libunwind-x86), 1) - LIBUNWIND_LIBS += -lunwind-x86 $(call detected,CONFIG_LIBUNWIND_X86) CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT + LDFLAGS += -lunwind -lunwind-x86 + have_libunwind = 1 endif ifneq ($(feature-libunwind), 1) msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); + NO_LOCAL_LIBUNWIND := 1 + else + have_libunwind = 1 + CFLAGS += -DHAVE_LIBUNWIND_LOCAL_SUPPORT + $(call detected,CONFIG_LOCAL_LIBUNWIND) + endif + + ifneq ($(have_libunwind), 1) NO_LIBUNWIND := 1 endif endif
@@ -392,7 +402,7 @@ else NO_DWARF_UNWIND := 1 endif -ifndef NO_LIBUNWIND +ifndef NO_LOCAL_LIBUNWIND ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) $(call feature_check,libunwind-debug-frame) ifneq ($(feature-libunwind-debug-frame), 1)
@@ -403,12 +413,15 @@ ifndef NO_LIBUNWIND # non-ARM has no dwarf_find_debug_frame() function: CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME endif - CFLAGS += -DHAVE_LIBUNWIND_SUPPORT EXTLIBS += $(LIBUNWIND_LIBS) CFLAGS += $(LIBUNWIND_CFLAGS) LDFLAGS += $(LIBUNWIND_LDFLAGS) endif +ifndef NO_LIBUNWIND + CFLAGS += -DHAVE_LIBUNWIND_SUPPORT +endif + ifndef NO_LIBAUDIT ifneq ($(feature-libaudit), 1) msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
tools/perf/util/Build +2 -1
@@ -97,7 +97,8 @@ libperf-$(CONFIG_DWARF) += probe-finder.o libperf-$(CONFIG_DWARF) += dwarf-aux.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o +libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o +libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind_common.o libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
tools/perf/util/thread.c +2 -3
@@ -41,9 +41,6 @@ struct thread *thread__new(pid_t pid, pid_t tid) thread->cpu =-1 ;INIT_LIST_HEAD (&thread->comm_list); -if (unwind__prepare_access (thread) <0 ) - goto err_thread; - comm_str =malloc (32 );if (!comm_str) goto err_thread;
@@ -57,6 +54,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)list_add (&comm->list, &thread->comm_list);atomic_set (&thread->refcnt,1 );RB_CLEAR_NODE (&thread->rb_node); + +register_null_unwind_libunwind_ops (thread); }return thread;
tools/perf/util/thread.h +13 -1
@@ -15,6 +15,17 @@struct thread_stack ; +struct unwind_entry ; +typedef int (*unwind_entry_cb_t )(struct unwind_entry *entry,void *arg); +struct unwind_libunwind_ops { +int (*prepare_access)(struct thread *thread); +void (*flush_access)(struct thread *thread); +void (*finish_access)(struct thread *thread); +int (*get_entries)(unwind_entry_cb_t cb,void *arg, +struct thread *thread, +struct perf_sample *data,int max_stack); +}; + struct thread { union { struct rb_node rb_node;
@@ -36,7 +47,8 @@ struct thread {void *priv;struct thread_stack *ts;#ifdef HAVE_LIBUNWIND_SUPPORT -unw_addr_space_t addr_space; +unw_addr_space_t addr_space; +struct unwind_libunwind_ops *unwind_libunwind_ops;#endif };
tools/perf/util/unwind-libunwind.c +38 -36
115 lines not on this page · raw message
tools/perf/util/unwind-libunwind_common.c new file +101 -0
101 lines not on this page · raw message
tools/perf/util/unwind.h +25 -10
@@ -21,20 +21,38 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,/* libunwind specific */ #ifdef HAVE_LIBUNWIND_SUPPORT int libunwind__arch_reg_id (int regnum); -int unwind__prepare_access (struct thread *thread);void unwind__flush_access (struct thread *thread);void unwind__finish_access (struct thread *thread);void unwind__get_arch (struct thread *thread,struct map *map); -#else -static inline int unwind__prepare_access (struct thread *thread__maybe_unused ) -{ -return 0 ; +void register_unwind_libunwind_ops (struct unwind_libunwind_ops *ops, +struct thread *thread); +void register_null_unwind_libunwind_ops (struct thread *thread); + +#ifndef HAVE_LIBUNWIND_LOCAL_SUPPORT +static inline void +register_local_unwind_libunwind_ops (struct thread *thread) { +register_null_unwind_libunwind_ops (thread); } +#else +void register_local_unwind_libunwind_ops (struct thread *thread); +#endif +#define unwind__get_entries (cb, arg, \ + thread, \ + data, max_stack) \ + thread->unwind_libunwind_ops->get_entries(cb, \ + arg, \ + thread, \ + data, \ + max_stack) + +#else static inline void unwind__flush_access (struct thread *thread__maybe_unused ) {}static inline void unwind__finish_access (struct thread *thread__maybe_unused ) {}static inline void unwind__get_arch (struct thread *thread__maybe_unused ,struct map *map__maybe_unused ) {} +static inline void +register_null_unwind_libunwind_ops (struct thread *thread__maybe_unused ) {}#endif #else static inline int
@@ -47,14 +65,11 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,return 0 ; } -static inline int unwind__prepare_access (struct thread *thread__maybe_unused ) -{ -return 0 ; -} -static inline void unwind__flush_access (struct thread *thread__maybe_unused ) {}static inline void unwind__finish_access (struct thread *thread__maybe_unused ) {}static inline void unwind__get_arch (struct thread *thread__maybe_unused ,struct map *map__maybe_unused ) {} +static inline void +register_null_unwind_libunwind_ops (struct thread *thread__maybe_unused ) {}#endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* __UNWIND_H */
Signature · 1 line
1.8.5.2
PATCH v3 6/7 perf callchain: Support x86 target platform
In reply to He KuangSupport x86(32-bit) cross platform callchain unwind.
--- .../arch/x86/include/libunwind/libunwind-arch.h | 18 ++++++++++ tools/perf/arch/x86/util/unwind-libunwind.c | 42 ++++++++++++++++++++++ tools/perf/util/Build | 6 ++++ tools/perf/util/unwind-libunwind.c | 2 +- tools/perf/util/unwind-libunwind_common.c | 7 ++-- tools/perf/util/unwind.h | 5 +++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 tools/perf/arch/x86/include/libunwind/libunwind-arch.h
tools/perf/arch/x86/include/libunwind/libunwind-arch.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _LIBUNWIND_ARCH_H +#define _LIBUNWIND_ARCH_H + +#include <libunwind-x86.h> +#include <../perf_regs.h> +#include <../../../../../../arch/x86/include/uapi/asm/perf_regs.h> + +#define LIBUNWIND_X86_32 +int libunwind__x86_reg_id (int regnum); + +#include <../../../x86/util/unwind-libunwind.c> + +#define LIBUNWIND__ARCH_REG_ID libunwind__x86_reg_id + +#define UNWT_PREFIX UNW_PASTE(UNW_PASTE(_U, x86), _) +#define UNWT_OBJ (fn) UNW_PASTE(UNWT_PREFIX, fn) + +#endif /* _LIBUNWIND_ARCH_H */
tools/perf/arch/x86/util/unwind-libunwind.c +42 -0
51 lines not on this page · raw message
tools/perf/util/Build +6 -0
@@ -1,3 +1,5 @@ +include ../scripts/Makefile.include + libperf-y += alias.o libperf-y += annotate.o libperf-y += build-id.o
@@ -99,6 +101,10 @@ libperf-$(CONFIG_DWARF) += dwarf-aux.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind_common.o +libperf-$(CONFIG_LIBUNWIND_X86) += unwind-libunwind_x86_32.o + +$(OUTPUT)util/unwind-libunwind_x86_32.o: util/unwind-libunwind.c arch/x86/util/unwind-libunwind.c + $(QUIET_CC)$(CC) $(CFLAGS) -DARCH_UNWIND_LIBUNWIND -Iarch/x86/include/libunwind -c -o $@ util/unwind-libunwind.c libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
tools/perf/util/unwind-libunwind.c +1 -1
@@ -527,7 +527,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,return 0 ; } - id =libunwind__arch_reg_id (regnum); + id =LIBUNWIND__ARCH_REG_ID (regnum);if (id <0 )return -EINVAL ;
tools/perf/util/unwind-libunwind_common.c +4 -3
@@ -83,10 +83,11 @@ void unwind__get_arch(struct thread *thread, struct map *map) dso_type == DSO__TYPE_64BIT);if (dso_type !=DSO__TYPE_64BIT ) {#ifdef HAVE_LIBUNWIND_X86_SUPPORT -pr_err ("unwind: target platform=%s is not implemented\n" , - arch); -#endif +register_unwind_libunwind_ops ( + &_Ux86_unwind_libunwind_ops, thread); +#else register_null_unwind_libunwind_ops (thread); +#endif }else use_local_unwind =1 ; }else {
tools/perf/util/unwind.h +5 -0
@@ -54,6 +54,11 @@ static inline void unwind__get_arch(struct thread *thread __maybe_unused,static inline void register_null_unwind_libunwind_ops (struct thread *thread__maybe_unused ) {}#endif + +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +extern struct unwind_libunwind_ops _Ux86_unwind_libunwind_ops; +#endif +#else static inline int unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
Signature · 1 line
1.8.5.2
PATCH v3 7/7 perf callchain: Support aarch64 cross-platform
In reply to He KuangSupport aarch64 cross platform callchain unwind.
--- .../perf/arch/arm64/include/libunwind/libunwind-arch.h | 18 ++++++++++++++++++ tools/perf/arch/arm64/util/unwind-libunwind.c | 5 ++++- tools/perf/config/Makefile | 12 ++++++++++++ tools/perf/util/Build | 4 ++++ tools/perf/util/unwind-libunwind_common.c | 12 ++++++++++++ tools/perf/util/unwind.h | 3 +++ 6 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm64/include/libunwind/libunwind-arch.h
tools/perf/arch/arm64/include/libunwind/libunwind-arch.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _LIBUNWIND_ARCH_H +#define _LIBUNWIND_ARCH_H + +#include <libunwind-aarch64.h> +#include <../perf_regs.h> +#include <../../../../../../arch/arm64/include/uapi/asm/perf_regs.h> + +#define LIBUNWIND_AARCH64 +int libunwind__aarch64_reg_id (int regnum); + +#include <../../../arm64/util/unwind-libunwind.c> + +#define LIBUNWIND__ARCH_REG_ID libunwind__aarch64_reg_id + +#define UNWT_PREFIX UNW_PASTE(UNW_PASTE(_U, aarch64), _) +#define UNWT_OBJ (fn) UNW_PASTE(UNWT_PREFIX, fn) + +#endif /* _LIBUNWIND_ARCH_H */
tools/perf/arch/arm64/util/unwind-libunwind.c +4 -1
@@ -1,11 +1,14 @@#include <errno.h> -#include <libunwind.h> #include "perf_regs.h" #include "../../util/unwind.h" #include "../../util/debug.h" +#ifndef LIBUNWIND_AARCH64 int libunwind__arch_reg_id(int regnum) +#else +int libunwind__aarch64_reg_id(int regnum) +#endif {switch (regnum) {case UNW_AARCH64_X0 :
tools/perf/config/Makefile +12 -0
@@ -353,6 +353,18 @@ ifndef NO_LIBUNWIND have_libunwind = 1 endif + ifeq ($(feature-libunwind-aarch64), 1) + $(call detected,CONFIG_LIBUNWIND_AARCH64) + CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT + LDFLAGS += -lunwind -lunwind-aarch64 + have_libunwind = 1 + $(call feature_check,libunwind-debug-frame-aarch64) + ifneq ($(feature-libunwind-debug-frame-aarch64), 1) + msg := $(warning No debug_frame support found in libunwind-aarch64); + CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64 + endif + endif + ifneq ($(feature-libunwind), 1) msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); NO_LOCAL_LIBUNWIND := 1
tools/perf/util/Build +4 -0
@@ -102,10 +102,14 @@ libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind_common.o libperf-$(CONFIG_LIBUNWIND_X86) += unwind-libunwind_x86_32.o +libperf-$(CONFIG_LIBUNWIND_AARCH64) += unwind-libunwind_arm64.o $(OUTPUT)util/unwind-libunwind_x86_32.o: util/unwind-libunwind.c arch/x86/util/unwind-libunwind.c $(QUIET_CC)$(CC) $(CFLAGS) -DARCH_UNWIND_LIBUNWIND -Iarch/x86/include/libunwind -c -o $@ util/unwind-libunwind.c +$(OUTPUT)util/unwind-libunwind_arm64.o: util/unwind-libunwind.c arch/arm64/util/unwind-libunwind.c + $(QUIET_CC)$(CC) $(CFLAGS) -DARCH_UNWIND_LIBUNWIND -Iarch/arm64/include/libunwind -c -o $@ util/unwind-libunwind.c + libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o libperf-y += scripting-engines/
tools/perf/util/unwind-libunwind_common.c +12 -0
@@ -90,6 +90,18 @@ void unwind__get_arch(struct thread *thread, struct map *map)#endif }else use_local_unwind =1 ; + }else if (!strcmp (arch,"aarch64" ) || !strncmp (arch,"arm" ,3 )) { +pr_debug ("Thread map is ARM, 64bit is %d, dso=%s\n" , + dso_type ==DSO__TYPE_64BIT , map->dso->name); +if (dso_type ==DSO__TYPE_64BIT ) { +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT +register_unwind_libunwind_ops ( + &_Uaarch64_unwind_libunwind_ops, thread); +#else +register_null_unwind_libunwind_ops (thread); +#endif + }else + use_local_unwind =1 ; }else { use_local_unwind =1 ; }
tools/perf/util/unwind.h +3 -0
@@ -58,6 +58,9 @@ register_null_unwind_libunwind_ops(struct thread *thread __maybe_unused) {}#ifdef HAVE_LIBUNWIND_X86_SUPPORT extern struct unwind_libunwind_ops _Ux86_unwind_libunwind_ops;#endif +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT +extern struct unwind_libunwind_ops _Uaarch64_unwind_libunwind_ops; +#endif #else static inline int
Signature · 1 line
1.8.5.2
cover Fixes on perf unwind
hi,
Patch 1-3 fix wrongly used PERF_REG_SP/IP by redefining those macros in the wrapper file according to the target platform, for example in "util/libunwind/x86_32.c".
The first 3 patches have been acked-by "Jiri Olsa" and not touched.
Patch 4 catches an error on python build_ext build.
Patch 5 fixes a NULL pointer deference which can cause segfault when the desired dso is not found.
Thank you.
He Kuang (5):
perf unwind: Change macro names of perf register perf unwind: Fix wrongly used regs for x86_32 unwind perf unwind: Fix wrongly used regs for aarch64 unwind perf tools: Let python use correct gcc for build_ext perf tools: Fix NULL pointer deference when vdso not found
tools/perf/Makefile.perf | 3 ++- tools/perf/util/libunwind/arm64.c | 5 +++++ tools/perf/util/libunwind/x86_32.c | 6 ++++++ tools/perf/util/unwind-libunwind-local.c | 6 ++++-- tools/perf/util/unwind.h | 9 +++++++++ tools/perf/util/vdso.c | 2 +- 6 files changed, 27 insertions(+), 4 deletions(-)
Signature · 1 line
1.8.5.2
PATCH 1/5 perf unwind: Change macro names of perf register
Use macro name prefixed with "LIBUNWIND_ARCH" for better understanding that the regs used by callbacks of libunwind are arch specific. The real regs used should be defined in the wrapper file of "unwind-libunwind-local.c" for each supported arch.
--- tools/perf/util/unwind-libunwind-local.c | 6 ++++-- tools/perf/util/unwind.h | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-)
tools/perf/util/unwind-libunwind-local.c +4 -2
@@ -462,7 +462,8 @@ static int access_mem(unw_addr_space_t __maybe_unused as,return 0 ; } - ret =perf_reg_value (&start, &ui->sample->user_regs,PERF_REG_SP ); + ret =perf_reg_value (&start, &ui->sample->user_regs, +LIBUNWIND__ARCH_REG_SP );if (ret)return ret;
@@ -621,7 +622,8 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,unw_cursor_t c;int ret, i =0 ; - ret =perf_reg_value (&val, &ui->sample->user_regs,PERF_REG_IP ); + ret =perf_reg_value (&val, &ui->sample->user_regs, +LIBUNWIND__ARCH_REG_IP );if (ret)return ret;
tools/perf/util/unwind.h +9 -0
@@ -32,6 +32,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,#ifndef LIBUNWIND__ARCH_REG_ID #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__arch_reg_id(regnum)#endif + +#ifndef LIBUNWIND__ARCH_REG_SP +#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP +#endif + +#ifndef LIBUNWIND__ARCH_REG_IP +#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP +#endif +int LIBUNWIND__ARCH_REG_ID (int regnum);int unwind__prepare_access (struct thread *thread,struct map *map);void unwind__flush_access (struct thread *thread);
Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/core] perf unwind: Change macro names of perf register
perf unwind: Change macro names of perf register
Commit-ID: 78ff1d6d8bf6bb3ee2b3781bbd88355a322435a4 Gitweb: http://git.kernel.org/tip/78ff1d6d8bf6bb3ee2b3781bbd88355a322435a4 Author: He Kuang <[email protected]> AuthorDate: Wed, 22 Jun 2016 06:57:02 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 23 Jun 2016 10:30:17 -0300
perf unwind: Change macro names of perf register
Use macro name prefixed with "LIBUNWIND_ARCH" for better understanding that the regs used by callbacks of libunwind are arch specific. The real regs used should be defined in the wrapper file of "unwind-libunwind-local.c" for each supported arch.
--- tools/perf/util/unwind-libunwind-local.c | 6 ++++-- tools/perf/util/unwind.h | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-)
tools/perf/util/unwind-libunwind-local.c +4 -2
@@ -462,7 +462,8 @@ static int access_mem(unw_addr_space_t __maybe_unused as,return 0 ; } - ret =perf_reg_value (&start, &ui->sample->user_regs,PERF_REG_SP ); + ret =perf_reg_value (&start, &ui->sample->user_regs, +LIBUNWIND__ARCH_REG_SP );if (ret)return ret;
@@ -621,7 +622,8 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,unw_cursor_t c;int ret, i =0 ; - ret =perf_reg_value (&val, &ui->sample->user_regs,PERF_REG_IP ); + ret =perf_reg_value (&val, &ui->sample->user_regs, +LIBUNWIND__ARCH_REG_IP );if (ret)return ret;
tools/perf/util/unwind.h +9 -0
@@ -32,6 +32,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,#ifndef LIBUNWIND__ARCH_REG_ID #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__arch_reg_id(regnum)#endif + +#ifndef LIBUNWIND__ARCH_REG_SP +#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP +#endif + +#ifndef LIBUNWIND__ARCH_REG_IP +#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP +#endif +int LIBUNWIND__ARCH_REG_ID (int regnum);int unwind__prepare_access (struct thread *thread,struct map *map);void unwind__flush_access (struct thread *thread);
PATCH 2/5 perf unwind: Fix wrongly used regs for x86_32 unwind
In reply to He KuangBy default, "unwind-libunwind-local.c" gets SP/IP register number according to the host platform, for remote unwind, we should use register number for target platform. Fix this by define LIBUNWIND_ARCH_REG_SP/IP in the wrapper file of x86_32 platform.
--- tools/perf/util/libunwind/x86_32.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/util/libunwind/x86_32.c +6 -0
@@ -12,7 +12,13 @@*/ #define REMOTE_UNWIND_LIBUNWIND + +/* Define arch specific functions & regs for libunwind, should be +* defined before including "unwind.h" +*/ #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__x86_reg_id(regnum) +#define LIBUNWIND__ARCH_REG_IP PERF_REG_X86_IP +#define LIBUNWIND__ARCH_REG_SP PERF_REG_X86_SP#include "unwind.h" #include "debug.h"
Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/core] perf unwind: Fix wrongly used regs for x86_32 unwind
perf unwind: Fix wrongly used regs for x86_32 unwind
Commit-ID: 5dafea097ac65bd01cc86801c399ae41dce79756 Gitweb: http://git.kernel.org/tip/5dafea097ac65bd01cc86801c399ae41dce79756 Author: He Kuang <[email protected]> AuthorDate: Wed, 22 Jun 2016 06:57:03 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 23 Jun 2016 10:30:21 -0300
perf unwind: Fix wrongly used regs for x86_32 unwind
By default, "unwind-libunwind-local.c" gets SP/IP register number according to the host platform, for remote unwind, we should use register number for target platform. Fix this by define LIBUNWIND_ARCH_REG_SP/IP in the wrapper file of x86_32 platform.
--- tools/perf/util/libunwind/x86_32.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/util/libunwind/x86_32.c +6 -0
@@ -12,7 +12,13 @@*/ #define REMOTE_UNWIND_LIBUNWIND + +/* Define arch specific functions & regs for libunwind, should be +* defined before including "unwind.h" +*/ #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__x86_reg_id(regnum) +#define LIBUNWIND__ARCH_REG_IP PERF_REG_X86_IP +#define LIBUNWIND__ARCH_REG_SP PERF_REG_X86_SP#include "unwind.h" #include "debug.h"
PATCH 3/5 perf unwind: Fix wrongly used regs for aarch64 unwind
In reply to He KuangBy default, "unwind-libunwind-local.c" gets SP/IP register number according to the host platform, for remote unwind, we should use register number for target platform. Fix this by define LIBUNWIND_ARCH_REG_SP/IP in the wrapper file of aarch64 platform.
--- tools/perf/util/libunwind/arm64.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/perf/util/libunwind/arm64.c +5 -0
@@ -13,7 +13,12 @@#define REMOTE_UNWIND_LIBUNWIND +/* Define arch specific functions & regs for libunwind, should be +* defined before including "unwind.h" +*/ #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__arm64_reg_id(regnum) +#define LIBUNWIND__ARCH_REG_IP PERF_REG_ARM64_PC +#define LIBUNWIND__ARCH_REG_SP PERF_REG_ARM64_SP#include "unwind.h" #include "debug.h"
Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/core] perf unwind: Fix wrongly used regs for aarch64 unwind
perf unwind: Fix wrongly used regs for aarch64 unwind
Commit-ID: 3bd03c9583bfb22cb82eeb09d8445bb79d27ae78 Gitweb: http://git.kernel.org/tip/3bd03c9583bfb22cb82eeb09d8445bb79d27ae78 Author: He Kuang <[email protected]> AuthorDate: Wed, 22 Jun 2016 06:57:04 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 23 Jun 2016 10:30:31 -0300
perf unwind: Fix wrongly used regs for aarch64 unwind
By default, "unwind-libunwind-local.c" gets SP/IP register number according to the host platform, for remote unwind, we should use register number for target platform. Fix this by define LIBUNWIND_ARCH_REG_SP/IP in the wrapper file of aarch64 platform.
--- tools/perf/util/libunwind/arm64.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/perf/util/libunwind/arm64.c +5 -0
@@ -13,7 +13,12 @@#define REMOTE_UNWIND_LIBUNWIND +/* Define arch specific functions & regs for libunwind, should be +* defined before including "unwind.h" +*/ #define LIBUNWIND__ARCH_REG_ID (regnum) libunwind__arm64_reg_id(regnum) +#define LIBUNWIND__ARCH_REG_IP PERF_REG_ARM64_PC +#define LIBUNWIND__ARCH_REG_SP PERF_REG_ARM64_SP#include "unwind.h" #include "debug.h"
PATCH 4/5 perf tools: Let python use correct gcc for build_ext
In reply to He KuangCurrently, python uses host gcc instead of cross-compile gcc in the last step of compiling build_ext(remove '--quiet' to show verbose):
cross-gcc ...
cross-gcc ...
creating ~/out/python_ext_build/lib
gcc -pthread -shared -Wl,-z ...
This is wrong but may not cause any errors unless the features detected by cross-compiler do not match those for host compiler, and causes the following errors:
/usr/lib64/gcc/bin/ld: cannot find -lunwind-x86
collect2: error: ld returned 1 exit status
error: command 'gcc' failed with exit status 1
cp: cannot stat ‘~/out/python_ext_build/lib/perf.so’: No such file or directory Makefile.perf:257: recipe for target '~/out/python/perf.so' failed make[1]: *** [~/out/python/perf.so] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
This issue is also reported and anwsered on stackoverflow.
--- tools/perf/Makefile.perf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/Makefile.perf +2 -1
@@ -254,7 +254,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) - $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ + $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ + CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ $(PYTHON_WORD) util/setup.py \ --quiet build_ext; \ mkdir -p $(OUTPUT)python && \
Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/core] perf tools: Let python use correct gcc for build_ext
perf tools: Let python use correct gcc for build_ext
Commit-ID: 48d8d5db4ac454e590ef7d440f456743d6cbaa94 Gitweb: http://git.kernel.org/tip/48d8d5db4ac454e590ef7d440f456743d6cbaa94 Author: He Kuang <[email protected]> AuthorDate: Wed, 22 Jun 2016 06:57:05 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 22 Jun 2016 16:11:42 -0300
perf tools: Let python use correct gcc for build_ext
Currently, python uses host gcc instead of cross-compile gcc in the last step of compiling build_ext(remove '--quiet' to show verbose):
cross-gcc ...
cross-gcc ...
creating ~/out/python_ext_build/lib
gcc -pthread -shared -Wl,-z ...
This is wrong but may not cause any errors unless the features detected by cross-compiler do not match those for host compiler, and causes the following errors:
/usr/lib64/gcc/bin/ld: cannot find -lunwind-x86
collect2: error: ld returned 1 exit status
error: command 'gcc' failed with exit status 1
cp: cannot stat ‘~/out/python_ext_build/lib/perf.so’: No such file or directory Makefile.perf:257: recipe for target '~/out/python/perf.so' failed make[1]: *** [~/out/python/perf.so] Error 1
Makefile:68: recipe for target 'all' failed
make: *** [all] Error 2
This issue is also reported and anwsered on stackoverflow.
--- tools/perf/Makefile.perf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/Makefile.perf +2 -1
@@ -254,7 +254,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) - $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ + $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ + CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ $(PYTHON_WORD) util/setup.py \ --quiet build_ext; \ mkdir -p $(OUTPUT)python && \
PATCH 5/5 perf tools: Fix NULL pointer deference when vdso not found
In reply to He KuangWe should check if 'dso' is a null pointer before passing it to the function dso__type(), otherwise a segfault will be raised in dso__data_get_fd(). In function machine__find_vdso(), the return value checking of 'dso' is missed and this patch fixes this issue.
--- tools/perf/util/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/vdso.c +1 -1
@@ -296,7 +296,7 @@ static struct dso *machine__find_vdso(struct machine *machine,if (!dso) { dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , true); -if (dso_type !=dso__type (dso, machine)) +if (dso && dso_type !=dso__type (dso, machine)) dso =NULL ; }break ;
Signature · 1 line
1.8.5.2
Re: [PATCH 5/5] perf tools: Fix NULL pointer deference when vdso not found
Hi,
This patch fixes a real crash problem when we do 'perf report' on an arm64 platform with arm32 program.
It is introduced by commit f9b2bdf228 ("perf tools: Find vdso with the consider of cross-platform"). From dmesg report, perf crashes in dso__type() because dso is NULL.
Still don't know why on x86 it never crash, but it is obviously that we need to check the return vaule from __dso__find(): it can be NULL.
So please consider pulling.
Thank you.
Quoted 23 lines · He Kuang
We should check if 'dso' is a null pointer before passing it to the function
dso__type(), otherwise a segfault will be raised indso__data_get_fd(). In functionmachine__find_vdso(), the return value checking of 'dso' is missed and this patch fixes this issue.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/vdso.c +1
-1@@ -296,7 +296,7 @@ static struct dso *machine__find_vdso(struct machine *machine,if (!dso) { dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , true); -if (dso_type !=dso__type (dso, machine)) +if (dso && dso_type !=dso__type (dso, machine)) dso =NULL ; }break ;
Re: [PATCH 5/5] perf tools: Fix NULL pointer deference when vdso not found
Quoted 9 lines · Wangnan (F)
Hi,
This patch fixes a real crash problem when we do 'perf report' on an arm64 platform with arm32 program.
It is introduced by commitf9b2bdf228("perf tools: Find vdso with the consider of cross-platform"). From dmesg report, perf crashes indso__type()because dso is NULL.Still don't know why on x86 it never crash, but it is obviously
This is because the fault only occured while dso_type==DSO__TYPE_32BIT, run 64bit executable won't enter the fault branch, but if we run a 32bit executable on x86_64, this bug can be reproduced easily.
# file ~/hello ~/hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 4.5.0, not stripped
# perf record -g hello Segmentation fault
Thank you.
Quoted 35 lines
that we need to check the return vaule from
__dso__find(): it can be NULL.So please consider pulling.
Thank you.
Quoted 24 lines · He Kuang
We should check if 'dso' is a null pointer before passing it to the function
dso__type(), otherwise a segfault will be raised indso__data_get_fd(). In functionmachine__find_vdso(), the return value checking of 'dso' is missed and this patch fixes this issue.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/vdso.c +1
-1@@ -296,7 +296,7 @@ static struct dso *machine__find_vdso(struct machine *machine, if (!dso) { dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , true); -if (dso_type !=dso__type (dso, machine)) +if (dso && dso_type !=dso__type (dso, machine)) dso =NULL ; }break;
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 5/5] perf tools: Fix NULL pointer deference when vdso not found
In reply to Wangnan (F)Em Thu, Jun 23, 2016 at 10:02:39AM +0800, Wangnan (F) escreveu:
Quoted 7 lines
Hi,
This patch fixes a real crash problem when we do 'perf report' on an arm64 platform with arm32 program.
It is introduced by commitf9b2bdf228("perf tools: Find vdso with the consider of cross-platform"). From dmesg report, perf crashes indso__type()because dso is NULL.
Ok, I removed f9b2bdf228 because of this crash, Ingo reported it, now that I see this new patch and checked that the crash was introduced by f9b2bdf228 I'll just combine those two and test again using a 32-bit hackbench on top of f9b2bdf228, to reproduce the crash, then on top of both patches combined.
- Arnaldo
Quoted 33 lines
Still don't know why on x86 it never crash, but it is obviously that we need to check the return vaule from
__dso__find(): it can be NULL.So please consider pulling.
Thank you.
Quoted 23 lines · He Kuang
We should check if 'dso' is a null pointer before passing it to the function
dso__type(), otherwise a segfault will be raised indso__data_get_fd(). In functionmachine__find_vdso(), the return value checking of 'dso' is missed and this patch fixes this issue.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/vdso.c +1
-1@@ -296,7 +296,7 @@ static struct dso *machine__find_vdso(struct machine *machine,if (!dso) { dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , true); -if (dso_type !=dso__type (dso, machine)) +if (dso && dso_type !=dso__type (dso, machine)) dso =NULL ; }break ;
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 5/5] perf tools: Fix NULL pointer deference when vdso not found
Em Thu, Jun 23, 2016 at 09:07:04AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Thu, Jun 23, 2016 at 10:02:39AM +0800, Wangnan (F) escreveu:
Quoted 7 lines
Hi,
This patch fixes a real crash problem when we do 'perf report' on an arm64 platform with arm32 program.
It is introduced by commitf9b2bdf228("perf tools: Find vdso with the consider of cross-platform"). From dmesg report, perf crashes indso__type()because dso is NULL.
Quoted 5 lines
Ok, I removed
f9b2bdf228because of this crash, Ingo reported it, now that I see this new patch and checked that the crash was introduced byf9b2bdf228I'll just combine those two and test again using a 32-bit hackbench on top off9b2bdf228, to reproduce the crash, then on top of both patches combined.
Tested, reproduced, ammended, fixed, applied, thanks!
- Arnaldo
Quoted 35 lines
- Arnaldo
Quoted 33 lines
Still don't know why on x86 it never crash, but it is obviously that we need to check the return vaule from
__dso__find(): it can be NULL.So please consider pulling.
Thank you.
Quoted 23 lines · He Kuang
We should check if 'dso' is a null pointer before passing it to the function
dso__type(), otherwise a segfault will be raised indso__data_get_fd(). In functionmachine__find_vdso(), the return value checking of 'dso' is missed and this patch fixes this issue.Signed-off-by He Kuang <[email protected]>--- tools/perf/util/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/vdso.c +1
-1@@ -296,7 +296,7 @@ static struct dso *machine__find_vdso(struct machine *machine,if (!dso) { dso =__dsos__find (&machine->dsos,DSO__NAME_VDSO , true); -if (dso_type !=dso__type (dso, machine)) +if (dso && dso_type !=dso__type (dso, machine)) dso =NULL ; }break ;
tip-bot for He Kuang
merge bot[tip:perf/core] perf tools: Find right DSO taking into account if binary is 32 or 64-bit
In reply to He Kuangperf tools: Find right DSO taking into account if binary is 32 or 64-bit
Commit-ID: 76c588f1f6b560c510953b390bc0a26c27cbfbd0 Gitweb: http://git.kernel.org/tip/76c588f1f6b560c510953b390bc0a26c27cbfbd0 Author: He Kuang <[email protected]> AuthorDate: Tue, 17 May 2016 09:04:54 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 23 Jun 2016 10:25:58 -0300
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.
--- tools/perf/util/vdso.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)
tools/perf/util/vdso.c +37 -3
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *sreturn 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;
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 0/5] Fixes on perf unwind
In reply to He KuangEm Wed, Jun 22, 2016 at 06:57:01AM +0000, He Kuang escreveu:
Quoted 7 lines
hi,
Patch 1-3 fix wrongly used PERF_REG_SP/IP by redefining those macros in the wrapper file according to the target platform, for example in "
util/libunwind/x86_32.c".
The first 3 patches have been acked-by "Jiri Olsa" and not touched.
Quoted 6 lines
Patch 4 catches an error on python
build_extbuild.Patch 5 fixes a NULL pointer deference which can cause segfault when the desired dso is not found.
Thank you.
Thanks, all applied.
- Arnaldo