|
9 | 9 | #include <linux/hardirq.h>
|
10 | 10 | #include <linux/preempt.h>
|
11 | 11 | #include <linux/ftrace.h>
|
| 12 | +#include <asm/text-patching.h> |
12 | 13 |
|
13 | 14 | #include "common.h"
|
14 | 15 |
|
@@ -36,23 +37,25 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
36 | 37 | if (kprobe_running()) {
|
37 | 38 | kprobes_inc_nmissed_count(p);
|
38 | 39 | } else {
|
39 |
| - unsigned long orig_ip = regs->ip; |
| 40 | + unsigned long orig_ip = instruction_pointer(regs); |
| 41 | + |
40 | 42 | /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
|
41 |
| - regs->ip = ip + sizeof(kprobe_opcode_t); |
| 43 | + instruction_pointer_set(regs, ip + INT3_INSN_SIZE); |
42 | 44 |
|
43 | 45 | __this_cpu_write(current_kprobe, p);
|
44 | 46 | kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
45 | 47 | if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
46 |
| - /* |
47 |
| - * Emulate singlestep (and also recover regs->ip) |
48 |
| - * as if there is a 5byte nop |
49 |
| - */ |
50 |
| - regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE; |
51 | 48 | if (unlikely(p->post_handler)) {
|
| 49 | + /* |
| 50 | + * Emulate singlestep (and also recover regs->ip) |
| 51 | + * as if there is a 5byte nop |
| 52 | + */ |
| 53 | + instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE); |
52 | 54 | kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
53 | 55 | p->post_handler(p, regs, 0);
|
54 | 56 | }
|
55 |
| - regs->ip = orig_ip; |
| 57 | + /* Recover IP address */ |
| 58 | + instruction_pointer_set(regs, orig_ip); |
56 | 59 | }
|
57 | 60 | /*
|
58 | 61 | * If pre_handler returns !0, it changes regs->ip. We have to
|
|
0 commit comments