linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4] perf tools: Fix build-id matching on vmlinux
@ 2014-09-22  8:04 Namhyung Kim
  2014-09-24  7:33 ` Ingo Molnar
  0 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-09-22  8:04 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, David Ahern, Adrian Hunter,
	Stephane Eranian, Andi Kleen, stable

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
   ...

Cc: stable@vger.kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/machine.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b2ec38bf211e..5661195a8cf6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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;
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v4] perf tools: Fix build-id matching on vmlinux
  2014-09-22  8:04 [PATCH v4] perf tools: Fix build-id matching on vmlinux Namhyung Kim
@ 2014-09-24  7:33 ` Ingo Molnar
  2014-09-29  4:45   ` Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Ingo Molnar @ 2014-09-24  7:33 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Namhyung Kim, LKML, Jiri Olsa, David Ahern, Adrian Hunter,
	Stephane Eranian, Andi Kleen, stable


* Namhyung Kim <namhyung@kernel.org> wrote:

> 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
>    ...
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/util/machine.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> index b2ec38bf211e..5661195a8cf6 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -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);

Please don't break the line just to pacify checkpatch.pl. Other 
than that:

Acked-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ing

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v4] perf tools: Fix build-id matching on vmlinux
  2014-09-24  7:33 ` Ingo Molnar
@ 2014-09-29  4:45   ` Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-09-29  4:45 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Paul Mackerras,
	Namhyung Kim, LKML, Jiri Olsa, David Ahern, Adrian Hunter,
	Stephane Eranian, Andi Kleen, stable

Hi Ingo and Arnaldo,

On Wed, 24 Sep 2014 09:33:56 +0200, Ingo Molnar wrote:
> * Namhyung Kim <namhyung@kernel.org> wrote:
>> @@ -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;
>> +			}

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.


>> +		}
>> +
>> +		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. :)


>
> Acked-by: Ingo Molnar <mingo@kernel.org>

Thanks anyway! :)

Namhyung

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5)
@ 2014-11-03  7:27 Namhyung Kim
  2014-11-03  7:27 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
                   ` (7 more replies)
  0 siblings, 8 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_halt


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]".

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


Cc: Adrian Hunter <adrian.hunter@intel.com>


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

-- 
2.1.2


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH 1/8] perf tools: Preparation for compressed kernel module support
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03 13:51   ` Jiri Olsa
  2014-11-03  7:27 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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 <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0247acfdfaca..3293e2e21814 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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.
  */
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index a316e4af321f..3782c82c6e44 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -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:
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 51a630301afa..946c7d62cb6e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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, '-', '_');
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 1e23a5bfb044..efc7eb6b8f0f 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -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;
 
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 078331140d8c..c69915c9d5bc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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.
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
  2014-11-03  7:27 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03 13:54   ` Jiri Olsa
  2014-11-03  7:27 ` [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all() Namhyung Kim
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_safe

After:
  $ 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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3caf7dab50e8..31a76ee92c93 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -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
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 71264e41fa85..79f906c7124e 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -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
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 7c68ec74a808..9ced746a139a 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -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
 
 ###############################
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644
index 000000000000..e111fff6240e
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-zlib.c
@@ -0,0 +1,9 @@
+#include <zlib.h>
+
+int main(void)
+{
+	z_stream zs;
+
+	inflateInit(&zs);
+	return 0;
+}
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 3293e2e21814..43bb3a7ccd81 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa0e2a4..7dc44cfe25b3 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -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 */
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 000000000000..495a449fc25c
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -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;
+}
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
  2014-11-03  7:27 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
  2014-11-03  7:27 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03  7:35   ` Adrian Hunter
  2014-11-03  7:27 ` [PATCH 4/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

The dsos__hit_all() and its friends are not used anywhere.  Let's get
rid of them.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/header.c | 41 -----------------------------------------
 tools/perf/util/header.h |  2 --
 2 files changed, 43 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0ecf4a304cbc..e7c762f54bee 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbaea64a5..d08cfe499404 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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
  */
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 4/8] perf tools: Rename dsos__write_buildid_table()
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
                   ` (2 preceding siblings ...)
  2014-11-03  7:27 ` [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all() Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03  7:27 ` [PATCH 5/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/header.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e7c762f54bee..6e1ff5d64276 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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;
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 5/8] perf build-id: Move build-id related functions to util/build-id.c
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
                   ` (3 preceding siblings ...)
  2014-11-03  7:27 ` [PATCH 4/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03  7:27 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 2e7c68e39330..acc50509f1d5 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -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) && copyfile(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;
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae392561470b..e24477cc92f2 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -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
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6e1ff5d64276..3e2c156d9c64 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -79,10 +79,7 @@ static int do_write(int fd, const void *buf, size_t size)
 	return 0;
 }
 
-#define NAME_ALIGN 64
-
-static int write_padded(int fd, const void *bf, size_t count,
-			size_t count_aligned)
+int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
 {
 	static const char zero_buf[NAME_ALIGN];
 	int err = do_write(fd, bf, count);
@@ -171,297 +168,6 @@ perf_header__set_cmdline(int argc, const char **argv)
 	return 0;
 }
 
-#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 = do_write(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;
-}
-
-static 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) && copyfile(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;
-}
-
-static 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;
-}
-
-static 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;
-}
-
 static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
 			    struct perf_evlist *evlist)
 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d08cfe499404..785be448ca37 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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
  */
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
                   ` (4 preceding siblings ...)
  2014-11-03  7:27 ` [PATCH 5/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03  7:27 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
  2014-11-03  7:27 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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

Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5091a27e6d28..582c4da155ea 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c69915c9d5bc..c24c5b83156c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index eb2c19bf8d90..ded3ca7266de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -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,
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 7/8] perf tools: Fix build-id matching on vmlinux
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
                   ` (5 preceding siblings ...)
  2014-11-03  7:27 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  2014-11-03  7:27 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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
   ...

Cc: Adrian Huner <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/header.c  |  2 +-
 tools/perf/util/machine.c | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e2c156d9c64..76442caca37e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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),
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 946c7d62cb6e..53f90e9c65fe 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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;
 
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name
  2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
                   ` (6 preceding siblings ...)
  2014-11-03  7:27 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
@ 2014-11-03  7:27 ` Namhyung Kim
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_unrolled

After:
  # 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

Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/machine.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 53f90e9c65fe..52e94902afb1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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);
 
 		/*
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
  2014-11-03  7:27 ` [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all() Namhyung Kim
@ 2014-11-03  7:35   ` Adrian Hunter
  2014-11-03  7:39     ` Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Adrian Hunter @ 2014-11-03  7:35 UTC (permalink / raw)
  To: Namhyung Kim, Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim, LKML,
	Jiri Olsa, David Ahern, Stephane Eranian

On 03/11/14 09:27, Namhyung Kim wrote:
> 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 <adrian.hunter@intel.com>
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.
    
    Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
    Cc: David Ahern <dsahern@gmail.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Namhyung Kim <namhyung@gmail.com>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Stephane Eranian <eranian@google.com>
    Link: http://lkml.kernel.org/r/1406035081-14301-15-git-send-email-adrian.hunter@intel.com
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>



> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  tools/perf/util/header.c | 41 -----------------------------------------
>  tools/perf/util/header.h |  2 --
>  2 files changed, 43 deletions(-)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 0ecf4a304cbc..e7c762f54bee 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -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)
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index 8f5cbaea64a5..d08cfe499404 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -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
>   */
> 


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
  2014-11-03  7:35   ` Adrian Hunter
@ 2014-11-03  7:39     ` Namhyung Kim
  2014-11-03  7:51       ` Adrian Hunter
  0 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03  7:39 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Jiri Olsa, David Ahern,
	Stephane Eranian

Hi Adrian,

On Mon, Nov 3, 2014 at 4:35 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 03/11/14 09:27, Namhyung Kim wrote:
>> 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 <adrian.hunter@intel.com>
> 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.

Oops, didn't notice.  Sorry for not checking the commit log.  So how
about moving it into util/build-id.c then?

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all()
  2014-11-03  7:39     ` Namhyung Kim
@ 2014-11-03  7:51       ` Adrian Hunter
  0 siblings, 0 replies; 43+ messages in thread
From: Adrian Hunter @ 2014-11-03  7:51 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Jiri Olsa, David Ahern,
	Stephane Eranian

On 03/11/14 09:39, Namhyung Kim wrote:
> Hi Adrian,
> 
> On Mon, Nov 3, 2014 at 4:35 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> On 03/11/14 09:27, Namhyung Kim wrote:
>>> 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 <adrian.hunter@intel.com>
>> 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.
> 
> Oops, didn't notice.  Sorry for not checking the commit log.  So how
> about moving it into util/build-id.c then?

OK by me.


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
  2014-11-03  7:27 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
@ 2014-11-03 13:51   ` Jiri Olsa
  2014-11-03 15:01     ` Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Jiri Olsa @ 2014-11-03 13:51 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

On Mon, Nov 03, 2014 at 04:27:51PM +0900, Namhyung Kim wrote:

SNIP

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

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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-03  7:27 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
@ 2014-11-03 13:54   ` Jiri Olsa
  2014-11-03 15:02     ` Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Jiri Olsa @ 2014-11-03 13:54 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

On Mon, Nov 03, 2014 at 04:27:52PM +0900, Namhyung Kim wrote:

SNIP

>   #
>   # 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
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
  2014-11-03 13:51   ` Jiri Olsa
@ 2014-11-03 15:01     ` Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03 15:01 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

Hi Jiri,

On Mon, Nov 3, 2014 at 10:51 PM, Jiri Olsa <jolsa@redhat.com> wrote:
> On Mon, Nov 03, 2014 at 04:27:51PM +0900, Namhyung Kim wrote:
>
> SNIP
>
>> +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;
>
> 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;


> 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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-03 13:54   ` Jiri Olsa
@ 2014-11-03 15:02     ` Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-03 15:02 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

On Mon, Nov 3, 2014 at 10:54 PM, Jiri Olsa <jolsa@redhat.com> wrote:
> On Mon, Nov 03, 2014 at 04:27:52PM +0900, Namhyung Kim wrote:
>
> SNIP
>
>>   #
>>   # 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
>>
>> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
>> ---
>>  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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6)
@ 2014-11-04  1:14 Namhyung Kim
  2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
                   ` (7 more replies)
  0 siblings, 8 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_halt


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]".

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


Cc: Adrian Hunter <adrian.hunter@intel.com>


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

-- 
2.1.2


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH 1/8] perf tools: Preparation for compressed kernel module support
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-04 10:58   ` Jiri Olsa
  2014-11-07  5:29   ` [tip:perf/core] perf symbols: " tip-bot for Namhyung Kim
  2014-11-04  1:14 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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 <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0247acfdfaca..36a607cf8f50 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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.
  */
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index a316e4af321f..3782c82c6e44 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -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:
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 51a630301afa..946c7d62cb6e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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, '-', '_');
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 1e23a5bfb044..efc7eb6b8f0f 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -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;
 
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 078331140d8c..c69915c9d5bc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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.
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
  2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-04 11:00   ` Jiri Olsa
  2014-11-04 14:15   ` [PATCH 2/8] " Arnaldo Carvalho de Melo
  2014-11-04  1:14 ` [PATCH 3/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_safe

After:
  $ 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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3caf7dab50e8..31a76ee92c93 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -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
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 71264e41fa85..79f906c7124e 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -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
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 7c68ec74a808..9ced746a139a 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -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
 
 ###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index a7d022e161c0..652e0098eba6 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -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;
 }
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644
index 000000000000..e111fff6240e
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-zlib.c
@@ -0,0 +1,9 @@
+#include <zlib.h>
+
+int main(void)
+{
+	z_stream zs;
+
+	inflateInit(&zs);
+	return 0;
+}
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 36a607cf8f50..3bf67fc34ed9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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, },
 };
 
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa0e2a4..7dc44cfe25b3 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -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 */
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 000000000000..495a449fc25c
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -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;
+}
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 3/8] perf tools: Rename dsos__write_buildid_table()
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
  2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
  2014-11-04  1:14 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-07  5:30   ` [tip:perf/core] perf build-id: " tip-bot for Namhyung Kim
  2014-11-04  1:14 ` [PATCH 4/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/header.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0ecf4a304cbc..be8d02eb97e9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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;
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 4/8] perf build-id: Move build-id related functions to util/build-id.c
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
                   ` (2 preceding siblings ...)
  2014-11-04  1:14 ` [PATCH 3/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-07  5:30   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2014-11-04  1:14 ` [PATCH 5/8] perf tools: Move disable_buildid_cache() " Namhyung Kim
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 2e7c68e39330..dd2a3e52ada1 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -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) && copyfile(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;
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae392561470b..666a3bd4f64e 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -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
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index be8d02eb97e9..3e2c156d9c64 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -79,10 +79,7 @@ static int do_write(int fd, const void *buf, size_t size)
 	return 0;
 }
 
-#define NAME_ALIGN 64
-
-static int write_padded(int fd, const void *bf, size_t count,
-			size_t count_aligned)
+int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
 {
 	static const char zero_buf[NAME_ALIGN];
 	int err = do_write(fd, bf, count);
@@ -171,338 +168,6 @@ perf_header__set_cmdline(int argc, const char **argv)
 	return 0;
 }
 
-#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 = do_write(fd, &b, sizeof(b));
-	if (err < 0)
-		return err;
-
-	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)
-{
-	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;
-}
-
-static 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) && copyfile(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;
-}
-
-static 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;
-}
-
-static 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;
-}
-
 static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
 			    struct perf_evlist *evlist)
 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbaea64a5..3bb90ac172a1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 5/8] perf tools: Move disable_buildid_cache() to util/build-id.c
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
                   ` (3 preceding siblings ...)
  2014-11-04  1:14 ` [PATCH 4/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-04  1:14 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

Also move static variable no_buildid_cache and check it in the
perf_session_cache_build_ids().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index dd2a3e52ada1..e8d79e5bfaf7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -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)
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 666a3bd4f64e..8236319514d5 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -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
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e2c156d9c64..3081f030aef0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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;
-}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 7dc44cfe25b3..76d23d83eae5 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR
 
 extern 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)
 {
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
                   ` (4 preceding siblings ...)
  2014-11-04  1:14 ` [PATCH 5/8] perf tools: Move disable_buildid_cache() " Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-04 13:29   ` Arnaldo Carvalho de Melo
  2014-11-07  5:30   ` [tip:perf/core] perf record: Do not save pathname in ./debug/ .build-id " tip-bot for Namhyung Kim
  2014-11-04  1:14 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
  2014-11-04  1:14 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
  7 siblings, 2 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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

Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 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(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5091a27e6d28..582c4da155ea 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c69915c9d5bc..c24c5b83156c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index eb2c19bf8d90..ded3ca7266de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -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,
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 7/8] perf tools: Fix build-id matching on vmlinux
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
                   ` (5 preceding siblings ...)
  2014-11-04  1:14 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-07  5:31   ` [tip:perf/core] " tip-bot for Namhyung Kim
  2014-11-04  1:14 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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
   ...

Cc: Adrian Huner <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/header.c  |  2 +-
 tools/perf/util/machine.c | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3081f030aef0..e86fffd89e2b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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),
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 946c7d62cb6e..53f90e9c65fe 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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;
 
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name
  2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
                   ` (6 preceding siblings ...)
  2014-11-04  1:14 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
@ 2014-11-04  1:14 ` Namhyung Kim
  2014-11-07  5:31   ` [tip:perf/core] " tip-bot for Namhyung Kim
  7 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-04  1:14 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
	Namhyung Kim, LKML, Jiri Olsa, Adrian Hunter, David Ahern,
	Stephane Eranian

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_unrolled

After:
  # 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

Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/machine.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 53f90e9c65fe..52e94902afb1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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);
 
 		/*
-- 
2.1.2


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 1/8] perf tools: Preparation for compressed kernel module support
  2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
@ 2014-11-04 10:58   ` Jiri Olsa
  2014-11-07  5:29   ` [tip:perf/core] perf symbols: " tip-bot for Namhyung Kim
  1 sibling, 0 replies; 43+ messages in thread
From: Jiri Olsa @ 2014-11-04 10:58 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

On Tue, Nov 04, 2014 at 10:14:27AM +0900, Namhyung Kim wrote:
> 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 <namhyung@kernel.org>

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04  1:14 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
@ 2014-11-04 11:00   ` Jiri Olsa
  2014-11-04 13:42     ` Arnaldo Carvalho de Melo
  2014-11-04 14:15   ` [PATCH 2/8] " Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 43+ messages in thread
From: Jiri Olsa @ 2014-11-04 11:00 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
	Paul Mackerras, Namhyung Kim, LKML, Adrian Hunter, David Ahern,
	Stephane Eranian

On Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim wrote:
> Now my Archlinux box shows module symbols correctly.

with the last comment addressed (-lz in test-all.bin):

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

> 
> 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_safe
> 
> After:
>   $ 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
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  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
> 
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 3caf7dab50e8..31a76ee92c93 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -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
> diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
> index 71264e41fa85..79f906c7124e 100644
> --- a/tools/perf/config/Makefile
> +++ b/tools/perf/config/Makefile
> @@ -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
> diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
> index 7c68ec74a808..9ced746a139a 100644
> --- a/tools/perf/config/feature-checks/Makefile
> +++ b/tools/perf/config/feature-checks/Makefile
> @@ -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
>  
>  ###############################
> diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
> index a7d022e161c0..652e0098eba6 100644
> --- a/tools/perf/config/feature-checks/test-all.c
> +++ b/tools/perf/config/feature-checks/test-all.c
> @@ -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;
>  }
> diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
> new file mode 100644
> index 000000000000..e111fff6240e
> --- /dev/null
> +++ b/tools/perf/config/feature-checks/test-zlib.c
> @@ -0,0 +1,9 @@
> +#include <zlib.h>
> +
> +int main(void)
> +{
> +	z_stream zs;
> +
> +	inflateInit(&zs);
> +	return 0;
> +}
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 36a607cf8f50..3bf67fc34ed9 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -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, },
>  };
>  
> diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> index 80bfdaa0e2a4..7dc44cfe25b3 100644
> --- a/tools/perf/util/util.h
> +++ b/tools/perf/util/util.h
> @@ -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 */
> diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
> new file mode 100644
> index 000000000000..495a449fc25c
> --- /dev/null
> +++ b/tools/perf/util/zlib.c
> @@ -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;
> +}
> -- 
> 2.1.2
> 

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
  2014-11-04  1:14 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
@ 2014-11-04 13:29   ` Arnaldo Carvalho de Melo
  2014-11-05  2:54     ` Namhyung Kim
  2014-11-07  5:30   ` [tip:perf/core] perf record: Do not save pathname in ./debug/ .build-id " tip-bot for Namhyung Kim
  1 sibling, 1 reply; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-11-04 13:29 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim, LKML,
	Jiri Olsa, Adrian Hunter, David Ahern, Stephane Eranian

Em Tue, Nov 04, 2014 at 10:14:32AM +0900, Namhyung Kim escreveu:
> 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 calling dso__load_vmlinux_path() which replaces dso->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
 
> 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
 
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  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(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 5091a27e6d28..582c4da155ea 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -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);
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index c69915c9d5bc..c24c5b83156c 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -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)
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index eb2c19bf8d90..ded3ca7266de 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -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,
> -- 
> 2.1.2

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04 11:00   ` Jiri Olsa
@ 2014-11-04 13:42     ` Arnaldo Carvalho de Melo
  2014-11-05  2:59       ` Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-11-04 13:42 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Namhyung Kim, Peter Zijlstra, Ingo Molnar, Paul Mackerras,
	Namhyung Kim, LKML, Adrian Hunter, David Ahern, Stephane Eranian

Em Tue, Nov 04, 2014 at 12:00:17PM +0100, Jiri Olsa escreveu:
> On Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim wrote:
> > Now my Archlinux box shows module symbols correctly.
> 
> with the last comment addressed (-lz in test-all.bin):
> 
> Acked-by: Jiri Olsa <jolsa@kernel.org>

Thanks, applied the series.

- Arnaldo

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04  1:14 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
  2014-11-04 11:00   ` Jiri Olsa
@ 2014-11-04 14:15   ` Arnaldo Carvalho de Melo
  2014-11-05  3:04     ` Namhyung Kim
  1 sibling, 1 reply; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-11-04 14:15 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim, LKML,
	Jiri Olsa, Adrian Hunter, David Ahern, Stephane Eranian

Em Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim escreveu:
> Now my Archlinux box shows module symbols correctly.

Now my RHEL6 box doesn't build:

> +++ b/tools/perf/util/dso.c
> @@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
>  	return ret;

>  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, },
>  };

  CC       /tmp/build/perf/util/dso.o
cc1: warnings being treated as errors
util/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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux
  2014-11-04 13:29   ` Arnaldo Carvalho de Melo
@ 2014-11-05  2:54     ` Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-05  2:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim, LKML,
	Jiri Olsa, Adrian Hunter, David Ahern, Stephane Eranian

Hi Arnaldo,

On Tue, 4 Nov 2014 10:29:04 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Nov 04, 2014 at 10:14:32AM +0900, Namhyung Kim escreveu:
>> 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 calling dso__load_vmlinux_path() which replaces dso->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 :-\

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.

>
> 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.

It'd be really appreciated!

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04 13:42     ` Arnaldo Carvalho de Melo
@ 2014-11-05  2:59       ` Namhyung Kim
  2014-11-07  5:30         ` [tip:perf/core] " tip-bot for Namhyung Kim
  0 siblings, 1 reply; 43+ messages in thread
From: Namhyung Kim @ 2014-11-05  2:59 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Peter Zijlstra, Ingo Molnar, Paul Mackerras,
	Namhyung Kim, LKML, Adrian Hunter, David Ahern, Stephane Eranian

On Tue, 4 Nov 2014 10:42:29 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Nov 04, 2014 at 12:00:17PM +0100, Jiri Olsa escreveu:
>> On Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim wrote:
>> > Now my Archlinux box shows module symbols correctly.
>> 
>> with the last comment addressed (-lz in test-all.bin):
>> 
>> Acked-by: Jiri Olsa <jolsa@kernel.org>
>
> 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. :-/


diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Mak
efile
index 7c68ec74a808..53f19b5dbc37 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -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

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 2/8] perf tools: Add gzip decompression support for kernel module
  2014-11-04 14:15   ` [PATCH 2/8] " Arnaldo Carvalho de Melo
@ 2014-11-05  3:04     ` Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: Namhyung Kim @ 2014-11-05  3:04 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim, LKML,
	Jiri Olsa, Adrian Hunter, David Ahern, Stephane Eranian

On Tue, 4 Nov 2014 11:15:08 -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Nov 04, 2014 at 10:14:28AM +0900, Namhyung Kim escreveu:
>> Now my Archlinux box shows module symbols correctly.
>
> Now my RHEL6 box doesn't build:
>
>> +++ b/tools/perf/util/dso.c
>> @@ -141,17 +141,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
>>  	return ret;
>
>>  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, },
>>  };
>
>   CC       /tmp/build/perf/util/dso.o
> cc1: warnings being treated as errors
> util/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 :-)

Also fixed and pushed to perf/vmlinux-v7 branch.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf symbols: Preparation for compressed kernel module support
  2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
  2014-11-04 10:58   ` Jiri Olsa
@ 2014-11-07  5:29   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung.kim, paulus, linux-kernel, jolsa, hpa, acme,
	adrian.hunter, tglx, mingo, a.p.zijlstra, dsahern, eranian,
	jolsa, namhyung

Commit-ID:  c00c48fc6e6ef63d83a7417923a06b08089bb34b
Gitweb:     http://git.kernel.org/tip/c00c48fc6e6ef63d83a7417923a06b08089bb34b
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:27 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0247acf..36a607c 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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.
  */
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index a316e4a..3782c82 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -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:
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 51a6303..946c7d6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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, '-', '_');
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 1e23a5b..efc7eb6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -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;
 
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 0783311..c69915c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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.

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf tools: Add gzip decompression support for kernel module
  2014-11-05  2:59       ` Namhyung Kim
@ 2014-11-07  5:30         ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, mingo, jolsa, adrian.hunter, tglx, namhyung,
	paulus, acme, eranian, namhyung.kim, dsahern, hpa, a.p.zijlstra

Commit-ID:  e92ce12ed6a46302f64269d2d406cf04525f0a8f
Gitweb:     http://git.kernel.org/tip/e92ce12ed6a46302f64269d2d406cf04525f0a8f
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Fri, 31 Oct 2014 16:51:38 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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_safe

After:
  $ 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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/87h9yexshi.fsf@sejong.aot.lge.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0ebcc4a..aecf61dc 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -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
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 71264e4..79f906c 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -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
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 7c68ec7..53f19b5 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -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
 
 ###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index a7d022e..652e009 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -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;
 }
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644
index 0000000..e111fff
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-zlib.c
@@ -0,0 +1,9 @@
+#include <zlib.h>
+
+int main(void)
+{
+	z_stream zs;
+
+	inflateInit(&zs);
+	return 0;
+}
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 36a607c..45be944 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -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)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa..7dc44cf 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -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 */
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 0000000..495a449
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -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;
+}

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf build-id: Rename dsos__write_buildid_table()
  2014-11-04  1:14 ` [PATCH 3/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
@ 2014-11-07  5:30   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, tglx, dsahern, paulus, mingo, namhyung.kim, hpa,
	namhyung, jolsa, linux-kernel, eranian, acme, a.p.zijlstra

Commit-ID:  714c9c4a98f722115e10d021ea80600f4427b71e
Gitweb:     http://git.kernel.org/tip/714c9c4a98f722115e10d021ea80600f4427b71e
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:29 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-4-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0ecf4a3..be8d02e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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;

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf build-id: Move build-id related functions to util/build-id.c
  2014-11-04  1:14 ` [PATCH 4/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
@ 2014-11-07  5:30   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, linux-kernel, dsahern, paulus, adrian.hunter,
	namhyung.kim, hpa, tglx, namhyung, jolsa, acme, a.p.zijlstra,
	mingo

Commit-ID:  e195fac8077f034b0160bf420bdf450ae476701d
Gitweb:     http://git.kernel.org/tip/e195fac8077f034b0160bf420bdf450ae476701d
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:30 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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);

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Link: http://lkml.kernel.org/r/545733E7.6010105@intel.com
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-5-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 2e7c68e..dd2a3e5 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -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) && copyfile(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;
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae39256..666a3bd 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -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
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index be8d02e..3e2c156 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -79,10 +79,7 @@ static int do_write(int fd, const void *buf, size_t size)
 	return 0;
 }
 
-#define NAME_ALIGN 64
-
-static int write_padded(int fd, const void *bf, size_t count,
-			size_t count_aligned)
+int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
 {
 	static const char zero_buf[NAME_ALIGN];
 	int err = do_write(fd, bf, count);
@@ -171,338 +168,6 @@ perf_header__set_cmdline(int argc, const char **argv)
 	return 0;
 }
 
-#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 = do_write(fd, &b, sizeof(b));
-	if (err < 0)
-		return err;
-
-	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)
-{
-	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;
-}
-
-static 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) && copyfile(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;
-}
-
-static 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;
-}
-
-static 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;
-}
-
 static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
 			    struct perf_evlist *evlist)
 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbae..3bb90ac 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf record: Do not save pathname in ./debug/ .build-id directory for vmlinux
  2014-11-04  1:14 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
  2014-11-04 13:29   ` Arnaldo Carvalho de Melo
@ 2014-11-07  5:30   ` tip-bot for Namhyung Kim
  1 sibling, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dsahern, namhyung, acme, tglx, a.p.zijlstra, linux-kernel,
	namhyung.kim, jolsa, paulus, hpa, adrian.hunter, mingo, eranian

Commit-ID:  00dc865798a31d3d5300dd5d70166a4a85f76a20
Gitweb:     http://git.kernel.org/tip/00dc865798a31d3d5300dd5d70166a4a85f76a20
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:32 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-7-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5091a27..582c4da 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c69915c..c24c5b8 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -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)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index eb2c19b..ded3ca7 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -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,

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf tools: Fix build-id matching on vmlinux
  2014-11-04  1:14 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
@ 2014-11-07  5:31   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: paulus, mingo, namhyung.kim, jolsa, acme, linux-kernel, eranian,
	dsahern, adrian.hunter, namhyung, tglx, a.p.zijlstra, hpa

Commit-ID:  b837a8bdc48925e6512412973b845c53cbe2b412
Gitweb:     http://git.kernel.org/tip/b837a8bdc48925e6512412973b845c53cbe2b412
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:33 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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
   ...

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/20140924073356.GB1962@gmail.com
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-8-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c  |  2 +-
 tools/perf/util/machine.c | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e2c156..76442ca 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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),
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 946c7d6..53f90e9 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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;
 

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [tip:perf/core] perf tools: Make vmlinux short name more like kallsyms short name
  2014-11-04  1:14 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
@ 2014-11-07  5:31   ` tip-bot for Namhyung Kim
  0 siblings, 0 replies; 43+ messages in thread
From: tip-bot for Namhyung Kim @ 2014-11-07  5:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, linux-kernel, jolsa, adrian.hunter, dsahern, eranian,
	paulus, namhyung, hpa, namhyung.kim, acme, mingo, a.p.zijlstra

Commit-ID:  96d78059d6d9da45d77078a219924304860497f2
Gitweb:     http://git.kernel.org/tip/96d78059d6d9da45d77078a219924304860497f2
Author:     Namhyung Kim <namhyung@kernel.org>
AuthorDate: Tue, 4 Nov 2014 10:14:34 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
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_unrolled

After:
  # 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

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-9-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/machine.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 53f90e9..52e9490 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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);
 
 		/*

^ permalink raw reply related	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2014-11-07  5:31 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-03  7:27 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v5) Namhyung Kim
2014-11-03  7:27 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
2014-11-03 13:51   ` Jiri Olsa
2014-11-03 15:01     ` Namhyung Kim
2014-11-03  7:27 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
2014-11-03 13:54   ` Jiri Olsa
2014-11-03 15:02     ` Namhyung Kim
2014-11-03  7:27 ` [PATCH 3/8] perf tools: Get rid of unused dsos__hit_all() Namhyung Kim
2014-11-03  7:35   ` Adrian Hunter
2014-11-03  7:39     ` Namhyung Kim
2014-11-03  7:51       ` Adrian Hunter
2014-11-03  7:27 ` [PATCH 4/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
2014-11-03  7:27 ` [PATCH 5/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
2014-11-03  7:27 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
2014-11-03  7:27 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
2014-11-03  7:27 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
  -- strict thread matches above, loose matches on Subject: below --
2014-11-04  1:14 [PATCHSET 0/8] perf tools: Fix build-id matching on vmlinux (v6) Namhyung Kim
2014-11-04  1:14 ` [PATCH 1/8] perf tools: Preparation for compressed kernel module support Namhyung Kim
2014-11-04 10:58   ` Jiri Olsa
2014-11-07  5:29   ` [tip:perf/core] perf symbols: " tip-bot for Namhyung Kim
2014-11-04  1:14 ` [PATCH 2/8] perf tools: Add gzip decompression support for kernel module Namhyung Kim
2014-11-04 11:00   ` Jiri Olsa
2014-11-04 13:42     ` Arnaldo Carvalho de Melo
2014-11-05  2:59       ` Namhyung Kim
2014-11-07  5:30         ` [tip:perf/core] " tip-bot for Namhyung Kim
2014-11-04 14:15   ` [PATCH 2/8] " Arnaldo Carvalho de Melo
2014-11-05  3:04     ` Namhyung Kim
2014-11-04  1:14 ` [PATCH 3/8] perf tools: Rename dsos__write_buildid_table() Namhyung Kim
2014-11-07  5:30   ` [tip:perf/core] perf build-id: " tip-bot for Namhyung Kim
2014-11-04  1:14 ` [PATCH 4/8] perf build-id: Move build-id related functions to util/build-id.c Namhyung Kim
2014-11-07  5:30   ` [tip:perf/core] " tip-bot for Namhyung Kim
2014-11-04  1:14 ` [PATCH 5/8] perf tools: Move disable_buildid_cache() " Namhyung Kim
2014-11-04  1:14 ` [PATCH 6/8] perf record: Do not save pathname in ./debug/.build-id directory for vmlinux Namhyung Kim
2014-11-04 13:29   ` Arnaldo Carvalho de Melo
2014-11-05  2:54     ` Namhyung Kim
2014-11-07  5:30   ` [tip:perf/core] perf record: Do not save pathname in ./debug/ .build-id " tip-bot for Namhyung Kim
2014-11-04  1:14 ` [PATCH 7/8] perf tools: Fix build-id matching on vmlinux Namhyung Kim
2014-11-07  5:31   ` [tip:perf/core] " tip-bot for Namhyung Kim
2014-11-04  1:14 ` [PATCH 8/8] perf tools: Make vmlinux short name more like kallsyms short name Namhyung Kim
2014-11-07  5:31   ` [tip:perf/core] " tip-bot for Namhyung Kim
2014-09-22  8:04 [PATCH v4] perf tools: Fix build-id matching on vmlinux Namhyung Kim
2014-09-24  7:33 ` Ingo Molnar
2014-09-29  4:45   ` Namhyung Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).