2013-04-05 02:39:11

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH] perf probe: Enhance error message on non-kprobeable functions

From: Namhyung Kim <[email protected]>

Some of kernel functions are not allowed to be used by kprobes for
some reason, so they're marked as __kprobe on the source code and
reside on ".kprobes.text" section.

However normal users which only see /proc/kallsyms don't know about
them and would get only general error message when tried to add a
probe on such function.

$ sudo ./perf probe do_page_fault
Failed to find path of kernel module.
Added new event:
Failed to write event: Invalid argument
Error: Failed to add events. (-1)

This patch enhance it by checking the special kprobes section address
and if to-be-probed function address is in the section, it would print
like this:

$ sudo ./perf probe do_page_fault
Failed to find path of kernel module.
Added new event:
Failed to write event: kprobes is not allowed for this function.
Error: Failed to add events. (-1)

Cc: OSDepend <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/probe-event.c | 47 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index aa04bf9c9ad7..3a49c47eb77c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -112,6 +112,38 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
NULL);
}

+static bool check_kprobes_section(const char *name)
+{
+ struct symbol *sym;
+ static uint64_t kprobes_start, kprobes_end;
+
+ if (!kprobes_start) {
+ sym = __find_kernel_function_by_name("__kprobes_text_start",
+ NULL);
+ if (sym == NULL)
+ return false;
+ kprobes_start = sym->start;
+
+ sym = __find_kernel_function_by_name("__kprobes_text_end",
+ NULL);
+ if (sym == NULL) {
+ /* invalidate start address too */
+ kprobes_start = 0;
+ return false;
+ }
+ kprobes_end = sym->start;
+ pr_debug("kprobes section: %#"PRIx64"-%#"PRIx64"\n",
+ kprobes_start, kprobes_end);
+ }
+
+ sym = __find_kernel_function_by_name(name, NULL);
+ if (sym) {
+ if (kprobes_start <= sym->start && sym->end <= kprobes_end)
+ return true;
+ }
+ return false;
+}
+
static struct map *kernel_get_module_map(const char *module)
{
struct rb_node *nd;
@@ -1773,9 +1805,18 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
pr_debug("Writing event: %s\n", buf);
if (!probe_event_dry_run) {
ret = write(fd, buf, strlen(buf));
- if (ret <= 0)
- pr_warning("Failed to write event: %s\n",
- strerror(errno));
+ if (ret <= 0) {
+ char errbuf[512];
+
+ /* save original error string before it's overwritten */
+ strerror_r(errno, errbuf, sizeof(errbuf));
+
+ if (!tev->uprobes && check_kprobes_section(tev->event)) {
+ scnprintf(errbuf, sizeof(errbuf),
+ "kprobes is not allowed for this function.");
+ }
+ pr_warning("Failed to write event: %s\n", errbuf);
+ }
}
free(buf);
return ret;
--
1.7.11.7


Subject: Re: [PATCH] perf probe: Enhance error message on non-kprobeable functions

(2013/04/05 11:39), Namhyung Kim wrote:
> From: Namhyung Kim <[email protected]>
>
> Some of kernel functions are not allowed to be used by kprobes for
> some reason, so they're marked as __kprobe on the source code and
> reside on ".kprobes.text" section.
>
> However normal users which only see /proc/kallsyms don't know about
> them and would get only general error message when tried to add a
> probe on such function.

Right,

>
> $ sudo ./perf probe do_page_fault
> Failed to find path of kernel module.
> Added new event:
> Failed to write event: Invalid argument
> Error: Failed to add events. (-1)
>
> This patch enhance it by checking the special kprobes section address
> and if to-be-probed function address is in the section, it would print
> like this:
>
> $ sudo ./perf probe do_page_fault
> Failed to find path of kernel module.
> Added new event:
> Failed to write event: kprobes is not allowed for this function.
> Error: Failed to add events. (-1)

Yeah, I agree that it is hard to know for perf probe users.
However, your implementation strongly depends on the current kernel,
I think we'd better export __kprobe_text_* as macros of symbol strings
in kprobes.h, and reuse it.
Or, export such no-probe symbols via /sys/kernel/debug/kprobes/noprobe_syms

Thank you,


--
Masami HIRAMATSU
IT Management Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: [email protected]