diff options
Diffstat (limited to 'arch/arm/kernel/kprobes.c')
-rw-r--r-- | arch/arm/kernel/kprobes.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index a9050bad443..b6e9a1cc1c5 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -207,6 +207,20 @@ static void __kprobes set_current_kprobe(struct kprobe *p) | |||
207 | __get_cpu_var(current_kprobe) = p; | 207 | __get_cpu_var(current_kprobe) = p; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void __kprobes | ||
211 | singlestep_skip(struct kprobe *p, struct pt_regs *regs) | ||
212 | { | ||
213 | #ifdef CONFIG_THUMB2_KERNEL | ||
214 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | ||
215 | if (is_wide_instruction(p->opcode)) | ||
216 | regs->ARM_pc += 4; | ||
217 | else | ||
218 | regs->ARM_pc += 2; | ||
219 | #else | ||
220 | regs->ARM_pc += 4; | ||
221 | #endif | ||
222 | } | ||
223 | |||
210 | static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, | 224 | static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, |
211 | struct kprobe_ctlblk *kcb) | 225 | struct kprobe_ctlblk *kcb) |
212 | { | 226 | { |
@@ -262,7 +276,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs) | |||
262 | /* impossible cases */ | 276 | /* impossible cases */ |
263 | BUG(); | 277 | BUG(); |
264 | } | 278 | } |
265 | } else { | 279 | } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) { |
280 | /* Probe hit and conditional execution check ok. */ | ||
266 | set_current_kprobe(p); | 281 | set_current_kprobe(p); |
267 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | 282 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; |
268 | 283 | ||
@@ -282,6 +297,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs) | |||
282 | } | 297 | } |
283 | reset_current_kprobe(); | 298 | reset_current_kprobe(); |
284 | } | 299 | } |
300 | } else { | ||
301 | /* | ||
302 | * Probe hit but conditional execution check failed, | ||
303 | * so just skip the instruction and continue as if | ||
304 | * nothing had happened. | ||
305 | */ | ||
306 | singlestep_skip(p, regs); | ||
285 | } | 307 | } |
286 | } else if (cur) { | 308 | } else if (cur) { |
287 | /* We probably hit a jprobe. Call its break handler. */ | 309 | /* We probably hit a jprobe. Call its break handler. */ |