Skip to content

Commit 954c669

Browse files
committedJul 15, 2017
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
1 parent 3ef073e commit 954c669

File tree

2 files changed

+225
-1
lines changed

2 files changed

+225
-1
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
From 8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 Mon Sep 17 00:00:00 2001
2+
From: Masami Hiramatsu <mhiramat@kernel.org>
3+
Date: Wed, 4 Jan 2017 12:30:19 +0900
4+
Subject: perf probe: Fix to probe on gcc generated symbols for offline kernel
5+
6+
From: Masami Hiramatsu <mhiramat@kernel.org>
7+
8+
commit 8a937a25a7e3c19d5fb3f9d92f605cf5fda219d8 upstream.
9+
10+
Fix perf-probe to show probe definition on gcc generated symbols for
11+
offline kernel (including cross-arch kernel image).
12+
13+
gcc sometimes optimizes functions and generate new symbols with suffixes
14+
such as ".constprop.N" or ".isra.N" etc. Since those symbol names are
15+
not recorded in DWARF, we have to find correct generated symbols from
16+
offline ELF binary to probe on it (kallsyms doesn't correct it). For
17+
online kernel or uprobes we don't need it because those are rebased on
18+
_text, or a section relative address.
19+
20+
E.g. Without this:
21+
22+
$ perf probe -k build-arm/vmlinux -F __slab_alloc*
23+
__slab_alloc.constprop.9
24+
$ perf probe -k build-arm/vmlinux -D __slab_alloc
25+
p:probe/__slab_alloc __slab_alloc+0
26+
27+
If you put above definition on target machine, it should fail
28+
because there is no __slab_alloc in kallsyms.
29+
30+
With this fix, perf probe shows correct probe definition on
31+
__slab_alloc.constprop.9:
32+
33+
$ perf probe -k build-arm/vmlinux -D __slab_alloc
34+
p:probe/__slab_alloc __slab_alloc.constprop.9+0
35+
36+
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
37+
Cc: Jiri Olsa <jolsa@redhat.com>
38+
Cc: Namhyung Kim <namhyung@kernel.org>
39+
Cc: Peter Zijlstra <peterz@infradead.org>
40+
Link: http://lkml.kernel.org/r/148350060434.19001.11864836288580083501.stgit@devbox
41+
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
42+
Cc: Krister Johansen <kjlx@templeofstupid.com>
43+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
44+
45+
---
46+
tools/perf/util/probe-event.c | 48 +++++++++++++++++++++++++++++++++++++++++-
47+
1 file changed, 47 insertions(+), 1 deletion(-)
48+
49+
--- a/tools/perf/util/probe-event.c
50+
+++ b/tools/perf/util/probe-event.c
51+
@@ -618,6 +618,51 @@ error:
52+
return ret ? : -ENOENT;
53+
}
54+
55+
+/*
56+
+ * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
57+
+ * and generate new symbols with suffixes such as .constprop.N or .isra.N
58+
+ * etc. Since those symbols are not recorded in DWARF, we have to find
59+
+ * correct generated symbols from offline ELF binary.
60+
+ * For online kernel or uprobes we don't need this because those are
61+
+ * rebased on _text, or already a section relative address.
62+
+ */
63+
+static int
64+
+post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
65+
+ int ntevs, const char *pathname)
66+
+{
67+
+ struct symbol *sym;
68+
+ struct map *map;
69+
+ unsigned long stext = 0;
70+
+ u64 addr;
71+
+ int i;
72+
+
73+
+ /* Prepare a map for offline binary */
74+
+ map = dso__new_map(pathname);
75+
+ if (!map || get_text_start_address(pathname, &stext) < 0) {
76+
+ pr_warning("Failed to get ELF symbols for %s\n", pathname);
77+
+ return -EINVAL;
78+
+ }
79+
+
80+
+ for (i = 0; i < ntevs; i++) {
81+
+ addr = tevs[i].point.address + tevs[i].point.offset - stext;
82+
+ sym = map__find_symbol(map, addr);
83+
+ if (!sym)
84+
+ continue;
85+
+ if (!strcmp(sym->name, tevs[i].point.symbol))
86+
+ continue;
87+
+ /* If we have no realname, use symbol for it */
88+
+ if (!tevs[i].point.realname)
89+
+ tevs[i].point.realname = tevs[i].point.symbol;
90+
+ else
91+
+ free(tevs[i].point.symbol);
92+
+ tevs[i].point.symbol = strdup(sym->name);
93+
+ tevs[i].point.offset = addr - sym->start;
94+
+ }
95+
+ map__put(map);
96+
+
97+
+ return 0;
98+
+}
99+
+
100+
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
101+
int ntevs, const char *exec)
102+
{
103+
@@ -694,7 +739,8 @@ post_process_kernel_probe_trace_events(s
104+
105+
/* Skip post process if the target is an offline kernel */
106+
if (symbol_conf.ignore_vmlinux_buildid)
107+
- return 0;
108+
+ return post_process_offline_probe_trace_events(tevs, ntevs,
109+
+ symbol_conf.vmlinux_name);
110+
111+
reloc_sym = kernel_get_ref_reloc_sym();
112+
if (!reloc_sym) {
113+
114+
---
115+
116+
From 3e96dac7c956089d3f23aca98c4dfca57b6aaf8a Mon Sep 17 00:00:00 2001
117+
From: Masami Hiramatsu <mhiramat@kernel.org>
118+
Date: Wed, 11 Jan 2017 15:00:47 +0900
119+
Subject: perf probe: Add error checks to offline probe post-processing
120+
121+
From: Masami Hiramatsu <mhiramat@kernel.org>
122+
123+
commit 3e96dac7c956089d3f23aca98c4dfca57b6aaf8a upstream.
124+
125+
Add error check codes on post processing and improve it for offline
126+
probe events as:
127+
128+
- post processing fails if no matched symbol found in map(-ENOENT)
129+
or strdup() failed(-ENOMEM).
130+
131+
- Even if the symbol name is the same, it updates symbol address
132+
and offset.
133+
134+
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
135+
Cc: Jiri Olsa <jolsa@redhat.com>
136+
Cc: Namhyung Kim <namhyung@kernel.org>
137+
Cc: Peter Zijlstra <peterz@infradead.org>
138+
Link: http://lkml.kernel.org/r/148411443738.9978.4617979132625405545.stgit@devbox
139+
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
140+
Cc: Krister Johansen <kjlx@templeofstupid.com>
141+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
142+
143+
---
144+
tools/perf/util/probe-event.c | 50 +++++++++++++++++++++++++++---------------
145+
1 file changed, 33 insertions(+), 17 deletions(-)
146+
147+
--- a/tools/perf/util/probe-event.c
148+
+++ b/tools/perf/util/probe-event.c
149+
@@ -618,6 +618,33 @@ error:
150+
return ret ? : -ENOENT;
151+
}
152+
153+
+/* Adjust symbol name and address */
154+
+static int post_process_probe_trace_point(struct probe_trace_point *tp,
155+
+ struct map *map, unsigned long offs)
156+
+{
157+
+ struct symbol *sym;
158+
+ u64 addr = tp->address + tp->offset - offs;
159+
+
160+
+ sym = map__find_symbol(map, addr);
161+
+ if (!sym)
162+
+ return -ENOENT;
163+
+
164+
+ if (strcmp(sym->name, tp->symbol)) {
165+
+ /* If we have no realname, use symbol for it */
166+
+ if (!tp->realname)
167+
+ tp->realname = tp->symbol;
168+
+ else
169+
+ free(tp->symbol);
170+
+ tp->symbol = strdup(sym->name);
171+
+ if (!tp->symbol)
172+
+ return -ENOMEM;
173+
+ }
174+
+ tp->offset = addr - sym->start;
175+
+ tp->address -= offs;
176+
+
177+
+ return 0;
178+
+}
179+
+
180+
/*
181+
* Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
182+
* and generate new symbols with suffixes such as .constprop.N or .isra.N
183+
@@ -630,11 +657,9 @@ static int
184+
post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
185+
int ntevs, const char *pathname)
186+
{
187+
- struct symbol *sym;
188+
struct map *map;
189+
unsigned long stext = 0;
190+
- u64 addr;
191+
- int i;
192+
+ int i, ret = 0;
193+
194+
/* Prepare a map for offline binary */
195+
map = dso__new_map(pathname);
196+
@@ -644,23 +669,14 @@ post_process_offline_probe_trace_events(
197+
}
198+
199+
for (i = 0; i < ntevs; i++) {
200+
- addr = tevs[i].point.address + tevs[i].point.offset - stext;
201+
- sym = map__find_symbol(map, addr);
202+
- if (!sym)
203+
- continue;
204+
- if (!strcmp(sym->name, tevs[i].point.symbol))
205+
- continue;
206+
- /* If we have no realname, use symbol for it */
207+
- if (!tevs[i].point.realname)
208+
- tevs[i].point.realname = tevs[i].point.symbol;
209+
- else
210+
- free(tevs[i].point.symbol);
211+
- tevs[i].point.symbol = strdup(sym->name);
212+
- tevs[i].point.offset = addr - sym->start;
213+
+ ret = post_process_probe_trace_point(&tevs[i].point,
214+
+ map, stext);
215+
+ if (ret < 0)
216+
+ break;
217+
}
218+
map__put(map);
219+
220+
- return 0;
221+
+ return ret;
222+
}
223+
224+
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,

‎pkgs/os-specific/linux/kernel/perf.nix

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ stdenv.mkDerivation {
1313

1414
inherit (kernel) src;
1515

16-
patches = kernel.patches ++ [ ./perf-binutils-path.patch ];
16+
patches = kernel.patches ++ [ ./perf-binutils-path.patch ./perf-offline-probe.patch ];
1717

1818
preConfigure = ''
1919
cd tools/perf

0 commit comments

Comments
 (0)
Please sign in to comment.