diff options
author | Tim Steinbach <tim@nequissimus.com> | 2017-07-14 20:02:15 -0400 |
---|---|---|
committer | Tim Steinbach <tim@nequissimus.com> | 2017-07-14 20:07:16 -0400 |
commit | 954c66983df36e50ec569dce6350b8a8344d99c2 (patch) | |
tree | f329a3bea18393c2525a976217f09772bbe60846 /pkgs/os-specific | |
parent | 3ef073e9f14e55defa2cb688ed389bc6fe1d5553 (diff) | |
download | nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar.gz nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar.bz2 nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar.lz nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar.xz nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.tar.zst nixlib-954c66983df36e50ec569dce6350b8a8344d99c2.zip |
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
Diffstat (limited to 'pkgs/os-specific')
-rw-r--r-- | pkgs/os-specific/linux/kernel/perf-offline-probe.patch | 224 | ||||
-rw-r--r-- | pkgs/os-specific/linux/kernel/perf.nix | 2 |
2 files changed, 225 insertions, 1 deletions
diff --git a/pkgs/os-specific/linux/kernel/perf-offline-probe.patch b/pkgs/os-specific/linux/kernel/perf-offline-probe.patch new file mode 100644 index 000000000000..7334a339c858 --- /dev/null +++ b/pkgs/os-specific/linux/kernel/perf-offline-probe.patch @@ -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, diff --git a/pkgs/os-specific/linux/kernel/perf.nix b/pkgs/os-specific/linux/kernel/perf.nix index 3fbad924568f..cb13167eebc5 100644 --- a/pkgs/os-specific/linux/kernel/perf.nix +++ b/pkgs/os-specific/linux/kernel/perf.nix @@ -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 |