diff options
| -rw-r--r-- | arch/arm/include/asm/probes.h | 9 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 61 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-common.c | 40 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-thumb.c | 175 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes.c | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.c | 33 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.h | 15 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-thumb.c | 15 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.c | 13 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.h | 8 |
10 files changed, 201 insertions, 170 deletions
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 737a9b310efc..4d014c4aa1e7 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h | |||
| @@ -21,9 +21,14 @@ | |||
| 21 | 21 | ||
| 22 | struct kprobe; | 22 | struct kprobe; |
| 23 | 23 | ||
| 24 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); | 24 | struct arch_specific_insn; |
| 25 | typedef void (kprobe_insn_handler_t)(kprobe_opcode_t, | ||
| 26 | struct arch_specific_insn *, | ||
| 27 | struct pt_regs *); | ||
| 25 | typedef unsigned long (kprobe_check_cc)(unsigned long); | 28 | typedef unsigned long (kprobe_check_cc)(unsigned long); |
| 26 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); | 29 | typedef void (kprobe_insn_singlestep_t)(kprobe_opcode_t, |
| 30 | struct arch_specific_insn *, | ||
| 31 | struct pt_regs *); | ||
| 27 | typedef void (kprobe_insn_fn_t)(void); | 32 | typedef void (kprobe_insn_fn_t)(void); |
| 28 | 33 | ||
| 29 | /* Architecture specific copy of original instruction. */ | 34 | /* Architecture specific copy of original instruction. */ |
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 8ebd84c48867..4a232e682e5a 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
| @@ -72,12 +72,11 @@ | |||
| 72 | "mov pc, "reg" \n\t" | 72 | "mov pc, "reg" \n\t" |
| 73 | #endif | 73 | #endif |
| 74 | 74 | ||
| 75 | |||
| 76 | static void __kprobes | 75 | static void __kprobes |
| 77 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 76 | emulate_ldrdstrd(kprobe_opcode_t insn, |
| 77 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
| 78 | { | 78 | { |
| 79 | kprobe_opcode_t insn = p->opcode; | 79 | unsigned long pc = regs->ARM_pc + 4; |
| 80 | unsigned long pc = (unsigned long)p->addr + 8; | ||
| 81 | int rt = (insn >> 12) & 0xf; | 80 | int rt = (insn >> 12) & 0xf; |
| 82 | int rn = (insn >> 16) & 0xf; | 81 | int rn = (insn >> 16) & 0xf; |
| 83 | int rm = insn & 0xf; | 82 | int rm = insn & 0xf; |
| @@ -92,7 +91,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
| 92 | BLX("%[fn]") | 91 | BLX("%[fn]") |
| 93 | : "=r" (rtv), "=r" (rt2v), "=r" (rnv) | 92 | : "=r" (rtv), "=r" (rt2v), "=r" (rnv) |
| 94 | : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), | 93 | : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), |
| 95 | [fn] "r" (p->ainsn.insn_fn) | 94 | [fn] "r" (asi->insn_fn) |
| 96 | : "lr", "memory", "cc" | 95 | : "lr", "memory", "cc" |
| 97 | ); | 96 | ); |
| 98 | 97 | ||
| @@ -103,10 +102,10 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | static void __kprobes | 104 | static void __kprobes |
| 106 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) | 105 | emulate_ldr(kprobe_opcode_t insn, |
| 106 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
| 107 | { | 107 | { |
| 108 | kprobe_opcode_t insn = p->opcode; | 108 | unsigned long pc = regs->ARM_pc + 4; |
| 109 | unsigned long pc = (unsigned long)p->addr + 8; | ||
| 110 | int rt = (insn >> 12) & 0xf; | 109 | int rt = (insn >> 12) & 0xf; |
| 111 | int rn = (insn >> 16) & 0xf; | 110 | int rn = (insn >> 16) & 0xf; |
| 112 | int rm = insn & 0xf; | 111 | int rm = insn & 0xf; |
| @@ -119,7 +118,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
| 119 | __asm__ __volatile__ ( | 118 | __asm__ __volatile__ ( |
| 120 | BLX("%[fn]") | 119 | BLX("%[fn]") |
| 121 | : "=r" (rtv), "=r" (rnv) | 120 | : "=r" (rtv), "=r" (rnv) |
| 122 | : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 121 | : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
| 123 | : "lr", "memory", "cc" | 122 | : "lr", "memory", "cc" |
| 124 | ); | 123 | ); |
| 125 | 124 | ||
| @@ -133,11 +132,11 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | static void __kprobes | 134 | static void __kprobes |
| 136 | emulate_str(struct kprobe *p, struct pt_regs *regs) | 135 | emulate_str(kprobe_opcode_t insn, |
| 136 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
| 137 | { | 137 | { |
| 138 | kprobe_opcode_t insn = p->opcode; | 138 | unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; |
| 139 | unsigned long rtpc = (unsigned long)p->addr + str_pc_offset; | 139 | unsigned long rnpc = regs->ARM_pc + 4; |
| 140 | unsigned long rnpc = (unsigned long)p->addr + 8; | ||
| 141 | int rt = (insn >> 12) & 0xf; | 140 | int rt = (insn >> 12) & 0xf; |
| 142 | int rn = (insn >> 16) & 0xf; | 141 | int rn = (insn >> 16) & 0xf; |
| 143 | int rm = insn & 0xf; | 142 | int rm = insn & 0xf; |
| @@ -151,7 +150,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
| 151 | __asm__ __volatile__ ( | 150 | __asm__ __volatile__ ( |
| 152 | BLX("%[fn]") | 151 | BLX("%[fn]") |
| 153 | : "=r" (rnv) | 152 | : "=r" (rnv) |
| 154 | : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 153 | : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
| 155 | : "lr", "memory", "cc" | 154 | : "lr", "memory", "cc" |
| 156 | ); | 155 | ); |
| 157 | 156 | ||
| @@ -160,10 +159,10 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
| 160 | } | 159 | } |
| 161 | 160 | ||
| 162 | static void __kprobes | 161 | static void __kprobes |
| 163 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | 162 | emulate_rd12rn16rm0rs8_rwflags(kprobe_opcode_t insn, |
| 163 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
| 164 | { | 164 | { |
| 165 | kprobe_opcode_t insn = p->opcode; | 165 | unsigned long pc = regs->ARM_pc + 4; |
| 166 | unsigned long pc = (unsigned long)p->addr + 8; | ||
| 167 | int rd = (insn >> 12) & 0xf; | 166 | int rd = (insn >> 12) & 0xf; |
| 168 | int rn = (insn >> 16) & 0xf; | 167 | int rn = (insn >> 16) & 0xf; |
| 169 | int rm = insn & 0xf; | 168 | int rm = insn & 0xf; |
| @@ -183,7 +182,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
| 183 | "mrs %[cpsr], cpsr \n\t" | 182 | "mrs %[cpsr], cpsr \n\t" |
| 184 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 183 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
| 185 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | 184 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), |
| 186 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 185 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
| 187 | : "lr", "memory", "cc" | 186 | : "lr", "memory", "cc" |
| 188 | ); | 187 | ); |
| 189 | 188 | ||
| @@ -195,9 +194,9 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
| 195 | } | 194 | } |
| 196 | 195 | ||
| 197 | static void __kprobes | 196 | static void __kprobes |
| 198 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 197 | emulate_rd12rn16rm0_rwflags_nopc(kprobe_opcode_t insn, |
| 198 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
| 199 | { | 199 | { |
| 200 | kprobe_opcode_t insn = p->opcode; | ||
| 201 | int rd = (insn >> 12) & 0xf; | 200 | int rd = (insn >> 12) & 0xf; |
| 202 | int rn = (insn >> 16) & 0xf; | 201 | int rn = (insn >> 16) & 0xf; |
| 203 | int rm = insn & 0xf; | 202 | int rm = insn & 0xf; |
| @@ -213,7 +212,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 213 | "mrs %[cpsr], cpsr \n\t" | 212 | "mrs %[cpsr], cpsr \n\t" |
| 214 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 213 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
| 215 | : "0" (rdv), "r" (rnv), "r" (rmv), | 214 | : "0" (rdv), "r" (rnv), "r" (rmv), |
| 216 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 215 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
| 217 | : "lr", "memory", "cc" | 216 | : "lr", "memory", "cc" |
| 218 | ); | 217 | ); |
| 219 | 218 | ||
| @@ -222,9 +221,10 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 222 | } | 221 | } |
| 223 | 222 | ||
| 224 | static void __kprobes | 223 | static void __kprobes |
| 225 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 224 | emulate_rd16rn12rm0rs8_rwflags_nopc(kprobe_opcode_t insn, |
| 225 | struct arch_specific_insn *asi, | ||
| 226 | struct pt_regs *regs) | ||
| 226 | { | 227 | { |
| 227 | kprobe_opcode_t insn = p->opcode; | ||
| 228 | int rd = (insn >> 16) & 0xf; | 228 | int rd = (insn >> 16) & 0xf; |
| 229 | int rn = (insn >> 12) & 0xf; | 229 | int rn = (insn >> 12) & 0xf; |
| 230 | int rm = insn & 0xf; | 230 | int rm = insn & 0xf; |
| @@ -242,7 +242,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 242 | "mrs %[cpsr], cpsr \n\t" | 242 | "mrs %[cpsr], cpsr \n\t" |
