perf tools: Fix build-id matching on vmlinux
Subsystems (2)
Namhyung Kim
maintainerPATCH v4 1/1 perf tools: Fix build-id matching on vmlinux
There's a problem on finding correct kernel symbols when perf report runs on a different kernel. Although a part of the problem was solved by the prior commit 0a7e6d1b6844 ("perf tools: Check recorded kernel version when finding vmlinux"), there's a remaining problem still.
When perf records samples, it synthesizes the kernel map using machine__mmap_name() and ref_reloc_sym like "[kernel.kallsyms]_text". You can easily see it using 'perf report -D' command.
After finishing record, it goes through the recorded events to find maps/dsos actually used. And then record build-id info of them.
During this process, it needs to load symbols in a dso and it'd call dso__load_vmlinux() since the default value of the symbol_conf.try_ vmlinux_path is true. However it changes dso->long_name to a real path of the vmlinux file (e.g. /lib/modules/3.16.0-rc2+/build/vmlinux) if one is running on a custom kernel.
It resulted in that perf report reads the build-id of the vmlinux, but cannot use it since it only knows about the [kernel.kallsyms] map. It then falls back to possible vmlinux paths by using the recorded kernel version (in case of a recent version) or a running kernel silently.
Even with the recent tools, this still has a possibility of breaking the result. As the build directory is a symbolic link, if one built a new kernel in the same directory with different source/config, the old link to vmlinux will point the new file. So it's absolutely needed to use build-id when finding a kernel image.
In this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper vmlinux [k] cpu_startup_entry
72.15% 0.00% swapper vmlinux [k] arch_cpu_idle
72.15% 0.00% swapper vmlinux [k] default_idle
71.87% 71.87% swapper vmlinux [k] native_safe_halt...
--- tools/perf/util/machine.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
tools/perf/util/machine.c +21 -2
@@ -12,6 +12,7 @@#include <stdbool.h> #include <symbol/kallsyms.h> #include "unwind.h" +#include "asm/bug.h" int machine__init (struct machine *machine,const char *root_dir,pid_t pid) {
@@ -1062,8 +1063,26 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos, node) { +const char *suffix; +size_t len =strlen (dso->long_name); + +if (WARN_ONCE (len <=3 ,"Too short dso name" )) +continue ; + + suffix = dso->long_name + len -3 ; +if (strcmp (suffix,".ko" )) { + kernel = dso; +break ; + } + } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);if (kernel ==NULL ) goto out_problem;
Signature · 1 line
2.1.0
Quoted 87 lines · Namhyung Kim
There's a problem on finding correct kernel symbols when perf report runs on a different kernel. Although a part of the problem was solved by the prior commit
0a7e6d1b6844("perf tools: Check recorded kernel version when finding vmlinux"), there's a remaining problem still.When perf records samples, it synthesizes the kernel map using
machine__mmap_name()andref_reloc_symlike "[kernel.kallsyms]_text". You can easily see it using 'perf report -D' command.After finishing record, it goes through the recorded events to find maps/dsos actually used. And then record build-id info of them.
During this process, it needs to load symbols in a dso and it'd call
dso__load_vmlinux()since the default value of the symbol_conf.try_vmlinux_pathis true. However it changesdso->long_nameto a real path of the vmlinux file (e.g./lib/modules/3.16.0-rc2+/build/vmlinux) if one is running on a custom kernel.It resulted in that perf report reads the build-id of the vmlinux, but cannot use it since it only knows about the [kernel.kallsyms] map. It then falls back to possible vmlinux paths by using the recorded kernel version (in case of a recent version) or a running kernel silently.
Even with the recent tools, this still has a possibility of breaking the result. As the build directory is a symbolic link, if one built a new kernel in the same directory with different source/config, the old link to vmlinux will point the new file. So it's absolutely needed to use build-id when finding a kernel image.
In this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
Before:
$ perf report # Children Self Command Shared Object Symbol # ........ ........ ....... ................. ............................... # 72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt 72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc 72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work 71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize ...After (for the same perf.data):
72.15% 0.00% swapper vmlinux [k] cpu_startup_entry 72.15% 0.00% swapper vmlinux [k] arch_cpu_idle 72.15% 0.00% swapper vmlinux [k] default_idle 71.87% 71.87% swapper vmlinux [k] native_safe_halt...
Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/util/machine.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)tools/perf/util/machine.c +11
-2@@ -12,6 +12,7 @@#include <stdbool.h> #include <symbol/kallsyms.h> #include "unwind.h" +#include "asm/bug.h" int machine__init (struct machine *machine,const char *root_dir,pid_t pid) {@@ -1062,8 +1063,26 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos, node) { +const char *suffix; +size_t len =strlen (dso->long_name); + +if (WARN_ONCE (len <=3 ,"Too short dso name" )) +continue ; +
tools/perf/util/machine.c static int machine__process_kernel_mmap_event(struct machine *machine, · line 1085
Quoted 10 lines
tools/perf/util/machine.c +10
-0+ suffix = dso->long_name + len -3 ; +if (strcmp (suffix,".ko" )) { + kernel = dso; +break ; + } + } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);
Please don't break the line just to pacify checkpatch.pl. Other than that:
Thanks,
Ing
Namhyung Kim
maintainerHi Ingo and Arnaldo,
Quoted 14 lines · Ingo Molnar
Quoted 13 lines · Namhyung Kim
tools/perf/util/machine.c +7
-2@@ -1062,8 +1063,26 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos, node) { +const char *suffix; +size_t len =strlen (dso->long_name); +
Quoted 8 lines
tools/perf/util/machine.c static int machine__process_kernel_mmap_event(struct machine *machine, · line 1080
Quoted 8 lines
tools/perf/util/machine.c +8
-0+if (WARN_ONCE (len <=3 ,"Too short dso name" )) +continue ; + + suffix = dso->long_name + len -3 ; +if (strcmp (suffix,".ko" )) { + kernel = dso; +break ; + }
I just noticed that the modules can be gzip'ed on some system (e.g. Arch) so that it no longer has the ".ko" suffix.
$ ls /lib/modules/`uname -r`/kernel/fs/btrfs/ btrfs.ko.gz
Actually in this case, the dso->long_name cannot be set since when perf record synthesizes module map events, it checks the ".ko" suffix also. :/
And I also guess that if one loads a custom module not in a canonical path, it again cannot find the long name (absolute path) of the module and it results in no ".ko" suffix in the long name - so the check will be broken too.
Quoted 8 lines
tools/perf/util/machine.c static int machine__process_kernel_mmap_event(struct machine *machine, · line 1085
Quoted 5 lines
tools/perf/util/machine.c +5
-0+ } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);Please don't break the line just to pacify checkpatch.pl. Other than that:
For non string literals too? Anyway in this case, it's already broken. :)
Quoted 2 lines
Acked-by Ingo Molnar <[email protected]>
Thanks anyway! :)
Namhyung
Namhyung Kim
maintainercover perf tools: Fix build-id matching on vmlinux (v5)
Hello,
This patchset addresses possible problem on kernel symbol matching. Since commit 5b7ba82a7591 ("perf symbols: Load kernel maps before using"), when perf record process samples to construct build-id table, it loads kernel map and it replaces dso->long_name. But perf report doesn't know about name other than [kernel.kallsyms] it failed to find existing kernel dso and falls back to running kernel's kallsyms.
So it's possible to report incorrect symbols for kernel functions if it runs on a different kernel:
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper [kernel.vmlinux] [k] cpu_startup_entry
72.15% 0.00% swapper [kernel.vmlinux] [k] arch_cpu_idle
72.15% 0.00% swapper [kernel.vmlinux] [k] default_idle
71.87% 71.87% swapper [kernel.vmlinux] [k] native_safe_haltIn this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
The patch 1-2 are to support module compression as some distro (e.g. Arch) already does it. The patch 3-5 are cleanup of build-id handling functions. The patch 6-7 are the main change of this series and finally patch 8 is just for suggestion which can be squashed into the previous patch or simply dropped.
You can get it on 'perf/vmlinux-v5' branch in my tree:
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Any comments are welcome, thanks
Namhyung
Namhyung Kim (8):
perf tools: Preparation for compressed kernel module support perf tools: Add gzip decompression support for kernel module perf tools: Get rid of unused dsos__hit_all()
perf tools: Rename dsos__write_buildid_table()
perf build-id: Move build-id related functions to util/build-id.c perf record: Do not save pathname in ./debug/.build-id directory for
vmlinux
perf tools: Fix build-id matching on vmlinux
perf tools: Make vmlinux short name more like kallsyms short name
tools/perf/Makefile.perf | 7 + tools/perf/builtin-record.c | 11 + tools/perf/config/Makefile | 15 +- tools/perf/config/feature-checks/Makefile | 6 +- tools/perf/config/feature-checks/test-zlib.c | 9 + tools/perf/util/build-id.c | 293 +++++++++++++++++++++++ tools/perf/util/build-id.h | 5 + tools/perf/util/dso.c | 71 ++++++ tools/perf/util/dso.h | 7 + tools/perf/util/header.c | 343 +-------------------------- tools/perf/util/header.h | 4 +- tools/perf/util/machine.c | 38 ++- tools/perf/util/symbol-elf.c | 35 ++- tools/perf/util/symbol.c | 19 +- tools/perf/util/symbol.h | 1 + tools/perf/util/util.h | 5 + tools/perf/util/zlib.c | 78 ++++++ 17 files changed, 593 insertions(+), 354 deletions(-) create mode 100644 tools/perf/config/feature-checks/test-zlib.c create mode 100644 tools/perf/util/zlib.c
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 1/8 perf tools: Preparation for compressed kernel module support
This patch adds basic support to handle compressed kernel module as some distro (such as Archlinux) carries on it now. The actual work using compression library will be added later.
--- tools/perf/util/dso.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 7 +++++ tools/perf/util/machine.c | 19 +++++++++++- tools/perf/util/symbol-elf.c | 35 ++++++++++++++++++++- tools/perf/util/symbol.c | 8 ++++- 5 files changed, 140 insertions(+), 3 deletions(-)
tools/perf/util/dso.c +74 -0
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', + [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', };
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :path__join3 (filename, size, symbol_conf.symfs, root_dir, dso->long_name);break ;case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :__symbol__join_symfs (filename, size, dso->long_name);break ;
@@ -137,6 +141,76 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } +static int decompress_dummy (const char *input__maybe_unused , +int output__maybe_unused ) +{ +return -1 ; +} + +static const struct { +const char *fmt; +int (*decompress)(const char *input,int output); +} compressions[] = { + {"gz" , decompress_dummy }, +}; + +bool is_supported_compression (const char *ext) +{ +unsigned i; + +for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +if (!strcmp (ext, compressions[i].fmt)) +return true; + } +return false; +} + +bool is_kmodule_extension (const char *ext) +{ +if (!strcmp (ext,"ko" )) +return true; + +if (ext[2 ] =='\0' || (ext[2 ] =='.' &&is_supported_compression (ext+3 ))) +return true; + +return false; +} + +bool is_kernel_module (const char *pathname,bool *compressed) +{ +const char *ext =strrchr (pathname,'.' ); + +if (ext ==NULL ) +return false; + +if (is_supported_compression (ext +1 )) { +if (compressed) + *compressed = true; + ext -=3 ; + }else if (compressed) + *compressed = false; + +return is_kmodule_extension (ext +1 ); +} + +bool decompress_to_file (const char *ext,const char *filename,int output_fd) +{ +unsigned i; + +for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +if (!strcmp (ext, compressions[i].fmt)) +return !compressions[i].decompress (filename, + output_fd); + } +return false; +} + +bool dso__needs_decompress (struct dso *dso) +{ +return dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE_COMP ; +} +/* * Global list of open DSOs and the counter. */
tools/perf/util/dso.h +7 -0
@@ -22,7 +22,9 @@ enum dso_binary_type {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE , DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -185,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);char dso__symtab_origin (const struct dso *dso);int dso__read_binary_type_filename (const struct dso *dso,enum dso_binary_type type,char *root_dir,char *filename,size_t size); +bool is_supported_compression (const char *ext); +bool is_kmodule_extension (const char *ext); +bool is_kernel_module (const char *pathname,bool *compressed); +bool decompress_to_file (const char *ext,const char *filename,int output_fd); +bool dso__needs_decompress (struct dso *dso);/* * The dso__data_* external interface provides following functions:
tools/perf/util/machine.c +18 -1
@@ -464,6 +464,7 @@ struct map *machine__new_module(struct machine *machine, u64 start, {struct map *map;struct dso *dso =__dsos__findnew (&machine->kernel_dsos, filename); +bool compressed;if (dso ==NULL )return NULL ;
@@ -476,6 +477,11 @@ struct map *machine__new_module(struct machine *machine, u64 start, dso->symtab_type =DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ; else dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; + +/* _KMODULE_COMP should be next to _KMODULE */ +if (is_kernel_module (filename, &compressed) && compressed) + dso->symtab_type++; +map_groups__insert (&machine->kmaps, map);return map; }
@@ -861,8 +867,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,struct map *map;char *long_name; -if (dot ==NULL ||strcmp (dot,".ko" )) +if (dot ==NULL )continue ; + +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 ) && +is_kmodule_extension (dot -2 )) + dot -=3 ; +snprintf (dso_name,sizeof (dso_name),"[%.*s]" , (int )(dot - dent->d_name), dent->d_name);
@@ -1044,6 +1056,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, dot =strrchr (name,'.' );if (dot ==NULL ) goto out_problem; +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 )) + dot -=3 ; +if (!is_kmodule_extension (dot +1 )) + goto out_problem;snprintf (short_module_name,sizeof (short_module_name),"[%.*s]" , (int )(dot - name), name);strxfrchar (short_module_name,'-' ,'_' );
tools/perf/util/symbol-elf.c +34 -1
@@ -546,6 +546,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)return 0 ; } +static int decompress_kmodule (struct dso *dso,const char *name, +enum dso_binary_type type) +{ +int fd; +const char *ext =strrchr (name,'.' ); +char tmpbuf[] ="/tmp/perf-kmod-XXXXXX" ; + +if ((type !=DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && + type !=DSO_BINARY_TYPE__GUEST_KMODULE_COMP ) || + type != dso->symtab_type) +return -1 ; + +if (!ext || !is_supported_compression (ext +1 )) +return -1 ; + + fd =mkstemp (tmpbuf); +if (fd <0 ) +return -1 ; + +if (!decompress_to_file (ext +1 , name, fd)) { +close (fd); + fd =-1 ; + } + +unlink (tmpbuf); + +return fd; +} +bool symsrc__possibly_runtime (struct symsrc *ss) {return ss->dynsym || ss->opdsec;
@@ -571,7 +600,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,Elf *elf;int fd; - fd =open (name,O_RDONLY ); +if (dso__needs_decompress (dso)) + fd =decompress_kmodule (dso, name, type); +else + fd =open (name,O_RDONLY ); +if (fd <0 )return -1 ;
tools/perf/util/symbol.c +7 -1
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , DSO_BINARY_TYPE__NOT_FOUND, };
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,return dso->kernel ==DSO_TYPE_GUEST_KERNEL ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :/* * kernel modules know their symtab type - it's set when * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)return -1 ; kmod = dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || - dso->symtab_type ==DSO_BINARY_TYPE__GUEST_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.
Signature · 1 line
2.1.2
Re: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
On Mon, Nov 03, 2014 at 04:27:51PM +0900, Namhyung Kim wrote:
SNIP
Quoted 21 lines
tools/perf/util/dso.c +21
-0+static int decompress_dummy (const char *input__maybe_unused , +int output__maybe_unused ) +{ +return -1 ; +} + +static const struct { +const char *fmt; +int (*decompress)(const char *input,int output); +} compressions[] = { + {"gz" , decompress_dummy }, +}; + +bool is_supported_compression (const char *ext) +{ +unsigned i; + +for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +if (!strcmp (ext, compressions[i].fmt)) +return true; + }
tools/perf/util/dso.c int dso__read_binary_type_filename(const struct dso *dso, · line 174
Quoted 10 lines
tools/perf/util/dso.c +10
-0+return false; +} + +bool is_kmodule_extension (const char *ext) +{ +if (!strcmp (ext,"ko" )) +return true; + +if (ext[2 ] =='\0' || (ext[2 ] =='.' &&is_supported_compression (ext+3 ))) +return true;
I got stuck in here.. so any 2 chars string is kernel module extension? plus how do u know ext[3] (or [2]) is valid memory?
thanks,
jirka
Namhyung Kim
maintainerRe: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
Hi Jiri,
Quoted 29 lines · Jiri Olsa
On Mon, Nov 03, 2014 at 04:27:51PM +0900, Namhyung Kim wrote:
SNIP
Quoted 25 lines
tools/perf/util/dso.c +25
-0+static int decompress_dummy (const char *input__maybe_unused , +int output__maybe_unused ) +{ +return -1 ; +} + +static const struct { +const char *fmt; +int (*decompress)(const char *input,int output); +} compressions[] = { + {"gz" , decompress_dummy }, +}; + +bool is_supported_compression (const char *ext) +{ +unsigned i; + +for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +if (!strcmp (ext, compressions[i].fmt)) +return true; + } +return false; +} + +bool is_kmodule_extension (const char *ext)
Quoted 8 lines
tools/perf/util/dso.c int dso__read_binary_type_filename(const struct dso *dso, · line 174
Quoted 6 lines
tools/perf/util/dso.c +6
-0+{ +if (!strcmp (ext,"ko" )) +return true; + +if (ext[2 ] =='\0' || (ext[2 ] =='.' &&is_supported_compression (ext+3 ))) +return true;I got stuck in here.. so any 2 chars string is kernel module extension?
Oops, the first check should be:
if (strncmp(ext, "ko", 2))
return false;Quoted 1 line
plus how do u know ext[3] (or [2]) is valid memory?
Hmm.. if it ends at ext[0] or ext[1], it should be checked in the first check above. And I check ext[2] first, and then access ext[3] and so on.
Thanks,
Namhyung
Namhyung Kim
maintainerPATCH 2/8 perf tools: Add gzip decompression support for kernel module
In reply to Namhyung KimNow my Archlinux box shows module symbols correctly.
Before:
$ perf report --stdio
Failed to open /tmp/perf-3477.map, continuing without symbols
no symbols found in /usr/bin/date, maybe install a debug package?
No kallsyms or vmlinux with build-id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 was found
[drm] with build id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 not found, continuing without symbols
No kallsyms or vmlinux with build-id edd931629094b660ca9dec09a1b635c8d87aa2ee was found
[jbd2] with build id edd931629094b660ca9dec09a1b635c8d87aa2ee not found, continuing without symbols
No kallsyms or vmlinux with build-id a7b1eada671c34933e5610bb920b2ca4945a82c3 was found
[ext4] with build id a7b1eada671c34933e5610bb920b2ca4945a82c3 not found, continuing without symbols
No kallsyms or vmlinux with build-id d69511fa3e5840e770336ef45b06c83fef8d74e3 was found
[scsi_mod] with build id d69511fa3e5840e770336ef45b06c83fef8d74e3 not found, continuing without symbols
No kallsyms or vmlinux with build-id af0430af13461af058770ee9b87afc07922c2e77 was found
[libata] with build id af0430af13461af058770ee9b87afc07922c2e77 not found, continuing without symbols
No kallsyms or vmlinux with build-id aaeedff8160ce631a5f0333591c6ff291201d29f was found
[libahci] with build id aaeedff8160ce631a5f0333591c6ff291201d29f not found, continuing without symbols
No kallsyms or vmlinux with build-id c57907712becaf662dc4981824bb372c0441d605 was found
[mac80211] with build id c57907712becaf662dc4981824bb372c0441d605 not found, continuing without symbols
No kallsyms or vmlinux with build-id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f was found
[iwldvm] with build id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f not found, continuing without symbols
No kallsyms or vmlinux with build-id 2d86086bf136bf374a2f029cf85a48194f9b950b was found
[cfg80211] with build id 2d86086bf136bf374a2f029cf85a48194f9b950b not found, continuing without symbols
No kallsyms or vmlinux with build-id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 was found
[iwlwifi] with build id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 not found, continuing without symbols
...
#
# Overhead Command Shared Object Symbol
# ........ ............... ....................... ........................................................
#
0.03% swapper [ext4] [k] 0x000000000000fe2e
0.03% swapper [kernel.kallsyms] [k] account_entity_enqueue
0.03% swapper [ext4] [k] 0x000000000000fc2b
0.03% irq/50-iwlwifi [iwlwifi] [k] 0x000000000000200b
0.03% swapper [kernel.kallsyms] [k] ktime_add_safe
0.03% swapper [kernel.kallsyms] [k] elv_completed_request
0.03% swapper [libata] [k] 0x0000000000003997
0.03% swapper [libahci] [k] 0x0000000000001f25
0.03% swapper [kernel.kallsyms] [k] rb_next
0.03% swapper [kernel.kallsyms] [k] blk_finish_request
0.03% swapper [ext4] [k] 0x0000000000010248
0.00% perf [kernel.kallsyms] [k] native_write_msr_safeAfter:
$ perf report --stdio Failed to open /tmp/perf-3477.map, continuing without symbols no symbols found in /usr/bin/tr, maybe install a debug package? ... # # Overhead Command Shared Object Symbol # ........ ............... ........................... ...................................................... #
0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap
0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid
0.02% firefox [e1000e] [k] __ew32_prepare
0.02% swapper [libahci] [k] ahci_handle_port_interrupt
0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock
0.02% swapper [e1000e] [k] e1000_clean_tx_irq
0.02% dwm [kernel.kallsyms] [k] __schedule
0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime
0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx
0.01% firefox [vdso] [.] __vdso_gettimeofday
0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 6 ++- tools/perf/config/feature-checks/test-zlib.c | 9 ++++ tools/perf/util/dso.c | 15 +++--- tools/perf/util/util.h | 5 ++ tools/perf/util/zlib.c | 78 ++++++++++++++++++++++++++++ 7 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 tools/perf/config/feature-checks/test-zlib.c create mode 100644 tools/perf/util/zlib.c
tools/perf/Makefile.perf +7 -0
@@ -66,6 +66,9 @@ include config/utilities.mak # # Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32 # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode +# +# Define NO_ZLIB if you do not want to support compressed kernel modules + ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -582,6 +585,10 @@ ifndef NO_LIBNUMA BUILTIN_OBJS += $(OUTPUT)bench/numa.o endif +ifndef NO_ZLIB + LIB_OBJS += $(OUTPUT)util/zlib.o +endif + ifdef ASCIIDOC8 export ASCIIDOC8 endif
tools/perf/config/Makefile +13 -2
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \ libunwind \ stackprotector-all \ timerfd \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib LIB_FEATURE_TESTS = \ dwarf \
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \ libpython \ libslang \ libunwind \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib VF_FEATURE_TESTS = \ backtrace \
@@ -604,6 +606,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),) CFLAGS += -DHAVE_LIBBFD_SUPPORT endif +ifndef NO_ZLIB + ifeq ($(feature-zlib), 1) + CFLAGS += -DHAVE_ZLIB_SUPPORT + EXTLIBS += -lz + else + NO_ZLIB := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORT
tools/perf/config/feature-checks/Makefile +5 -1
@@ -29,7 +29,8 @@ FILES= \ test-timerfd.bin \ test-libdw-dwarf-unwind.bin \ test-compile-32.bin \ - test-compile-x32.bin + test-compile-x32.bin \ + test-zlib.bin CC := $(CROSS_COMPILE)gcc -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -139,6 +140,9 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) test-compile-x32.bin: $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c +test-zlib.bin: + $(BUILD) -lz + -include *.d ###############################
tools/perf/config/feature-checks/test-zlib.c new file +9 -0
@@ -0,0 +1,9 @@ +#include <zlib.h> + +int main (void ) +{ +z_stream zs; + +inflateInit (&zs); +return 0 ; +}
tools/perf/util/dso.c +6 -9
@@ -141,24 +141,21 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } -static int decompress_dummy (const char *input__maybe_unused , -int output__maybe_unused ) -{ -return -1 ; -} -static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif + {NULL , }, };bool is_supported_compression (const char *ext) {unsigned i; -for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +for (i =0 ; compressions[i].fmt; i++) {if (!strcmp (ext, compressions[i].fmt))return true; }
@@ -197,7 +194,7 @@ bool decompress_to_file(const char *ext, const char *filename, int output_fd) {unsigned i; -for (i =0 ; i <ARRAY_SIZE (compressions); i++) { +for (i =0 ; compressions[i].fmt; i++) {if (!strcmp (ext, compressions[i].fmt))return !compressions[i].decompress (filename, output_fd);
tools/perf/util/util.h +5 -0
@@ -351,4 +351,9 @@ void mem_bswap_32(void *src, int byte_size);const char *get_filename_for_perf_kvm (void );bool find_process (const char *name); + +#ifdef HAVE_ZLIB_SUPPORT +int gzip_decompress_to_file (const char *input,int output_fd); +#endif +#endif /* GIT_COMPAT_UTIL_H */
tools/perf/util/zlib.c new file +78 -0
78 lines not on this page · raw message
Signature · 1 line
2.1.2
Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
On Mon, Nov 03, 2014 at 04:27:52PM +0900, Namhyung Kim wrote:
SNIP
Quoted 19 lines
#
# Overhead Command Shared Object Symbol # ........ ............... ........................... ......................................................#
0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap 0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid 0.02% firefox [e1000e] [k] __ew32_prepare 0.02% swapper [libahci] [k] ahci_handle_port_interrupt 0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock 0.02% swapper [e1000e] [k] e1000_clean_tx_irq 0.02% dwm [kernel.kallsyms] [k] __schedule 0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime 0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx 0.01% firefox [vdso] [.] __vdso_gettimeofday 0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13
Quoted 6 lines
Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 6 ++- tools/perf/config/feature-checks/test-zlib.c | 9 ++++
missing update for feature-checks/test-all.c
thanks,
jirka
Namhyung Kim
maintainerRe: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
Quoted 23 lines · Jiri Olsa
On Mon, Nov 03, 2014 at 04:27:52PM +0900, Namhyung Kim wrote:
SNIP
Quoted 19 lines
#
# Overhead Command Shared Object Symbol # ........ ............... ........................... ......................................................#
0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap 0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid 0.02% firefox [e1000e] [k] __ew32_prepare 0.02% swapper [libahci] [k] ahci_handle_port_interrupt 0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock 0.02% swapper [e1000e] [k] e1000_clean_tx_irq 0.02% dwm [kernel.kallsyms] [k] __schedule 0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime 0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx 0.01% firefox [vdso] [.] __vdso_gettimeofday 0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13
Quoted 8 lines
Quoted 6 lines
Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 6 ++- tools/perf/config/feature-checks/test-zlib.c | 9 ++++missing update for
feature-checks/test-all.c
Ah, right. Will add. :)
Thanks,
Namhyung
Namhyung Kim
maintainerPATCH 3/8 perf tools: Get rid of unused dsos__hit_all()
In reply to Namhyung KimThe dsos__hit_all() and its friends are not used anywhere. Let's get rid of them.
--- tools/perf/util/header.c | 41 ----------------------------------------- tools/perf/util/header.h | 2 -- 2 files changed, 43 deletions(-)
tools/perf/util/header.c +0 -41
@@ -200,47 +200,6 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,return write_padded (fd, name, name_len +1 , len); } -static int __dsos__hit_all (struct list_head *head) -{ -struct dso *pos; - -list_for_each_entry (pos, head, node) - pos->hit = true; - -return 0 ; -} - -static int machine__hit_all_dsos (struct machine *machine) -{ -int err; - - err =__dsos__hit_all (&machine->kernel_dsos.head); -if (err) -return err; - -return __dsos__hit_all (&machine->user_dsos.head); -} - -int dsos__hit_all (struct perf_session *session) -{ -struct rb_node *nd; -int err; - - err =machine__hit_all_dsos (&session->machines.host); -if (err) -return err; - -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { - struct machine *pos = rb_entry(nd, struct machine, rb_node); - - err =machine__hit_all_dsos (pos); -if (err) -return err; - } - -return 0 ; -} -static int __dsos__write_buildid_table (struct list_head *head,struct machine *machine,pid_t pid,u16 misc,int fd)
tools/perf/util/header.h +0 -2
@@ -151,8 +151,6 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session);bool is_perf_magic (u64 magic); -int dsos__hit_all (struct perf_session *session); -/* * arch specific callback */
Signature · 1 line
2.1.2
Adrian Hunter
reviewerRe: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
Quoted 2 lines · Namhyung Kim
The
dsos__hit_all()and its friends are not used anywhere. Let's get rid of them.
They were added for Intel PT preparation. Intel PT is still on its way, so they are still needed. Note the commit was:
commit 1f625b0b3dd641b74ba21640a1fea19a3dd893a2
Author: Adrian Hunter <[email protected]> Date: Tue Jul 22 16:17:23 2014 +0300
perf tools: Add dsos__hit_all()
Add ability to mark all dsos as hit.
This is needed in the case of Instruction Tracing. It takes so long to decode an Instruction Trace that it is not worth doing just to determine which dsos are hit. A later patch takes this into use.
Quoted 73 lines
Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/util/header.c | 41 ----------------------------------------- tools/perf/util/header.h | 2 -- 2 files changed, 43 deletions(-)tools/perf/util/header.c +0
-41@@ -200,47 +200,6 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,return write_padded (fd, name, name_len +1 , len); } -static int __dsos__hit_all (struct list_head *head) -{ -struct dso *pos; - -list_for_each_entry (pos, head, node) - pos->hit = true; - -return 0 ; -} - -static int machine__hit_all_dsos (struct machine *machine) -{ -int err; - - err =__dsos__hit_all (&machine->kernel_dsos.head); -if (err) -return err; - -return __dsos__hit_all (&machine->user_dsos.head); -} - -int dsos__hit_all (struct perf_session *session) -{ -struct rb_node *nd; -int err; - - err =machine__hit_all_dsos (&session->machines.host); -if (err) -return err; - -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { - struct machine *pos = rb_entry(nd, struct machine, rb_node); - - err =machine__hit_all_dsos (pos); -if (err) -return err; - } - -return 0 ; -} -static int __dsos__write_buildid_table (struct list_head *head,struct machine *machine,pid_t pid,u16 misc,int fd)tools/perf/util/header.h +0
-2@@ -151,8 +151,6 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session);bool is_perf_magic (u64 magic); -int dsos__hit_all (struct perf_session *session); -/* * arch specific callback */
Namhyung Kim
maintainerRe: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
Hi Adrian,
Quoted 11 lines · Adrian Hunter
Quoted 2 lines · Namhyung Kim
The
dsos__hit_all()and its friends are not used anywhere. Let's get rid of them.They were added for Intel PT preparation. Intel PT is still on its way, so they are still needed. Note the commit was:
commit
1f625b0b3dd641b74ba21640a1fea19a3dd893a2Author: Adrian Hunter <[email protected]> Date: Tue Jul 22 16:17:23 2014 +0300
Quoted 7 lines
perf tools: Add
dsos__hit_all()Add ability to mark all dsos as hit.
This is needed in the case of Instruction Tracing. It takes so long to decode an Instruction Trace that it is not worth doing just to determine which dsos are hit. A later patch takes this into use.
Oops, didn't notice. Sorry for not checking the commit log. So how about moving it into util/build-id.c then?
Thanks,
Namhyung
Adrian Hunter
reviewerRe: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
Quoted 16 lines · Namhyung Kim
Hi Adrian,
Quoted 13 lines · Adrian Hunter
Quoted 2 lines · Namhyung Kim
The
dsos__hit_all()and its friends are not used anywhere. Let's get rid of them.They were added for Intel PT preparation. Intel PT is still on its way, so they are still needed. Note the commit was:
commit
1f625b0b3dd641b74ba21640a1fea19a3dd893a2Author: Adrian Hunter <[email protected]> Date: Tue Jul 22 16:17:23 2014 +0300perf tools: Add
dsos__hit_all()
Quoted 8 lines
Quoted 5 lines
Add ability to mark all dsos as hit.
This is needed in the case of Instruction Tracing. It takes so long to decode an Instruction Trace that it is not worth doing just to determine which dsos are hit. A later patch takes this into use.
Oops, didn't notice. Sorry for not checking the commit log. So how about moving it into
util/build-id.cthen?
OK by me.
Namhyung Kim
maintainerPATCH 4/8 perf tools: Rename dsos__write_buildid_table()
In reply to Namhyung KimThe dsos__write_buildid_table() is not use struct dso and it mostly uses perf_session struct. So rename it to perf_session__write_buildid_ table() so that it corresponds to other related functions such as perf_session__read_build_ids() and perf_session__cache_build_ids().
--- tools/perf/util/header.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/header.c +2 -4
@@ -256,10 +256,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)return err; } -static int dsos__write_buildid_table (struct perf_header *header,int fd) +static int perf_session__write_buildid_table (struct perf_session *session,int fd) { -struct perf_session *session =container_of (header, - struct perf_session, header);struct rb_node *nd;int err =machine__write_buildid_table (&session->machines.host, fd);
@@ -482,7 +480,7 @@ static int write_build_id(int fd, struct perf_header *h,if (!perf_session__read_build_ids (session, true))return -1 ; - err =dsos__write_buildid_table (h, fd); + err =perf_session__write_buildid_table (session, fd);if (err <0 ) {pr_debug ("failed to write buildid table\n" );return err;
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 5/8 perf build-id: Move build-id related functions to util/build-id.c
In reply to Namhyung KimIt'd be better managing those functions in a separate place as util/header.c file is already big.
It now exports following 3 functions to others:
bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); int perf_session__write_buildid_table(struct perf_session *session, int fd); int perf_session__cache_build_ids(struct perf_session *session);
--- tools/perf/util/build-id.c | 293 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/build-id.h | 5 + tools/perf/util/header.c | 296 +-------------------------------------------- tools/perf/util/header.h | 4 + 4 files changed, 303 insertions(+), 295 deletions(-)
tools/perf/util/build-id.c +293 -0
@@ -15,6 +15,8 @@#include "debug.h" #include "session.h" #include "tool.h" +#include "header.h" +#include "vdso.h" int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event,
@@ -105,3 +107,294 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) build_id_hex, build_id_hex + 2);return bf; } + +#define dsos__for_each_with_build_id (pos, head) \ + list_for_each_entry(pos, head, node) \ + if (!pos->has_build_id) \ + continue; \ + else + +static int write_buildid (const char *name,size_t name_len,u8 *build_id, +pid_t pid,u16 misc,int fd) +{ +int err; +struct build_id_event b; +size_t len; + + len = name_len +1 ; + len =PERF_ALIGN (len,NAME_ALIGN ); + +memset (&b,0 ,sizeof (b)); +memcpy (&b.build_id, build_id,BUILD_ID_SIZE ); + b.pid = pid; + b.header.misc = misc; + b.header.size =sizeof (b) + len; + + err =writen (fd, &b,sizeof (b)); +if (err <0 ) +return err; + +return write_padded (fd, name, name_len +1 , len); +} + +static int __dsos__write_buildid_table (struct list_head *head, +struct machine *machine, +pid_t pid,u16 misc,int fd) +{ +char nm[PATH_MAX ]; +struct dso *pos; + +dsos__for_each_with_build_id (pos, head) { +int err; +const char *name; +size_t name_len; + +if (!pos->hit) +continue ; + +if (dso__is_vdso (pos)) { + name = pos->short_name; + name_len = pos->short_name_len +1 ; + }else if (dso__is_kcore (pos)) { +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + name_len =strlen (nm) +1 ; + }else { + name = pos->long_name; + name_len = pos->long_name_len +1 ; + } + + err =write_buildid (name, name_len, pos->build_id, + pid, misc, fd); +if (err) +return err; + } + +return 0 ; +} + +static int machine__write_buildid_table (struct machine *machine,int fd) +{ +int err; +u16 kmisc =PERF_RECORD_MISC_KERNEL , + umisc =PERF_RECORD_MISC_USER ; + +if (!machine__is_host (machine)) { + kmisc =PERF_RECORD_MISC_GUEST_KERNEL ; + umisc =PERF_RECORD_MISC_GUEST_USER ; + } + + err =__dsos__write_buildid_table (&machine->kernel_dsos.head, machine, + machine->pid, kmisc, fd); +if (err ==0 ) + err =__dsos__write_buildid_table (&machine->user_dsos.head, + machine, machine->pid, umisc, + fd); +return err; +} + +int perf_session__write_buildid_table (struct perf_session *session,int fd) +{ +struct rb_node *nd; +int err =machine__write_buildid_table (&session->machines.host, fd); + +if (err) +return err; + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + err =machine__write_buildid_table (pos, fd); +if (err) +break ; + } +return err; +} + +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, +const char *name,bool is_kallsyms,bool is_vdso) +{ +const size_t size =PATH_MAX ; +char *realname, *filename =zalloc (size), + *linkname =zalloc (size), *targetname; +int len, err =-1 ; +bool slash = is_kallsyms || is_vdso; + +if (is_kallsyms) { +if (symbol_conf.kptr_restrict) { +pr_debug ("Not caching a kptr_restrict'ed /proc/kallsyms\n" ); + err =0 ; + goto out_free; + } + realname = (char *) name; + }else + realname =realpath (name,NULL ); + +if (realname ==NULL || filename ==NULL || linkname ==NULL ) + goto out_free; + + len =scnprintf (filename, size,"%s%s%s" , + debugdir, slash ?"/" :"" , + is_vdso ?DSO__NAME_VDSO : realname); +if (mkdir_p (filename,0755 )) + goto out_free; + +snprintf (filename + len, size - len,"/%s" , sbuild_id); + +if (access (filename,F_OK )) { +if (is_kallsyms) { +if (copyfile ("/proc/kallsyms" , filename)) + goto out_free; + }else if (link (realname, filename) &©file (name, filename)) + goto out_free; + } + + len =scnprintf (linkname, size,"%s/.build-id/%.2s" , + debugdir, sbuild_id); + +if (access (linkname,X_OK ) &&mkdir_p (linkname,0755 )) + goto out_free; + +snprintf (linkname + len, size - len,"/%s" , sbuild_id +2 ); + targetname = filename +strlen (debugdir) -5 ; +memcpy (targetname,"../.." ,5 ); + +if (symlink (targetname, linkname) ==0 ) + err =0 ; +out_free: +if (!is_kallsyms) +free (realname); +free (filename); +free (linkname); +return err; +} + +static int build_id_cache__add_b (const u8 *build_id,size_t build_id_size, +const char *name,const char *debugdir, +bool is_kallsyms,bool is_vdso) +{ +char sbuild_id[BUILD_ID_SIZE *2 +1 ]; + +build_id__sprintf (build_id, build_id_size, sbuild_id); + +return build_id_cache__add_s (sbuild_id, debugdir, name, + is_kallsyms, is_vdso); +} + +int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir) +{ +const size_t size =PATH_MAX ; +char *filename =zalloc (size), + *linkname =zalloc (size); +int err =-1 ; + +if (filename ==NULL || linkname ==NULL ) + goto out_free; + +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, sbuild_id +2 ); + +if (access (linkname,F_OK )) + goto out_free; + +if (readlink (linkname, filename, size -1 ) <0 ) + goto out_free; + +if (unlink (linkname)) + goto out_free; + +/* +* Since the link is relative, we must make it absolute: +*/ +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, filename); + +if (unlink (linkname)) + goto out_free; + + err =0 ; +out_free: +free (filename); +free (linkname); +return err; +} + +static int dso__cache_build_id (struct dso *dso,struct machine *machine, +const char *debugdir) +{ +bool is_kallsyms = dso->kernel && dso->long_name[0 ] !='/' ; +bool is_vdso =dso__is_vdso (dso); +const char *name = dso->long_name; +char nm[PATH_MAX ]; + +if (dso__is_kcore (dso)) { + is_kallsyms = true; +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + } +return build_id_cache__add_b (dso->build_id,sizeof (dso->build_id), name, + debugdir, is_kallsyms, is_vdso); +} + +static int __dsos__cache_build_ids (struct list_head *head, +struct machine *machine,const char *debugdir) +{ +struct dso *pos; +int err =0 ; + +dsos__for_each_with_build_id (pos, head) +if (dso__cache_build_id (pos, machine, debugdir)) + err =-1 ; + +return err; +} + +static int machine__cache_build_ids (struct machine *machine,const char *debugdir) +{ +int ret =__dsos__cache_build_ids (&machine->kernel_dsos.head, machine, + debugdir); + ret |=__dsos__cache_build_ids (&machine->user_dsos.head, machine, + debugdir); +return ret; +} + +int perf_session__cache_build_ids (struct perf_session *session) +{ +struct rb_node *nd; +int ret; +char debugdir[PATH_MAX ]; + +snprintf (debugdir,sizeof (debugdir),"%s" , buildid_dir); + +if (mkdir (debugdir,0755 ) !=0 && errno !=EEXIST ) +return -1 ; + + ret =machine__cache_build_ids (&session->machines.host, debugdir); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__cache_build_ids (pos, debugdir); + } +return ret ?-1 :0 ; +} + +static bool machine__read_build_ids (struct machine *machine,bool with_hits) +{ +bool ret; + + ret =__dsos__read_build_ids (&machine->kernel_dsos.head, with_hits); + ret |=__dsos__read_build_ids (&machine->user_dsos.head, with_hits); +return ret; +} + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits) +{ +struct rb_node *nd; +bool ret =machine__read_build_ids (&session->machines.host, with_hits); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__read_build_ids (pos, with_hits); + } + +return ret; +}
tools/perf/util/build-id.h +5 -0
@@ -15,4 +15,9 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);int build_id__mark_dso_hit (struct perf_tool *tool,union perf_event *event,struct perf_sample *sample,struct perf_evsel *evsel,struct machine *machine); + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits); +int perf_session__write_buildid_table (struct perf_session *session,int fd); +int perf_session__cache_build_ids (struct perf_session *session); +#endif
tools/perf/util/header.c +1 -295
308 lines not on this page · raw message
tools/perf/util/header.h +4 -0
@@ -151,6 +151,10 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session);bool is_perf_magic (u64 magic); +#define NAME_ALIGN 64 + +int write_padded (int fd,const void *bf,size_t count,size_t count_aligned); +/* * arch specific callback */
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 6/8 perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
In reply to Namhyung KimWhen perf record finishes a session recording, it then pre-process samples in order to write build-id info from actually used DSOs. During this process it'll call map__load() for kernel map, and it ends up calling dso__load_vmlinux_path() which replaces dso->long_name.
But this function checks kernel's build-id before searching vmlinux path so it'll have the cryptic name which can be confusing to users IMHO.
This patch adds a flag to skip the build-id check during record, so it'll have a vmlinux path for the kernel dso->long_name.
Before:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.196 MB perf.data (~8545 samples) ] Looking at the vmlinux_path (7 entries long) Using /home/namhyung/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 for symbols
After:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.193 MB perf.data (~8432 samples) ] Looking at the vmlinux_path (7 entries long) Using /lib/modules/3.16.4-1-ARCH/build/vmlinux for symbols
--- tools/perf/builtin-record.c | 11 +++++++++++ tools/perf/util/symbol.c | 11 ++++++----- tools/perf/util/symbol.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +11 -0
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)if (size ==0 )return 0 ; +/* +* During this process, it'll load kernel map and replace the +* dso->long_name to a real pathname it found. In this case +* we prefer the vmlinux path like +* /lib/modules/3.16.4/build/vmlinux +* +* rather than build-id path (in debug directory). +* $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 +*/ + symbol_conf.ignore_vmlinux_buildid = true; +return __perf_session__process_events (session, start, size - start, size, &build_id__mark_dso_hit_ops);
tools/perf/util/symbol.c +6 -5
@@ -1511,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, symbol_filter_t filter) {int i, err =0 ; -char *filename; +char *filename =NULL ; -pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , - vmlinux_path__nr_entries +1 ); - - filename =dso__build_id_filename (dso,NULL ,0 ); +if (!symbol_conf.ignore_vmlinux_buildid) + filename =dso__build_id_filename (dso,NULL ,0 );if (filename !=NULL ) { err =dso__load_vmlinux (dso, map, filename, true, filter);if (err >0 )
@@ -1524,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,free (filename); } +pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , + vmlinux_path__nr_entries +1 ); +for (i =0 ; i < vmlinux_path__nr_entries; ++i) { err =dso__load_vmlinux (dso, map, vmlinux_path[i], false, filter);if (err >0 )
tools/perf/util/symbol.h +1 -0
@@ -105,6 +105,7 @@ struct symbol_conf {unsigned short nr_events;bool try_vmlinux_path, ignore_vmlinux, + ignore_vmlinux_buildid, show_kernel_path, use_modules, sort_by_name,
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 7/8 perf tools: Fix build-id matching on vmlinux
In reply to Namhyung KimThere's a problem on finding correct kernel symbols when perf report runs on a different kernel. Although a part of the problem was solved by the prior commit 0a7e6d1b6844 ("perf tools: Check recorded kernel version when finding vmlinux"), there's a remaining problem still.
When perf records samples, it synthesizes the kernel map using machine__mmap_name() and ref_reloc_sym like "[kernel.kallsyms]_text". You can easily see it using 'perf report -D' command.
After finishing record, it goes through the recorded events to find maps/dsos actually used. And then record build-id info of them.
During this process, it needs to load symbols in a dso and it'd call dso__load_vmlinux_path() since the default value of the symbol_conf. try_vmlinux_path is true. However it changes dso->long_name to a real path of the vmlinux file (e.g. /lib/modules/3.16.4/build/vmlinux) if one is running on a custom kernel.
It resulted in that perf report reads the build-id of the vmlinux, but cannot use it since it only knows about the [kernel.kallsyms] map. It then falls back to possible vmlinux paths by using the recorded kernel version (in case of a recent version) or a running kernel silently.
Even with the recent tools, this still has a possibility of breaking the result. As the build directory is a symbolic link, if one built a new kernel in the same directory with different source/config, the old link to vmlinux will point the new file. So it's absolutely needed to use build-id when finding a kernel image.
In this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper vmlinux [k] cpu_startup_entry
72.15% 0.00% swapper vmlinux [k] arch_cpu_idle
72.15% 0.00% swapper vmlinux [k] default_idle
71.87% 71.87% swapper vmlinux [k] native_safe_halt...
--- tools/perf/util/header.c | 2 +- tools/perf/util/machine.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/header.c +1 -1
@@ -1269,7 +1269,7 @@ static int __event_process_build_id(struct build_id_event *bev,dso__set_build_id (dso, &bev->build_id); -if (filename[0 ] =='[' ) +if (!is_kernel_module (filename,NULL )) dso->kernel = dso_type; build_id__sprintf(dso->build_id, sizeof(dso->build_id),
tools/perf/util/machine.c +14 -2
@@ -1085,8 +1085,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos.head, node) { +if (is_kernel_module (dso->long_name,NULL )) +continue ; + + kernel = dso; +break ; + } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);if (kernel ==NULL ) goto out_problem;
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 8/8 perf tools: Make vmlinux short name more like kallsyms short name
In reply to Namhyung KimThe previous patch changed kernel dso name from '[kernel.kallsyms]' to vmlinux. However it might add confusion to old users accustomed to the old name. So change the short name to '[kernel.vmlinux]' to reduce such confusion.
Before:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper vmlinux [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper vmlinux [k] cpuidle_enter_state
1.03% sleep vmlinux [k] copy_user_generic_unrolledAfter:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper [kernel.vmlinux] [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper [kernel.vmlinux] [k] cpuidle_enter_state
1.03% sleep [kernel.vmlinux] [k] copy_user_generic_unrolled--- tools/perf/util/machine.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/machine.c +3 -0
@@ -1106,6 +1106,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,if (__machine__create_kernel_maps (machine, kernel) <0 ) goto out_problem; +if (strstr (dso->long_name,"vmlinux" )) +dso__set_short_name (dso,"[kernel.vmlinux]" , false); +machine__set_kernel_mmap_len (machine, event);/*
Signature · 1 line
2.1.2
Namhyung Kim
maintainercover perf tools: Fix build-id matching on vmlinux (v6)
Hello,
This patchset addresses possible problem on kernel symbol matching. Since commit 5b7ba82a7591 ("perf symbols: Load kernel maps before using"), when perf record process samples to construct build-id table, it loads kernel map and it replaces dso->long_name. But perf report doesn't know about name other than [kernel.kallsyms] it failed to find existing kernel dso and falls back to running kernel's kallsyms.
So it's possible to report incorrect symbols for kernel functions if it runs on a different kernel:
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper [kernel.vmlinux] [k] cpu_startup_entry
72.15% 0.00% swapper [kernel.vmlinux] [k] arch_cpu_idle
72.15% 0.00% swapper [kernel.vmlinux] [k] default_idle
71.87% 71.87% swapper [kernel.vmlinux] [k] native_safe_haltIn this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
The patch 1-2 are to support module compression as some distro (e.g. Arch) already does it. The patch 3-5 are cleanup of build-id handling functions. The patch 6-7 are the main change of this series and finally patch 8 is just for suggestion which can be squashed into the previous patch or simply dropped.
* changes from v5)
- keep dsos__hit_all() in util/build-id.c (Adrian)
- fix bug in is_kernel_module function (Jiri)
- add missing zlib test to test-all.c (Jiri)
- move disable_buildid_cache function also
You can get it on 'perf/vmlinux-v6' branch in my tree:
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Any comments are welcome, thanks
Namhyung
Namhyung Kim (8):
perf tools: Preparation for compressed kernel module support perf tools: Add gzip decompression support for kernel module perf tools: Rename dsos__write_buildid_table()
perf build-id: Move build-id related functions to util/build-id.c perf tools: Move disable_buildid_cache() to util/build-id.c perf record: Do not save pathname in ./debug/.build-id directory for
vmlinux
perf tools: Fix build-id matching on vmlinux
perf tools: Make vmlinux short name more like kallsyms short name
tools/perf/Makefile.perf | 7 + tools/perf/builtin-record.c | 11 + tools/perf/config/Makefile | 15 +- tools/perf/config/feature-checks/Makefile | 6 +- tools/perf/config/feature-checks/test-all.c | 5 + tools/perf/config/feature-checks/test-zlib.c | 9 + tools/perf/util/build-id.c | 345 ++++++++++++++++++++++++++ tools/perf/util/build-id.h | 12 + tools/perf/util/dso.c | 71 ++++++ tools/perf/util/dso.h | 7 + tools/perf/util/header.c | 353 +-------------------------- tools/perf/util/header.h | 8 +- tools/perf/util/machine.c | 38 ++- tools/perf/util/symbol-elf.c | 35 ++- tools/perf/util/symbol.c | 19 +- tools/perf/util/symbol.h | 1 + tools/perf/util/util.h | 6 +- tools/perf/util/zlib.c | 78 ++++++ 18 files changed, 658 insertions(+), 368 deletions(-) create mode 100644 tools/perf/config/feature-checks/test-zlib.c create mode 100644 tools/perf/util/zlib.c
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 1/8 perf tools: Preparation for compressed kernel module support
This patch adds basic support to handle compressed kernel module as some distro (such as Archlinux) carries on it now. The actual work using compression library will be added later.
--- tools/perf/util/dso.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 7 +++++ tools/perf/util/machine.c | 19 ++++++++++- tools/perf/util/symbol-elf.c | 35 ++++++++++++++++++++- tools/perf/util/symbol.c | 8 ++++- 5 files changed, 141 insertions(+), 3 deletions(-)
tools/perf/util/dso.c +75 -0
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', + [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', };
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :path__join3 (filename, size, symbol_conf.symfs, root_dir, dso->long_name);break ;case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :__symbol__join_symfs (filename, size, dso->long_name);break ;
@@ -137,6 +141,77 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } +static int decompress_dummy (const char *input__maybe_unused , +int output__maybe_unused ) +{ +return -1 ; +} + +static const struct { +const char *fmt; +int (*decompress)(const char *input,int output); +} compressions[] = { + {"gz" , decompress_dummy }, + {NULL , }, +}; + +bool is_supported_compression (const char *ext) +{ +unsigned i; + +for (i =0 ; compressions[i].fmt; i++) { +if (!strcmp (ext, compressions[i].fmt)) +return true; + } +return false; +} + +bool is_kmodule_extension (const char *ext) +{ +if (strncmp (ext,"ko" ,2 )) +return false; + +if (ext[2 ] =='\0' || (ext[2 ] =='.' &&is_supported_compression (ext+3 ))) +return true; + +return false; +} + +bool is_kernel_module (const char *pathname,bool *compressed) +{ +const char *ext =strrchr (pathname,'.' ); + +if (ext ==NULL ) +return false; + +if (is_supported_compression (ext +1 )) { +if (compressed) + *compressed = true; + ext -=3 ; + }else if (compressed) + *compressed = false; + +return is_kmodule_extension (ext +1 ); +} + +bool decompress_to_file (const char *ext,const char *filename,int output_fd) +{ +unsigned i; + +for (i =0 ; compressions[i].fmt; i++) { +if (!strcmp (ext, compressions[i].fmt)) +return !compressions[i].decompress (filename, + output_fd); + } +return false; +} + +bool dso__needs_decompress (struct dso *dso) +{ +return dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE_COMP ; +} +/* * Global list of open DSOs and the counter. */
tools/perf/util/dso.h +7 -0
@@ -22,7 +22,9 @@ enum dso_binary_type {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE , DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -185,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);char dso__symtab_origin (const struct dso *dso);int dso__read_binary_type_filename (const struct dso *dso,enum dso_binary_type type,char *root_dir,char *filename,size_t size); +bool is_supported_compression (const char *ext); +bool is_kmodule_extension (const char *ext); +bool is_kernel_module (const char *pathname,bool *compressed); +bool decompress_to_file (const char *ext,const char *filename,int output_fd); +bool dso__needs_decompress (struct dso *dso);/* * The dso__data_* external interface provides following functions:
tools/perf/util/machine.c +18 -1
@@ -464,6 +464,7 @@ struct map *machine__new_module(struct machine *machine, u64 start, {struct map *map;struct dso *dso =__dsos__findnew (&machine->kernel_dsos, filename); +bool compressed;if (dso ==NULL )return NULL ;
@@ -476,6 +477,11 @@ struct map *machine__new_module(struct machine *machine, u64 start, dso->symtab_type =DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ; else dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; + +/* _KMODULE_COMP should be next to _KMODULE */ +if (is_kernel_module (filename, &compressed) && compressed) + dso->symtab_type++; +map_groups__insert (&machine->kmaps, map);return map; }
@@ -861,8 +867,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,struct map *map;char *long_name; -if (dot ==NULL ||strcmp (dot,".ko" )) +if (dot ==NULL )continue ; + +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 ) && +is_kmodule_extension (dot -2 )) + dot -=3 ; +snprintf (dso_name,sizeof (dso_name),"[%.*s]" , (int )(dot - dent->d_name), dent->d_name);
@@ -1044,6 +1056,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, dot =strrchr (name,'.' );if (dot ==NULL ) goto out_problem; +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 )) + dot -=3 ; +if (!is_kmodule_extension (dot +1 )) + goto out_problem;snprintf (short_module_name,sizeof (short_module_name),"[%.*s]" , (int )(dot - name), name);strxfrchar (short_module_name,'-' ,'_' );
tools/perf/util/symbol-elf.c +34 -1
@@ -546,6 +546,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)return 0 ; } +static int decompress_kmodule (struct dso *dso,const char *name, +enum dso_binary_type type) +{ +int fd; +const char *ext =strrchr (name,'.' ); +char tmpbuf[] ="/tmp/perf-kmod-XXXXXX" ; + +if ((type !=DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && + type !=DSO_BINARY_TYPE__GUEST_KMODULE_COMP ) || + type != dso->symtab_type) +return -1 ; + +if (!ext || !is_supported_compression (ext +1 )) +return -1 ; + + fd =mkstemp (tmpbuf); +if (fd <0 ) +return -1 ; + +if (!decompress_to_file (ext +1 , name, fd)) { +close (fd); + fd =-1 ; + } + +unlink (tmpbuf); + +return fd; +} +bool symsrc__possibly_runtime (struct symsrc *ss) {return ss->dynsym || ss->opdsec;
@@ -571,7 +600,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,Elf *elf;int fd; - fd =open (name,O_RDONLY ); +if (dso__needs_decompress (dso)) + fd =decompress_kmodule (dso, name, type); +else + fd =open (name,O_RDONLY ); +if (fd <0 )return -1 ;
tools/perf/util/symbol.c +7 -1
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , DSO_BINARY_TYPE__NOT_FOUND, };
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,return dso->kernel ==DSO_TYPE_GUEST_KERNEL ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :/* * kernel modules know their symtab type - it's set when * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)return -1 ; kmod = dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || - dso->symtab_type ==DSO_BINARY_TYPE__GUEST_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.
Signature · 1 line
2.1.2
Re: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
Quoted 5 lines · Namhyung Kim
This patch adds basic support to handle compressed kernel module as some distro (such as Archlinux) carries on it now. The actual work using compression library will be added later.
Signed-off-by Namhyung Kim <[email protected]>
thanks,
jirka
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf symbols: Preparation for compressed kernel module support
In reply to Namhyung Kimperf symbols: Preparation for compressed kernel module support
Commit-ID: c00c48fc6e6ef63d83a7417923a06b08089bb34b Gitweb: http://git.kernel.org/tip/c00c48fc6e6ef63d83a7417923a06b08089bb34b Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:27 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 4 Nov 2014 10:15:53 -0300
perf symbols: Preparation for compressed kernel module support
This patch adds basic support to handle compressed kernel module as some distro (such as Archlinux) carries on it now. The actual work using compression library will be added later.
--- tools/perf/util/dso.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 7 +++++ tools/perf/util/machine.c | 19 ++++++++++- tools/perf/util/symbol-elf.c | 35 ++++++++++++++++++++- tools/perf/util/symbol.c | 8 ++++- 5 files changed, 141 insertions(+), 3 deletions(-)
tools/perf/util/dso.c +75 -0
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso) [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', + [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', };
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,break ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :path__join3 (filename, size, symbol_conf.symfs, root_dir, dso->long_name);break ;case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :__symbol__join_symfs (filename, size, dso->long_name);break ;
@@ -137,6 +141,77 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } +static int decompress_dummy (const char *input__maybe_unused , +int output__maybe_unused ) +{ +return -1 ; +} + +static const struct { +const char *fmt; +int (*decompress)(const char *input,int output); +} compressions[] = { + {"gz" , decompress_dummy }, + {NULL , }, +}; + +bool is_supported_compression (const char *ext) +{ +unsigned i; + +for (i =0 ; compressions[i].fmt; i++) { +if (!strcmp (ext, compressions[i].fmt)) +return true; + } +return false; +} + +bool is_kmodule_extension (const char *ext) +{ +if (strncmp (ext,"ko" ,2 )) +return false; + +if (ext[2 ] =='\0' || (ext[2 ] =='.' &&is_supported_compression (ext+3 ))) +return true; + +return false; +} + +bool is_kernel_module (const char *pathname,bool *compressed) +{ +const char *ext =strrchr (pathname,'.' ); + +if (ext ==NULL ) +return false; + +if (is_supported_compression (ext +1 )) { +if (compressed) + *compressed = true; + ext -=3 ; + }else if (compressed) + *compressed = false; + +return is_kmodule_extension (ext +1 ); +} + +bool decompress_to_file (const char *ext,const char *filename,int output_fd) +{ +unsigned i; + +for (i =0 ; compressions[i].fmt; i++) { +if (!strcmp (ext, compressions[i].fmt)) +return !compressions[i].decompress (filename, + output_fd); + } +return false; +} + +bool dso__needs_decompress (struct dso *dso) +{ +return dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || + dso->symtab_type ==DSO_BINARY_TYPE__GUEST_KMODULE_COMP ; +} +/* * Global list of open DSOs and the counter. */
tools/perf/util/dso.h +7 -0
@@ -22,7 +22,9 @@ enum dso_binary_type {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE , DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -185,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);char dso__symtab_origin (const struct dso *dso);int dso__read_binary_type_filename (const struct dso *dso,enum dso_binary_type type,char *root_dir,char *filename,size_t size); +bool is_supported_compression (const char *ext); +bool is_kmodule_extension (const char *ext); +bool is_kernel_module (const char *pathname,bool *compressed); +bool decompress_to_file (const char *ext,const char *filename,int output_fd); +bool dso__needs_decompress (struct dso *dso);/* * The dso__data_* external interface provides following functions:
tools/perf/util/machine.c +18 -1
@@ -464,6 +464,7 @@ struct map *machine__new_module(struct machine *machine, u64 start, {struct map *map;struct dso *dso =__dsos__findnew (&machine->kernel_dsos, filename); +bool compressed;if (dso ==NULL )return NULL ;
@@ -476,6 +477,11 @@ struct map *machine__new_module(struct machine *machine, u64 start, dso->symtab_type =DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ; else dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; + +/* _KMODULE_COMP should be next to _KMODULE */ +if (is_kernel_module (filename, &compressed) && compressed) + dso->symtab_type++; +map_groups__insert (&machine->kmaps, map);return map; }
@@ -861,8 +867,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,struct map *map;char *long_name; -if (dot ==NULL ||strcmp (dot,".ko" )) +if (dot ==NULL )continue ; + +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 ) && +is_kmodule_extension (dot -2 )) + dot -=3 ; +snprintf (dso_name,sizeof (dso_name),"[%.*s]" , (int )(dot - dent->d_name), dent->d_name);
@@ -1044,6 +1056,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, dot =strrchr (name,'.' );if (dot ==NULL ) goto out_problem; +/* On some system, modules are compressed like .ko.gz */ +if (is_supported_compression (dot +1 )) + dot -=3 ; +if (!is_kmodule_extension (dot +1 )) + goto out_problem;snprintf (short_module_name,sizeof (short_module_name),"[%.*s]" , (int )(dot - name), name);strxfrchar (short_module_name,'-' ,'_' );
tools/perf/util/symbol-elf.c +34 -1
@@ -546,6 +546,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)return 0 ; } +static int decompress_kmodule (struct dso *dso,const char *name, +enum dso_binary_type type) +{ +int fd; +const char *ext =strrchr (name,'.' ); +char tmpbuf[] ="/tmp/perf-kmod-XXXXXX" ; + +if ((type !=DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && + type !=DSO_BINARY_TYPE__GUEST_KMODULE_COMP ) || + type != dso->symtab_type) +return -1 ; + +if (!ext || !is_supported_compression (ext +1 )) +return -1 ; + + fd =mkstemp (tmpbuf); +if (fd <0 ) +return -1 ; + +if (!decompress_to_file (ext +1 , name, fd)) { +close (fd); + fd =-1 ; + } + +unlink (tmpbuf); + +return fd; +} +bool symsrc__possibly_runtime (struct symsrc *ss) {return ss->dynsym || ss->opdsec;
@@ -571,7 +600,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,Elf *elf;int fd; - fd =open (name,O_RDONLY ); +if (dso__needs_decompress (dso)) + fd =decompress_kmodule (dso, name, type); +else + fd =open (name,O_RDONLY ); +if (fd <0 )return -1 ;
tools/perf/util/symbol.c +7 -1
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {DSO_BINARY_TYPE__BUILDID_DEBUGINFO ,DSO_BINARY_TYPE__SYSTEM_PATH_DSO ,DSO_BINARY_TYPE__GUEST_KMODULE , +DSO_BINARY_TYPE__GUEST_KMODULE_COMP ,DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE , +DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , DSO_BINARY_TYPE__NOT_FOUND, };
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,return dso->kernel ==DSO_TYPE_GUEST_KERNEL ;case DSO_BINARY_TYPE__GUEST_KMODULE : +case DSO_BINARY_TYPE__GUEST_KMODULE_COMP :case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE : +case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP :/* * kernel modules know their symtab type - it's set when * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)return -1 ; kmod = dso->symtab_type ==DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || - dso->symtab_type ==DSO_BINARY_TYPE__GUEST_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.
Namhyung Kim
maintainerPATCH 2/8 perf tools: Add gzip decompression support for kernel module
In reply to Namhyung KimNow my Archlinux box shows module symbols correctly.
Before:
$ perf report --stdio
Failed to open /tmp/perf-3477.map, continuing without symbols
no symbols found in /usr/bin/date, maybe install a debug package?
No kallsyms or vmlinux with build-id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 was found
[drm] with build id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 not found, continuing without symbols
No kallsyms or vmlinux with build-id edd931629094b660ca9dec09a1b635c8d87aa2ee was found
[jbd2] with build id edd931629094b660ca9dec09a1b635c8d87aa2ee not found, continuing without symbols
No kallsyms or vmlinux with build-id a7b1eada671c34933e5610bb920b2ca4945a82c3 was found
[ext4] with build id a7b1eada671c34933e5610bb920b2ca4945a82c3 not found, continuing without symbols
No kallsyms or vmlinux with build-id d69511fa3e5840e770336ef45b06c83fef8d74e3 was found
[scsi_mod] with build id d69511fa3e5840e770336ef45b06c83fef8d74e3 not found, continuing without symbols
No kallsyms or vmlinux with build-id af0430af13461af058770ee9b87afc07922c2e77 was found
[libata] with build id af0430af13461af058770ee9b87afc07922c2e77 not found, continuing without symbols
No kallsyms or vmlinux with build-id aaeedff8160ce631a5f0333591c6ff291201d29f was found
[libahci] with build id aaeedff8160ce631a5f0333591c6ff291201d29f not found, continuing without symbols
No kallsyms or vmlinux with build-id c57907712becaf662dc4981824bb372c0441d605 was found
[mac80211] with build id c57907712becaf662dc4981824bb372c0441d605 not found, continuing without symbols
No kallsyms or vmlinux with build-id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f was found
[iwldvm] with build id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f not found, continuing without symbols
No kallsyms or vmlinux with build-id 2d86086bf136bf374a2f029cf85a48194f9b950b was found
[cfg80211] with build id 2d86086bf136bf374a2f029cf85a48194f9b950b not found, continuing without symbols
No kallsyms or vmlinux with build-id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 was found
[iwlwifi] with build id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 not found, continuing without symbols
...
#
# Overhead Command Shared Object Symbol
# ........ ............... ....................... ........................................................
#
0.03% swapper [ext4] [k] 0x000000000000fe2e
0.03% swapper [kernel.kallsyms] [k] account_entity_enqueue
0.03% swapper [ext4] [k] 0x000000000000fc2b
0.03% irq/50-iwlwifi [iwlwifi] [k] 0x000000000000200b
0.03% swapper [kernel.kallsyms] [k] ktime_add_safe
0.03% swapper [kernel.kallsyms] [k] elv_completed_request
0.03% swapper [libata] [k] 0x0000000000003997
0.03% swapper [libahci] [k] 0x0000000000001f25
0.03% swapper [kernel.kallsyms] [k] rb_next
0.03% swapper [kernel.kallsyms] [k] blk_finish_request
0.03% swapper [ext4] [k] 0x0000000000010248
0.00% perf [kernel.kallsyms] [k] native_write_msr_safeAfter:
$ perf report --stdio Failed to open /tmp/perf-3477.map, continuing without symbols no symbols found in /usr/bin/tr, maybe install a debug package? ... # # Overhead Command Shared Object Symbol # ........ ............... ........................... ...................................................... #
0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap
0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid
0.02% firefox [e1000e] [k] __ew32_prepare
0.02% swapper [libahci] [k] ahci_handle_port_interrupt
0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock
0.02% swapper [e1000e] [k] e1000_clean_tx_irq
0.02% dwm [kernel.kallsyms] [k] __schedule
0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime
0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx
0.01% firefox [vdso] [.] __vdso_gettimeofday
0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 6 ++- tools/perf/config/feature-checks/test-all.c | 5 ++ tools/perf/config/feature-checks/test-zlib.c | 9 ++++ tools/perf/util/dso.c | 10 ++-- tools/perf/util/util.h | 5 ++ tools/perf/util/zlib.c | 78 ++++++++++++++++++++++++++++ 8 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 tools/perf/config/feature-checks/test-zlib.c create mode 100644 tools/perf/util/zlib.c
tools/perf/Makefile.perf +7 -0
@@ -66,6 +66,9 @@ include config/utilities.mak # # Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32 # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode +# +# Define NO_ZLIB if you do not want to support compressed kernel modules + ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -582,6 +585,10 @@ ifndef NO_LIBNUMA BUILTIN_OBJS += $(OUTPUT)bench/numa.o endif +ifndef NO_ZLIB + LIB_OBJS += $(OUTPUT)util/zlib.o +endif + ifdef ASCIIDOC8 export ASCIIDOC8 endif
tools/perf/config/Makefile +13 -2
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \ libunwind \ stackprotector-all \ timerfd \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib LIB_FEATURE_TESTS = \ dwarf \
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \ libpython \ libslang \ libunwind \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib VF_FEATURE_TESTS = \ backtrace \
@@ -604,6 +606,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),) CFLAGS += -DHAVE_LIBBFD_SUPPORT endif +ifndef NO_ZLIB + ifeq ($(feature-zlib), 1) + CFLAGS += -DHAVE_ZLIB_SUPPORT + EXTLIBS += -lz + else + NO_ZLIB := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORT
tools/perf/config/feature-checks/Makefile +5 -1
@@ -29,7 +29,8 @@ FILES= \ test-timerfd.bin \ test-libdw-dwarf-unwind.bin \ test-compile-32.bin \ - test-compile-x32.bin + test-compile-x32.bin \ + test-zlib.bin CC := $(CROSS_COMPILE)gcc -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -139,6 +140,9 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) test-compile-x32.bin: $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c +test-zlib.bin: + $(BUILD) -lz + -include *.d ###############################
tools/perf/config/feature-checks/test-all.c +5 -0
@@ -93,6 +93,10 @@# include "test-sync-compare-and-swap.c" #undef main +#define main main_test_zlib +# include "test-zlib.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -116,6 +120,7 @@ int main(int argc, char *argv[])main_test_stackprotector_all ();main_test_libdw_dwarf_unwind ();main_test_sync_compare_and_swap (argc, argv); +main_test_zlib ();return 0 ; }
tools/perf/config/feature-checks/test-zlib.c new file +9 -0
@@ -0,0 +1,9 @@ +#include <zlib.h> + +int main (void ) +{ +z_stream zs; + +inflateInit (&zs); +return 0 ; +}
tools/perf/util/dso.c +3 -7
@@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } -static int decompress_dummy (const char *input__maybe_unused , -int output__maybe_unused ) -{ -return -1 ; -} -static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif {NULL , }, };
tools/perf/util/util.h +5 -0
@@ -351,4 +351,9 @@ void mem_bswap_32(void *src, int byte_size);const char *get_filename_for_perf_kvm (void );bool find_process (const char *name); + +#ifdef HAVE_ZLIB_SUPPORT +int gzip_decompress_to_file (const char *input,int output_fd); +#endif +#endif /* GIT_COMPAT_UTIL_H */
tools/perf/util/zlib.c new file +78 -0
78 lines not on this page · raw message
Signature · 1 line
2.1.2
Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
Quoted 1 line · Namhyung Kim
Now my Archlinux box shows module symbols correctly.
with the last comment addressed (-lz in test-all.bin):
thanks,
jirka
Quoted 334 lines
Before:
$ perf report --stdio Failed to open /tmp/perf-3477.map, continuing without symbols no symbols found in /usr/bin/date, maybe install a debug package? No kallsyms or vmlinux with build-id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 was found [drm] with build id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 not found, continuing without symbols No kallsyms or vmlinux with build-id edd931629094b660ca9dec09a1b635c8d87aa2ee was found [jbd2] with build id edd931629094b660ca9dec09a1b635c8d87aa2ee not found, continuing without symbols No kallsyms or vmlinux with build-id a7b1eada671c34933e5610bb920b2ca4945a82c3 was found [ext4] with build id a7b1eada671c34933e5610bb920b2ca4945a82c3 not found, continuing without symbols No kallsyms or vmlinux with build-id d69511fa3e5840e770336ef45b06c83fef8d74e3 was found [scsi_mod] with build id d69511fa3e5840e770336ef45b06c83fef8d74e3 not found, continuing without symbols No kallsyms or vmlinux with build-id af0430af13461af058770ee9b87afc07922c2e77 was found [libata] with build id af0430af13461af058770ee9b87afc07922c2e77 not found, continuing without symbols No kallsyms or vmlinux with build-id aaeedff8160ce631a5f0333591c6ff291201d29f was found [libahci] with build id aaeedff8160ce631a5f0333591c6ff291201d29f not found, continuing without symbols No kallsyms or vmlinux with build-id c57907712becaf662dc4981824bb372c0441d605 was found [mac80211] with build id c57907712becaf662dc4981824bb372c0441d605 not found, continuing without symbols No kallsyms or vmlinux with build-id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f was found [iwldvm] with build id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f not found, continuing without symbols No kallsyms or vmlinux with build-id 2d86086bf136bf374a2f029cf85a48194f9b950b was found [cfg80211] with build id 2d86086bf136bf374a2f029cf85a48194f9b950b not found, continuing without symbols No kallsyms or vmlinux with build-id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 was found [iwlwifi] with build id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 not found, continuing without symbols ... # # Overhead Command Shared Object Symbol # ........ ............... ....................... ........................................................ # 0.03% swapper [ext4] [k] 0x000000000000fe2e 0.03% swapper [kernel.kallsyms] [k] account_entity_enqueue 0.03% swapper [ext4] [k] 0x000000000000fc2b 0.03% irq/50-iwlwifi [iwlwifi] [k] 0x000000000000200b 0.03% swapper [kernel.kallsyms] [k] ktime_add_safe 0.03% swapper [kernel.kallsyms] [k] elv_completed_request 0.03% swapper [libata] [k] 0x0000000000003997 0.03% swapper [libahci] [k] 0x0000000000001f25 0.03% swapper [kernel.kallsyms] [k] rb_next 0.03% swapper [kernel.kallsyms] [k] blk_finish_request 0.03% swapper [ext4] [k] 0x0000000000010248 0.00% perf [kernel.kallsyms] [k] native_write_msr_safeAfter:
$ perf report --stdio Failed to open /tmp/perf-3477.map, continuing without symbols no symbols found in /usr/bin/tr, maybe install a debug package? ... # # Overhead Command Shared Object Symbol # ........ ............... ........................... ...................................................... #0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap 0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid 0.02% firefox [e1000e] [k] __ew32_prepare 0.02% swapper [libahci] [k] ahci_handle_port_interrupt 0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock 0.02% swapper [e1000e] [k] e1000_clean_tx_irq 0.02% dwm [kernel.kallsyms] [k] __schedule 0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime 0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers 0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx 0.01% firefox [vdso] [.] __vdso_gettimeofday 0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 6 ++- tools/perf/config/feature-checks/test-all.c | 5 ++ tools/perf/config/feature-checks/test-zlib.c | 9 ++++ tools/perf/util/dso.c | 10 ++-- tools/perf/util/util.h | 5 ++ tools/perf/util/zlib.c | 78 ++++++++++++++++++++++++++++ 8 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 tools/perf/config/feature-checks/test-zlib.c create mode 100644 tools/perf/util/zlib.ctools/perf/Makefile.perf +7
-0@@ -66,6 +66,9 @@ include config/utilities.mak # # Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32 # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode +# +# Define NO_ZLIB if you do not want to support compressed kernel modules + ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd)))@@ -582,6 +585,10 @@ ifndef NO_LIBNUMA BUILTIN_OBJS += $(OUTPUT)bench/numa.o endif +ifndef NO_ZLIB + LIB_OBJS += $(OUTPUT)util/zlib.o +endif + ifdef ASCIIDOC8 export ASCIIDOC8 endiftools/perf/config/Makefile +13
-2@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \ libunwind \ stackprotector-all \ timerfd \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib LIB_FEATURE_TESTS = \ dwarf \@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \ libpython \ libslang \ libunwind \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib VF_FEATURE_TESTS = \ backtrace \@@ -604,6 +606,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),) CFLAGS += -DHAVE_LIBBFD_SUPPORT endif +ifndef NO_ZLIB + ifeq ($(feature-zlib), 1) + CFLAGS += -DHAVE_ZLIB_SUPPORT + EXTLIBS += -lz + else + NO_ZLIB := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORTtools/perf/config/feature-checks/Makefile +5
-1@@ -29,7 +29,8 @@ FILES= \ test-timerfd.bin \ test-libdw-dwarf-unwind.bin \ test-compile-32.bin \ - test-compile-x32.bin + test-compile-x32.bin \ + test-zlib.bin CC := $(CROSS_COMPILE)gcc -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config@@ -139,6 +140,9 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) test-compile-x32.bin: $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c +test-zlib.bin: + $(BUILD) -lz + -include *.d ###############################tools/perf/config/feature-checks/test-all.c +5
-0@@ -93,6 +93,10 @@# include "test-sync-compare-and-swap.c" #undef main +#define main main_test_zlib +# include "test-zlib.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();@@ -116,6 +120,7 @@ int main(int argc, char *argv[])main_test_stackprotector_all ();main_test_libdw_dwarf_unwind ();main_test_sync_compare_and_swap (argc, argv); +main_test_zlib ();return 0 ; }tools/perf/config/feature-checks/test-zlib.c new file +9
-0@@ -0,0 +1,9 @@ +#include <zlib.h> + +int main (void ) +{ +z_stream zs; + +inflateInit (&zs); +return 0 ; +}tools/perf/util/dso.c +3
-7@@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } -static int decompress_dummy (const char *input__maybe_unused , -int output__maybe_unused ) -{ -return -1 ; -} -static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif {NULL , }, };tools/perf/util/util.h +5
-0@@ -351,4 +351,9 @@ void mem_bswap_32(void *src, int byte_size);const char *get_filename_for_perf_kvm (void );bool find_process (const char *name); + +#ifdef HAVE_ZLIB_SUPPORT +int gzip_decompress_to_file (const char *input,int output_fd); +#endif +#endif /* GIT_COMPAT_UTIL_H */ tools/perf/util/zlib.c new file +78
-0@@ -0,0 +1,78 @@ +#include <stdio.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <zlib.h> + +#include "util/util.h" +#include "util/debug.h" + + +#define CHUNK_SIZE 16384 + +int gzip_decompress_to_file (const char *input,int output_fd) +{ +int ret =Z_STREAM_ERROR ; +int input_fd; +void *ptr; +int len; +struct stat stbuf; +unsigned char buf[CHUNK_SIZE ]; +z_stream zs = { + .zalloc =Z_NULL , + .zfree =Z_NULL , + .opaque =Z_NULL , + .avail_in =0 , + .next_in =Z_NULL , + }; + + input_fd =open (input,O_RDONLY ); +if (input_fd <0 ) +return -1 ; + +if (fstat (input_fd, &stbuf) <0 ) + goto out_close; + + ptr =mmap (NULL , stbuf.st_size,PROT_READ ,MAP_PRIVATE , input_fd,0 ); +if (ptr ==MAP_FAILED ) + goto out_close; + +if (inflateInit2 (&zs,16 +MAX_WBITS ) !=Z_OK ) + goto out_unmap; + + zs.next_in = ptr; + zs.avail_in = stbuf.st_size; + +do { + zs.next_out = buf; + zs.avail_out =CHUNK_SIZE ; + + ret =inflate (&zs,Z_NO_FLUSH ); +switch (ret) { +case Z_NEED_DICT : + ret =Z_DATA_ERROR ; +/* fall through */ +case Z_DATA_ERROR : +case Z_MEM_ERROR : + goto out; +default : +break ; + } + + len =CHUNK_SIZE - zs.avail_out; +if (writen (output_fd, buf, len) != len) { + ret =Z_DATA_ERROR ; + goto out; + } + + }while (ret !=Z_STREAM_END ); + +out: +inflateEnd (&zs); +out_unmap: +munmap (ptr, stbuf.st_size); +out_close: +close (input_fd); + +return ret ==Z_STREAM_END ?0 :-1 ; +}Signature · 1 line
2.1.2
Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
Em Tue, Nov 04, 2014 at 12:00:17PM +0100, Jiri Olsa escreveu:
Quoted 6 lines · Namhyung Kim
Quoted 1 line
Now my Archlinux box shows module symbols correctly.
with the last comment addressed (-lz in test-all.bin):
Acked-by Jiri Olsa <[email protected]>
Thanks, applied the series.
- Arnaldo
Namhyung Kim
maintainerRe: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Tue, Nov 04, 2014 at 12:00:17PM +0100, Jiri Olsa escreveu:
Quoted 6 lines · Namhyung Kim
Quoted 1 line
Now my Archlinux box shows module symbols correctly.
with the last comment addressed (-lz in test-all.bin):
Acked-by Jiri Olsa <[email protected]>Thanks, applied the series.
Oh-oh, wait. I need to add -lz to test-all.bin target in Makefile so you need to apply this hunk, sorry. :-/
tools/perf/config/feature-checks/Mak renamed from tools/perf/config/feature-checks/Makefile +0 -0
efile
index 7c68ec74a808..53f19b5dbc37 100644
tools/perf/config/feature-checks/Makefile +1 -1
@@ -41,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) ############################### test-all.bin: - $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl + $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz test-hello.bin: $(BUILD)
I pushed this to 'perf/vmlinux-v7' branch. Please check it there.
Thanks,
Namhyung
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf tools: Add gzip decompression support for kernel module
perf tools: Add gzip decompression support for kernel module
Commit-ID: e92ce12ed6a46302f64269d2d406cf04525f0a8f Gitweb: http://git.kernel.org/tip/e92ce12ed6a46302f64269d2d406cf04525f0a8f Author: Namhyung Kim <[email protected]> AuthorDate: Fri, 31 Oct 2014 16:51:38 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:11:26 -0300
perf tools: Add gzip decompression support for kernel module
Now my Archlinux box shows module symbols correctly.
Before:
$ perf report --stdio
Failed to open /tmp/perf-3477.map, continuing without symbols
no symbols found in /usr/bin/date, maybe install a debug package?
No kallsyms or vmlinux with build-id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 was found
[drm] with build id 7b4ea0a49ae2111925857099aaf05c3246ff33e0 not found, continuing without symbols
No kallsyms or vmlinux with build-id edd931629094b660ca9dec09a1b635c8d87aa2ee was found
[jbd2] with build id edd931629094b660ca9dec09a1b635c8d87aa2ee not found, continuing without symbols
No kallsyms or vmlinux with build-id a7b1eada671c34933e5610bb920b2ca4945a82c3 was found
[ext4] with build id a7b1eada671c34933e5610bb920b2ca4945a82c3 not found, continuing without symbols
No kallsyms or vmlinux with build-id d69511fa3e5840e770336ef45b06c83fef8d74e3 was found
[scsi_mod] with build id d69511fa3e5840e770336ef45b06c83fef8d74e3 not found, continuing without symbols
No kallsyms or vmlinux with build-id af0430af13461af058770ee9b87afc07922c2e77 was found
[libata] with build id af0430af13461af058770ee9b87afc07922c2e77 not found, continuing without symbols
No kallsyms or vmlinux with build-id aaeedff8160ce631a5f0333591c6ff291201d29f was found
[libahci] with build id aaeedff8160ce631a5f0333591c6ff291201d29f not found, continuing without symbols
No kallsyms or vmlinux with build-id c57907712becaf662dc4981824bb372c0441d605 was found
[mac80211] with build id c57907712becaf662dc4981824bb372c0441d605 not found, continuing without symbols
No kallsyms or vmlinux with build-id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f was found
[iwldvm] with build id e0589077cc0ec8c3e4c40eb9f2d9e69d236bee8f not found, continuing without symbols
No kallsyms or vmlinux with build-id 2d86086bf136bf374a2f029cf85a48194f9b950b was found
[cfg80211] with build id 2d86086bf136bf374a2f029cf85a48194f9b950b not found, continuing without symbols
No kallsyms or vmlinux with build-id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 was found
[iwlwifi] with build id 4493c48599bdb3d91d0f8db5150e0be33fdd9221 not found, continuing without symbols
...
#
# Overhead Command Shared Object Symbol
# ........ ............... ....................... ........................................................
#
0.03% swapper [ext4] [k] 0x000000000000fe2e
0.03% swapper [kernel.kallsyms] [k] account_entity_enqueue
0.03% swapper [ext4] [k] 0x000000000000fc2b
0.03% irq/50-iwlwifi [iwlwifi] [k] 0x000000000000200b
0.03% swapper [kernel.kallsyms] [k] ktime_add_safe
0.03% swapper [kernel.kallsyms] [k] elv_completed_request
0.03% swapper [libata] [k] 0x0000000000003997
0.03% swapper [libahci] [k] 0x0000000000001f25
0.03% swapper [kernel.kallsyms] [k] rb_next
0.03% swapper [kernel.kallsyms] [k] blk_finish_request
0.03% swapper [ext4] [k] 0x0000000000010248
0.00% perf [kernel.kallsyms] [k] native_write_msr_safeAfter:
$ perf report --stdio Failed to open /tmp/perf-3477.map, continuing without symbols no symbols found in /usr/bin/tr, maybe install a debug package? ... # # Overhead Command Shared Object Symbol # ........ ............... ........................... ...................................................... #
0.04% kworker/u16:3 [ext4] [k] ext4_read_block_bitmap
0.03% kworker/u16:0 [mac80211] [k] ieee80211_sta_reset_beacon_monitor
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_get_bssid
0.02% firefox [e1000e] [k] __ew32_prepare
0.02% swapper [libahci] [k] ahci_handle_port_interrupt
0.02% emacs libglib-2.0.so.0.4000.0 [.] g_mutex_unlock
0.02% swapper [e1000e] [k] e1000_clean_tx_irq
0.02% dwm [kernel.kallsyms] [k] __schedule
0.02% gnome-terminal- [vdso] [.] __vdso_clock_gettime
0.02% swapper [e1000e] [k] e1000_alloc_rx_buffers
0.02% irq/50-iwlwifi [mac80211] [k] ieee80211_rx
0.01% firefox [vdso] [.] __vdso_gettimeofday
0.01% irq/50-iwlwifi [iwlwifi] [k] iwl_pcie_rxq_restock.part.13--- tools/perf/Makefile.perf | 7 +++ tools/perf/config/Makefile | 15 +++++- tools/perf/config/feature-checks/Makefile | 8 ++- tools/perf/config/feature-checks/test-all.c | 5 ++ tools/perf/config/feature-checks/test-zlib.c | 9 ++++ tools/perf/util/dso.c | 12 ++--- tools/perf/util/util.h | 5 ++ tools/perf/util/zlib.c | 78 ++++++++++++++++++++++++++++ 8 files changed, 127 insertions(+), 12 deletions(-)
tools/perf/Makefile.perf +7 -0
@@ -66,6 +66,9 @@ include config/utilities.mak # # Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32 # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode +# +# Define NO_ZLIB if you do not want to support compressed kernel modules + ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -584,6 +587,10 @@ ifndef NO_LIBNUMA BUILTIN_OBJS += $(OUTPUT)bench/numa.o endif +ifndef NO_ZLIB + LIB_OBJS += $(OUTPUT)util/zlib.o +endif + ifdef ASCIIDOC8 export ASCIIDOC8 endif
tools/perf/config/Makefile +13 -2
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \ libunwind \ stackprotector-all \ timerfd \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib LIB_FEATURE_TESTS = \ dwarf \
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \ libpython \ libslang \ libunwind \ - libdw-dwarf-unwind + libdw-dwarf-unwind \ + zlib VF_FEATURE_TESTS = \ backtrace \
@@ -604,6 +606,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),) CFLAGS += -DHAVE_LIBBFD_SUPPORT endif +ifndef NO_ZLIB + ifeq ($(feature-zlib), 1) + CFLAGS += -DHAVE_ZLIB_SUPPORT + EXTLIBS += -lz + else + NO_ZLIB := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORT
tools/perf/config/feature-checks/Makefile +6 -2
@@ -29,7 +29,8 @@ FILES= \ test-timerfd.bin \ test-libdw-dwarf-unwind.bin \ test-compile-32.bin \ - test-compile-x32.bin + test-compile-x32.bin \ + test-zlib.bin CC := $(CROSS_COMPILE)gcc -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -41,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) ############################### test-all.bin: - $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl + $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz test-hello.bin: $(BUILD)
@@ -139,6 +140,9 @@ test-compile-32.bin: test-compile-x32.bin: $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c +test-zlib.bin: + $(BUILD) -lz + -include *.d ###############################
tools/perf/config/feature-checks/test-all.c +5 -0
@@ -93,6 +93,10 @@# include "test-sync-compare-and-swap.c" #undef main +#define main main_test_zlib +# include "test-zlib.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -116,6 +120,7 @@ int main(int argc, char *argv[])main_test_stackprotector_all ();main_test_libdw_dwarf_unwind ();main_test_sync_compare_and_swap (argc, argv); +main_test_zlib ();return 0 ; }
tools/perf/config/feature-checks/test-zlib.c new file +9 -0
@@ -0,0 +1,9 @@ +#include <zlib.h> + +int main (void ) +{ +z_stream zs; + +inflateInit (&zs); +return 0 ; +}
tools/perf/util/dso.c +4 -8
@@ -141,18 +141,14 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret; } -static int decompress_dummy (const char *input__maybe_unused , -int output__maybe_unused ) -{ -return -1 ; -} -static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, - {NULL , }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif + {NULL ,NULL }, };bool is_supported_compression (const char *ext)
tools/perf/util/util.h +5 -0
@@ -351,4 +351,9 @@ void mem_bswap_32(void *src, int byte_size);const char *get_filename_for_perf_kvm (void );bool find_process (const char *name); + +#ifdef HAVE_ZLIB_SUPPORT +int gzip_decompress_to_file (const char *input,int output_fd); +#endif +#endif /* GIT_COMPAT_UTIL_H */
tools/perf/util/zlib.c new file +78 -0
78 lines not on this page · raw message
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
In reply to Namhyung KimEm Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim escreveu:
Quoted 1 line
Now my Archlinux box shows module symbols correctly.
Now my RHEL6 box doesn't build:
Quoted 4 lines
+++
b/tools/perf/util/dso.ctools/perf/util/dso.c +0
-0@@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret;
tools/perf/util/dso.c int dso__read_binary_type_filename(const struct dso *dso, · line 151
Quoted 10 lines
tools/perf/util/dso.c +3
-1static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif {NULL , }, };
CC /tmp/build/perf/util/dso.o
cc1: warnings being treated as errorsutil/dso.c:151: error: missing initializer util/dso.c:151: error: (near initialization for ‘compressions[1].decompress’)
make[1]: *** [/tmp/build/perf/util/dso.o] Error 1
make: Leaving directory `/home/gita/perf-3.18.0-rc1/tools/perf'
make: *** [install] Error 2
[acme@zoo linux]$
Will try and fix it, nevermind :-)
- Arnaldo
Namhyung Kim
maintainerRe: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
Quoted 30 lines · Arnaldo Carvalho de Melo
Em Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim escreveu:
Quoted 1 line
Now my Archlinux box shows module symbols correctly.
Now my RHEL6 box doesn't build:
Quoted 4 lines
+++
b/tools/perf/util/dso.ctools/perf/util/dso.c +0
-0@@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,return ret;tools/perf/util/dso.c int dso__read_binary_type_filename(const struct dso *dso, · line 151
Quoted 10 lines
tools/perf/util/dso.c +3
-1static const struct {const char *fmt;int (*decompress)(const char *input,int output); } compressions[] = { - {"gz" , decompress_dummy }, +#ifdef HAVE_ZLIB_SUPPORT + {"gz" , gzip_decompress_to_file }, +#endif {NULL , }, };CC
/tmp/build/perf/util/dso.o
cc1: warnings being treated as errorsutil/dso.c:151: error: missing initializerutil/dso.c:151: error: (near initialization for ‘compressions[1].decompress’)
make[1]: *** [/tmp/build/perf/util/dso.o] Error 1
make: Leaving directory `/home/gita/perf-3.18.0-rc1/tools/perf'
make: *** [install] Error 2
[acme@zoo linux]$
Quoted 1 line
Will try and fix it, nevermind :-)
Also fixed and pushed to perf/vmlinux-v7 branch.
Thanks,
Namhyung
Namhyung Kim
maintainerPATCH 3/8 perf tools: Rename dsos__write_buildid_table()
In reply to Namhyung KimThe dsos__write_buildid_table() is not use struct dso and it mostly uses perf_session struct. So rename it to perf_session__write_buildid_ table() so that it corresponds to other related functions such as perf_session__read_build_ids() and perf_session__cache_build_ids().
--- tools/perf/util/header.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/header.c +2 -4
@@ -297,10 +297,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)return err; } -static int dsos__write_buildid_table (struct perf_header *header,int fd) +static int perf_session__write_buildid_table (struct perf_session *session,int fd) { -struct perf_session *session =container_of (header, - struct perf_session, header);struct rb_node *nd;int err =machine__write_buildid_table (&session->machines.host, fd);
@@ -523,7 +521,7 @@ static int write_build_id(int fd, struct perf_header *h,if (!perf_session__read_build_ids (session, true))return -1 ; - err =dsos__write_buildid_table (h, fd); + err =perf_session__write_buildid_table (session, fd);if (err <0 ) {pr_debug ("failed to write buildid table\n" );return err;
Signature · 1 line
2.1.2
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf build-id: Rename dsos__write_buildid_table()
perf build-id: Rename dsos__write_buildid_table()
Commit-ID: 714c9c4a98f722115e10d021ea80600f4427b71e Gitweb: http://git.kernel.org/tip/714c9c4a98f722115e10d021ea80600f4427b71e Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:29 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:14:07 -0300
perf build-id: Rename dsos__write_buildid_table()
The dsos__write_buildid_table() is not use struct dso and it mostly uses perf_session struct.
So rename it to perf_session__write_buildid_ table() so that it corresponds to other related functions such as perf_session__read_build_ids() and perf_session__cache_build_ids().
--- tools/perf/util/header.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/header.c +2 -4
@@ -297,10 +297,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)return err; } -static int dsos__write_buildid_table (struct perf_header *header,int fd) +static int perf_session__write_buildid_table (struct perf_session *session,int fd) { -struct perf_session *session =container_of (header, - struct perf_session, header);struct rb_node *nd;int err =machine__write_buildid_table (&session->machines.host, fd);
@@ -523,7 +521,7 @@ static int write_build_id(int fd, struct perf_header *h,if (!perf_session__read_build_ids (session, true))return -1 ; - err =dsos__write_buildid_table (h, fd); + err =perf_session__write_buildid_table (session, fd);if (err <0 ) {pr_debug ("failed to write buildid table\n" );return err;
Namhyung Kim
maintainerPATCH 4/8 perf build-id: Move build-id related functions to util/build-id.c
In reply to Namhyung KimIt'd be better managing those functions in a separate place as util/header.c file is already big.
It now exports following 3 functions to others:
bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); int perf_session__write_buildid_table(struct perf_session *session, int fd); int perf_session__cache_build_ids(struct perf_session *session);
--- tools/perf/util/build-id.c | 334 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/build-id.h | 11 ++ tools/perf/util/header.c | 337 +-------------------------------------------- tools/perf/util/header.h | 8 +- 4 files changed, 349 insertions(+), 341 deletions(-)
tools/perf/util/build-id.c +334 -0
@@ -15,6 +15,8 @@#include "debug.h" #include "session.h" #include "tool.h" +#include "header.h" +#include "vdso.h" int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event,
@@ -105,3 +107,335 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) build_id_hex, build_id_hex + 2);return bf; } + +#define dsos__for_each_with_build_id (pos, head) \ + list_for_each_entry(pos, head, node) \ + if (!pos->has_build_id) \ + continue; \ + else + +static int write_buildid (const char *name,size_t name_len,u8 *build_id, +pid_t pid,u16 misc,int fd) +{ +int err; +struct build_id_event b; +size_t len; + + len = name_len +1 ; + len =PERF_ALIGN (len,NAME_ALIGN ); + +memset (&b,0 ,sizeof (b)); +memcpy (&b.build_id, build_id,BUILD_ID_SIZE ); + b.pid = pid; + b.header.misc = misc; + b.header.size =sizeof (b) + len; + + err =writen (fd, &b,sizeof (b)); +if (err <0 ) +return err; + +return write_padded (fd, name, name_len +1 , len); +} + +static int __dsos__write_buildid_table (struct list_head *head, +struct machine *machine, +pid_t pid,u16 misc,int fd) +{ +char nm[PATH_MAX ]; +struct dso *pos; + +dsos__for_each_with_build_id (pos, head) { +int err; +const char *name; +size_t name_len; + +if (!pos->hit) +continue ; + +if (dso__is_vdso (pos)) { + name = pos->short_name; + name_len = pos->short_name_len +1 ; + }else if (dso__is_kcore (pos)) { +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + name_len =strlen (nm) +1 ; + }else { + name = pos->long_name; + name_len = pos->long_name_len +1 ; + } + + err =write_buildid (name, name_len, pos->build_id, + pid, misc, fd); +if (err) +return err; + } + +return 0 ; +} + +static int machine__write_buildid_table (struct machine *machine,int fd) +{ +int err; +u16 kmisc =PERF_RECORD_MISC_KERNEL , + umisc =PERF_RECORD_MISC_USER ; + +if (!machine__is_host (machine)) { + kmisc =PERF_RECORD_MISC_GUEST_KERNEL ; + umisc =PERF_RECORD_MISC_GUEST_USER ; + } + + err =__dsos__write_buildid_table (&machine->kernel_dsos.head, machine, + machine->pid, kmisc, fd); +if (err ==0 ) + err =__dsos__write_buildid_table (&machine->user_dsos.head, + machine, machine->pid, umisc, + fd); +return err; +} + +int perf_session__write_buildid_table (struct perf_session *session,int fd) +{ +struct rb_node *nd; +int err =machine__write_buildid_table (&session->machines.host, fd); + +if (err) +return err; + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + err =machine__write_buildid_table (pos, fd); +if (err) +break ; + } +return err; +} + +static int __dsos__hit_all (struct list_head *head) +{ +struct dso *pos; + +list_for_each_entry (pos, head, node) + pos->hit = true; + +return 0 ; +} + +static int machine__hit_all_dsos (struct machine *machine) +{ +int err; + + err =__dsos__hit_all (&machine->kernel_dsos.head); +if (err) +return err; + +return __dsos__hit_all (&machine->user_dsos.head); +} + +int dsos__hit_all (struct perf_session *session) +{ +struct rb_node *nd; +int err; + + err =machine__hit_all_dsos (&session->machines.host); +if (err) +return err; + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + + err =machine__hit_all_dsos (pos); +if (err) +return err; + } + +return 0 ; +} + +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, +const char *name,bool is_kallsyms,bool is_vdso) +{ +const size_t size =PATH_MAX ; +char *realname, *filename =zalloc (size), + *linkname =zalloc (size), *targetname; +int len, err =-1 ; +bool slash = is_kallsyms || is_vdso; + +if (is_kallsyms) { +if (symbol_conf.kptr_restrict) { +pr_debug ("Not caching a kptr_restrict'ed /proc/kallsyms\n" ); + err =0 ; + goto out_free; + } + realname = (char *) name; + }else + realname =realpath (name,NULL ); + +if (realname ==NULL || filename ==NULL || linkname ==NULL ) + goto out_free; + + len =scnprintf (filename, size,"%s%s%s" , + debugdir, slash ?"/" :"" , + is_vdso ?DSO__NAME_VDSO : realname); +if (mkdir_p (filename,0755 )) + goto out_free; + +snprintf (filename + len, size - len,"/%s" , sbuild_id); + +if (access (filename,F_OK )) { +if (is_kallsyms) { +if (copyfile ("/proc/kallsyms" , filename)) + goto out_free; + }else if (link (realname, filename) &©file (name, filename)) + goto out_free; + } + + len =scnprintf (linkname, size,"%s/.build-id/%.2s" , + debugdir, sbuild_id); + +if (access (linkname,X_OK ) &&mkdir_p (linkname,0755 )) + goto out_free; + +snprintf (linkname + len, size - len,"/%s" , sbuild_id +2 ); + targetname = filename +strlen (debugdir) -5 ; +memcpy (targetname,"../.." ,5 ); + +if (symlink (targetname, linkname) ==0 ) + err =0 ; +out_free: +if (!is_kallsyms) +free (realname); +free (filename); +free (linkname); +return err; +} + +static int build_id_cache__add_b (const u8 *build_id,size_t build_id_size, +const char *name,const char *debugdir, +bool is_kallsyms,bool is_vdso) +{ +char sbuild_id[BUILD_ID_SIZE *2 +1 ]; + +build_id__sprintf (build_id, build_id_size, sbuild_id); + +return build_id_cache__add_s (sbuild_id, debugdir, name, + is_kallsyms, is_vdso); +} + +int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir) +{ +const size_t size =PATH_MAX ; +char *filename =zalloc (size), + *linkname =zalloc (size); +int err =-1 ; + +if (filename ==NULL || linkname ==NULL ) + goto out_free; + +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, sbuild_id +2 ); + +if (access (linkname,F_OK )) + goto out_free; + +if (readlink (linkname, filename, size -1 ) <0 ) + goto out_free; + +if (unlink (linkname)) + goto out_free; + +/* +* Since the link is relative, we must make it absolute: +*/ +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, filename); + +if (unlink (linkname)) + goto out_free; + + err =0 ; +out_free: +free (filename); +free (linkname); +return err; +} + +static int dso__cache_build_id (struct dso *dso,struct machine *machine, +const char *debugdir) +{ +bool is_kallsyms = dso->kernel && dso->long_name[0 ] !='/' ; +bool is_vdso =dso__is_vdso (dso); +const char *name = dso->long_name; +char nm[PATH_MAX ]; + +if (dso__is_kcore (dso)) { + is_kallsyms = true; +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + } +return build_id_cache__add_b (dso->build_id,sizeof (dso->build_id), name, + debugdir, is_kallsyms, is_vdso); +} + +static int __dsos__cache_build_ids (struct list_head *head, +struct machine *machine,const char *debugdir) +{ +struct dso *pos; +int err =0 ; + +dsos__for_each_with_build_id (pos, head) +if (dso__cache_build_id (pos, machine, debugdir)) + err =-1 ; + +return err; +} + +static int machine__cache_build_ids (struct machine *machine,const char *debugdir) +{ +int ret =__dsos__cache_build_ids (&machine->kernel_dsos.head, machine, + debugdir); + ret |=__dsos__cache_build_ids (&machine->user_dsos.head, machine, + debugdir); +return ret; +} + +int perf_session__cache_build_ids (struct perf_session *session) +{ +struct rb_node *nd; +int ret; +char debugdir[PATH_MAX ]; + +snprintf (debugdir,sizeof (debugdir),"%s" , buildid_dir); + +if (mkdir (debugdir,0755 ) !=0 && errno !=EEXIST ) +return -1 ; + + ret =machine__cache_build_ids (&session->machines.host, debugdir); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__cache_build_ids (pos, debugdir); + } +return ret ?-1 :0 ; +} + +static bool machine__read_build_ids (struct machine *machine,bool with_hits) +{ +bool ret; + + ret =__dsos__read_build_ids (&machine->kernel_dsos.head, with_hits); + ret |=__dsos__read_build_ids (&machine->user_dsos.head, with_hits); +return ret; +} + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits) +{ +struct rb_node *nd; +bool ret =machine__read_build_ids (&session->machines.host, with_hits); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__read_build_ids (pos, with_hits); + } + +return ret; +}
tools/perf/util/build-id.h +11 -0
@@ -15,4 +15,15 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);int build_id__mark_dso_hit (struct perf_tool *tool,union perf_event *event,struct perf_sample *sample,struct perf_evsel *evsel,struct machine *machine); + +int dsos__hit_all (struct perf_session *session); + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits); +int perf_session__write_buildid_table (struct perf_session *session,int fd); +int perf_session__cache_build_ids (struct perf_session *session); + +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, +const char *name,bool is_kallsyms,bool is_vdso); +int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); +#endif
tools/perf/util/header.c +1 -336
349 lines not on this page · raw message
tools/perf/util/header.h +3 -5
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,int perf_header__fprintf_info (struct perf_session *s,FILE *fp,bool full); -int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, -const char *name,bool is_kallsyms,bool is_vdso); -int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); -int perf_event__synthesize_attr (struct perf_tool *tool,struct perf_event_attr *attr,u32 ids,u64 *id,perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session);bool is_perf_magic (u64 magic); -int dsos__hit_all (struct perf_session *session); +#define NAME_ALIGN 64 + +int write_padded (int fd,const void *bf,size_t count,size_t count_aligned);/* * arch specific callback
Signature · 1 line
2.1.2
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf build-id: Move build-id related functions to util/build-id.c
perf build-id: Move build-id related functions to util/build-id.c
Commit-ID: e195fac8077f034b0160bf420bdf450ae476701d Gitweb: http://git.kernel.org/tip/e195fac8077f034b0160bf420bdf450ae476701d Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:30 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:14:07 -0300
perf build-id: Move build-id related functions to util/build-id.c
It'd be better managing those functions in a separate place as util/header.c file is already big.
It now exports following 3 functions to others:
bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); int perf_session__write_buildid_table(struct perf_session *session, int fd); int perf_session__cache_build_ids(struct perf_session *session);
--- tools/perf/util/build-id.c | 334 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/build-id.h | 11 ++ tools/perf/util/header.c | 337 +-------------------------------------------- tools/perf/util/header.h | 8 +- 4 files changed, 349 insertions(+), 341 deletions(-)
tools/perf/util/build-id.c +334 -0
@@ -15,6 +15,8 @@#include "debug.h" #include "session.h" #include "tool.h" +#include "header.h" +#include "vdso.h" int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event,
@@ -105,3 +107,335 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) build_id_hex, build_id_hex + 2);return bf; } + +#define dsos__for_each_with_build_id (pos, head) \ + list_for_each_entry(pos, head, node) \ + if (!pos->has_build_id) \ + continue; \ + else + +static int write_buildid (const char *name,size_t name_len,u8 *build_id, +pid_t pid,u16 misc,int fd) +{ +int err; +struct build_id_event b; +size_t len; + + len = name_len +1 ; + len =PERF_ALIGN (len,NAME_ALIGN ); + +memset (&b,0 ,sizeof (b)); +memcpy (&b.build_id, build_id,BUILD_ID_SIZE ); + b.pid = pid; + b.header.misc = misc; + b.header.size =sizeof (b) + len; + + err =writen (fd, &b,sizeof (b)); +if (err <0 ) +return err; + +return write_padded (fd, name, name_len +1 , len); +} + +static int __dsos__write_buildid_table (struct list_head *head, +struct machine *machine, +pid_t pid,u16 misc,int fd) +{ +char nm[PATH_MAX ]; +struct dso *pos; + +dsos__for_each_with_build_id (pos, head) { +int err; +const char *name; +size_t name_len; + +if (!pos->hit) +continue ; + +if (dso__is_vdso (pos)) { + name = pos->short_name; + name_len = pos->short_name_len +1 ; + }else if (dso__is_kcore (pos)) { +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + name_len =strlen (nm) +1 ; + }else { + name = pos->long_name; + name_len = pos->long_name_len +1 ; + } + + err =write_buildid (name, name_len, pos->build_id, + pid, misc, fd); +if (err) +return err; + } + +return 0 ; +} + +static int machine__write_buildid_table (struct machine *machine,int fd) +{ +int err; +u16 kmisc =PERF_RECORD_MISC_KERNEL , + umisc =PERF_RECORD_MISC_USER ; + +if (!machine__is_host (machine)) { + kmisc =PERF_RECORD_MISC_GUEST_KERNEL ; + umisc =PERF_RECORD_MISC_GUEST_USER ; + } + + err =__dsos__write_buildid_table (&machine->kernel_dsos.head, machine, + machine->pid, kmisc, fd); +if (err ==0 ) + err =__dsos__write_buildid_table (&machine->user_dsos.head, + machine, machine->pid, umisc, + fd); +return err; +} + +int perf_session__write_buildid_table (struct perf_session *session,int fd) +{ +struct rb_node *nd; +int err =machine__write_buildid_table (&session->machines.host, fd); + +if (err) +return err; + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + err =machine__write_buildid_table (pos, fd); +if (err) +break ; + } +return err; +} + +static int __dsos__hit_all (struct list_head *head) +{ +struct dso *pos; + +list_for_each_entry (pos, head, node) + pos->hit = true; + +return 0 ; +} + +static int machine__hit_all_dsos (struct machine *machine) +{ +int err; + + err =__dsos__hit_all (&machine->kernel_dsos.head); +if (err) +return err; + +return __dsos__hit_all (&machine->user_dsos.head); +} + +int dsos__hit_all (struct perf_session *session) +{ +struct rb_node *nd; +int err; + + err =machine__hit_all_dsos (&session->machines.host); +if (err) +return err; + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + + err =machine__hit_all_dsos (pos); +if (err) +return err; + } + +return 0 ; +} + +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, +const char *name,bool is_kallsyms,bool is_vdso) +{ +const size_t size =PATH_MAX ; +char *realname, *filename =zalloc (size), + *linkname =zalloc (size), *targetname; +int len, err =-1 ; +bool slash = is_kallsyms || is_vdso; + +if (is_kallsyms) { +if (symbol_conf.kptr_restrict) { +pr_debug ("Not caching a kptr_restrict'ed /proc/kallsyms\n" ); + err =0 ; + goto out_free; + } + realname = (char *) name; + }else + realname =realpath (name,NULL ); + +if (realname ==NULL || filename ==NULL || linkname ==NULL ) + goto out_free; + + len =scnprintf (filename, size,"%s%s%s" , + debugdir, slash ?"/" :"" , + is_vdso ?DSO__NAME_VDSO : realname); +if (mkdir_p (filename,0755 )) + goto out_free; + +snprintf (filename + len, size - len,"/%s" , sbuild_id); + +if (access (filename,F_OK )) { +if (is_kallsyms) { +if (copyfile ("/proc/kallsyms" , filename)) + goto out_free; + }else if (link (realname, filename) &©file (name, filename)) + goto out_free; + } + + len =scnprintf (linkname, size,"%s/.build-id/%.2s" , + debugdir, sbuild_id); + +if (access (linkname,X_OK ) &&mkdir_p (linkname,0755 )) + goto out_free; + +snprintf (linkname + len, size - len,"/%s" , sbuild_id +2 ); + targetname = filename +strlen (debugdir) -5 ; +memcpy (targetname,"../.." ,5 ); + +if (symlink (targetname, linkname) ==0 ) + err =0 ; +out_free: +if (!is_kallsyms) +free (realname); +free (filename); +free (linkname); +return err; +} + +static int build_id_cache__add_b (const u8 *build_id,size_t build_id_size, +const char *name,const char *debugdir, +bool is_kallsyms,bool is_vdso) +{ +char sbuild_id[BUILD_ID_SIZE *2 +1 ]; + +build_id__sprintf (build_id, build_id_size, sbuild_id); + +return build_id_cache__add_s (sbuild_id, debugdir, name, + is_kallsyms, is_vdso); +} + +int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir) +{ +const size_t size =PATH_MAX ; +char *filename =zalloc (size), + *linkname =zalloc (size); +int err =-1 ; + +if (filename ==NULL || linkname ==NULL ) + goto out_free; + +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, sbuild_id +2 ); + +if (access (linkname,F_OK )) + goto out_free; + +if (readlink (linkname, filename, size -1 ) <0 ) + goto out_free; + +if (unlink (linkname)) + goto out_free; + +/* +* Since the link is relative, we must make it absolute: +*/ +snprintf (linkname, size,"%s/.build-id/%.2s/%s" , + debugdir, sbuild_id, filename); + +if (unlink (linkname)) + goto out_free; + + err =0 ; +out_free: +free (filename); +free (linkname); +return err; +} + +static int dso__cache_build_id (struct dso *dso,struct machine *machine, +const char *debugdir) +{ +bool is_kallsyms = dso->kernel && dso->long_name[0 ] !='/' ; +bool is_vdso =dso__is_vdso (dso); +const char *name = dso->long_name; +char nm[PATH_MAX ]; + +if (dso__is_kcore (dso)) { + is_kallsyms = true; +machine__mmap_name (machine, nm,sizeof (nm)); + name = nm; + } +return build_id_cache__add_b (dso->build_id,sizeof (dso->build_id), name, + debugdir, is_kallsyms, is_vdso); +} + +static int __dsos__cache_build_ids (struct list_head *head, +struct machine *machine,const char *debugdir) +{ +struct dso *pos; +int err =0 ; + +dsos__for_each_with_build_id (pos, head) +if (dso__cache_build_id (pos, machine, debugdir)) + err =-1 ; + +return err; +} + +static int machine__cache_build_ids (struct machine *machine,const char *debugdir) +{ +int ret =__dsos__cache_build_ids (&machine->kernel_dsos.head, machine, + debugdir); + ret |=__dsos__cache_build_ids (&machine->user_dsos.head, machine, + debugdir); +return ret; +} + +int perf_session__cache_build_ids (struct perf_session *session) +{ +struct rb_node *nd; +int ret; +char debugdir[PATH_MAX ]; + +snprintf (debugdir,sizeof (debugdir),"%s" , buildid_dir); + +if (mkdir (debugdir,0755 ) !=0 && errno !=EEXIST ) +return -1 ; + + ret =machine__cache_build_ids (&session->machines.host, debugdir); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__cache_build_ids (pos, debugdir); + } +return ret ?-1 :0 ; +} + +static bool machine__read_build_ids (struct machine *machine,bool with_hits) +{ +bool ret; + + ret =__dsos__read_build_ids (&machine->kernel_dsos.head, with_hits); + ret |=__dsos__read_build_ids (&machine->user_dsos.head, with_hits); +return ret; +} + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits) +{ +struct rb_node *nd; +bool ret =machine__read_build_ids (&session->machines.host, with_hits); + +for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |=machine__read_build_ids (pos, with_hits); + } + +return ret; +}
tools/perf/util/build-id.h +11 -0
@@ -15,4 +15,15 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);int build_id__mark_dso_hit (struct perf_tool *tool,union perf_event *event,struct perf_sample *sample,struct perf_evsel *evsel,struct machine *machine); + +int dsos__hit_all (struct perf_session *session); + +bool perf_session__read_build_ids (struct perf_session *session,bool with_hits); +int perf_session__write_buildid_table (struct perf_session *session,int fd); +int perf_session__cache_build_ids (struct perf_session *session); + +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, +const char *name,bool is_kallsyms,bool is_vdso); +int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); +#endif
tools/perf/util/header.c +1 -336
349 lines not on this page · raw message
tools/perf/util/header.h +3 -5
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,int perf_header__fprintf_info (struct perf_session *s,FILE *fp,bool full); -int build_id_cache__add_s (const char *sbuild_id,const char *debugdir, -const char *name,bool is_kallsyms,bool is_vdso); -int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); -int perf_event__synthesize_attr (struct perf_tool *tool,struct perf_event_attr *attr,u32 ids,u64 *id,perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool, struct perf_session *session);bool is_perf_magic (u64 magic); -int dsos__hit_all (struct perf_session *session); +#define NAME_ALIGN 64 + +int write_padded (int fd,const void *bf,size_t count,size_t count_aligned);/* * arch specific callback
Namhyung Kim
maintainerPATCH 5/8 perf tools: Move disable_buildid_cache() to util/build-id.c
In reply to Namhyung KimAlso move static variable no_buildid_cache and check it in the perf_session_cache_build_ids().
--- tools/perf/util/build-id.c | 11 +++++++++++ tools/perf/util/build-id.h | 1 + tools/perf/util/header.c | 10 +--------- tools/perf/util/util.h | 1 - 4 files changed, 13 insertions(+), 10 deletions(-)
tools/perf/util/build-id.c +11 -0
@@ -18,6 +18,9 @@#include "header.h" #include "vdso.h" + +static bool no_buildid_cache; + int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample,
@@ -251,6 +254,11 @@ int dsos__hit_all(struct perf_session *session)return 0 ; } +void disable_buildid_cache (void ) +{ + no_buildid_cache = true; +} +int build_id_cache__add_s (const char *sbuild_id,const char *debugdir,const char *name,bool is_kallsyms,bool is_vdso) {
@@ -404,6 +412,9 @@ int perf_session__cache_build_ids(struct perf_session *session)int ret;char debugdir[PATH_MAX ]; +if (no_buildid_cache) +return 0 ; +snprintf (debugdir,sizeof (debugdir),"%s" , buildid_dir);if (mkdir (debugdir,0755 ) !=0 && errno !=EEXIST )
tools/perf/util/build-id.h +1 -0
@@ -25,5 +25,6 @@ int perf_session__cache_build_ids(struct perf_session *session);int build_id_cache__add_s (const char *sbuild_id,const char *debugdir,const char *name,bool is_kallsyms,bool is_vdso);int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); +void disable_buildid_cache (void );#endif
tools/perf/util/header.c +1 -9
@@ -24,8 +24,6 @@#include "build-id.h" #include "data.h" -static bool no_buildid_cache = false; -static u32 header_argc;static const char **header_argv;
@@ -191,8 +189,7 @@ static int write_build_id(int fd, struct perf_header *h,pr_debug ("failed to write buildid table\n" );return err; } -if (!no_buildid_cache) -perf_session__cache_build_ids (session); +perf_session__cache_build_ids (session);return 0 ; }
@@ -2790,8 +2787,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, session);return 0 ; } - -void disable_buildid_cache (void ) -{ - no_buildid_cache = true; -}
tools/perf/util/util.h +0 -1
@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NORextern int prefixcmp (const char *str,const char *prefix);extern void set_buildid_dir (void ); -extern void disable_buildid_cache (void );static inline const char *skip_prefix (const char *str,const char *prefix) {
Signature · 1 line
2.1.2
Namhyung Kim
maintainerPATCH 6/8 perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
In reply to Namhyung KimWhen perf record finishes a session recording, it then pre-process samples in order to write build-id info from actually used DSOs. During this process it'll call map__load() for kernel map, and it ends up calling dso__load_vmlinux_path() which replaces dso->long_name.
But this function checks kernel's build-id before searching vmlinux path so it'll have the cryptic name which can be confusing to users IMHO.
This patch adds a flag to skip the build-id check during record, so it'll have a vmlinux path for the kernel dso->long_name.
Before:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.196 MB perf.data (~8545 samples) ] Looking at the vmlinux_path (7 entries long) Using /home/namhyung/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 for symbols
After:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.193 MB perf.data (~8432 samples) ] Looking at the vmlinux_path (7 entries long) Using /lib/modules/3.16.4-1-ARCH/build/vmlinux for symbols
--- tools/perf/builtin-record.c | 11 +++++++++++ tools/perf/util/symbol.c | 11 ++++++----- tools/perf/util/symbol.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +11 -0
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)if (size ==0 )return 0 ; +/* +* During this process, it'll load kernel map and replace the +* dso->long_name to a real pathname it found. In this case +* we prefer the vmlinux path like +* /lib/modules/3.16.4/build/vmlinux +* +* rather than build-id path (in debug directory). +* $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 +*/ + symbol_conf.ignore_vmlinux_buildid = true; +return __perf_session__process_events (session, start, size - start, size, &build_id__mark_dso_hit_ops);
tools/perf/util/symbol.c +6 -5
@@ -1511,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, symbol_filter_t filter) {int i, err =0 ; -char *filename; +char *filename =NULL ; -pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , - vmlinux_path__nr_entries +1 ); - - filename =dso__build_id_filename (dso,NULL ,0 ); +if (!symbol_conf.ignore_vmlinux_buildid) + filename =dso__build_id_filename (dso,NULL ,0 );if (filename !=NULL ) { err =dso__load_vmlinux (dso, map, filename, true, filter);if (err >0 )
@@ -1524,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,free (filename); } +pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , + vmlinux_path__nr_entries +1 ); +for (i =0 ; i < vmlinux_path__nr_entries; ++i) { err =dso__load_vmlinux (dso, map, vmlinux_path[i], false, filter);if (err >0 )
tools/perf/util/symbol.h +1 -0
@@ -105,6 +105,7 @@ struct symbol_conf {unsigned short nr_events;bool try_vmlinux_path, ignore_vmlinux, + ignore_vmlinux_buildid, show_kernel_path, use_modules, sort_by_name,
Signature · 1 line
2.1.2
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
Em Tue, Nov 04, 2014 at 10:14:32AM +0900, Namhyung Kim escreveu:
Quoted 4 lines
When perf record finishes a session recording, it then pre-process samples in order to write build-id info from actually used DSOs. During this process it'll call
map__load()for kernel map, and it ends up callingdso__load_vmlinux_path()which replacesdso->long_name.
Can't we achieve the same end result without introducing yet another symbol_conf entry?
I think there are way too many there, we need to remove, not add :-\
I'll add this since it improve the end result, but if you don't beat me to it I'll try to remove this symbol_conf entry while keeping the end result you achieved with it.
- Arnaldo
Quoted 96 lines
But this function checks kernel's build-id before searching vmlinux path so it'll have the cryptic name which can be confusing to users IMHO.
This patch adds a flag to skip the build-id check during record, so it'll have a vmlinux path for the kernel
dso->long_name.Before:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.196 MB perf.data (~8545 samples) ] Looking at the vmlinux_path (7 entries long) Using /home/namhyung/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 for symbolsAfter:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.193 MB perf.data (~8432 samples) ] Looking at the vmlinux_path (7 entries long) Using /lib/modules/3.16.4-1-ARCH/build/vmlinux for symbolsCc Adrian Hunter <[email protected]>Signed-off-by Namhyung Kim <[email protected]>--- tools/perf/builtin-record.c | 11 +++++++++++ tools/perf/util/symbol.c | 11 ++++++----- tools/perf/util/symbol.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-)tools/perf/builtin-record.c +11
-0@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)if (size ==0 )return 0 ; +/* +* During this process, it'll load kernel map and replace the +* dso->long_name to a real pathname it found. In this case +* we prefer the vmlinux path like +* /lib/modules/3.16.4/build/vmlinux +* +* rather than build-id path (in debug directory). +* $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 +*/ + symbol_conf.ignore_vmlinux_buildid = true; +return __perf_session__process_events (session, start, size - start, size, &build_id__mark_dso_hit_ops);tools/perf/util/symbol.c +6
-5@@ -1511,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, symbol_filter_t filter) {int i, err =0 ; -char *filename; +char *filename =NULL ; -pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , - vmlinux_path__nr_entries +1 ); - - filename =dso__build_id_filename (dso,NULL ,0 ); +if (!symbol_conf.ignore_vmlinux_buildid) + filename =dso__build_id_filename (dso,NULL ,0 );if (filename !=NULL ) { err =dso__load_vmlinux (dso, map, filename, true, filter);if (err >0 )@@ -1524,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,free (filename); } +pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , + vmlinux_path__nr_entries +1 ); +for (i =0 ; i < vmlinux_path__nr_entries; ++i) { err =dso__load_vmlinux (dso, map, vmlinux_path[i], false, filter);if (err >0 )tools/perf/util/symbol.h +1
-0@@ -105,6 +105,7 @@ struct symbol_conf {unsigned short nr_events;bool try_vmlinux_path, ignore_vmlinux, + ignore_vmlinux_buildid, show_kernel_path, use_modules, sort_by_name,Signature · 1 line
2.1.2
Namhyung Kim
maintainerRe: [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
Hi Arnaldo,
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Tue, Nov 04, 2014 at 10:14:32AM +0900, Namhyung Kim escreveu:
Quoted 4 lines
When perf record finishes a session recording, it then pre-process samples in order to write build-id info from actually used DSOs. During this process it'll call
map__load()for kernel map, and it ends up callingdso__load_vmlinux_path()which replacesdso->long_name.Can't we achieve the same end result without introducing yet another
symbol_confentry?I think there are way too many there, we need to remove, not add :-\
Agreed.
I also wanted to do it without a new entry, but failed to find a good way of it as it's a common code called both from record and report path and lives in a deep inside of sample processing.
Quoted 4 lines
I'll add this since it improve the end result, but if you don't beat me to it I'll try to remove this
symbol_confentry while keeping the end result you achieved with it.
It'd be really appreciated!
Thanks,
Namhyung
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf record: Do not save pathname in ./debug/ .build-id directory for vmlinux
In reply to Namhyung Kimperf record: Do not save pathname in ./debug/.build-id directory for vmlinux
Commit-ID: 00dc865798a31d3d5300dd5d70166a4a85f76a20 Gitweb: http://git.kernel.org/tip/00dc865798a31d3d5300dd5d70166a4a85f76a20 Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:32 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:14:08 -0300
perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
When perf record finishes a session, it pre-processes samples in order to write build-id info from DSOs that had samples.
During this process it'll call map__load() for the kernel map, and it ends up calling dso__load_vmlinux_path() which replaces dso->long_name.
But this function checks kernel's build-id before searching vmlinux path so it'll end up with a cryptic name, the pathname for the entry in the ~/.debug cache, which can be confusing to users.
This patch adds a flag to skip the build-id check during record, so that it'll have the original vmlinux path for the kernel dso->long_name, not the entry in the ~/.debug cache.
Before:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.196 MB perf.data (~8545 samples) ] Looking at the vmlinux_path (7 entries long) Using /home/namhyung/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 for symbols
After:
# perf record -va sleep 3 mmap size 528384B [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.193 MB perf.data (~8432 samples) ] Looking at the vmlinux_path (7 entries long) Using /lib/modules/3.16.4-1-ARCH/build/vmlinux for symbols
--- tools/perf/builtin-record.c | 11 +++++++++++ tools/perf/util/symbol.c | 11 ++++++----- tools/perf/util/symbol.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +11 -0
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)if (size ==0 )return 0 ; +/* +* During this process, it'll load kernel map and replace the +* dso->long_name to a real pathname it found. In this case +* we prefer the vmlinux path like +* /lib/modules/3.16.4/build/vmlinux +* +* rather than build-id path (in debug directory). +* $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 +*/ + symbol_conf.ignore_vmlinux_buildid = true; +return __perf_session__process_events (session, start, size - start, size, &build_id__mark_dso_hit_ops);
tools/perf/util/symbol.c +6 -5
@@ -1511,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, symbol_filter_t filter) {int i, err =0 ; -char *filename; +char *filename =NULL ; -pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , - vmlinux_path__nr_entries +1 ); - - filename =dso__build_id_filename (dso,NULL ,0 ); +if (!symbol_conf.ignore_vmlinux_buildid) + filename =dso__build_id_filename (dso,NULL ,0 );if (filename !=NULL ) { err =dso__load_vmlinux (dso, map, filename, true, filter);if (err >0 )
@@ -1524,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,free (filename); } +pr_debug ("Looking at the vmlinux_path (%d entries long)\n" , + vmlinux_path__nr_entries +1 ); +for (i =0 ; i < vmlinux_path__nr_entries; ++i) { err =dso__load_vmlinux (dso, map, vmlinux_path[i], false, filter);if (err >0 )
tools/perf/util/symbol.h +1 -0
@@ -105,6 +105,7 @@ struct symbol_conf {unsigned short nr_events;bool try_vmlinux_path, ignore_vmlinux, + ignore_vmlinux_buildid, show_kernel_path, use_modules, sort_by_name,
Namhyung Kim
maintainerPATCH 7/8 perf tools: Fix build-id matching on vmlinux
In reply to Namhyung KimThere's a problem on finding correct kernel symbols when perf report runs on a different kernel. Although a part of the problem was solved by the prior commit 0a7e6d1b6844 ("perf tools: Check recorded kernel version when finding vmlinux"), there's a remaining problem still.
When perf records samples, it synthesizes the kernel map using machine__mmap_name() and ref_reloc_sym like "[kernel.kallsyms]_text". You can easily see it using 'perf report -D' command.
After finishing record, it goes through the recorded events to find maps/dsos actually used. And then record build-id info of them.
During this process, it needs to load symbols in a dso and it'd call dso__load_vmlinux_path() since the default value of the symbol_conf. try_vmlinux_path is true. However it changes dso->long_name to a real path of the vmlinux file (e.g. /lib/modules/3.16.4/build/vmlinux) if one is running on a custom kernel.
It resulted in that perf report reads the build-id of the vmlinux, but cannot use it since it only knows about the [kernel.kallsyms] map. It then falls back to possible vmlinux paths by using the recorded kernel version (in case of a recent version) or a running kernel silently.
Even with the recent tools, this still has a possibility of breaking the result. As the build directory is a symbolic link, if one built a new kernel in the same directory with different source/config, the old link to vmlinux will point the new file. So it's absolutely needed to use build-id when finding a kernel image.
In this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper vmlinux [k] cpu_startup_entry
72.15% 0.00% swapper vmlinux [k] arch_cpu_idle
72.15% 0.00% swapper vmlinux [k] default_idle
71.87% 71.87% swapper vmlinux [k] native_safe_halt...
--- tools/perf/util/header.c | 2 +- tools/perf/util/machine.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/header.c +1 -1
@@ -1266,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,dso__set_build_id (dso, &bev->build_id); -if (filename[0 ] =='[' ) +if (!is_kernel_module (filename,NULL )) dso->kernel = dso_type; build_id__sprintf(dso->build_id, sizeof(dso->build_id),
tools/perf/util/machine.c +14 -2
@@ -1085,8 +1085,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos.head, node) { +if (is_kernel_module (dso->long_name,NULL )) +continue ; + + kernel = dso; +break ; + } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);if (kernel ==NULL ) goto out_problem;
Signature · 1 line
2.1.2
tip-bot for Namhyung Kim
merge botperf tools: Fix build-id matching on vmlinux
Commit-ID: b837a8bdc48925e6512412973b845c53cbe2b412 Gitweb: http://git.kernel.org/tip/b837a8bdc48925e6512412973b845c53cbe2b412 Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:33 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:14:08 -0300
perf tools: Fix build-id matching on vmlinux
There's a problem on finding correct kernel symbols when perf report runs on a different kernel. Although a part of the problem was solved by the prior commit 0a7e6d1b6844 ("perf tools: Check recorded kernel version when finding vmlinux"), there's a remaining problem still.
When perf records samples, it synthesizes the kernel map using machine__mmap_name() and ref_reloc_sym like "[kernel.kallsyms]_text". You can easily see it using 'perf report -D' command.
After finishing record, it goes through the recorded events to find maps/dsos actually used. And then record build-id info of them.
During this process, it needs to load symbols in a dso and it'd call dso__load_vmlinux_path() since the default value of the symbol_conf. try_vmlinux_path is true. However it changes dso->long_name to a real path of the vmlinux file (e.g. /lib/modules/3.16.4/build/vmlinux) if one is running on a custom kernel.
It resulted in that perf report reads the build-id of the vmlinux, but cannot use it since it only knows about the [kernel.kallsyms] map. It then falls back to possible vmlinux paths by using the recorded kernel version (in case of a recent version) or a running kernel silently.
Even with the recent tools, this still has a possibility of breaking the result. As the build directory is a symbolic link, if one built a new kernel in the same directory with different source/config, the old link to vmlinux will point the new file. So it's absolutely needed to use build-id when finding a kernel image.
In this patch, it's now changed to try to search a kernel dso in the existing dso list which was constructed during build-id table parsing so it'll always have a build-id. If not found, search "[kernel.kallsyms]".
Before:
$ perf report
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ...............................
#
72.15% 0.00% swapper [kernel.kallsyms] [k] set_curr_task_rt
72.15% 0.00% swapper [kernel.kallsyms] [k] native_calibrate_tsc
72.15% 0.00% swapper [kernel.kallsyms] [k] tsc_refine_calibration_work
71.87% 71.87% swapper [kernel.kallsyms] [k] module_finalize
...After (for the same perf.data):
72.15% 0.00% swapper vmlinux [k] cpu_startup_entry
72.15% 0.00% swapper vmlinux [k] arch_cpu_idle
72.15% 0.00% swapper vmlinux [k] default_idle
71.87% 71.87% swapper vmlinux [k] native_safe_halt...
--- tools/perf/util/header.c | 2 +- tools/perf/util/machine.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/header.c +1 -1
@@ -1269,7 +1269,7 @@ static int __event_process_build_id(struct build_id_event *bev,dso__set_build_id (dso, &bev->build_id); -if (filename[0 ] =='[' ) +if (!is_kernel_module (filename,NULL )) dso->kernel = dso_type; build_id__sprintf(dso->build_id, sizeof(dso->build_id),
tools/perf/util/machine.c +14 -2
@@ -1085,8 +1085,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,* Should be there already, from the build-id table in * the header. */ -struct dso *kernel =__dsos__findnew (&machine->kernel_dsos, - kmmap_prefix); +struct dso *kernel =NULL ; +struct dso *dso; + +list_for_each_entry (dso, &machine->kernel_dsos.head, node) { +if (is_kernel_module (dso->long_name,NULL )) +continue ; + + kernel = dso; +break ; + } + +if (kernel ==NULL ) + kernel =__dsos__findnew (&machine->kernel_dsos, + kmmap_prefix);if (kernel ==NULL ) goto out_problem;
Namhyung Kim
maintainerPATCH 8/8 perf tools: Make vmlinux short name more like kallsyms short name
In reply to Namhyung KimThe previous patch changed kernel dso name from '[kernel.kallsyms]' to vmlinux. However it might add confusion to old users accustomed to the old name. So change the short name to '[kernel.vmlinux]' to reduce such confusion.
Before:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper vmlinux [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper vmlinux [k] cpuidle_enter_state
1.03% sleep vmlinux [k] copy_user_generic_unrolledAfter:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper [kernel.vmlinux] [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper [kernel.vmlinux] [k] cpuidle_enter_state
1.03% sleep [kernel.vmlinux] [k] copy_user_generic_unrolled--- tools/perf/util/machine.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/machine.c +3 -0
@@ -1106,6 +1106,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,if (__machine__create_kernel_maps (machine, kernel) <0 ) goto out_problem; +if (strstr (dso->long_name,"vmlinux" )) +dso__set_short_name (dso,"[kernel.vmlinux]" , false); +machine__set_kernel_mmap_len (machine, event);/*
Signature · 1 line
2.1.2
tip-bot for Namhyung Kim
merge bot[tip:perf/core] perf tools: Make vmlinux short name more like kallsyms short name
perf tools: Make vmlinux short name more like kallsyms short name
Commit-ID: 96d78059d6d9da45d77078a219924304860497f2 Gitweb: http://git.kernel.org/tip/96d78059d6d9da45d77078a219924304860497f2 Author: Namhyung Kim <[email protected]> AuthorDate: Tue, 4 Nov 2014 10:14:34 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 5 Nov 2014 10:14:09 -0300
perf tools: Make vmlinux short name more like kallsyms short name
The previous patch changed kernel dso name from '[kernel.kallsyms]' to vmlinux. However it might add confusion to old users accustomed to the old name. So change the short name to '[kernel.vmlinux]' to reduce such confusion.
Before:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper vmlinux [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper vmlinux [k] cpuidle_enter_state
1.03% sleep vmlinux [k] copy_user_generic_unrolledAfter:
# Overhead Command Shared Object Symbol
# ........ .............. ....................... ...............................
#
9.83% swapper [kernel.vmlinux] [k] intel_idle
4.10% awk libc-2.20.so [.] __strcmp_sse2
1.86% sed libc-2.20.so [.] __strcmp_sse2
1.78% netctl-auto libc-2.20.so [.] __strcmp_sse2
1.23% netctl-auto libc-2.20.so [.] __mbrtowc
1.21% firefox libxul.so [.] 0x00000000024b62bd
1.20% swapper [kernel.vmlinux] [k] cpuidle_enter_state
1.03% sleep [kernel.vmlinux] [k] copy_user_generic_unrolled--- tools/perf/util/machine.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/machine.c +3 -0
@@ -1106,6 +1106,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,if (__machine__create_kernel_maps (machine, kernel) <0 ) goto out_problem; +if (strstr (dso->long_name,"vmlinux" )) +dso__set_short_name (dso,"[kernel.vmlinux]" , false); +machine__set_kernel_mmap_len (machine, event);/*