perf: Apply patch for offline kernels
As per https://lkml.org/lkml/2017/7/13/314, perf is broken in 4.9.36 and 4.9.37 Patches in this commit are taken from https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/commit/?id=39f4f2c018bd831c325e11983f8893caf72fd9eb This will allow perf to build again and should be included in a future 4.9.x release, allowing the custom patching to be removed again
This commit is contained in:
parent
3ef073e9f1
commit
954c66983d
224
pkgs/os-specific/linux/kernel/perf-offline-probe.patch
Normal file
224
pkgs/os-specific/linux/kernel/perf-offline-probe.patch
Normal file
@ -0,0 +1,224 @@
|
||||
From 8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 Mon Sep 17 00:00:00 2001
|
||||
From: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
Date: Wed, 4 Jan 2017 12:30:19 +0900
|
||||
Subject: perf probe: Fix to probe on gcc generated symbols for offline kernel
|
||||
|
||||
From: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
|
||||
commit 8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 upstream.
|
||||
|
||||
Fix perf-probe to show probe definition on gcc generated symbols for
|
||||
offline kernel (including cross-arch kernel image).
|
||||
|
||||
gcc sometimes optimizes functions and generate new symbols with suffixes
|
||||
such as ".constprop.N" or ".isra.N" etc. Since those symbol names are
|
||||
not recorded in DWARF, we have to find correct generated symbols from
|
||||
offline ELF binary to probe on it (kallsyms doesn't correct it). For
|
||||
online kernel or uprobes we don't need it because those are rebased on
|
||||
_text, or a section relative address.
|
||||
|
||||
E.g. Without this:
|
||||
|
||||
$ perf probe -k build-arm/vmlinux -F __slab_alloc*
|
||||
__slab_alloc.constprop.9
|
||||
$ perf probe -k build-arm/vmlinux -D __slab_alloc
|
||||
p:probe/__slab_alloc __slab_alloc+0
|
||||
|
||||
If you put above definition on target machine, it should fail
|
||||
because there is no __slab_alloc in kallsyms.
|
||||
|
||||
With this fix, perf probe shows correct probe definition on
|
||||
__slab_alloc.constprop.9:
|
||||
|
||||
$ perf probe -k build-arm/vmlinux -D __slab_alloc
|
||||
p:probe/__slab_alloc __slab_alloc.constprop.9+0
|
||||
|
||||
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
Cc: Jiri Olsa <jolsa@redhat.com>
|
||||
Cc: Namhyung Kim <namhyung@kernel.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Link: http://lkml.kernel.org/r/148350060434.19001.11864836288580083501.stgit@devbox
|
||||
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
Cc: Krister Johansen <kjlx@templeofstupid.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
---
|
||||
tools/perf/util/probe-event.c | 48 +++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 47 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/perf/util/probe-event.c
|
||||
+++ b/tools/perf/util/probe-event.c
|
||||
@@ -618,6 +618,51 @@ error:
|
||||
return ret ? : -ENOENT;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
|
||||
+ * and generate new symbols with suffixes such as .constprop.N or .isra.N
|
||||
+ * etc. Since those symbols are not recorded in DWARF, we have to find
|
||||
+ * correct generated symbols from offline ELF binary.
|
||||
+ * For online kernel or uprobes we don't need this because those are
|
||||
+ * rebased on _text, or already a section relative address.
|
||||
+ */
|
||||
+static int
|
||||
+post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
|
||||
+ int ntevs, const char *pathname)
|
||||
+{
|
||||
+ struct symbol *sym;
|
||||
+ struct map *map;
|
||||
+ unsigned long stext = 0;
|
||||
+ u64 addr;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Prepare a map for offline binary */
|
||||
+ map = dso__new_map(pathname);
|
||||
+ if (!map || get_text_start_address(pathname, &stext) < 0) {
|
||||
+ pr_warning("Failed to get ELF symbols for %s\n", pathname);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < ntevs; i++) {
|
||||
+ addr = tevs[i].point.address + tevs[i].point.offset - stext;
|
||||
+ sym = map__find_symbol(map, addr);
|
||||
+ if (!sym)
|
||||
+ continue;
|
||||
+ if (!strcmp(sym->name, tevs[i].point.symbol))
|
||||
+ continue;
|
||||
+ /* If we have no realname, use symbol for it */
|
||||
+ if (!tevs[i].point.realname)
|
||||
+ tevs[i].point.realname = tevs[i].point.symbol;
|
||||
+ else
|
||||
+ free(tevs[i].point.symbol);
|
||||
+ tevs[i].point.symbol = strdup(sym->name);
|
||||
+ tevs[i].point.offset = addr - sym->start;
|
||||
+ }
|
||||
+ map__put(map);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
|
||||
int ntevs, const char *exec)
|
||||
{
|
||||
@@ -694,7 +739,8 @@ post_process_kernel_probe_trace_events(s
|
||||
|
||||
/* Skip post process if the target is an offline kernel */
|
||||
if (symbol_conf.ignore_vmlinux_buildid)
|
||||
- return 0;
|
||||
+ return post_process_offline_probe_trace_events(tevs, ntevs,
|
||||
+ symbol_conf.vmlinux_name);
|
||||
|
||||
reloc_sym = kernel_get_ref_reloc_sym();
|
||||
if (!reloc_sym) {
|
||||
|
||||
---
|
||||
|
||||
From 3e96dac7c956089d3f23aca98c4dfca57b6aaf8a Mon Sep 17 00:00:00 2001
|
||||
From: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
Date: Wed, 11 Jan 2017 15:00:47 +0900
|
||||
Subject: perf probe: Add error checks to offline probe post-processing
|
||||
|
||||
From: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
|
||||
commit 3e96dac7c956089d3f23aca98c4dfca57b6aaf8a upstream.
|
||||
|
||||
Add error check codes on post processing and improve it for offline
|
||||
probe events as:
|
||||
|
||||
- post processing fails if no matched symbol found in map(-ENOENT)
|
||||
or strdup() failed(-ENOMEM).
|
||||
|
||||
- Even if the symbol name is the same, it updates symbol address
|
||||
and offset.
|
||||
|
||||
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
Cc: Jiri Olsa <jolsa@redhat.com>
|
||||
Cc: Namhyung Kim <namhyung@kernel.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Link: http://lkml.kernel.org/r/148411443738.9978.4617979132625405545.stgit@devbox
|
||||
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
Cc: Krister Johansen <kjlx@templeofstupid.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
---
|
||||
tools/perf/util/probe-event.c | 50 +++++++++++++++++++++++++++---------------
|
||||
1 file changed, 33 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/tools/perf/util/probe-event.c
|
||||
+++ b/tools/perf/util/probe-event.c
|
||||
@@ -618,6 +618,33 @@ error:
|
||||
return ret ? : -ENOENT;
|
||||
}
|
||||
|
||||
+/* Adjust symbol name and address */
|
||||
+static int post_process_probe_trace_point(struct probe_trace_point *tp,
|
||||
+ struct map *map, unsigned long offs)
|
||||
+{
|
||||
+ struct symbol *sym;
|
||||
+ u64 addr = tp->address + tp->offset - offs;
|
||||
+
|
||||
+ sym = map__find_symbol(map, addr);
|
||||
+ if (!sym)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ if (strcmp(sym->name, tp->symbol)) {
|
||||
+ /* If we have no realname, use symbol for it */
|
||||
+ if (!tp->realname)
|
||||
+ tp->realname = tp->symbol;
|
||||
+ else
|
||||
+ free(tp->symbol);
|
||||
+ tp->symbol = strdup(sym->name);
|
||||
+ if (!tp->symbol)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ tp->offset = addr - sym->start;
|
||||
+ tp->address -= offs;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
|
||||
* and generate new symbols with suffixes such as .constprop.N or .isra.N
|
||||
@@ -630,11 +657,9 @@ static int
|
||||
post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
|
||||
int ntevs, const char *pathname)
|
||||
{
|
||||
- struct symbol *sym;
|
||||
struct map *map;
|
||||
unsigned long stext = 0;
|
||||
- u64 addr;
|
||||
- int i;
|
||||
+ int i, ret = 0;
|
||||
|
||||
/* Prepare a map for offline binary */
|
||||
map = dso__new_map(pathname);
|
||||
@@ -644,23 +669,14 @@ post_process_offline_probe_trace_events(
|
||||
}
|
||||
|
||||
for (i = 0; i < ntevs; i++) {
|
||||
- addr = tevs[i].point.address + tevs[i].point.offset - stext;
|
||||
- sym = map__find_symbol(map, addr);
|
||||
- if (!sym)
|
||||
- continue;
|
||||
- if (!strcmp(sym->name, tevs[i].point.symbol))
|
||||
- continue;
|
||||
- /* If we have no realname, use symbol for it */
|
||||
- if (!tevs[i].point.realname)
|
||||
- tevs[i].point.realname = tevs[i].point.symbol;
|
||||
- else
|
||||
- free(tevs[i].point.symbol);
|
||||
- tevs[i].point.symbol = strdup(sym->name);
|
||||
- tevs[i].point.offset = addr - sym->start;
|
||||
+ ret = post_process_probe_trace_point(&tevs[i].point,
|
||||
+ map, stext);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
}
|
||||
map__put(map);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
|
@ -13,7 +13,7 @@ stdenv.mkDerivation {
|
||||
|
||||
inherit (kernel) src;
|
||||
|
||||
patches = kernel.patches ++ [ ./perf-binutils-path.patch ];
|
||||
patches = kernel.patches ++ [ ./perf-binutils-path.patch ./perf-offline-probe.patch ];
|
||||
|
||||
preConfigure = ''
|
||||
cd tools/perf
|
||||
|
Loading…
Reference in New Issue
Block a user