Add support for remote unwind
Subsystems (2)
v2 cover Add support for remote unwind
v1 url:
http://thread.gmane.org/gmane.linux.kernel/2216256
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 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)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 (9):
perf tools: Omit DWARF judgement when recording dwarf callchain perf script: Add options for custom vdso path
perf build: Add build-test for libunwind cross-platforms support perf build: Add build-test for debug-frame on arm/arm64 perf tools: Add methods to test dso is 64-bit or 32-bit 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 | 8 +- tools/build/feature/Makefile | 23 +++++ 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-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 | 7 +- tools/perf/util/thread.h | 14 ++- tools/perf/util/unwind-libunwind.c | 49 +++++++-- tools/perf/util/unwind-libunwind_common.c | 113 +++++++++++++++++++++ tools/perf/util/unwind.h | 48 +++++++-- tools/perf/util/util.c | 2 - 26 files changed, 585 insertions(+), 28 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 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 v2 1/9 perf tools: Omit DWARF judgement when recording dwarf callchain
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
@@ -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 v2 1/9] perf tools: Omit DWARF judgement when recording dwarf callchain
Em Tue, May 10, 2016 at 07:40:29AM +0000, He Kuang escreveu:
Quoted 5 lines
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.
I had this one already applied, thanks.
- Arnaldo
Quoted 28 lines
Signed-off-by He Kuang <[email protected]>Acked-by Jiri Olsa <[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
PATCH v2 2/9 perf script: Add options for custom vdso path
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.
Currently, perf does try to read vdso binary in '.debug' folder, but the filename of the vdso file is generated randomly based on VDSO__TEMP_FILE_NAME template, such a filename is not reliable and users need a way to provide the path of their own vdso binary file.
--- 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
@@ -13,6 +13,7 @@ char dso__symtab_origin(const struct dso *dso)static const char origin[] = { [DSO_BINARY_TYPE__KALLSYMS ] ='k' , [DSO_BINARY_TYPE__VMLINUX ] ='v' , + [DSO_BINARY_TYPE__VDSO ] ='D' , [DSO_BINARY_TYPE__JAVA_JIT ] ='j' , [DSO_BINARY_TYPE__DEBUGLINK ] ='l' , [DSO_BINARY_TYPE__BUILD_ID_CACHE ] ='B' ,
@@ -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__VDSO : + { +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__VDSO ,DSO_BINARY_TYPE__NOT_FOUND , };int i =0 ;
tools/perf/util/dso.h +1 -0
@@ -30,6 +30,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , +DSO_BINARY_TYPE__VDSO , DSO_BINARY_TYPE__NOT_FOUND, };
tools/perf/util/symbol.c +1 -0
@@ -1363,6 +1363,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO :case DSO_BINARY_TYPE__BUILDID_DEBUGINFO :case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO : +case DSO_BINARY_TYPE__VDSO :return !kmod && dso->kernel ==DSO_TYPE_USER ;case DSO_BINARY_TYPE__KALLSYMS :
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 v2 2/9] perf script: Add options for custom vdso path
Em Tue, May 10, 2016 at 07:40:30AM +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.
Currently, perf does try to read vdso binary in '.debug' folder, but the filename of the vdso file is generated randomly based on
VDSO__TEMP_FILE_NAMEtemplate, such a filename is not reliable and users need a way to provide the path of their own vdso binary file.
But this becomes one more burden to the user :-\ Why not calculate a build-id from the VDSO file contents, copy it to ~/.debug/.build-id/ab/cdef01020304 and insert that into the perf.data file so that at analysis time we do all this automatically?
We can of course have a way to manually provide it, but having it as the main way for users doesn't seem a good interface. Am I missing something?
- Arnaldo
Quoted 92 lines
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 +7
-0@@ -13,6 +13,7 @@ char dso__symtab_origin(const struct dso *dso)static const char origin[] = { [DSO_BINARY_TYPE__KALLSYMS ] ='k' , [DSO_BINARY_TYPE__VMLINUX ] ='v' , + [DSO_BINARY_TYPE__VDSO ] ='D' , [DSO_BINARY_TYPE__JAVA_JIT ] ='j' , [DSO_BINARY_TYPE__DEBUGLINK ] ='l' , [DSO_BINARY_TYPE__BUILD_ID_CACHE ] ='B' ,@@ -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__VDSO : + { +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__VDSO ,DSO_BINARY_TYPE__NOT_FOUND , };int i =0 ;tools/perf/util/dso.h +1
-0@@ -30,6 +30,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , +DSO_BINARY_TYPE__VDSO , DSO_BINARY_TYPE__NOT_FOUND, };tools/perf/util/symbol.c +1
-0@@ -1363,6 +1363,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO :case DSO_BINARY_TYPE__BUILDID_DEBUGINFO :case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO : +case DSO_BINARY_TYPE__VDSO :return !kmod && dso->kernel ==DSO_TYPE_USER ;case DSO_BINARY_TYPE__KALLSYMS :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 v2 2/9] perf script: Add options for custom vdso path
Quoted 14 lines · Arnaldo Carvalho de Melo
Em Tue, May 10, 2016 at 07:40:30AM +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.
Currently, perf does try to read vdso binary in '.debug' folder, but the filename of the vdso file is generated randomly based on
VDSO__TEMP_FILE_NAMEtemplate, such a filename is not reliable and users need a way to provide the path of their own vdso binary file.But this becomes one more burden to the user :-\ Why not calculate a build-id from the VDSO file contents, copy it to ~/.debug/.build-id/ab/cdef01020304 and insert that into the perf.data file so that at analysis time we do all this automatically?
Quoted 5 lines
We can of course have a way to manually provide it, but having it as the main way for users doesn't seem a good interface. Am I missing something?
- Arnaldo
OK, I'll try as you suggested!
Quoted 93 lines
Quoted 93 lines
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 +7
-0@@ -13,6 +13,7 @@ char dso__symtab_origin(const struct dso *dso)static const char origin[] = { [DSO_BINARY_TYPE__KALLSYMS ] ='k' , [DSO_BINARY_TYPE__VMLINUX ] ='v' , + [DSO_BINARY_TYPE__VDSO ] ='D' , [DSO_BINARY_TYPE__JAVA_JIT ] ='j' , [DSO_BINARY_TYPE__DEBUGLINK ] ='l' , [DSO_BINARY_TYPE__BUILD_ID_CACHE ] ='B' ,@@ -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__VDSO : + { +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__VDSO ,DSO_BINARY_TYPE__NOT_FOUND , };int i =0 ;tools/perf/util/dso.h +1
-0@@ -30,6 +30,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , +DSO_BINARY_TYPE__VDSO , DSO_BINARY_TYPE__NOT_FOUND, };tools/perf/util/symbol.c +1
-0@@ -1363,6 +1363,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO :case DSO_BINARY_TYPE__BUILDID_DEBUGINFO :case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO : +case DSO_BINARY_TYPE__VDSO :return !kmod && dso->kernel ==DSO_TYPE_USER ;case DSO_BINARY_TYPE__KALLSYMS :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
PATCH v2 3/9 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 | 4 ++++ 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, 127 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 +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/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 v2 3/9] perf build: Add build-test for libunwind cross-platforms support
Quoted 5 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]>
thanks,
jirka
Re: [PATCH v2 3/9] perf build: Add build-test for libunwind cross-platforms support
Em Wed, May 11, 2016 at 01:52:30PM +0200, Jiri Olsa escreveu:
Quoted 8 lines · He Kuang
Quoted 5 lines
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]>Acked-by Jiri Olsa <[email protected]>
Thanks, applied
tip-bot for He Kuang
merge bot[tip:perf/core] perf build: Add build-test for libunwind cross-platforms support
In reply to He Kuangperf build: Add build-test for libunwind cross-platforms support
Commit-ID: b1d960000ca12508c25776f1fd375ee81578ae1f Gitweb: http://git.kernel.org/tip/b1d960000ca12508c25776f1fd375ee81578ae1f Author: He Kuang <[email protected]> AuthorDate: Tue, 10 May 2016 07:40:31 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 11 May 2016 12:24:58 -0300
perf build: Add build-test for libunwind cross-platforms support
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.
--- tools/build/Makefile.feature | 4 ++++ 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, 127 insertions(+)
tools/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/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 ; +}
PATCH v2 4/9 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 | 4 +++- tools/build/feature/Makefile | 7 +++++++ tools/build/feature/test-libunwind-debug-frame-aarch64.c | 16 ++++++++++++++++ tools/build/feature/test-libunwind-debug-frame-arm.c | 16 ++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c create mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c
tools/build/Makefile.feature +3 -1
@@ -73,7 +73,9 @@ FEATURE_TESTS_EXTRA := \ libbabeltrace \ liberty \ liberty-z \ - libunwind-debug-frame + libunwind-debug-frame \ + libunwind-debug-frame-arm \ + libunwind-debug-frame-aarch64 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
tools/build/feature/Makefile +7 -0
@@ -31,6 +31,8 @@ FILES= \ 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 \
@@ -119,6 +121,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 ; +}
Signature · 1 line
1.8.5.2
Re: [PATCH v2 4/9] perf build: Add build-test for debug-frame on arm/arm64
Quoted 4 lines · He Kuang
Debug-frame for remote platforms is not related to the host platform, so we should test each platform separately.
Signed-off-by He Kuang <[email protected]>
thanks,
jirka
Re: [PATCH v2 4/9] perf build: Add build-test for debug-frame on arm/arm64
Em Wed, May 11, 2016 at 01:58:41PM +0200, Jiri Olsa escreveu:
Quoted 7 lines · He Kuang
Quoted 4 lines
Debug-frame for remote platforms is not related to the host platform, so we should test each platform separately.
Signed-off-by He Kuang <[email protected]>Acked-by Jiri Olsa <[email protected]>
Thanks, applied
tip-bot for He Kuang
merge bot[tip:perf/core] perf build: Add build-test for debug-frame on arm/arm64
In reply to He Kuangperf build: Add build-test for debug-frame on arm/arm64
Commit-ID: f9be7eefcce9de7323c922bea6b45183eb9ef5f0 Gitweb: http://git.kernel.org/tip/f9be7eefcce9de7323c922bea6b45183eb9ef5f0 Author: He Kuang <[email protected]> AuthorDate: Tue, 10 May 2016 07:40:32 +0000 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 11 May 2016 12:24:58 -0300
perf build: Add build-test for debug-frame on arm/arm64
Debug-frame for remote platforms is not related to the host platform, so we should test each platform separately.
--- tools/build/Makefile.feature | 4 +++- tools/build/feature/Makefile | 7 +++++++ ...ibunwind-debug-frame.c => test-libunwind-debug-frame-aarch64.c} | 2 +- ...st-libunwind-debug-frame.c => test-libunwind-debug-frame-arm.c} | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-)
tools/build/Makefile.feature +3 -1
@@ -73,7 +73,9 @@ FEATURE_TESTS_EXTRA := \ libbabeltrace \ liberty \ liberty-z \ - libunwind-debug-frame + libunwind-debug-frame \ + libunwind-debug-frame-arm \ + libunwind-debug-frame-aarch64 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
tools/build/feature/Makefile +7 -0
@@ -31,6 +31,8 @@ FILES= \ 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 \
@@ -119,6 +121,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 renamed from tools/build/feature/test-libunwind-debug-frame.c +1 -1
@@ -1,4 +1,4 @@ -#include <libunwind.h> +#include <libunwind-aarch64.h> #include <stdlib.h> extern int
tools/build/feature/test-libunwind-debug-frame-arm.c renamed from tools/build/feature/test-libunwind-debug-frame.c +1 -1
@@ -1,4 +1,4 @@ -#include <libunwind.h> +#include <libunwind-arm.h> #include <stdlib.h> extern int
PATCH v2 5/9 perf tools: Add methods to test dso is 64-bit or 32-bit
In reply to He Kuang32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to 'thread->map' instead of the host architecture.
This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
--- tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 3 files changed, 67 insertions(+)
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);
Signature · 1 line
1.8.5.2
Adrian Hunter
reviewerRe: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
Quoted 6 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using dso->is_64_bit set by dso__load_sym() ?
Quoted 109 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 3 files changed, 67 insertions(+)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@@ -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);
Re: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
hi
Quoted 8 lines · Adrian Hunter
Quoted 6 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using
dso->is_64_bitset bydso__load_sym()?
I've noticed this variable, but it's value is not as its name said:
util/dso.c: 1067 dso->is_64_bit = (sizeof(void *) == 8);
This is only related to the host architecture.
A closer one is 'is_64_bit' in 'struct symsrc', but the value is assigned after dso loaded. So I think we should provide individual methods to get that value.
Thanks.
Quoted 110 lines
Quoted 109 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 3 files changed, 67 insertions(+)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@@ -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);
Adrian Hunter
reviewerRe: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
Quoted 8 lines · Hekuang
hi
Quoted 5 lines · Adrian Hunter
Quoted 4 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.
Quoted 7 lines
Quoted 3 lines
Quoted 2 lines
This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using
dso->is_64_bitset bydso__load_sym()?I've noticed this variable, but it's value is not as its name said:
util/dso.c: 1067dso->is_64_bit= (sizeof(void *)== 8);
That is just initialization i.e. before we know what it is we assume it is the same as the host.
Quoted 6 lines
This is only related to the host architecture.
A closer one is '
is_64_bit' in 'struct symsrc', but the value is assigned after dso
loaded. So I think we should provide individual methods to get that value.
Are you saying you don't load dsos? Or that is_64_bit is set incorrectly?
Quoted 116 lines
Thanks.
Quoted 110 lines
Quoted 109 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 3 files changed, 67 insertions(+)tools/perf/util/symbol-elf.c +15
-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 +48
-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);
Re: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
Quoted 18 lines · Adrian Hunter
Quoted 8 lines · Hekuang
hi
Quoted 5 lines · Adrian Hunter
Quoted 4 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.Quoted 6 lines
Quoted 3 lines
Quoted 2 lines
This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using
dso->is_64_bitset bydso__load_sym()?I've noticed this variable, but it's value is not as its name said:
util/dso.c: 1067dso->is_64_bit= (sizeof(void *)== 8);That is just initialization i.e. before we know what it is we assume it is the same as the host.
Quoted 7 lines
Quoted 5 lines
This is only related to the host architecture.
A closer one is '
is_64_bit' in 'struct symsrc', but the value is assigned after dso
loaded. So I think we should provide individual methods to get that value.Are you saying you don't load dsos? Or that
is_64_bitis set incorrectly?
Yes, I know it's the inital value, but the correct value is assigned in function dso__load_sym(), and have a look at the call stack(gdb):
#0 dso__load_sym #1 in dso__load #2 in map__load #3 in map__find_symbol #4 in thread__find_addr_location #5 in entry #6 in get_entries #7 in _Ux86__unwind__get_entries #8 in thread__resolve_callchain
I think we should choose the right unwind method before dso__load_sym(). i.e. line#7, which is called before dso__load_sym().
I'm not very familiar with this, what's your opinion?
Thanks.
Quoted 113 lines
Quoted 112 lines
Thanks.
Quoted 108 lines
Quoted 108 lines
Signed-off-by He Kuang <[email protected]>--- tools/perf/util/symbol-elf.c | 16 +++++++++++++++ tools/perf/util/symbol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 2 ++ 3 files changed, 67 insertions(+)tools/perf/util/symbol-elf.c +15
-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 +48
-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);
Adrian Hunter
reviewerRe: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
Quoted 43 lines · Hekuang
Quoted 18 lines · Adrian Hunter
Quoted 8 lines · Hekuang
hi
Quoted 5 lines · Adrian Hunter
Quoted 4 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.Quoted 6 lines
Quoted 3 lines
Quoted 2 lines
This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using
dso->is_64_bitset bydso__load_sym()?I've noticed this variable, but it's value is not as its name said:
util/dso.c: 1067dso->is_64_bit= (sizeof(void *)== 8);That is just initialization i.e. before we know what it is we assume it is the same as the host.
Quoted 7 lines
Quoted 5 lines
This is only related to the host architecture.
A closer one is '
is_64_bit' in 'struct symsrc', but the value is assigned after dso
loaded. So I think we should provide individual methods to get that value.Are you saying you don't load dsos? Or that
is_64_bitis set incorrectly?Yes, I know it's the inital value, but the correct value is assigned in function
dso__load_sym(), and have a look at the call stack(gdb):#0 dso__load_sym #1 in dso__load #2 in map__load #3 in map__find_symbol #4 in thread__find_addr_location #5 in entry #6 in get_entries #7 in _Ux86__unwind__get_entries #8 in thread__resolve_callchain
Quoted 4 lines
I think we should choose the right unwind method before
dso__load_sym(). i.e. line#7, which is called beforedso__load_sym().I'm not very familiar with this, what's your opinion?
Have you considered calling map__load() instead of dso_is_64_bit()
Re: [PATCH v2 5/9] perf tools: Add methods to test dso is 64-bit or 32-bit
Quoted 42 lines · Adrian Hunter
Quoted 41 lines · Hekuang
Quoted 18 lines · Adrian Hunter
Quoted 8 lines · Hekuang
hi
Quoted 5 lines · Adrian Hunter
Quoted 4 lines · He Kuang
32-bit programs can be run on 64-bit machines, so we should choose unwind methods according to '
thread->map' instead of the host architecture.Quoted 6 lines
Quoted 3 lines
Quoted 2 lines
This patch adds methods to test whether a dso is 64-bit or 32-bit by the class info in elf.
What about using
dso->is_64_bitset bydso__load_sym()?I've noticed this variable, but it's value is not as its name said:
util/dso.c: 1067dso->is_64_bit= (sizeof(void *)== 8);That is just initialization i.e. before we know what it is we assume it is the same as the host.
Quoted 7 lines
Quoted 5 lines
This is only related to the host architecture.
A closer one is '
is_64_bit' in 'struct symsrc', but the value is assigned after dso
loaded. So I think we should provide individual methods to get that value.Are you saying you don't load dsos? Or that
is_64_bitis set incorrectly?Yes, I know it's the inital value, but the correct value is assigned in function
dso__load_sym(), and have a look at the call stack(gdb):#0 dso__load_sym #1 in dso__load #2 in map__load #3 in map__find_symbol #4 in thread__find_addr_location #5 in entry #6 in get_entries #7 in _Ux86__unwind__get_entries #8 in thread__resolve_callchain
Quoted 5 lines
Quoted 4 lines
I think we should choose the right unwind method before
dso__load_sym(). i.e. line#7, which is called beforedso__load_sym().I'm not very familiar with this, what's your opinion?
Have you considered calling
map__load()instead ofdso_is_64_bit()
IMO, map__load() is heavy than dso_is_64_bit() test, because the dso tested by unwind_get_arch(thread, map) may or may not be referenced in the unwind process. For example, a thread can have a large map but that map never appeared in the callcains in perf.data.
Or in other words, should we load all symbols for that elf flag or add a new method targeted for that purpose only.
Thanks.
Quoted 3 lines
PATCH v2 6/9 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 | 32 ++++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 5 +++++ 4 files changed, 45 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 +32 -0
@@ -680,3 +680,35 @@ 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; +int is_64_bit; + +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 + } +}
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 v2 7/9 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 | 73 +++++++++++----------- tools/perf/util/unwind-libunwind_common.c | 100 ++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 35 ++++++++--- 7 files changed, 196 insertions(+), 53 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 -35
114 lines not on this page · raw message
tools/perf/util/unwind-libunwind_common.c new file +100 -0
100 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 v2 8/9 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
@@ -82,10 +82,11 @@ void unwind__get_arch(struct thread *thread, struct map *map)pr_debug ("unwind: thread map is X86, 64bit is %d\n" , is_64_bit);if (!is_64_bit) {#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 v2 9/9 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
@@ -89,6 +89,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" , + 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); +#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