954c66983d
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
225 lines
6.9 KiB
Diff
225 lines
6.9 KiB
Diff
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,
|