kprobes: indirectly call kprobe_target
[linux-2.6/mini2440.git] / kernel / test_kprobes.c
blob9c0127ead6abe6986de7a374bd7e332a3584df17
1 /*
2 * test_kprobes.c - simple sanity test for *probes
4 * Copyright IBM Corp. 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it would be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/kprobes.h>
19 #include <linux/random.h>
21 #define div_factor 3
23 static u32 rand1, preh_val, posth_val, jph_val;
24 static int errors, handler_errors, num_tests;
25 static u32 (*target)(u32 value);
27 static noinline u32 kprobe_target(u32 value)
29 return (value / div_factor);
32 static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
34 preh_val = (rand1 / div_factor);
35 return 0;
38 static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
39 unsigned long flags)
41 if (preh_val != (rand1 / div_factor)) {
42 handler_errors++;
43 printk(KERN_ERR "Kprobe smoke test failed: "
44 "incorrect value in post_handler\n");
46 posth_val = preh_val + div_factor;
49 static struct kprobe kp = {
50 .symbol_name = "kprobe_target",
51 .pre_handler = kp_pre_handler,
52 .post_handler = kp_post_handler
55 static int test_kprobe(void)
57 int ret;
59 ret = register_kprobe(&kp);
60 if (ret < 0) {
61 printk(KERN_ERR "Kprobe smoke test failed: "
62 "register_kprobe returned %d\n", ret);
63 return ret;
66 ret = target(rand1);
67 unregister_kprobe(&kp);
69 if (preh_val == 0) {
70 printk(KERN_ERR "Kprobe smoke test failed: "
71 "kprobe pre_handler not called\n");
72 handler_errors++;
75 if (posth_val == 0) {
76 printk(KERN_ERR "Kprobe smoke test failed: "
77 "kprobe post_handler not called\n");
78 handler_errors++;
81 return 0;
84 static u32 j_kprobe_target(u32 value)
86 if (value != rand1) {
87 handler_errors++;
88 printk(KERN_ERR "Kprobe smoke test failed: "
89 "incorrect value in jprobe handler\n");
92 jph_val = rand1;
93 jprobe_return();
94 return 0;
97 static struct jprobe jp = {
98 .entry = j_kprobe_target,
99 .kp.symbol_name = "kprobe_target"
102 static int test_jprobe(void)
104 int ret;
106 ret = register_jprobe(&jp);
107 if (ret < 0) {
108 printk(KERN_ERR "Kprobe smoke test failed: "
109 "register_jprobe returned %d\n", ret);
110 return ret;
113 ret = target(rand1);
114 unregister_jprobe(&jp);
115 if (jph_val == 0) {
116 printk(KERN_ERR "Kprobe smoke test failed: "
117 "jprobe handler not called\n");
118 handler_errors++;
121 return 0;
124 #ifdef CONFIG_KRETPROBES
125 static u32 krph_val;
127 static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
129 krph_val = (rand1 / div_factor);
130 return 0;
133 static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
135 unsigned long ret = regs_return_value(regs);
137 if (ret != (rand1 / div_factor)) {
138 handler_errors++;
139 printk(KERN_ERR "Kprobe smoke test failed: "
140 "incorrect value in kretprobe handler\n");
142 if (krph_val == 0) {
143 handler_errors++;
144 printk(KERN_ERR "Kprobe smoke test failed: "
145 "call to kretprobe entry handler failed\n");
148 krph_val = rand1;
149 return 0;
152 static struct kretprobe rp = {
153 .handler = return_handler,
154 .entry_handler = entry_handler,
155 .kp.symbol_name = "kprobe_target"
158 static int test_kretprobe(void)
160 int ret;
162 ret = register_kretprobe(&rp);
163 if (ret < 0) {
164 printk(KERN_ERR "Kprobe smoke test failed: "
165 "register_kretprobe returned %d\n", ret);
166 return ret;
169 ret = target(rand1);
170 unregister_kretprobe(&rp);
171 if (krph_val != rand1) {
172 printk(KERN_ERR "Kprobe smoke test failed: "
173 "kretprobe handler not called\n");
174 handler_errors++;
177 return 0;
179 #endif /* CONFIG_KRETPROBES */
181 int init_test_probes(void)
183 int ret;
185 target = kprobe_target;
187 do {
188 rand1 = random32();
189 } while (rand1 <= div_factor);
191 printk(KERN_INFO "Kprobe smoke test started\n");
192 num_tests++;
193 ret = test_kprobe();
194 if (ret < 0)
195 errors++;
197 num_tests++;
198 ret = test_jprobe();
199 if (ret < 0)
200 errors++;
202 #ifdef CONFIG_KRETPROBES
203 num_tests++;
204 ret = test_kretprobe();
205 if (ret < 0)
206 errors++;
207 #endif /* CONFIG_KRETPROBES */
209 if (errors)
210 printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
211 "%d tests failed\n", errors, num_tests);
212 else if (handler_errors)
213 printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
214 "running handlers\n", handler_errors);
215 else
216 printk(KERN_INFO "Kprobe smoke test passed successfully\n");
218 return 0;