Subject: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

From: Ananth N Mavinakayanahalli <[email protected]>

Here is a quick and naive smoke test for kprobes. This is intended to
just verify if some unrelated change broke the *probes subsystem. It is
self contained, architecture agnostic and isn't of any great use by itself.

This needs to be built in the kernel and runs a basic set of tests to
verify if kprobes, jprobes and kretprobes run fine on the kernel. In case
of an error, it'll print out a message with a "BUG" prefix.

This is a start; we intend to add more tests to this bucket over time.

Thanks to Jim Keniston and Masami Hiramatsu for comments and suggestions.

Tested on x86 (32/64) and powerpc.

Signed-off-by: Ananth N Mavinakayanahalli <[email protected]>
Acked-by: Masami Hiramatsu <[email protected]>
---
include/linux/kprobes.h | 10 ++
kernel/Makefile | 1
kernel/kprobes.c | 2
kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/Kconfig.debug | 12 ++
5 files changed, 241 insertions(+)

Index: linux-2.6.24-rc6/kernel/Makefile
===================================================================
--- linux-2.6.24-rc6.orig/kernel/Makefile
+++ linux-2.6.24-rc6/kernel/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
obj-$(CONFIG_SECCOMP) += seccomp.o
obj-$(CONFIG_DEBUG_SYNCHRO_TEST) += synchro-test.o
obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
+obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o
obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o
ifeq ($(CONFIG_PREEMPT_RCU),y)
Index: linux-2.6.24-rc6/kernel/test_kprobes.c
===================================================================
--- /dev/null
+++ linux-2.6.24-rc6/kernel/test_kprobes.c
@@ -0,0 +1,216 @@
+/*
+ * test_kprobes.c - simple sanity test for *probes
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/random.h>
+
+#define div_factor 3
+
+static u32 rand1, preh_val, posth_val, jph_val;
+static int errors, handler_errors, num_tests;
+
+static noinline u32 kprobe_target(u32 value)
+{
+ /*
+ * gcc ignores noinline on some architectures unless we stuff
+ * sufficient lard into the function. The get_kprobe() here is
+ * just for that.
+ *
+ * NOTE: We aren't concerned about the correctness of get_kprobe()
+ * here; hence, this call is neither under !preempt nor with the
+ * kprobe_mutex held. This is fine(tm)
+ */
+ if (get_kprobe((void *)0xdeadbeef))
+ printk(KERN_INFO "Kprobe smoke test: probe on 0xdeadbeef!\n");
+
+ return (value / div_factor);
+}
+
+static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ preh_val = (rand1 / div_factor);
+ return 0;
+}
+
+static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ if (preh_val != (rand1 / div_factor)) {
+ handler_errors++;
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "incorrect value in post_handler\n");
+ }
+ posth_val = preh_val + div_factor;
+}
+
+static struct kprobe kp = {
+ .symbol_name = "kprobe_target",
+ .pre_handler = kp_pre_handler,
+ .post_handler = kp_post_handler
+};
+
+static int test_kprobe(void)
+{
+ int ret;
+
+ ret = register_kprobe(&kp);
+ if (ret < 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "register_kprobe returned %d\n", ret);
+ return ret;
+ }
+
+ ret = kprobe_target(rand1);
+ unregister_kprobe(&kp);
+
+ if (preh_val == 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "kprobe pre_handler not called\n");
+ handler_errors++;
+ }
+
+ if (posth_val == 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "kprobe post_handler not called\n");
+ handler_errors++;
+ }
+
+ return 0;
+}
+
+static u32 j_kprobe_target(u32 value)
+{
+ if (value != rand1) {
+ handler_errors++;
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "incorrect value in jprobe handler\n");
+ }
+
+ jph_val = rand1;
+ jprobe_return();
+ return 0;
+}
+
+static struct jprobe jp = {
+ .entry = j_kprobe_target,
+ .kp.symbol_name = "kprobe_target"
+};
+
+static int test_jprobe(void)
+{
+ int ret;
+
+ ret = register_jprobe(&jp);
+ if (ret < 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "register_jprobe returned %d\n", ret);
+ return ret;
+ }
+
+ ret = kprobe_target(rand1);
+ unregister_jprobe(&jp);
+ if (jph_val == 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "jprobe handler not called\n");
+ handler_errors++;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_KRETPROBES
+static u32 krph_val;
+
+static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ unsigned long ret = regs_return_value(regs);
+
+ if (ret != (rand1 / div_factor)) {
+ handler_errors++;
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "incorrect value in kretprobe handler\n");
+ }
+
+ krph_val = (rand1 / div_factor);
+ return 0;
+}
+
+static struct kretprobe rp = {
+ .handler = return_handler,
+ .kp.symbol_name = "kprobe_target"
+};
+
+static int test_kretprobe(void)
+{
+ int ret;
+
+ ret = register_kretprobe(&rp);
+ if (ret < 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "register_kretprobe returned %d\n", ret);
+ return ret;
+ }
+
+ ret = kprobe_target(rand1);
+ unregister_kretprobe(&rp);
+ if (krph_val == 0) {
+ printk(KERN_ERR "Kprobe smoke test failed: "
+ "kretprobe handler not called\n");
+ handler_errors++;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_KRETPROBES */
+
+int init_test_probes(void)
+{
+ int ret;
+
+ do {
+ rand1 = random32();
+ } while (rand1 <= div_factor);
+
+ printk(KERN_INFO "Kprobe smoke test started\n");
+ num_tests++;
+ ret = test_kprobe();
+ if (ret < 0)
+ errors++;
+
+ num_tests++;
+ ret = test_jprobe();
+ if (ret < 0)
+ errors++;
+
+#ifdef CONFIG_KRETPROBES
+ num_tests++;
+ ret = test_kretprobe();
+ if (ret < 0)
+ errors++;
+#endif /* CONFIG_KRETPROBES */
+
+ if (errors)
+ printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
+ "%d tests failed\n", errors, num_tests);
+ else if (handler_errors)
+ printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
+ "running handlers\n", handler_errors);
+ else
+ printk(KERN_INFO "Kprobe smoke test passed successfully\n");
+
+ return 0;
+}
Index: linux-2.6.24-rc6/lib/Kconfig.debug
===================================================================
--- linux-2.6.24-rc6.orig/lib/Kconfig.debug
+++ linux-2.6.24-rc6/lib/Kconfig.debug
@@ -511,6 +511,18 @@ config RCU_TORTURE_TEST
Say M if you want the RCU torture tests to build as a module.
Say N if you are unsure.

+config KPROBES_SANITY_TEST
+ bool "Kprobes sanity tests"
+ depends on DEBUG_KERNEL
+ depends on KPROBES
+ default n
+ help
+ This option provides for testing basic kprobes functionality on
+ boot. A sample kprobe, jprobe and kretprobe are inserted and
+ verified for functionality.
+
+ Say N if you are unsure.
+
config LKDTM
tristate "Linux Kernel Dump Test Tool Module"
depends on DEBUG_KERNEL
Index: linux-2.6.24-rc6/include/linux/kprobes.h
===================================================================
--- linux-2.6.24-rc6.orig/include/linux/kprobes.h
+++ linux-2.6.24-rc6/include/linux/kprobes.h
@@ -182,6 +182,15 @@ static inline void kretprobe_assert(stru
}
}

+#ifdef CONFIG_KPROBES_SANITY_TEST
+extern int init_test_probes(void);
+#else
+static inline int init_test_probes(void)
+{
+ return 0;
+}
+#endif /* CONFIG_KPROBES_SANITY_TEST */
+
extern spinlock_t kretprobe_lock;
extern struct mutex kprobe_mutex;
extern int arch_prepare_kprobe(struct kprobe *p);
@@ -227,6 +236,7 @@ void unregister_kretprobe(struct kretpro

void kprobe_flush_task(struct task_struct *tk);
void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
+
#else /* CONFIG_KPROBES */

#define __kprobes /**/
Index: linux-2.6.24-rc6/kernel/kprobes.c
===================================================================
--- linux-2.6.24-rc6.orig/kernel/kprobes.c
+++ linux-2.6.24-rc6/kernel/kprobes.c
@@ -821,6 +821,8 @@ static int __init init_kprobes(void)
if (!err)
err = register_die_notifier(&kprobe_exceptions_nb);

+ if (!err)
+ init_test_probes();
return err;
}


2008-01-08 09:16:59

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot


* Ananth N Mavinakayanahalli <[email protected]> wrote:

> From: Ananth N Mavinakayanahalli <[email protected]>
>
> Here is a quick and naive smoke test for kprobes. This is intended to
> just verify if some unrelated change broke the *probes subsystem. It
> is self contained, architecture agnostic and isn't of any great use by
> itself.
>
> This needs to be built in the kernel and runs a basic set of tests to
> verify if kprobes, jprobes and kretprobes run fine on the kernel. In
> case of an error, it'll print out a message with a "BUG" prefix.

yay! Picked this up into x86.git for testing.

small detail: i moved the kernel/Makefile change to another spot (see
below), this way it integrates without rejects with rcu-preempt and with
the kgdb changes.

Ingo

Index: linux-x86.q/kernel/Makefile
===================================================================
--- linux-x86.q.orig/kernel/Makefile
+++ linux-x86.q/kernel/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
+obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_AUDIT_TREE) += audit_tree.o

2008-01-08 21:00:38

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

Ananth N Mavinakayanahalli <[email protected]> writes:
> kernel/kprobes.c | 2
> kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++

Can you put this somewhere else please? I know there are already some
test files in kernel/* but imho they all belong into some other directory.

+ if (!err)
+ init_test_probes();
return err;

Couldn't this be just a normal initcall? Perhaps even a module_init(),
then it would be possible to use as a module too.

-Andi

2008-01-08 22:22:35

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot


* Andi Kleen <[email protected]> wrote:

> Ananth N Mavinakayanahalli <[email protected]> writes:
> > kernel/kprobes.c | 2
> > kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
>
> Can you put this somewhere else please? I know there are already some
> test files in kernel/* but imho they all belong into some other
> directory.

agreed - lib/* would be the right place i think - we've got
lib/locking-selftest.c already.

Ingo

2008-01-08 22:47:18

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Tue, Jan 08, 2008 at 11:18:02PM +0100, Ingo Molnar wrote:
>
> * Andi Kleen <[email protected]> wrote:
>
> > Ananth N Mavinakayanahalli <[email protected]> writes:
> > > kernel/kprobes.c | 2
> > > kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
> >
> > Can you put this somewhere else please? I know there are already some
> > test files in kernel/* but imho they all belong into some other
> > directory.
>
> agreed - lib/* would be the right place i think - we've got
> lib/locking-selftest.c already.

Why not test/ ?

I felt a little bad about not introducing arch/x86/test/ for pageattr-test.c either.

-Andi

2008-01-08 22:51:48

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot


* Andi Kleen <[email protected]> wrote:

> > agreed - lib/* would be the right place i think - we've got
> > lib/locking-selftest.c already.
>
> Why not test/ ?
>
> I felt a little bad about not introducing arch/x86/test/ for
> pageattr-test.c either.

yeah, test/ would be even better, and then move locking-selftest over
there too, plus the rt-mutex tester as well i suspect, and rcutorture.

Ingo

2008-01-08 23:16:06

by Jim Keniston

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Tue, 2008-01-08 at 22:00 +0100, Andi Kleen wrote:
> Ananth N Mavinakayanahalli <[email protected]> writes:
> > kernel/kprobes.c | 2
> > kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
>
> Can you put this somewhere else please? I know there are already some
> test files in kernel/* but imho they all belong into some other directory.
>
> + if (!err)
> + init_test_probes();
> return err;
>
> Couldn't this be just a normal initcall? Perhaps even a module_init(),
> then it would be possible to use as a module too.
>
> -Andi

I have no problem with that, but if we want to make it buildable as a
module, the call to get_kprobe() needs to be replaced with some other
gcc-inline-defeating mechanism, or we need to export get_probe(). I
much prefer the former, since get_kprobe() is a kprobes-internal
function.

Anybody know an architecture-independent way (other than noinline, which
doesn't always work) of making gcc decide not to inline a function?
E.g., does taking (and using) the function's address do it?

Jim Keniston

>From Ananth's patch:
+static noinline u32 kprobe_target(u32 value)
+{
+ /*
+ * gcc ignores noinline on some architectures unless we stuff
+ * sufficient lard into the function. The get_kprobe() here is
+ * just for that.
+ *
+ * NOTE: We aren't concerned about the correctness of
get_kprobe()
+ * here; hence, this call is neither under !preempt nor with the
+ * kprobe_mutex held. This is fine(tm)
+ */
+ if (get_kprobe((void *)0xdeadbeef))
+ printk(KERN_INFO "Kprobe smoke test: probe on
0xdeadbeef!\n");
+
+ return (value / div_factor);
+}

2008-01-08 23:26:23

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

> I have no problem with that, but if we want to make it buildable as a
> module, the call to get_kprobe() needs to be replaced with some other
> gcc-inline-defeating mechanism, or we need to export get_probe(). I

It's still unclear where noinline does not work (do you have details on that?
It sounds a little dubious) but there are lots of different other ways to prevent gcc
from inlining anything.

e.g. you can use stdarg or computed goto or a variable length local array


> much prefer the former, since get_kprobe() is a kprobes-internal
> function.
>
> Anybody know an architecture-independent way (other than noinline, which
> doesn't always work) of making gcc decide not to inline a function?

Details?

> E.g., does taking (and using) the function's address do it?

No, that just creates another out of line copy.

-Andi

2008-01-09 07:43:20

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

From: Ananth N Mavinakayanahalli <[email protected]>
Date: Tue, 8 Jan 2008 12:03:34 +0530

> Here is a quick and naive smoke test for kprobes.

Thanks very much for writing this.

It will come in handy for me when I work on sparc64
kretprobe support.

2008-01-09 08:00:26

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Tue, Jan 08, 2008 at 11:18:02PM +0100, Ingo Molnar wrote:
>
> * Andi Kleen <[email protected]> wrote:
>
> > Ananth N Mavinakayanahalli <[email protected]> writes:
> > > kernel/kprobes.c | 2
> > > kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
> >
> > Can you put this somewhere else please? I know there are already some
> > test files in kernel/* but imho they all belong into some other
> > directory.
>
> agreed - lib/* would be the right place i think - we've got
> lib/locking-selftest.c already.

Actually the right place would be to have a separate toplevel directory
I think, and a separate menu in the kernel config machinery. Thay way
tests are in one place and easily spottable.

2008-01-09 08:08:16

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Wed, Jan 09, 2008 at 08:00:03AM +0000, Christoph Hellwig wrote:
> On Tue, Jan 08, 2008 at 11:18:02PM +0100, Ingo Molnar wrote:
> >
> > * Andi Kleen <[email protected]> wrote:
> >
> > > Ananth N Mavinakayanahalli <[email protected]> writes:
> > > > kernel/kprobes.c | 2
> > > > kernel/test_kprobes.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > > Can you put this somewhere else please? I know there are already some
> > > test files in kernel/* but imho they all belong into some other
> > > directory.
> >
> > agreed - lib/* would be the right place i think - we've got
> > lib/locking-selftest.c already.
>
> Actually the right place would be to have a separate toplevel directory
> I think, and a separate menu in the kernel config machinery. Thay way
> tests are in one place and easily spottable.

Seconded...

Sam

2008-01-09 20:29:36

by Jim Keniston

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Wed, 2008-01-09 at 00:28 +0100, Andi Kleen wrote:
> > I have no problem with that, but if we want to make it buildable as a
> > module, the call to get_kprobe() needs to be replaced with some other
> > gcc-inline-defeating mechanism, or we need to export get_probe(). I
>
> It's still unclear where noinline does not work (do you have details on that?
> It sounds a little dubious) ...

Here's a simplified version of a module we've used to gauge kprobes
performance. On my system (i386, 2.6.23-rc8 at the moment, gcc version
4.1.2), the module calls the (empty) probed function (probeme) niter
times, but reports zero probe hits -- indicating probeme was inlined
even though it was declared noinline.

If I change probeme to a varargs function, per your suggestion -- see
diffs below -- the proper number of probe hits are reported.
----- noinline.c -----
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kprobes.h>

/*
* Sample usage: insmod noinline.ko niter=5000000
* printk should report 5000000 calls.
*/

static int niter = 0;
module_param(niter, int, 0);
MODULE_PARM_DESC(niter, "iterations");

static int ncalls = 0;

static int counter_hdlr(struct kprobe *p, struct pt_regs *regs)
{
ncalls++;
return 0;
}

// #define noinline __attribute__((noinline))
noinline static void probeme(void)
{
}

struct kprobe kp = {
.addr = (kprobe_opcode_t*) probeme,
.pre_handler = counter_hdlr
};

static int __init noinline_init(void)
{
int ret;
int i;
u64 start, stop;

ret = register_kprobe(&kp);
if (ret != 0) {
printk(KERN_ERR "register_kprobe returns %d\n", ret);
return ret;
}

start = get_jiffies_64();
for (i = 1; i <= niter; i++)
probeme();
stop = get_jiffies_64();
printk(KERN_INFO "noinline test: %d iterations in %lld jiffies\n",
niter, stop-start);
printk(KERN_INFO "Counted %d calls\n", ncalls);
return 0;
}

static void __exit noinline_exit(void)
{
unregister_kprobe(&kp);
printk(KERN_INFO "noinline test: exiting...\n");
}

module_init(noinline_init);
module_exit(noinline_exit);
MODULE_LICENSE("GPL");
----- Change probeme to a varargs function -----
--- noinline.c 2008-01-09 11:26:09.000000000 -0800
+++ noinline2.c 2008-01-09 11:59:54.000000000 -0800
@@ -22,8 +22,13 @@
}

// #define noinline __attribute__((noinline))
-noinline static void probeme(void)
+noinline static void probeme(int nargs, ...)
{
+ va_list args;
+ va_start(args, nargs);
+ while (nargs-- > 0)
+ printk(KERN_INFO "%p\n", va_arg(args, char*));
+ va_end(args);
}

struct kprobe kp = {
@@ -45,9 +50,9 @@

start = get_jiffies_64();
for (i = 1; i <= niter; i++)
- probeme();
+ probeme(0);
stop = get_jiffies_64();
- printk(KERN_INFO "noinline test: %d iterations in %lld jiffies\n",
+ printk(KERN_INFO "noinline2 test: %d iterations in %lld jiffies\n",
niter, stop-start);
printk(KERN_INFO "Counted %d calls\n", ncalls);
return 0;
@@ -56,7 +61,7 @@
static void __exit noinline_exit(void)
{
unregister_kprobe(&kp);
- printk(KERN_INFO "noinline test: exiting...\n");
+ printk(KERN_INFO "noinline2 test: exiting...\n");
}

module_init(noinline_init);

...
> -Andi

Thanks for the suggestions.
Jim

2008-01-09 21:18:46

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Wed, Jan 09, 2008 at 12:24:00PM -0800, Jim Keniston wrote:
> On Wed, 2008-01-09 at 00:28 +0100, Andi Kleen wrote:
> > > I have no problem with that, but if we want to make it buildable as a
> > > module, the call to get_kprobe() needs to be replaced with some other
> > > gcc-inline-defeating mechanism, or we need to export get_probe(). I
> >
> > It's still unclear where noinline does not work (do you have details on that?
> > It sounds a little dubious) ...
>
> Here's a simplified version of a module we've used to gauge kprobes
> performance. On my system (i386, 2.6.23-rc8 at the moment, gcc version
> 4.1.2), the module calls the (empty) probed function (probeme) niter
> times, but reports zero probe hits -- indicating probeme was inlined
> even though it was declared noinline.

Yes indeed looks like a gcc bug. Have you reported it?

-Andi

2008-01-09 22:39:37

by Jim Keniston

[permalink] [raw]
Subject: Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

On Wed, 2008-01-09 at 22:21 +0100, Andi Kleen wrote:
> On Wed, Jan 09, 2008 at 12:24:00PM -0800, Jim Keniston wrote:
> > On Wed, 2008-01-09 at 00:28 +0100, Andi Kleen wrote:
> > > > I have no problem with that, but if we want to make it buildable as a
> > > > module, the call to get_kprobe() needs to be replaced with some other
> > > > gcc-inline-defeating mechanism, or we need to export get_probe(). I
> > >
> > > It's still unclear where noinline does not work (do you have details on that?
> > > It sounds a little dubious) ...
> >
> > Here's a simplified version of a module we've used to gauge kprobes
> > performance. On my system (i386, 2.6.23-rc8 at the moment, gcc version
> > 4.1.2), the module calls the (empty) probed function (probeme) niter
> > times, but reports zero probe hits -- indicating probeme was inlined
> > even though it was declared noinline.
>
> Yes indeed looks like a gcc bug. Have you reported it?
>
> -Andi

There's already a gcc bug report that appears to describe the same
problem:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34563
There seems to be some doubt as to whether it's really a bug, so I added
my 2 cents, including a pointer to this thread.

Jim