Add support for remote unwind
Subsystems (2)
cover Add support for remote unwind
Currently, 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 do remote unwind on other platforms/machines.
This patch set adds build tests for the supported platforms for remote unwinding, and checks the map elf info for each thread, use remote unwind methods instead.
Only x86 and aarch64 is added in this patch set to show the work flow, other platforms can be added easily.
We can see the right result for unwind infos on different machines, for example: we record perf.data on i686 qemu with '-g' option and parse it on x86_64 machine.
before this patchset:
hello 1071 [000] 417.567832: probe:sys_close: (c1169d60)
c1169d61 sys_close ([kernel.kallsyms])
c189c0d7 sysenter_past_esp ([kernel.kallsyms])
b77c8ba9 [unknown] ([vdso32])after:
hello 1071 [000] 417.567832: probe:sys_close: (c1169d60)
c1169d61 sys_close ([kernel.kallsyms])
c189c0d7 sysenter_past_esp ([kernel.kallsyms])
b77c8ba9 [unknown] ([vdso32])
b76e51cc close (/lib/libc-2.22.so)
804842e fib (/tmp/hello)
804849d main (/tmp/hello)
b762546e __libc_start_main (/lib/libc-2.22.so)
8048341 _start (/tmp/hello)Thanks, discussion welcomed.
He Kuang (8):
perf tools: Omit DWARF judgement when recording dwarf callchain perf script: Add options for custom vdso name
perf build: Add build-test for libunwind cross-platforms support perf build: Add build-test for debug-frame on arm/arm64 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
tools/build/Makefile.feature | 11 +++- tools/build/feature/Makefile | 26 +++++++- tools/build/feature/test-libunwind-aarch64.c | 26 ++++++++ tools/build/feature/test-libunwind-arm.c | 27 +++++++++ .../feature/test-libunwind-debug-frame-aarch64.c | 16 +++++ .../build/feature/test-libunwind-debug-frame-arm.c | 16 +++++ tools/build/feature/test-libunwind-debug-frame.c | 16 ----- tools/build/feature/test-libunwind-x86.c | 27 +++++++++ tools/build/feature/test-libunwind-x86_64.c | 27 +++++++++ .../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/builtin-script.c | 2 + tools/perf/config/Makefile | 35 ++++++++++- tools/perf/util/Build | 13 +++- tools/perf/util/dso.c | 7 +++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol-elf.c | 16 +++++ tools/perf/util/symbol.c | 50 ++++++++++++++++ tools/perf/util/symbol.h | 3 + tools/perf/util/thread.c | 70 ++++++++++++++++++++-- tools/perf/util/thread.h | 14 ++++- tools/perf/util/unwind-libunwind.c | 50 +++++++++++++--- tools/perf/util/unwind-libunwind_common.c | 60 +++++++++++++++++++ tools/perf/util/unwind.h | 30 ++++++++++ tools/perf/util/util.c | 2 - 27 files changed, 589 insertions(+), 39 deletions(-) create mode 100644 tools/build/feature/test-libunwind-aarch64.c create mode 100644 tools/build/feature/test-libunwind-arm.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c delete mode 100644 tools/build/feature/test-libunwind-debug-frame.c create mode 100644 tools/build/feature/test-libunwind-x86.c create mode 100644 tools/build/feature/test-libunwind-x86_64.c 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 1/8 perf tools: Omit DWARF judgement when recording dwarf callchain
There's no need for dwarf support when perf recording with callchain.
--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)
tools/perf/util/util.c +0 -2
@@ -471,7 +471,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;
@@ -487,7 +486,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/8] perf tools: Omit DWARF judgement when recording dwarf callchain
Em Fri, May 06, 2016 at 08:59:07AM +0000, He Kuang escreveu:
Quoted 1 line
There's no need for dwarf support when perf recording with callchain.
Can you rewrite this? We do need to have support for dwarf when processing "dwarf style" callchains.
- Arnaldo
Quoted 27 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)tools/perf/util/util.c +0
-2@@ -471,7 +471,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;@@ -487,7 +486,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;Signature · 1 line
1.8.5.2
Re: [PATCH 1/8] perf tools: Omit DWARF judgement when recording dwarf callchain
In reply to He KuangQuoted 3 lines · He Kuang
There's no need for dwarf support when perf recording with callchain.
Signed-off-by He Kuang <[email protected]>
thanks,
jirka
Quoted 27 lines
--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)tools/perf/util/util.c +0
-2@@ -471,7 +471,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;@@ -487,7 +486,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 1/8] perf tools: Omit DWARF judgement when recording dwarf callchain
Em Sat, May 07, 2016 at 08:03:46PM +0200, Jiri Olsa escreveu:
Quoted 6 lines · He Kuang
Quoted 3 lines
There's no need for dwarf support when perf recording with callchain.
Signed-off-by He Kuang <[email protected]>Acked-by Jiri Olsa <[email protected]>
Ok, due to your Ack I went on to read the code and indeed, with this changeset description:
"There is no need to check for DWARF unwinding support when using the 'dwarf' callchain record method, as this will only ask the kernel to collect stack dumps for later DWARF CFI processing, which can be done in another machine, where the support for DWARF unwinding need to be present."
Thanks,
- Arnaldo
Quoted 30 lines
thanks,
jirkaQuoted 27 lines
--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)tools/perf/util/util.c +0
-2@@ -471,7 +471,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;@@ -487,7 +486,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;Signature · 1 line
1.8.5.2
Re: [PATCH 1/8] perf tools: Omit DWARF judgement when recording dwarf callchain
ok
Quoted 49 lines · Arnaldo Carvalho de Melo
Em Sat, May 07, 2016 at 08:03:46PM +0200, Jiri Olsa escreveu:
Quoted 5 lines · He Kuang
Quoted 3 lines
There's no need for dwarf support when perf recording with callchain.
Signed-off-by He Kuang <[email protected]>Acked-by Jiri Olsa <[email protected]>Ok, due to your Ack I went on to read the code and indeed, with this changeset description:
"There is no need to check for DWARF unwinding support when using the 'dwarf' callchain record method, as this will only ask the kernel to collect stack dumps for later DWARF CFI processing, which can be done in another machine, where the support for DWARF unwinding need to be present."
Thanks,
- Arnaldo
Quoted 30 lines
thanks,
jirkaQuoted 27 lines
--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)tools/perf/util/util.c +0
-2@@ -471,7 +471,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;@@ -487,7 +486,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;Signature · 1 line
1.8.5.2
tip-bot for He Kuang
merge bot[tip:perf/core] perf callchain: Recording 'dwarf' callchains do not need DWARF unwinding support
In reply to He Kuangperf callchain: Recording 'dwarf' callchains do not need DWARF unwinding support
Commit-ID: 841e3558b2de6d8c53dae4f01c7a81cd53e42e5c Gitweb: http://git.kernel.org/tip/841e3558b2de6d8c53dae4f01c7a81cd53e42e5c Author: He Kuang <[email protected]> AuthorDate: Fri, 6 May 2016 08:59:07 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 9 May 2016 13:29:36 -0300
perf callchain: Recording 'dwarf' callchains do not need DWARF unwinding support
There is no need to check for DWARF unwinding support when using the 'dwarf' callchain record method, as this will only ask the kernel to collect stack dumps for later DWARF CFI processing, which can be done in another machine, where the support for DWARF unwinding need to be present.
--- tools/perf/util/util.c | 2 -- 1 file changed, 2 deletions(-)
tools/perf/util/util.c +0 -2
@@ -507,7 +507,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) "needed for --call-graph fp\n");break ; -#ifdef HAVE_DWARF_UNWIND_SUPPORT /* Dwarf style */ }else if (!strncmp (name,"dwarf" ,sizeof ("dwarf" ))) {const unsigned long default_stack_dump_size =8192 ;
@@ -523,7 +522,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) ret =get_stack_size (tok, &size); param->dump_size = size; } -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { param->record_mode =CALLCHAIN_LBR ;
PATCH 2/8 perf script: Add options for custom vdso name
In reply to He KuangWhen unwinding callchain on different machine, vdso info should be provided so the unwind process won't be interrupted if address fell into vdso region.
--- tools/perf/builtin-script.c | 2 ++ tools/perf/util/dso.c | 7 +++++++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 1 + 5 files changed, 12 insertions(+)
tools/perf/builtin-script.c +2 -0
@@ -2001,6 +2001,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "file", "vmlinux pathname"),OPT_STRING (0 ,"kallsyms" , &symbol_conf.kallsyms_name,"file" ,"kallsyms pathname" ), +OPT_STRING (0 ,"vdso" , &symbol_conf.vdso_name, +"file" ,"vdso pathname" ),OPT_BOOLEAN ('G' ,"hide-call-graph" , &no_callchain,"When printing symbols do not display call chain" ), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
tools/perf/util/dso.c +7 -0
@@ -21,6 +21,7 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', + [DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM] = 'r', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
@@ -113,6 +114,11 @@ int dso__read_binary_type_filename(const struct dso *dso, build_id_hex, build_id_hex + 2);break ; +case DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM : + { +snprintf (filename, size,"%s" , symbol_conf.vdso_name); +break ; + }case DSO_BINARY_TYPE__VMLINUX :case DSO_BINARY_TYPE__GUEST_VMLINUX :case DSO_BINARY_TYPE__SYSTEM_PATH_DSO :
@@ -487,6 +493,7 @@ static void try_to_open_dso(struct dso *dso, struct machine *machine)enum dso_binary_type binary_type_data[] = {DSO_BINARY_TYPE__BUILD_ID_CACHE ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO , +DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM ,DSO_BINARY_TYPE__NOT_FOUND , };int i =0 ;
tools/perf/util/dso.h +1 -0
@@ -23,6 +23,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__UBUNTU_DEBUGINFO ,DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO , +DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM ,DSO_BINARY_TYPE__GUEST_KMODULE ,DSO_BINARY_TYPE__GUEST_KMODULE_COMP , DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
tools/perf/util/symbol.c +1 -0
@@ -1359,6 +1359,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__JAVA_JIT :case DSO_BINARY_TYPE__DEBUGLINK :case DSO_BINARY_TYPE__SYSTEM_PATH_DSO : +case DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM :case DSO_BINARY_TYPE__FEDORA_DEBUGINFO :case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO :case DSO_BINARY_TYPE__BUILDID_DEBUGINFO :
tools/perf/util/symbol.h +1 -0
@@ -114,6 +114,7 @@ struct symbol_conf { report_hierarchy;const char *vmlinux_name, *kallsyms_name, + *vdso_name, *source_prefix, *field_sep; const char *default_guest_vmlinux_name,
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 2/8] perf script: Add options for custom vdso name
Em Fri, May 06, 2016 at 08:59:08AM +0000, He Kuang escreveu:
Quoted 39 lines
When unwinding callchain on different machine, vdso info should be provided so the unwind process won't be interrupted if address fell into vdso region.
Signed-off-by He Kuang <[email protected]>--- tools/perf/builtin-script.c | 2 ++ tools/perf/util/dso.c | 7 +++++++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 1 + 5 files changed, 12 insertions(+)tools/perf/builtin-script.c +2
-0@@ -2001,6 +2001,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "file", "vmlinux pathname"),OPT_STRING (0 ,"kallsyms" , &symbol_conf.kallsyms_name,"file" ,"kallsyms pathname" ), +OPT_STRING (0 ,"vdso" , &symbol_conf.vdso_name, +"file" ,"vdso pathname" ),OPT_BOOLEAN ('G' ,"hide-call-graph" , &no_callchain,"When printing symbols do not display call chain" ), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",tools/perf/util/dso.c +1
-0@@ -21,6 +21,7 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', + [DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM] = 'r', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
tools/perf/util/dso.c int dso__read_binary_type_filename(const struct dso *dso, · line 121
Quoted 8 lines
tools/perf/util/dso.c +5
-0@@ -113,6 +114,11 @@ int dso__read_binary_type_filename(const struct dso *dso, build_id_hex, build_id_hex + 2);break ; +case DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM : + { +snprintf (filename, size,"%s" , symbol_conf.vdso_name); +break ; + }
Remove the {}, not needed at all.
tools/perf/util/dso.c static void try_to_open_dso(struct dso *dso, struct machine *machine) · line 496
Quoted 8 lines
tools/perf/util/dso.c +1
-0case DSO_BINARY_TYPE__VMLINUX :case DSO_BINARY_TYPE__GUEST_VMLINUX :case DSO_BINARY_TYPE__SYSTEM_PATH_DSO :@@ -487,6 +493,7 @@ static void try_to_open_dso(struct dso *dso, struct machine *machine)enum dso_binary_type binary_type_data[] = {DSO_BINARY_TYPE__BUILD_ID_CACHE ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO , +DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM ,
Why do you call it a "DSO_CUSTOM" in some places while in others you call it vdso_name?
Quoted 41 lines
tools/perf/util/dso.c +0
-0DSO_BINARY_TYPE__NOT_FOUND, };int i =0 ;tools/perf/util/dso.h +1
-0@@ -23,6 +23,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__UBUNTU_DEBUGINFO ,DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO , +DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM ,DSO_BINARY_TYPE__GUEST_KMODULE ,DSO_BINARY_TYPE__GUEST_KMODULE_COMP , DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,tools/perf/util/symbol.c +1
-0@@ -1359,6 +1359,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__JAVA_JIT :case DSO_BINARY_TYPE__DEBUGLINK :case DSO_BINARY_TYPE__SYSTEM_PATH_DSO : +case DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM :case DSO_BINARY_TYPE__FEDORA_DEBUGINFO :case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO :case DSO_BINARY_TYPE__BUILDID_DEBUGINFO :tools/perf/util/symbol.h +1
-0@@ -114,6 +114,7 @@ struct symbol_conf { report_hierarchy;const char *vmlinux_name, *kallsyms_name, + *vdso_name, *source_prefix, *field_sep; const char *default_guest_vmlinux_name,Signature · 1 line
1.8.5.2
Re: [PATCH 2/8] perf script: Add options for custom vdso name
In reply to He KuangQuoted 51 lines · He Kuang
When unwinding callchain on different machine, vdso info should be provided so the unwind process won't be interrupted if address fell into vdso region.
Signed-off-by He Kuang <[email protected]>--- tools/perf/builtin-script.c | 2 ++ tools/perf/util/dso.c | 7 +++++++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 1 + 5 files changed, 12 insertions(+)tools/perf/builtin-script.c +2
-0@@ -2001,6 +2001,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "file", "vmlinux pathname"),OPT_STRING (0 ,"kallsyms" , &symbol_conf.kallsyms_name,"file" ,"kallsyms pathname" ), +OPT_STRING (0 ,"vdso" , &symbol_conf.vdso_name, +"file" ,"vdso pathname" ),OPT_BOOLEAN ('G' ,"hide-call-graph" , &no_callchain,"When printing symbols do not display call chain" ), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",tools/perf/util/dso.c +6
-0@@ -21,6 +21,7 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', + [DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM] = 'r', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',@@ -113,6 +114,11 @@ int dso__read_binary_type_filename(const struct dso *dso, build_id_hex, build_id_hex + 2);break ; +case DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM : + { +snprintf (filename, size,"%s" , symbol_conf.vdso_name); +break ; + }case DSO_BINARY_TYPE__VMLINUX :case DSO_BINARY_TYPE__GUEST_VMLINUX :case DSO_BINARY_TYPE__SYSTEM_PATH_DSO :
tools/perf/util/dso.c static void try_to_open_dso(struct dso *dso, struct machine *machine) · line 496
Quoted 4 lines
tools/perf/util/dso.c +1
-0@@ -487,6 +493,7 @@ static void try_to_open_dso(struct dso *dso, struct machine *machine)enum dso_binary_type binary_type_data[] = {DSO_BINARY_TYPE__BUILD_ID_CACHE ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO , +DSO_BINARY_TYPE__SYSTEM_PATH_DSO_CUSTOM ,
could you please elaborate on how this one gets set? don't we already store it under .debug?
also it seems fairly vdso specific, we shouldn't call it DSO_CUSTOM
thanks,
jirka
PATCH 3/8 perf build: Add build-test for libunwind cross-platforms support
In reply to He KuangCurrently only test for local libunwind. We should check all supported platforms so we can use them to parse perf.data with callchain info on different machines.
--- tools/build/Makefile.feature | 8 ++++++++ tools/build/feature/Makefile | 16 ++++++++++++++++ tools/build/feature/test-libunwind-aarch64.c | 26 ++++++++++++++++++++++++++ tools/build/feature/test-libunwind-arm.c | 27 +++++++++++++++++++++++++++ tools/build/feature/test-libunwind-x86.c | 27 +++++++++++++++++++++++++++ tools/build/feature/test-libunwind-x86_64.c | 27 +++++++++++++++++++++++++++ 6 files changed, 131 insertions(+) create mode 100644 tools/build/feature/test-libunwind-aarch64.c create mode 100644 tools/build/feature/test-libunwind-arm.c create mode 100644 tools/build/feature/test-libunwind-x86.c create mode 100644 tools/build/feature/test-libunwind-x86_64.c
tools/build/Makefile.feature +8 -0
@@ -49,6 +49,10 @@ FEATURE_TESTS_BASIC := \ libslang \ libcrypto \ libunwind \ + libunwind-x86 \ + libunwind-x86_64 \ + libunwind-arm \ + libunwind-aarch64 \ pthread-attr-setaffinity-np \ stackprotector-all \ timerfd \
@@ -92,6 +96,10 @@ FEATURE_DISPLAY ?= \ libslang \ libcrypto \ libunwind \ + libunwind-x86 \ + libunwind-x86_64 \ + libunwind-arm \ + libunwind-aarch64 \ libdw-dwarf-unwind \ zlib \ lzma \
tools/build/feature/Makefile +16 -0
@@ -27,6 +27,10 @@ FILES= \ test-libcrypto.bin \ test-libunwind.bin \ test-libunwind-debug-frame.bin \ + test-libunwind-x86.bin \ + test-libunwind-x86_64.bin \ + test-libunwind-arm.bin \ + test-libunwind-aarch64.bin \ test-pthread-attr-setaffinity-np.bin \ test-stackprotector-all.bin \ test-timerfd.bin \
@@ -103,6 +107,18 @@ $(OUTPUT)test-libunwind.bin: $(OUTPUT)test-libunwind-debug-frame.bin: $(BUILD) -lelf +$(OUTPUT)test-libunwind-x86.bin: + $(BUILD) -lelf -lunwind-x86 + +$(OUTPUT)test-libunwind-x86_64.bin: + $(BUILD) -lelf -lunwind-x86_64 + +$(OUTPUT)test-libunwind-arm.bin: + $(BUILD) -lelf -lunwind-arm + +$(OUTPUT)test-libunwind-aarch64.bin: + $(BUILD) -lelf -lunwind-aarch64 + $(OUTPUT)test-libaudit.bin: $(BUILD) -laudit
tools/build/feature/test-libunwind-aarch64.c new file +26 -0
@@ -0,0 +1,26 @@ +#include <libunwind-aarch64.h> +#include <stdlib.h> + +extern int UNW_OBJ (dwarf_search_unwind_table ) (unw_addr_space_t as, +unw_word_t ip, +unw_dyn_info_t *di, +unw_proc_info_t *pi, +int need_unwind_info,void *arg); + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +static unw_accessors_t accessors; + +int main (void ) +{ +unw_addr_space_t addr_space; + + addr_space =unw_create_addr_space (&accessors,0 ); +if (addr_space) +return 0 ; + +unw_init_remote (NULL , addr_space,NULL ); +dwarf_search_unwind_table (addr_space,0 ,NULL ,NULL ,0 ,NULL ); + +return 0 ; +}
tools/build/feature/test-libunwind-arm.c new file +27 -0
@@ -0,0 +1,27 @@ +#include <libunwind-arm.h> +#include <stdlib.h> + +extern int UNW_OBJ (dwarf_search_unwind_table ) (unw_addr_space_t as, +unw_word_t ip, +unw_dyn_info_t *di, +unw_proc_info_t *pi, +int need_unwind_info,void *arg); + + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +static unw_accessors_t accessors; + +int main (void ) +{ +unw_addr_space_t addr_space; + + addr_space =unw_create_addr_space (&accessors,0 ); +if (addr_space) +return 0 ; + +unw_init_remote (NULL , addr_space,NULL ); +dwarf_search_unwind_table (addr_space,0 ,NULL ,NULL ,0 ,NULL ); + +return 0 ; +}
tools/build/feature/test-libunwind-x86.c new file +27 -0
@@ -0,0 +1,27 @@ +#include <libunwind-x86.h> +#include <stdlib.h> + +extern int UNW_OBJ (dwarf_search_unwind_table ) (unw_addr_space_t as, +unw_word_t ip, +unw_dyn_info_t *di, +unw_proc_info_t *pi, +int need_unwind_info,void *arg); + + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +static unw_accessors_t accessors; + +int main (void ) +{ +unw_addr_space_t addr_space; + + addr_space =unw_create_addr_space (&accessors,0 ); +if (addr_space) +return 0 ; + +unw_init_remote (NULL , addr_space,NULL ); +dwarf_search_unwind_table (addr_space,0 ,NULL ,NULL ,0 ,NULL ); + +return 0 ; +}
tools/build/feature/test-libunwind-x86_64.c new file +27 -0
@@ -0,0 +1,27 @@ +#include <libunwind-x86_64.h> +#include <stdlib.h> + +extern int UNW_OBJ (dwarf_search_unwind_table ) (unw_addr_space_t as, +unw_word_t ip, +unw_dyn_info_t *di, +unw_proc_info_t *pi, +int need_unwind_info,void *arg); + + +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) + +static unw_accessors_t accessors; + +int main (void ) +{ +unw_addr_space_t addr_space; + + addr_space =unw_create_addr_space (&accessors,0 ); +if (addr_space) +return 0 ; + +unw_init_remote (NULL , addr_space,NULL ); +dwarf_search_unwind_table (addr_space,0 ,NULL ,NULL ,0 ,NULL ); + +return 0 ; +}
Signature · 1 line
1.8.5.2
Re: [PATCH 3/8] perf build: Add build-test for libunwind cross-platforms support
Quoted 34 lines · He Kuang
Currently only test for local libunwind. We should check all supported platforms so we can use them to parse perf.data with callchain info on different machines.
Signed-off-by He Kuang <[email protected]>--- tools/build/Makefile.feature | 8 ++++++++ tools/build/feature/Makefile | 16 ++++++++++++++++ tools/build/feature/test-libunwind-aarch64.c | 26 ++++++++++++++++++++++++++ tools/build/feature/test-libunwind-arm.c | 27 +++++++++++++++++++++++++++ tools/build/feature/test-libunwind-x86.c | 27 +++++++++++++++++++++++++++ tools/build/feature/test-libunwind-x86_64.c | 27 +++++++++++++++++++++++++++ 6 files changed, 131 insertions(+) create mode 100644 tools/build/feature/test-libunwind-aarch64.c create mode 100644 tools/build/feature/test-libunwind-arm.c create mode 100644 tools/build/feature/test-libunwind-x86.c create mode 100644 tools/build/feature/test-libunwind-x86_64.ctools/build/Makefile.feature +4
-0@@ -49,6 +49,10 @@ FEATURE_TESTS_BASIC := \ libslang \ libcrypto \ libunwind \ + libunwind-x86 \ + libunwind-x86_64 \ + libunwind-arm \ + libunwind-aarch64 \ pthread-attr-setaffinity-np \ stackprotector-all \ timerfd \
tools/build/Makefile.feature FEATURE_DISPLAY ?= \ · line 102
Quoted 7 lines
tools/build/Makefile.feature +4
-0@@ -92,6 +96,10 @@ FEATURE_DISPLAY ?= \ libslang \ libcrypto \ libunwind \ + libunwind-x86 \ + libunwind-x86_64 \ + libunwind-arm \ + libunwind-aarch64 \
I dont think we should display status of libs needed only for cross builds it'll be OFF for most of the people and create unnecessary tension ;-)
thanks,
jirka
PATCH 4/8 perf build: Add build-test for debug-frame on arm/arm64
In reply to He KuangDebug-frame for remote platforms is not related to the host platform, so we should test each platform separately.
--- tools/build/Makefile.feature | 3 ++- tools/build/feature/Makefile | 10 +++++++--- tools/build/feature/test-libunwind-debug-frame-aarch64.c | 16 ++++++++++++++++ tools/build/feature/test-libunwind-debug-frame-arm.c | 16 ++++++++++++++++ tools/build/feature/test-libunwind-debug-frame.c | 16 ---------------- 5 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c delete mode 100644 tools/build/feature/test-libunwind-debug-frame.c
tools/build/Makefile.feature +2 -1
@@ -73,7 +73,8 @@ FEATURE_TESTS_EXTRA := \ libbabeltrace \ liberty \ liberty-z \ - libunwind-debug-frame + libunwind-debug-frame-arm \ + libunwind-debug-frame-aarch64 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
tools/build/feature/Makefile +7 -3
@@ -26,11 +26,12 @@ FILES= \ test-libslang.bin \ test-libcrypto.bin \ test-libunwind.bin \ - test-libunwind-debug-frame.bin \ test-libunwind-x86.bin \ test-libunwind-x86_64.bin \ test-libunwind-arm.bin \ test-libunwind-aarch64.bin \ + test-libunwind-debug-frame-arm.bin \ + test-libunwind-debug-frame-aarch64.bin \ test-pthread-attr-setaffinity-np.bin \ test-stackprotector-all.bin \ test-timerfd.bin \
@@ -105,8 +106,6 @@ $(OUTPUT)test-numa_num_possible_cpus.bin: $(OUTPUT)test-libunwind.bin: $(BUILD) -lelf -$(OUTPUT)test-libunwind-debug-frame.bin: - $(BUILD) -lelf $(OUTPUT)test-libunwind-x86.bin: $(BUILD) -lelf -lunwind-x86
@@ -119,6 +118,11 @@ $(OUTPUT)test-libunwind-arm.bin: $(OUTPUT)test-libunwind-aarch64.bin: $(BUILD) -lelf -lunwind-aarch64 +$(OUTPUT)test-libunwind-debug-frame-arm.bin: + $(BUILD) -lelf -lunwind-arm + +$(OUTPUT)test-libunwind-debug-frame-aarch64.bin: + $(BUILD) -lelf -lunwind-aarch64 $(OUTPUT)test-libaudit.bin: $(BUILD) -laudit
tools/build/feature/test-libunwind-debug-frame-aarch64.c new file +16 -0
@@ -0,0 +1,16 @@ +#include <libunwind-aarch64.h> +#include <stdlib.h> + +extern int +UNW_OBJ (dwarf_find_debug_frame ) (int found,unw_dyn_info_t *di_debug, +unw_word_t ip,unw_word_t segbase, +const char *obj_name,unw_word_t start, +unw_word_t end); + +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) + +int main (void ) +{ +dwarf_find_debug_frame (0 ,NULL ,0 ,0 ,NULL ,0 ,0 ); +return 0 ; +}
tools/build/feature/test-libunwind-debug-frame-arm.c new file +16 -0
@@ -0,0 +1,16 @@ +#include <libunwind-arm.h> +#include <stdlib.h> + +extern int +UNW_OBJ (dwarf_find_debug_frame ) (int found,unw_dyn_info_t *di_debug, +unw_word_t ip,unw_word_t segbase, +const char *obj_name,unw_word_t start, +unw_word_t end); + +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) + +int main (void ) +{ +dwarf_find_debug_frame (0 ,NULL ,0 ,0 ,NULL ,0 ,0 ); +return 0 ; +}
tools/build/feature/test-libunwind-debug-frame.c deleted +0 -16
@@ -1,16 +0,0 @@ -#include <libunwind.h> -#include <stdlib.h> - -extern int -UNW_OBJ (dwarf_find_debug_frame ) (int found,unw_dyn_info_t *di_debug, -unw_word_t ip,unw_word_t segbase, -const char *obj_name,unw_word_t start, -unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - -int main (void ) -{ -dwarf_find_debug_frame (0 ,NULL ,0 ,0 ,NULL ,0 ,0 ); -return 0 ; -}
Signature · 1 line
1.8.5.2
Re: [PATCH 4/8] perf build: Add build-test for debug-frame on arm/arm64
Quoted 2 lines · He Kuang
Debug-frame for remote platforms is not related to the host platform, so we should test each platform separately.
SNIP
Quoted 6 lines
tools/build/feature/test-libunwind-debug-frame.c deleted +0
-0
tools/build/feature/test-libunwind-debug-frame.c line 10
Quoted 10 lines
tools/build/feature/test-libunwind-debug-frame.c deleted +0
-10@@ -1,16 +0,0 @@ -#include <libunwind.h> -#include <stdlib.h> - -extern int -UNW_OBJ (dwarf_find_debug_frame ) (int found,unw_dyn_info_t *di_debug, -unw_word_t ip,unw_word_t segbase, -const char *obj_name,unw_word_t start, -unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
hum but we still use this in standard libdw unwind from find_proc_info in util/unwind-libunwind.c
should we keep the generic version as well?
thanks,
jirka
PATCH 5/8 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(32bit) on x86(64bit) machine.
This patch shows proper error messages when we do remote unwind x86(32bit) on other machines.
Same thing for other platforms will be added in next patches.
--- tools/perf/config/Makefile | 6 ++++++ tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ tools/perf/util/thread.c | 31 ++++++++++++++++++++++++++++ 5 files changed, 104 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/symbol-elf.c +16 -0
@@ -636,6 +636,22 @@ bool __weak elf__needs_adjust_symbols(GElf_Ehdr ehdr)return ehdr.e_type ==ET_EXEC || ehdr.e_type ==ET_REL ; } +int elf_is_64_bit (char *name) +{ +Elf *elf; +int fd; + + fd =open (name,O_RDONLY ); +if (fd <0 ) +return -1 ; + + elf =elf_begin (fd,PERF_ELF_C_READ_MMAP ,NULL ); +if (elf ==NULL ) +return -1 ; + +return (gelf_getclass (elf) ==ELFCLASS64 ); +} +int symsrc__init (struct symsrc *ss,struct dso *dso,const char *name,enum dso_binary_type type) {
tools/perf/util/symbol.c +49 -0
55 lines not on this page · raw message
tools/perf/util/symbol.h +2 -0
@@ -308,6 +308,8 @@ int setup_list(struct strlist **list, const char *list_str, const char *list_name);int setup_intlist (struct intlist **list,const char *list_str,const char *list_name); +int elf_is_64_bit (char *name); +int dso_is_64_bit (struct dso *dso,struct map *map);#ifdef HAVE_LIBELF_SUPPORT bool elf__needs_adjust_symbols (GElf_Ehdr ehdr);
tools/perf/util/thread.c +31 -0
@@ -184,8 +184,39 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)void thread__insert_map (struct thread *thread,struct map *map) { +char *__maybe_unused arch; +int __maybe_unused is_64_bit; +map_groups__fixup_overlappings (thread->mg, map, stderr);map_groups__insert (thread->mg, map); + +#ifdef HAVE_LIBUNWIND_SUPPORT +if (!thread->mg->machine->env) +return ; + + is_64_bit =dso_is_64_bit (map->dso, map); +if (is_64_bit <0 ) +return ; + +if (thread->addr_space) +pr_debug ("Thread map already set, 64bit is %d, dso=%s\n" , + is_64_bit, 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" , is_64_bit); + if (!is_64_bit) +#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 + } +#endif } static int thread__clone_map_groups(struct thread *thread,
Signature · 1 line
1.8.5.2
Re: [PATCH 5/8] perf tools: Promote proper messages for cross-platform unwind
Quoted 167 lines · He Kuang
Currently, 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(32bit) on x86(64bit) machine.
This patch shows proper error messages when we do remote unwind x86(32bit) on other machines.
Same thing for other platforms will be added in next patches.
Signed-off-by He Kuang <[email protected]>--- tools/perf/config/Makefile | 6 ++++++ tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ tools/perf/util/thread.c | 31 ++++++++++++++++++++++++++++ 5 files changed, 104 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 := 1tools/perf/util/symbol-elf.c +16
-0@@ -636,6 +636,22 @@ bool __weak elf__needs_adjust_symbols(GElf_Ehdr ehdr)return ehdr.e_type ==ET_EXEC || ehdr.e_type ==ET_REL ; } +int elf_is_64_bit (char *name) +{ +Elf *elf; +int fd; + + fd =open (name,O_RDONLY ); +if (fd <0 ) +return -1 ; + + elf =elf_begin (fd,PERF_ELF_C_READ_MMAP ,NULL ); +if (elf ==NULL ) +return -1 ; + +return (gelf_getclass (elf) ==ELFCLASS64 ); +} +int symsrc__init (struct symsrc *ss,struct dso *dso,const char *name,enum dso_binary_type type) {tools/perf/util/symbol.c +49
-0@@ -1395,6 +1395,55 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, } } +int dso_is_64_bit (struct dso *dso,struct map *map) +{ +char *name; +u_int i; +bool kmod; +char *root_dir = (char *)"" ; +struct machine *machine; + +if (map->groups && map->groups->machine) + machine = map->groups->machine; +else + machine =NULL ; + +if (machine) + root_dir = machine->root_dir; + + name =malloc (PATH_MAX ); +if (!name) +return -1 ; + + kmod = dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || + dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE_COMP ; + +/* +* Iterate over candidate debug images. +* Keep track of "interesting" ones (those which have a symtab, dynsym, +* and/or opd section) for processing. +*/ +for (i =0 ; i <DSO_BINARY_TYPE__SYMTAB_CNT ; i++) { +enum dso_binary_type symtab_type = binary_type_symtab[i]; + +if (!dso__is_compatible_symtab_type (dso, kmod, symtab_type)) +continue ; + +if (dso__read_binary_type_filename (dso, symtab_type, + root_dir, name,PATH_MAX )) +continue ; + +if (!is_regular_file (name)) +continue ; + +return elf_is_64_bit (name); + } + +return -1 ; +} +int dso__load (struct dso *dso,struct map *map,symbol_filter_t filter) {char *name;tools/perf/util/symbol.h +2
-0@@ -308,6 +308,8 @@ int setup_list(struct strlist **list, const char *list_str, const char *list_name);int setup_intlist (struct intlist **list,const char *list_str,const char *list_name); +int elf_is_64_bit (char *name); +int dso_is_64_bit (struct dso *dso,struct map *map);#ifdef HAVE_LIBELF_SUPPORT bool elf__needs_adjust_symbols (GElf_Ehdr ehdr);tools/perf/util/thread.c +21
-0@@ -184,8 +184,39 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)void thread__insert_map (struct thread *thread,struct map *map) { +char *__maybe_unused arch; +int __maybe_unused is_64_bit; +map_groups__fixup_overlappings (thread->mg, map, stderr);map_groups__insert (thread->mg, map); + +#ifdef HAVE_LIBUNWIND_SUPPORT +if (!thread->mg->machine->env) +return ; + + is_64_bit =dso_is_64_bit (map->dso, map); +if (is_64_bit <0 ) +return ; + +if (thread->addr_space) +pr_debug ("Thread map already set, 64bit is %d, dso=%s\n" , + is_64_bit, map->dso->name); + + arch = thread->mg->machine->env->arch; + +if (!strcmp (arch,"x86_64" ) + || !strcmp (arch,"x86" ) + || !strcmp (arch,"i686" )) {
tools/perf/util/thread.c size_t thread__fprintf(struct thread *thread, FILE *fp) · line 219
Quoted 10 lines
tools/perf/util/thread.c +10
-0+pr_debug ("Thread map is X86, 64bit is %d\n" , is_64_bit); + if (!is_64_bit) +#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 + } +#endif
could you please move above code under unwind object, like we do with unwind__prepare_access in thread__new?
also we could unite both names somehome now we have 2 callbacks to unwind code from generic code
thanks,
jirka
Re: [PATCH 5/8] perf tools: Promote proper messages for cross-platform unwind
In reply to He KuangOn Fri, May 06, 2016 at 08:59:11AM +0000, He Kuang wrote:
SNIP
Quoted 44 lines
tools/perf/util/symbol.c +36
-0+if (machine) + root_dir = machine->root_dir; + + name =malloc (PATH_MAX ); +if (!name) +return -1 ; + + kmod = dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || + dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE_COMP ; + +/* +* Iterate over candidate debug images. +* Keep track of "interesting" ones (those which have a symtab, dynsym, +* and/or opd section) for processing. +*/ +for (i =0 ; i <DSO_BINARY_TYPE__SYMTAB_CNT ; i++) { +enum dso_binary_type symtab_type = binary_type_symtab[i]; + +if (!dso__is_compatible_symtab_type (dso, kmod, symtab_type)) +continue ; + +if (dso__read_binary_type_filename (dso, symtab_type, + root_dir, name,PATH_MAX )) +continue ; + +if (!is_regular_file (name)) +continue ; + +return elf_is_64_bit (name); + } + +return -1 ; +} +int dso__load (struct dso *dso,struct map *map,symbol_filter_t filter) {char *name;tools/perf/util/symbol.h +0
-0
tools/perf/util/symbol.h int setup_list(struct strlist **list, const char *list_str, · line 312
Quoted 5 lines
tools/perf/util/symbol.h +2
-0@@ -308,6 +308,8 @@ int setup_list(struct strlist **list, const char *list_str, const char *list_name);int setup_intlist (struct intlist **list,const char *list_str,const char *list_name); +int elf_is_64_bit (char *name); +int dso_is_64_bit (struct dso *dso,struct map *map);
please put above 2 functions addition into separate patch
thanks,
jirka
PATCH 6/8 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.
--- tools/perf/config/Makefile | 19 ++++++++-- tools/perf/util/Build | 3 +- tools/perf/util/thread.c | 29 +++++++++++---- tools/perf/util/thread.h | 14 +++++++- tools/perf/util/unwind-libunwind.c | 48 +++++++++++++++++++++---- tools/perf/util/unwind-libunwind_common.c | 60 +++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 22 ++++++++++++ 7 files changed, 178 insertions(+), 17 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 +23 -6
@@ -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,9 @@ 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); +#ifdef HAVE_LIBUNWIND_SUPPORT +register_null_unwind_libunwind_ops (thread); +#endif }return thread;
@@ -82,7 +82,9 @@ void thread__delete(struct thread *thread)list_del (&comm->list);comm__free (comm); } -unwind__finish_access (thread); +#ifdef HAVE_LIBUNWIND_SUPPORT + thread->unwind_libunwind_ops->finish_access (thread); +#endif free (thread); }
@@ -144,8 +146,10 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,return -ENOMEM ;list_add (&new->list, &thread->comm_list); +#ifdef HAVE_LIBUNWIND_SUPPORT if (exec) -unwind__flush_access (thread); + thread->unwind_libunwind_ops->flush_access (thread); +#endif } thread->comm_set = true;
@@ -208,14 +212,27 @@ void thread__insert_map(struct thread *thread, struct map *map) || !strcmp(arch, "x86") || !strcmp(arch, "i686")) {pr_debug ("Thread map is X86, 64bit is %d\n" , is_64_bit); - if (!is_64_bit) +if (!is_64_bit) {#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 + goto err; + } + } else { +register_local_unwind_libunwind_ops (thread); } + +if (thread->unwind_libunwind_ops->prepare_access (thread) <0 ) +return ; + +return ; + +err:__maybe_unused +register_null_unwind_libunwind_ops (thread); +return ;#endif }
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 +42 -6
87 lines not on this page · raw message
tools/perf/util/unwind-libunwind_common.c new file +60 -0
60 lines not on this page · raw message
tools/perf/util/unwind.h +22 -0
@@ -24,6 +24,28 @@ 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); +int register_unwind_libunwind_ops (struct unwind_libunwind_ops *ops, +struct thread *thread); +int register_null_unwind_libunwind_ops (struct thread *thread); + +#ifndef HAVE_LIBUNWIND_LOCAL_SUPPORT +static inline int +register_local_unwind_libunwind_ops (struct thread *thread) { +return register_null_unwind_libunwind_ops (thread); +} +#else +int 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 int unwind__prepare_access (struct thread *thread__maybe_unused ) {
Signature · 1 line
1.8.5.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 6/8] perf callchain: Add support for cross-platform unwind
Em Fri, May 06, 2016 at 08:59:12AM +0000, He Kuang escreveu:
Quoted 106 lines
Use 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.
Signed-off-by He Kuang <[email protected]>--- tools/perf/config/Makefile | 19 ++++++++-- tools/perf/util/Build | 3 +- tools/perf/util/thread.c | 29 +++++++++++---- tools/perf/util/thread.h | 14 +++++++- tools/perf/util/unwind-libunwind.c | 48 +++++++++++++++++++++---- tools/perf/util/unwind-libunwind_common.c | 60 +++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 22 ++++++++++++ 7 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 tools/perf/util/unwind-libunwind_common.ctools/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.otools/perf/util/thread.c +0
-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;
tools/perf/util/thread.c struct thread *thread__new(pid_t pid, pid_t tid) · line 59
Quoted 6 lines
tools/perf/util/thread.c +3
-0@@ -57,6 +54,9 @@ 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); +#ifdef HAVE_LIBUNWIND_SUPPORT +register_null_unwind_libunwind_ops (thread); +#endif
Could you please avoid having all those ifdefs sprinkled in the .c file? For instance, the above ifdef/endif should be dropped and instead, at a central place, a header probably, or at most at the start of the .c file, you should have one ifdef block, the else should just make the above function, for instance, be:
#ifdef HAVE_LIBUNWIND_SUPPORT
void register_null_unwind_libunwind_ops(struct thread *thread); #else
static inline
void register_null_unwind_libunwind_ops(struct thread *thread __maybe_unused) {
}
#endif
Quoted 15 lines
tools/perf/util/thread.c +3
-1}return thread;@@ -82,7 +82,9 @@ void thread__delete(struct thread *thread)list_del (&comm->list);comm__free (comm); } -unwind__finish_access (thread); +#ifdef HAVE_LIBUNWIND_SUPPORT + thread->unwind_libunwind_ops->finish_access (thread); +#endif free (thread); }
tools/perf/util/thread.c int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, · line 152
Quoted 8 lines
tools/perf/util/thread.c +3
-1@@ -144,8 +146,10 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,return -ENOMEM ;list_add (&new->list, &thread->comm_list); +#ifdef HAVE_LIBUNWIND_SUPPORT if (exec) -unwind__flush_access (thread); + thread->unwind_libunwind_ops->flush_access (thread); +#endif
You see, here the original code should be left untouched and you would change unwind__flush_access() instead to be:
#ifdef HAVE_LIBUNWIND_SUPPORT
void unwind__flush_access(struct thread *thread)
{
thread->unwind_libunwind_ops->flush_access(thread);
}#else
void unwind__flush_access(struct thread *thread __maybe_unused) {
}
#endif
combine the above if/else/endif with the previous and with all the others, please.
Quoted 263 lines
tools/perf/util/thread.c +14
-1} thread->comm_set = true;@@ -208,14 +212,27 @@ void thread__insert_map(struct thread *thread, struct map *map) || !strcmp(arch, "x86") || !strcmp(arch, "i686")) {pr_debug ("Thread map is X86, 64bit is %d\n" , is_64_bit); - if (!is_64_bit) +if (!is_64_bit) {#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 + goto err; + } + } else { +register_local_unwind_libunwind_ops (thread); } + +if (thread->unwind_libunwind_ops->prepare_access (thread) <0 ) +return ; + +return ; + +err:__maybe_unused +register_null_unwind_libunwind_ops (thread); +return ;#endif }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 +42
-6@@ -22,6 +22,9 @@#include <unistd.h> #include <sys/mman.h> #include <linux/list.h> +#ifdef ARCH_UNWIND_LIBUNWIND +#include "libunwind-arch.h" +#endif #include <libunwind.h> #include <libunwind-ptrace.h> #include "callchain.h" @@ -34,6 +37,22 @@#include "debug.h" #include "asm/bug.h" +#ifndef ARCH_UNWIND_LIBUNWIND +#define LIBUNWIND__ARCH_REG_ID libunwind__arch_reg_id +#define LOCAL_UNWIND_LIBUNWIND +#undef UNWT_OBJ +#define UNWT_OBJ (x) _##x +#else +#undef NO_LIBUNWIND_DEBUG_FRAME +#if defined(LIBUNWIND_ARM ) && !defined(NO_LIBUNWIND_DEBUG_FRAME_ARM ) +#elif defined(LIBUNWIND_AARCH64 ) && \ + defined(NO_LIBUNWIND_DEBUG_FRAME_ARM_AARCH64 ) +#else +#define NO_LIBUNWIND_DEBUG_FRAME +#endif +#endif + + extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, unw_word_t ip,@@ -579,7 +598,7 @@ static unw_accessors_t accessors = { .get_proc_name = get_proc_name, }; -int unwind__prepare_access (struct thread *thread) +static int UNWT_OBJ (_unwind__prepare_access )(struct thread *thread) {if (callchain_param.record_mode !=CALLCHAIN_DWARF )return 0 ;@@ -594,7 +613,7 @@ int unwind__prepare_access(struct thread *thread)return 0 ; } -void unwind__flush_access (struct thread *thread) +static void UNWT_OBJ (_unwind__flush_access )(struct thread *thread) {if (callchain_param.record_mode !=CALLCHAIN_DWARF )return ;@@ -602,7 +621,7 @@ void unwind__flush_access(struct thread *thread)unw_flush_cache (thread->addr_space,0 ,0 ); } -void unwind__finish_access (struct thread *thread) +static void UNWT_OBJ (_unwind__finish_access )(struct thread *thread) {if (callchain_param.record_mode !=CALLCHAIN_DWARF )return ;@@ -662,9 +681,10 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,return ret; } -int unwind__get_entries (unwind_entry_cb_t cb,void *arg, -struct thread *thread, -struct perf_sample *data,int max_stack) +static int UNWT_OBJ (_unwind__get_entries )(unwind_entry_cb_t cb,void *arg, +struct thread *thread, +struct perf_sample *data, +int max_stack) {struct unwind_info ui = { .sample = data,@@ -680,3 +700,19 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,return get_entries (&ui, cb, arg, max_stack); } + +struct unwind_libunwind_ops +UNWT_OBJ (unwind_libunwind_ops ) = { + .prepare_access =UNWT_OBJ (_unwind__prepare_access), + .flush_access =UNWT_OBJ (_unwind__flush_access), + .finish_access =UNWT_OBJ (_unwind__finish_access), + .get_entries =UNWT_OBJ (_unwind__get_entries), +}; + +#ifdef LOCAL_UNWIND_LIBUNWIND +int register_local_unwind_libunwind_ops (struct thread *thread) +{ + thread->unwind_libunwind_ops = &UNWT_OBJ (unwind_libunwind_ops); +return 0 ; +} +#endif tools/perf/util/unwind-libunwind_common.c new file +60
-0@@ -0,0 +1,60 @@ +#include <elf.h> +#include <gelf.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <linux/list.h> +#include <libunwind.h> +#include <libunwind-ptrace.h> +#include "callchain.h" +#include "thread.h" +#include "session.h" +#include "perf_regs.h" +#include "unwind.h" +#include "symbol.h" +#include "util.h" +#include "debug.h" +#include "asm/bug.h" + +static int __null__prepare_access (struct thread *thread__maybe_unused ) +{ +return 0 ; +} + +static void __null__flush_access (struct thread *thread__maybe_unused ) +{ +} + +static void __null__finish_access (struct thread *thread__maybe_unused ) +{ +} + +static int __null__get_entries (unwind_entry_cb_t cb__maybe_unused , +void *arg__maybe_unused , +struct thread *thread__maybe_unused , +struct perf_sample *data__maybe_unused , +int max_stack__maybe_unused ) +{ +return 0 ; +} + +static struct unwind_libunwind_ops null_unwind_libunwind_ops = { + .prepare_access = __null__prepare_access, + .flush_access = __null__flush_access, + .finish_access = __null__finish_access, + .get_entries = __null__get_entries, +}; + +int register_null_unwind_libunwind_ops (struct thread *thread) +{ + thread->unwind_libunwind_ops = &null_unwind_libunwind_ops; +return 0 ; +} + +int register_unwind_libunwind_ops (struct unwind_libunwind_ops *ops, +struct thread *thread) +{ + thread->unwind_libunwind_ops = ops; +return 0 ; +}tools/perf/util/unwind.h +22
-0@@ -24,6 +24,28 @@ 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); +int register_unwind_libunwind_ops (struct unwind_libunwind_ops *ops, +struct thread *thread); +int register_null_unwind_libunwind_ops (struct thread *thread); + +#ifndef HAVE_LIBUNWIND_LOCAL_SUPPORT +static inline int +register_local_unwind_libunwind_ops (struct thread *thread) { +return register_null_unwind_libunwind_ops (thread); +} +#else +int 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 int unwind__prepare_access (struct thread *thread__maybe_unused ) {Signature · 1 line
1.8.5.2
PATCH 7/8 perf callchain: Support x86 target platform
In reply to He KuangSupport x86(32bit) 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/thread.c | 10 +++--- tools/perf/util/unwind-libunwind.c | 2 +- tools/perf/util/unwind.h | 5 +++ 6 files changed, 77 insertions(+), 6 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/thread.c +5 -5
@@ -214,12 +214,12 @@ void thread__insert_map(struct thread *thread, struct map *map)pr_debug ("Thread map is X86, 64bit is %d\n" , is_64_bit);if (!is_64_bit) {#ifdef HAVE_LIBUNWIND_X86_SUPPORT -pr_err ("target platform=%s is not implemented!\n" , - arch); +register_unwind_libunwind_ops ( + &_Ux86_unwind_libunwind_ops, thread);#else -pr_err ("target platform=%s is not supported!\n" , arch); -#endif +register_null_unwind_libunwind_ops (thread); goto err; +#endif } }else {register_local_unwind_libunwind_ops (thread);
@@ -231,7 +231,7 @@ void thread__insert_map(struct thread *thread, struct map *map)return ; err:__maybe_unused -register_null_unwind_libunwind_ops (thread); +pr_err ("target platform=%s not support!\n" , arch);return ;#endif }
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.h +5 -0
@@ -55,6 +55,11 @@ 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 ) {}#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 8/8 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/thread.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/thread.c +12 -0
@@ -221,6 +221,18 @@ void thread__insert_map(struct thread *thread, struct map *map) goto err;#endif } + }else if (!strcmp (arch,"aarch64" ) || !strncmp (arch,"arm" ,3 )) { +pr_debug ("Thread map is ARM, 64bit is %d, dso=%s\n" , + is_64_bit, map->dso->name); +if (is_64_bit) { +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT +register_unwind_libunwind_ops ( + &_Uaarch64_unwind_libunwind_ops, thread); +#else +register_null_unwind_libunwind_ops (thread); + goto err; +#endif + } }else {register_local_unwind_libunwind_ops (thread); }
tools/perf/util/unwind.h +3 -0
@@ -59,6 +59,9 @@ static inline void unwind__finish_access(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
Arnaldo Carvalho de Melo
maintainerEm Fri, May 06, 2016 at 08:59:06AM +0000, He Kuang escreveu:
Quoted 4 lines
Currently, 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 do remote unwind on other platforms/machines.
Thanks for working on this, being able to record on one machine and do analysis in another, of a different hw architectures is indeed a goal for the perf tools!
Jiri, if you could please take a look, that would be really great!
- Arnaldo
Quoted 83 lines
This patch set adds build tests for the supported platforms for remote unwinding, and checks the map elf info for each thread, use remote unwind methods instead.
Only x86 and aarch64 is added in this patch set to show the work flow, other platforms can be added easily.
We can see the right result for unwind infos on different machines, for example: we record perf.data on i686 qemu with '-g' option and parse it on
x86_64machine.before this patchset:
hello 1071 [000] 417.567832: probe:sys_close: (
c1169d60)c1169d61 sys_close ([kernel.kallsyms]) c189c0d7 sysenter_past_esp ([kernel.kallsyms]) b77c8ba9 [unknown] ([vdso32])after:
hello 1071 [000] 417.567832: probe:sys_close: (
c1169d60)c1169d61 sys_close ([kernel.kallsyms]) c189c0d7 sysenter_past_esp ([kernel.kallsyms]) b77c8ba9 [unknown] ([vdso32]) b76e51cc close (/lib/libc-2.22.so) 804842e fib (/tmp/hello) 804849d main (/tmp/hello) b762546e __libc_start_main (/lib/libc-2.22.so) 8048341 _start (/tmp/hello)Thanks, discussion welcomed.
He Kuang (8):
perf tools: Omit DWARF judgement when recording dwarf callchain perf script: Add options for custom vdso name
perf build: Add build-test for libunwind cross-platforms support perf build: Add build-test for debug-frame on arm/arm64 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-platformtools/build/Makefile.feature | 11 +++- tools/build/feature/Makefile | 26 +++++++- tools/build/feature/test-libunwind-aarch64.c | 26 ++++++++ tools/build/feature/test-libunwind-arm.c | 27 +++++++++ .../feature/test-libunwind-debug-frame-aarch64.c | 16 +++++ .../build/feature/test-libunwind-debug-frame-arm.c | 16 +++++ tools/build/feature/test-libunwind-debug-frame.c | 16 ----- tools/build/feature/test-libunwind-x86.c | 27 +++++++++ tools/build/feature/test-libunwind-x86_64.c | 27 +++++++++ .../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/builtin-script.c | 2 + tools/perf/config/Makefile | 35 ++++++++++- tools/perf/util/Build | 13 +++- tools/perf/util/dso.c | 7 +++ tools/perf/util/dso.h | 1 + tools/perf/util/symbol-elf.c | 16 +++++ tools/perf/util/symbol.c | 50 ++++++++++++++++ tools/perf/util/symbol.h | 3 + tools/perf/util/thread.c | 70 ++++++++++++++++++++-- tools/perf/util/thread.h | 14 ++++- tools/perf/util/unwind-libunwind.c | 50 +++++++++++++--- tools/perf/util/unwind-libunwind_common.c | 60 +++++++++++++++++++ tools/perf/util/unwind.h | 30 ++++++++++ tools/perf/util/util.c | 2 - 27 files changed, 589 insertions(+), 39 deletions(-) create mode 100644 tools/build/feature/test-libunwind-aarch64.c create mode 100644 tools/build/feature/test-libunwind-arm.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c delete mode 100644 tools/build/feature/test-libunwind-debug-frame.c create mode 100644 tools/build/feature/test-libunwind-x86.c create mode 100644 tools/build/feature/test-libunwind-x86_64.c 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.cSignature · 1 line
1.8.5.2