diff options
author | David A. Long <dave.long@linaro.org> | 2014-03-07 11:19:32 -0500 |
---|---|---|
committer | David A. Long <dave.long@linaro.org> | 2014-03-18 16:39:37 -0400 |
commit | 7579f4b3764337b39087d10496af0e741cbfe570 (patch) | |
tree | 009a68f8615a04fa038874522493006c2efb8022 | |
parent | 3e6cd394bb10c2d65322e5f5d2ff0a9074d903a1 (diff) |
ARM: Remove use of struct kprobe from generic probes code
Change the generic ARM probes code to pass in the opcode and architecture-specific
structure separately instead of using struct kprobe, so we do not pollute
code being used only for uprobes or other non-kprobes instruction
interpretation.
Signed-off-by: David A. Long <dave.long@linaro.org>
Acked-by: Jon Medhurst <tixy@linaro.org>
-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" |
243 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 243 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
244 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), | 244 | : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), |
245 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 245 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
246 | : "lr", "memory", "cc" | 246 | : "lr", "memory", "cc" |
247 | ); | 247 | ); |
248 | 248 | ||
@@ -251,9 +251,9 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
251 | } | 251 | } |
252 | 252 | ||
253 | static void __kprobes | 253 | static void __kprobes |
254 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | 254 | emulate_rd12rm0_noflags_nopc(kprobe_opcode_t insn, |
255 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
255 | { | 256 | { |
256 | kprobe_opcode_t insn = p->opcode; | ||
257 | int rd = (insn >> 12) & 0xf; | 257 | int rd = (insn >> 12) & 0xf; |
258 | int rm = insn & 0xf; | 258 | int rm = insn & 0xf; |
259 | 259 | ||
@@ -263,7 +263,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
263 | __asm__ __volatile__ ( | 263 | __asm__ __volatile__ ( |
264 | BLX("%[fn]") | 264 | BLX("%[fn]") |
265 | : "=r" (rdv) | 265 | : "=r" (rdv) |
266 | : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 266 | : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn) |
267 | : "lr", "memory", "cc" | 267 | : "lr", "memory", "cc" |
268 | ); | 268 | ); |
269 | 269 | ||
@@ -271,9 +271,10 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
271 | } | 271 | } |
272 | 272 | ||
273 | static void __kprobes | 273 | static void __kprobes |
274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(kprobe_opcode_t insn, |
275 | struct arch_specific_insn *asi, | ||
276 | struct pt_regs *regs) | ||
275 | { | 277 | { |
276 | kprobe_opcode_t insn = p->opcode; | ||
277 | int rdlo = (insn >> 12) & 0xf; | 278 | int rdlo = (insn >> 12) & 0xf; |
278 | int rdhi = (insn >> 16) & 0xf; | 279 | int rdhi = (insn >> 16) & 0xf; |
279 | int rn = insn & 0xf; | 280 | int rn = insn & 0xf; |
@@ -291,7 +292,7 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
291 | "mrs %[cpsr], cpsr \n\t" | 292 | "mrs %[cpsr], cpsr \n\t" |
292 | : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) | 293 | : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) |
293 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), | 294 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), |
294 | "2" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 295 | "2" (cpsr), [fn] "r" (asi->insn_fn) |
295 | : "lr", "memory", "cc" | 296 | : "lr", "memory", "cc" |
296 | ); | 297 | ); |
297 | 298 | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index 029b79c6face..abe03890f84d 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c | |||
@@ -17,9 +17,10 @@ | |||
17 | #include "kprobes.h" | 17 | #include "kprobes.h" |
18 | 18 | ||
19 | 19 | ||
20 | static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | 20 | static void __kprobes simulate_ldm1stm1(kprobe_opcode_t insn, |
21 | struct arch_specific_insn *asi, | ||
22 | struct pt_regs *regs) | ||
21 | { | 23 | { |
22 | kprobe_opcode_t insn = p->opcode; | ||
23 | int rn = (insn >> 16) & 0xf; | 24 | int rn = (insn >> 16) & 0xf; |
24 | int lbit = insn & (1 << 20); | 25 | int lbit = insn & (1 << 20); |
25 | int wbit = insn & (1 << 21); | 26 | int wbit = insn & (1 << 21); |
@@ -58,24 +59,31 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | |||
58 | } | 59 | } |
59 | } | 60 | } |
60 | 61 | ||
61 | static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) | 62 | static void __kprobes simulate_stm1_pc(kprobe_opcode_t insn, |
63 | struct arch_specific_insn *asi, | ||
64 | struct pt_regs *regs) | ||
62 | { | 65 | { |
63 | regs->ARM_pc = (long)p->addr + str_pc_offset; | 66 | unsigned long addr = regs->ARM_pc - 4; |
64 | simulate_ldm1stm1(p, regs); | 67 | |
65 | regs->ARM_pc = (long)p->addr + 4; | 68 | regs->ARM_pc = (long)addr + str_pc_offset; |
69 | simulate_ldm1stm1(insn, asi, regs); | ||
70 | regs->ARM_pc = (long)addr + 4; | ||
66 | } | 71 | } |
67 | 72 | ||
68 | static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs) | 73 | static void __kprobes simulate_ldm1_pc(kprobe_opcode_t insn, |
74 | struct arch_specific_insn *asi, | ||
75 | struct pt_regs *regs) | ||
69 | { | 76 | { |
70 | simulate_ldm1stm1(p, regs); | 77 | simulate_ldm1stm1(insn, asi, regs); |
71 | load_write_pc(regs->ARM_pc, regs); | 78 | load_write_pc(regs->ARM_pc, regs); |
72 | } | 79 | } |
73 | 80 | ||
74 | static void __kprobes | 81 | static void __kprobes |
75 | emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) | 82 | emulate_generic_r0_12_noflags(kprobe_opcode_t insn, |
83 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
76 | { | 84 | { |
77 | register void *rregs asm("r1") = regs; | 85 | register void *rregs asm("r1") = regs; |
78 | register void *rfn asm("lr") = p->ainsn.insn_fn; | 86 | register void *rfn asm("lr") = asi->insn_fn; |
79 | 87 | ||
80 | __asm__ __volatile__ ( | 88 | __asm__ __volatile__ ( |
81 | "stmdb sp!, {%[regs], r11} \n\t" | 89 | "stmdb sp!, {%[regs], r11} \n\t" |
@@ -99,15 +107,19 @@ emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) | |||
99 | } | 107 | } |
100 | 108 | ||
101 | static void __kprobes | 109 | static void __kprobes |
102 | emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs) | 110 | emulate_generic_r2_14_noflags(kprobe_opcode_t insn, |
111 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
103 | { | 112 | { |
104 | emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2)); | 113 | emulate_generic_r0_12_noflags(insn, asi, |
114 | (struct pt_regs *)(regs->uregs+2)); | ||
105 | } | 115 | } |
106 | 116 | ||
107 | static void __kprobes | 117 | static void __kprobes |
108 | emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) | 118 | emulate_ldm_r3_15(kprobe_opcode_t insn, |
119 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
109 | { | 120 | { |
110 | emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3)); | 121 | emulate_generic_r0_12_noflags(insn, asi, |
122 | (struct pt_regs *)(regs->uregs+3)); | ||
111 | load_write_pc(regs->ARM_pc, regs); | 123 | load_write_pc(regs->ARM_pc, regs); |
112 | } | 124 | } |
113 | 125 | ||
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index d83f6092920a..adc08f8d4a1c 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c | |||
@@ -20,24 +20,13 @@ | |||
20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | 20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ |
21 | t32_emulate_rdlo12rdhi8rn16rm0_noflags | 21 | t32_emulate_rdlo12rdhi8rn16rm0_noflags |
22 | 22 | ||
23 | /* | ||
24 | * Return the PC value for a probe in thumb code. | ||
25 | * This is the address of the probed instruction plus 4. | ||
26 | * We subtract one because the address will have bit zero set to indicate | ||
27 | * a pointer to thumb code. | ||
28 | */ | ||
29 | static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) | ||
30 | { | ||
31 | return (unsigned long)p->addr - 1 + 4; | ||
32 | } | ||
33 | |||
34 | /* t32 thumb actions */ | 23 | /* t32 thumb actions */ |
35 | 24 | ||
36 | static void __kprobes | 25 | static void __kprobes |
37 | t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | 26 | t32_simulate_table_branch(kprobe_opcode_t insn, |
27 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
38 | { | 28 | { |
39 | kprobe_opcode_t insn = p->opcode; | 29 | unsigned long pc = regs->ARM_pc; |
40 | unsigned long pc = thumb_probe_pc(p); | ||
41 | int rn = (insn >> 16) & 0xf; | 30 | int rn = (insn >> 16) & 0xf; |
42 | int rm = insn & 0xf; | 31 | int rm = insn & 0xf; |
43 | 32 | ||
@@ -54,19 +43,19 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | |||
54 | } | 43 | } |
55 | 44 | ||
56 | static void __kprobes | 45 | static void __kprobes |
57 | t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) | 46 | t32_simulate_mrs(kprobe_opcode_t insn, |
47 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
58 | { | 48 | { |
59 | kprobe_opcode_t insn = p->opcode; | ||
60 | int rd = (insn >> 8) & 0xf; | 49 | int rd = (insn >> 8) & 0xf; |
61 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | 50 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ |
62 | regs->uregs[rd] = regs->ARM_cpsr & mask; | 51 | regs->uregs[rd] = regs->ARM_cpsr & mask; |
63 | } | 52 | } |
64 | 53 | ||
65 | static void __kprobes | 54 | static void __kprobes |
66 | t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) | 55 | t32_simulate_cond_branch(kprobe_opcode_t insn, |
56 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
67 | { | 57 | { |
68 | kprobe_opcode_t insn = p->opcode; | 58 | unsigned long pc = regs->ARM_pc; |
69 | unsigned long pc = thumb_probe_pc(p); | ||
70 | 59 | ||
71 | long offset = insn & 0x7ff; /* imm11 */ | 60 | long offset = insn & 0x7ff; /* imm11 */ |
72 | offset += (insn & 0x003f0000) >> 5; /* imm6 */ | 61 | offset += (insn & 0x003f0000) >> 5; /* imm6 */ |
@@ -88,10 +77,10 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
88 | } | 77 | } |
89 | 78 | ||
90 | static void __kprobes | 79 | static void __kprobes |
91 | t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | 80 | t32_simulate_branch(kprobe_opcode_t insn, |
81 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
92 | { | 82 | { |
93 | kprobe_opcode_t insn = p->opcode; | 83 | unsigned long pc = regs->ARM_pc; |
94 | unsigned long pc = thumb_probe_pc(p); | ||
95 | 84 | ||
96 | long offset = insn & 0x7ff; /* imm11 */ | 85 | long offset = insn & 0x7ff; /* imm11 */ |
97 | offset += (insn & 0x03ff0000) >> 5; /* imm10 */ | 86 | offset += (insn & 0x03ff0000) >> 5; /* imm10 */ |
@@ -104,7 +93,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | |||
104 | 93 | ||
105 | if (insn & (1 << 14)) { | 94 | if (insn & (1 << 14)) { |
106 | /* BL or BLX */ | 95 | /* BL or BLX */ |
107 | regs->ARM_lr = (unsigned long)p->addr + 4; | 96 | regs->ARM_lr = regs->ARM_pc | 1; |
108 | if (!(insn & (1 << 12))) { | 97 | if (!(insn & (1 << 12))) { |
109 | /* BLX so switch to ARM mode */ | 98 | /* BLX so switch to ARM mode */ |
110 | regs->ARM_cpsr &= ~PSR_T_BIT; | 99 | regs->ARM_cpsr &= ~PSR_T_BIT; |
@@ -116,10 +105,10 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) | |||
116 | } | 105 | } |
117 | 106 | ||
118 | static void __kprobes | 107 | static void __kprobes |
119 | t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) | 108 | t32_simulate_ldr_literal(kprobe_opcode_t insn, |
109 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
120 | { | 110 | { |
121 | kprobe_opcode_t insn = p->opcode; | 111 | unsigned long addr = regs->ARM_pc & ~3; |
122 | unsigned long addr = thumb_probe_pc(p) & ~3; | ||
123 | int rt = (insn >> 12) & 0xf; | 112 | int rt = (insn >> 12) & 0xf; |
124 | unsigned long rtv; | 113 | unsigned long rtv; |
125 | 114 | ||
@@ -168,10 +157,10 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
168 | } | 157 | } |
169 | 158 | ||
170 | static void __kprobes | 159 | static void __kprobes |
171 | t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 160 | t32_emulate_ldrdstrd(kprobe_opcode_t insn, |
161 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
172 | { | 162 | { |
173 | kprobe_opcode_t insn = p->opcode; | 163 | unsigned long pc = regs->ARM_pc & ~3; |
174 | unsigned long pc = thumb_probe_pc(p) & ~3; | ||
175 | int rt1 = (insn >> 12) & 0xf; | 164 | int rt1 = (insn >> 12) & 0xf; |
176 | int rt2 = (insn >> 8) & 0xf; | 165 | int rt2 = (insn >> 8) & 0xf; |
177 | int rn = (insn >> 16) & 0xf; | 166 | int rn = (insn >> 16) & 0xf; |
@@ -184,7 +173,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
184 | __asm__ __volatile__ ( | 173 | __asm__ __volatile__ ( |
185 | "blx %[fn]" | 174 | "blx %[fn]" |
186 | : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) | 175 | : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) |
187 | : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn) | 176 | : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn) |
188 | : "lr", "memory", "cc" | 177 | : "lr", "memory", "cc" |
189 | ); | 178 | ); |
190 | 179 | ||
@@ -195,9 +184,9 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
195 | } | 184 | } |
196 | 185 | ||
197 | static void __kprobes | 186 | static void __kprobes |
198 | t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | 187 | t32_emulate_ldrstr(kprobe_opcode_t insn, |
188 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
199 | { | 189 | { |
200 | kprobe_opcode_t insn = p->opcode; | ||
201 | int rt = (insn >> 12) & 0xf; | 190 | int rt = (insn >> 12) & 0xf; |
202 | int rn = (insn >> 16) & 0xf; | 191 | int rn = (insn >> 16) & 0xf; |
203 | int rm = insn & 0xf; | 192 | int rm = insn & 0xf; |
@@ -209,7 +198,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | |||
209 | __asm__ __volatile__ ( | 198 | __asm__ __volatile__ ( |
210 | "blx %[fn]" | 199 | "blx %[fn]" |
211 | : "=r" (rtv), "=r" (rnv) | 200 | : "=r" (rtv), "=r" (rnv) |
212 | : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) | 201 | : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) |
213 | : "lr", "memory", "cc" | 202 | : "lr", "memory", "cc" |
214 | ); | 203 | ); |
215 | 204 | ||
@@ -221,9 +210,9 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) | |||
221 | } | 210 | } |
222 | 211 | ||
223 | static void __kprobes | 212 | static void __kprobes |
224 | t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | 213 | t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn, |
214 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
225 | { | 215 | { |
226 | kprobe_opcode_t insn = p->opcode; | ||
227 | int rd = (insn >> 8) & 0xf; | 216 | int rd = (insn >> 8) & 0xf; |
228 | int rn = (insn >> 16) & 0xf; | 217 | int rn = (insn >> 16) & 0xf; |
229 | int rm = insn & 0xf; | 218 | int rm = insn & 0xf; |
@@ -239,7 +228,7 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
239 | "mrs %[cpsr], cpsr \n\t" | 228 | "mrs %[cpsr], cpsr \n\t" |
240 | : "=r" (rdv), [cpsr] "=r" (cpsr) | 229 | : "=r" (rdv), [cpsr] "=r" (cpsr) |
241 | : "0" (rdv), "r" (rnv), "r" (rmv), | 230 | : "0" (rdv), "r" (rnv), "r" (rmv), |
242 | "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 231 | "1" (cpsr), [fn] "r" (asi->insn_fn) |
243 | : "lr", "memory", "cc" | 232 | : "lr", "memory", "cc" |
244 | ); | 233 | ); |
245 | 234 | ||
@@ -248,10 +237,10 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
248 | } | 237 | } |
249 | 238 | ||
250 | static void __kprobes | 239 | static void __kprobes |
251 | t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | 240 | t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn, |
241 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
252 | { | 242 | { |
253 | kprobe_opcode_t insn = p->opcode; | 243 | unsigned long pc = regs->ARM_pc; |
254 | unsigned long pc = thumb_probe_pc(p); | ||
255 | int rd = (insn >> 8) & 0xf; | 244 | int rd = (insn >> 8) & 0xf; |
256 | 245 | ||
257 | register unsigned long rdv asm("r1") = regs->uregs[rd]; | 246 | register unsigned long rdv asm("r1") = regs->uregs[rd]; |
@@ -260,7 +249,7 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
260 | __asm__ __volatile__ ( | 249 | __asm__ __volatile__ ( |
261 | "blx %[fn]" | 250 | "blx %[fn]" |
262 | : "=r" (rdv) | 251 | : "=r" (rdv) |
263 | : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) | 252 | : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) |
264 | : "lr", "memory", "cc" | 253 | : "lr", "memory", "cc" |
265 | ); | 254 | ); |
266 | 255 | ||
@@ -268,9 +257,9 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
268 | } | 257 | } |
269 | 258 | ||
270 | static void __kprobes | 259 | static void __kprobes |
271 | t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | 260 | t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn, |
261 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
272 | { | 262 | { |
273 | kprobe_opcode_t insn = p->opcode; | ||
274 | int rd = (insn >> 8) & 0xf; | 263 | int rd = (insn >> 8) & 0xf; |
275 | int rn = (insn >> 16) & 0xf; | 264 | int rn = (insn >> 16) & 0xf; |
276 | 265 | ||
@@ -280,7 +269,7 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
280 | __asm__ __volatile__ ( | 269 | __asm__ __volatile__ ( |
281 | "blx %[fn]" | 270 | "blx %[fn]" |
282 | : "=r" (rdv) | 271 | : "=r" (rdv) |
283 | : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) | 272 | : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) |
284 | : "lr", "memory", "cc" | 273 | : "lr", "memory", "cc" |
285 | ); | 274 | ); |
286 | 275 | ||
@@ -288,9 +277,10 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) | |||
288 | } | 277 | } |
289 | 278 | ||
290 | static void __kprobes | 279 | static void __kprobes |
291 | t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) | 280 | t32_emulate_rdlo12rdhi8rn16rm0_noflags(kprobe_opcode_t insn, |
281 | struct arch_specific_insn *asi, | ||
282 | struct pt_regs *regs) | ||
292 | { | 283 | { |
293 | kprobe_opcode_t insn = p->opcode; | ||
294 | int rdlo = (insn >> 12) & 0xf; | 284 | int rdlo = (insn >> 12) & 0xf; |
295 | int rdhi = (insn >> 8) & 0xf; | 285 | int rdhi = (insn >> 8) & 0xf; |
296 | int rn = (insn >> 16) & 0xf; | 286 | int rn = (insn >> 16) & 0xf; |
@@ -305,7 +295,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) | |||
305 | "blx %[fn]" | 295 | "blx %[fn]" |
306 | : "=r" (rdlov), "=r" (rdhiv) | 296 | : "=r" (rdlov), "=r" (rdhiv) |
307 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), | 297 | : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), |
308 | [fn] "r" (p->ainsn.insn_fn) | 298 | [fn] "r" (asi->insn_fn) |
309 | : "lr", "memory", "cc" | 299 | : "lr", "memory", "cc" |
310 | ); | 300 | ); |
311 | 301 | ||
@@ -315,33 +305,33 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) | |||
315 | /* t16 thumb actions */ | 305 | /* t16 thumb actions */ |
316 | 306 | ||
317 | static void __kprobes | 307 | static void __kprobes |
318 | t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) | 308 | t16_simulate_bxblx(kprobe_opcode_t insn, |
309 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
319 | { | 310 | { |
320 | kprobe_opcode_t insn = p->opcode; | 311 | unsigned long pc = regs->ARM_pc + 2; |
321 | unsigned long pc = thumb_probe_pc(p); | ||
322 | int rm = (insn >> 3) & 0xf; | 312 | int rm = (insn >> 3) & 0xf; |
323 | unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; | 313 | unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; |
324 | 314 | ||
325 | if (insn & (1 << 7)) /* BLX ? */ | 315 | if (insn & (1 << 7)) /* BLX ? */ |
326 | regs->ARM_lr = (unsigned long)p->addr + 2; | 316 | regs->ARM_lr = regs->ARM_pc | 1; |
327 | 317 | ||
328 | bx_write_pc(rmv, regs); | 318 | bx_write_pc(rmv, regs); |
329 | } | 319 | } |
330 | 320 | ||
331 | static void __kprobes | 321 | static void __kprobes |
332 | t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) | 322 | t16_simulate_ldr_literal(kprobe_opcode_t insn, |
323 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
333 | { | 324 | { |
334 | kprobe_opcode_t insn = p->opcode; | 325 | unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3); |
335 | unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3); | ||
336 | long index = insn & 0xff; | 326 | long index = insn & 0xff; |
337 | int rt = (insn >> 8) & 0x7; | 327 | int rt = (insn >> 8) & 0x7; |
338 | regs->uregs[rt] = base[index]; | 328 | regs->uregs[rt] = base[index]; |
339 | } | 329 | } |
340 | 330 | ||
341 | static void __kprobes | 331 | static void __kprobes |
342 | t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) | 332 | t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn, |
333 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
343 | { | 334 | { |
344 | kprobe_opcode_t insn = p->opcode; | ||
345 | unsigned long* base = (unsigned long *)regs->ARM_sp; | 335 | unsigned long* base = (unsigned long *)regs->ARM_sp; |
346 | long index = insn & 0xff; | 336 | long index = insn & 0xff; |
347 | int rt = (insn >> 8) & 0x7; | 337 | int rt = (insn >> 8) & 0x7; |
@@ -352,20 +342,20 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) | |||
352 | } | 342 | } |
353 | 343 | ||
354 | static void __kprobes | 344 | static void __kprobes |
355 | t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) | 345 | t16_simulate_reladr(kprobe_opcode_t insn, |
346 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
356 | { | 347 | { |
357 | kprobe_opcode_t insn = p->opcode; | ||
358 | unsigned long base = (insn & 0x800) ? regs->ARM_sp | 348 | unsigned long base = (insn & 0x800) ? regs->ARM_sp |
359 | : (thumb_probe_pc(p) & ~3); | 349 | : ((regs->ARM_pc + 2) & ~3); |
360 | long offset = insn & 0xff; | 350 | long offset = insn & 0xff; |
361 | int rt = (insn >> 8) & 0x7; | 351 | int rt = (insn >> 8) & 0x7; |
362 | regs->uregs[rt] = base + offset * 4; | 352 | regs->uregs[rt] = base + offset * 4; |
363 | } | 353 | } |
364 | 354 | ||
365 | static void __kprobes | 355 | static void __kprobes |
366 | t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) | 356 | t16_simulate_add_sp_imm(kprobe_opcode_t insn, |
357 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
367 | { | 358 | { |
368 | kprobe_opcode_t insn = p->opcode; | ||
369 | long imm = insn & 0x7f; | 359 | long imm = insn & 0x7f; |
370 | if (insn & 0x80) /* SUB */ | 360 | if (insn & 0x80) /* SUB */ |
371 | regs->ARM_sp -= imm * 4; | 361 | regs->ARM_sp -= imm * 4; |
@@ -374,21 +364,22 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) | |||
374 | } | 364 | } |
375 | 365 | ||
376 | static void __kprobes | 366 | static void __kprobes |
377 | t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) | 367 | t16_simulate_cbz(kprobe_opcode_t insn, |
368 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
378 | { | 369 | { |
379 | kprobe_opcode_t insn = p->opcode; | ||
380 | int rn = insn & 0x7; | 370 | int rn = insn & 0x7; |
381 | kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; | 371 | kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; |
382 | if (nonzero & 0x800) { | 372 | if (nonzero & 0x800) { |
383 | long i = insn & 0x200; | 373 | long i = insn & 0x200; |
384 | long imm5 = insn & 0xf8; | 374 | long imm5 = insn & 0xf8; |
385 | unsigned long pc = thumb_probe_pc(p); | 375 | unsigned long pc = regs->ARM_pc + 2; |
386 | regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); | 376 | regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); |
387 | } | 377 | } |
388 | } | 378 | } |
389 | 379 | ||
390 | static void __kprobes | 380 | static void __kprobes |
391 | t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | 381 | t16_simulate_it(kprobe_opcode_t insn, |
382 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
392 | { | 383 | { |
393 | /* | 384 | /* |
394 | * The 8 IT state bits are split into two parts in CPSR: | 385 | * The 8 IT state bits are split into two parts in CPSR: |
@@ -396,7 +387,6 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | |||
396 | * ITSTATE<7:2> are in CPSR<15:10> | 387 | * ITSTATE<7:2> are in CPSR<15:10> |
397 | * The new IT state is in the lower byte of insn. | 388 | * The new IT state is in the lower byte of insn. |
398 | */ | 389 | */ |
399 | kprobe_opcode_t insn = p->opcode; | ||
400 | unsigned long cpsr = regs->ARM_cpsr; | 390 | unsigned long cpsr = regs->ARM_cpsr; |
401 | cpsr &= ~PSR_IT_MASK; | 391 | cpsr &= ~PSR_IT_MASK; |
402 | cpsr |= (insn & 0xfc) << 8; | 392 | cpsr |= (insn & 0xfc) << 8; |
@@ -405,10 +395,11 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs) | |||
405 | } | 395 | } |
406 | 396 | ||
407 | static void __kprobes | 397 | static void __kprobes |
408 | t16_singlestep_it(struct kprobe *p, struct pt_regs *regs) | 398 | t16_singlestep_it(kprobe_opcode_t insn, |
399 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
409 | { | 400 | { |
410 | regs->ARM_pc += 2; | 401 | regs->ARM_pc += 2; |
411 | t16_simulate_it(p, regs); | 402 | t16_simulate_it(insn, asi, regs); |
412 | } | 403 | } |
413 | 404 | ||
414 | static enum kprobe_insn __kprobes | 405 | static enum kprobe_insn __kprobes |
@@ -420,10 +411,10 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
420 | } | 411 | } |
421 | 412 | ||
422 | static void __kprobes | 413 | static void __kprobes |
423 | t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) | 414 | t16_simulate_cond_branch(kprobe_opcode_t insn, |
415 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
424 | { | 416 | { |
425 | kprobe_opcode_t insn = p->opcode; | 417 | unsigned long pc = regs->ARM_pc + 2; |
426 | unsigned long pc = thumb_probe_pc(p); | ||
427 | long offset = insn & 0x7f; | 418 | long offset = insn & 0x7f; |
428 | offset -= insn & 0x80; /* Apply sign bit */ | 419 | offset -= insn & 0x80; /* Apply sign bit */ |
429 | regs->ARM_pc = pc + (offset * 2); | 420 | regs->ARM_pc = pc + (offset * 2); |
@@ -440,17 +431,18 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
440 | } | 431 | } |
441 | 432 | ||
442 | static void __kprobes | 433 | static void __kprobes |
443 | t16_simulate_branch(struct kprobe *p, struct pt_regs *regs) | 434 | t16_simulate_branch(kprobe_opcode_t insn, |
435 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
444 | { | 436 | { |
445 | kprobe_opcode_t insn = p->opcode; | 437 | unsigned long pc = regs->ARM_pc + 2; |
446 | unsigned long pc = thumb_probe_pc(p); | ||
447 | long offset = insn & 0x3ff; | 438 | long offset = insn & 0x3ff; |
448 | offset -= insn & 0x400; /* Apply sign bit */ | 439 | offset -= insn & 0x400; /* Apply sign bit */ |
449 | regs->ARM_pc = pc + (offset * 2); | 440 | regs->ARM_pc = pc + (offset * 2); |
450 | } | 441 | } |
451 | 442 | ||
452 | static unsigned long __kprobes | 443 | static unsigned long __kprobes |
453 | t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | 444 | t16_emulate_loregs(kprobe_opcode_t insn, |
445 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
454 | { | 446 | { |
455 | unsigned long oldcpsr = regs->ARM_cpsr; | 447 | unsigned long oldcpsr = regs->ARM_cpsr; |
456 | unsigned long newcpsr; | 448 | unsigned long newcpsr; |
@@ -463,7 +455,7 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | |||
463 | "mrs %[newcpsr], cpsr \n\t" | 455 | "mrs %[newcpsr], cpsr \n\t" |
464 | : [newcpsr] "=r" (newcpsr) | 456 | : [newcpsr] "=r" (newcpsr) |
465 | : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), | 457 | : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), |
466 | [fn] "r" (p->ainsn.insn_fn) | 458 | [fn] "r" (asi->insn_fn) |
467 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 459 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
468 | "lr", "memory", "cc" | 460 | "lr", "memory", "cc" |
469 | ); | 461 | ); |
@@ -472,24 +464,26 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | |||
472 | } | 464 | } |
473 | 465 | ||
474 | static void __kprobes | 466 | static void __kprobes |
475 | t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) | 467 | t16_emulate_loregs_rwflags(kprobe_opcode_t insn, |
468 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
476 | { | 469 | { |
477 | regs->ARM_cpsr = t16_emulate_loregs(p, regs); | 470 | regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs); |
478 | } | 471 | } |
479 | 472 | ||
480 | static void __kprobes | 473 | static void __kprobes |
481 | t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) | 474 | t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn, |
475 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
482 | { | 476 | { |
483 | unsigned long cpsr = t16_emulate_loregs(p, regs); | 477 | unsigned long cpsr = t16_emulate_loregs(insn, asi, regs); |
484 | if (!in_it_block(cpsr)) | 478 | if (!in_it_block(cpsr)) |
485 | regs->ARM_cpsr = cpsr; | 479 | regs->ARM_cpsr = cpsr; |
486 | } | 480 | } |
487 | 481 | ||
488 | static void __kprobes | 482 | static void __kprobes |
489 | t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) | 483 | t16_emulate_hiregs(kprobe_opcode_t insn, |
484 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
490 | { | 485 | { |
491 | kprobe_opcode_t insn = p->opcode; | 486 | unsigned long pc = regs->ARM_pc + 2; |
492 | unsigned long pc = thumb_probe_pc(p); | ||
493 | int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); | 487 | int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); |
494 | int rm = (insn >> 3) & 0xf; | 488 | int rm = (insn >> 3) & 0xf; |
495 | 489 | ||
@@ -505,7 +499,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) | |||
505 | "blx %[fn] \n\t" | 499 | "blx %[fn] \n\t" |
506 | "mrs %[cpsr], cpsr \n\t" | 500 | "mrs %[cpsr], cpsr \n\t" |
507 | : "=r" (rdnv), [cpsr] "=r" (cpsr) | 501 | : "=r" (rdnv), [cpsr] "=r" (cpsr) |
508 | : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) | 502 | : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn) |
509 | : "lr", "memory", "cc" | 503 | : "lr", "memory", "cc" |
510 | ); | 504 | ); |
511 | 505 | ||
@@ -528,7 +522,8 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
528 | } | 522 | } |
529 | 523 | ||
530 | static void __kprobes | 524 | static void __kprobes |
531 | t16_emulate_push(struct kprobe *p, struct pt_regs *regs) | 525 | t16_emulate_push(kprobe_opcode_t insn, |
526 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
532 | { | 527 | { |
533 | __asm__ __volatile__ ( | 528 | __asm__ __volatile__ ( |
534 | "ldr r9, [%[regs], #13*4] \n\t" | 529 | "ldr r9, [%[regs], #13*4] \n\t" |
@@ -537,7 +532,7 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs) | |||
537 | "blx %[fn] \n\t" | 532 | "blx %[fn] \n\t" |
538 | "str r9, [%[regs], #13*4] \n\t" | 533 | "str r9, [%[regs], #13*4] \n\t" |
539 | : | 534 | : |
540 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 535 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
541 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", | 536 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", |
542 | "lr", "memory", "cc" | 537 | "lr", "memory", "cc" |
543 | ); | 538 | ); |
@@ -559,7 +554,8 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi, | |||
559 | } | 554 | } |
560 | 555 | ||
561 | static void __kprobes | 556 | static void __kprobes |
562 | t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) | 557 | t16_emulate_pop_nopc(kprobe_opcode_t insn, |
558 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
563 | { | 559 | { |
564 | __asm__ __volatile__ ( | 560 | __asm__ __volatile__ ( |
565 | "ldr r9, [%[regs], #13*4] \n\t" | 561 | "ldr r9, [%[regs], #13*4] \n\t" |
@@ -568,14 +564,15 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) | |||
568 | "stmia %[regs], {r0-r7} \n\t" | 564 | "stmia %[regs], {r0-r7} \n\t" |
569 | "str r9, [%[regs], #13*4] \n\t" | 565 | "str r9, [%[regs], #13*4] \n\t" |
570 | : | 566 | : |
571 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 567 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
572 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", | 568 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", |
573 | "lr", "memory", "cc" | 569 | "lr", "memory", "cc" |
574 | ); | 570 | ); |
575 | } | 571 | } |
576 | 572 | ||
577 | static void __kprobes | 573 | static void __kprobes |
578 | t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) | 574 | t16_emulate_pop_pc(kprobe_opcode_t insn, |
575 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
579 | { | 576 | { |
580 | register unsigned long pc asm("r8"); | 577 | register unsigned long pc asm("r8"); |
581 | 578 | ||
@@ -586,7 +583,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) | |||
586 | "stmia %[regs], {r0-r7} \n\t" | 583 | "stmia %[regs], {r0-r7} \n\t" |
587 | "str r9, [%[regs], #13*4] \n\t" | 584 | "str r9, [%[regs], #13*4] \n\t" |
588 | : "=r" (pc) | 585 | : "=r" (pc) |
589 | : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) | 586 | : [regs] "r" (regs), [fn] "r" (asi->insn_fn) |
590 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", | 587 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", |
591 | "lr", "memory", "cc" | 588 | "lr", "memory", "cc" |
592 | ); | 589 | ); |
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index a757c3c22381..b4a3028edffe 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -204,7 +204,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs) | |||
204 | static inline void __kprobes | 204 | static inline void __kprobes |
205 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) | 205 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
206 | { | 206 | { |
207 | p->ainsn.insn_singlestep(p, regs); | 207 | p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); |
208 | } | 208 | } |
209 | 209 | ||
210 | /* | 210 | /* |
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c index 496e0e913fa6..36002e5d0f0e 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/kernel/probes-arm.c | |||
@@ -19,9 +19,8 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
21 | #include <linux/ptrace.h> | 21 | #include <linux/ptrace.h> |
22 | #include <linux/kprobes.h> | ||
23 | 22 | ||
24 | #include "kprobes.h" | 23 | #include "probes.h" |
25 | #include "probes-arm.h" | 24 | #include "probes-arm.h" |
26 | 25 | ||
27 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | 26 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) |
@@ -58,10 +57,10 @@ | |||
58 | * read and write of flags. | 57 | * read and write of flags. |
59 | */ | 58 | */ |
60 | 59 | ||
61 | void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | 60 | void __kprobes simulate_bbl(kprobe_opcode_t insn, |
61 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
62 | { | 62 | { |
63 | kprobe_opcode_t insn = p->opcode; | 63 | long iaddr = (long) regs->ARM_pc - 4; |
64 | long iaddr = (long)p->addr; | ||
65 | int disp = branch_displacement(insn); | 64 | int disp = branch_displacement(insn); |
66 | 65 | ||
67 | if (insn & (1 << 24)) | 66 | if (insn & (1 << 24)) |
@@ -70,10 +69,10 @@ void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | |||
70 | regs->ARM_pc = iaddr + 8 + disp; | 69 | regs->ARM_pc = iaddr + 8 + disp; |
71 | } | 70 | } |
72 | 71 | ||
73 | void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | 72 | void __kprobes simulate_blx1(kprobe_opcode_t insn, |
73 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
74 | { | 74 | { |
75 | kprobe_opcode_t insn = p->opcode; | 75 | long iaddr = (long) regs->ARM_pc - 4; |
76 | long iaddr = (long)p->addr; | ||
77 | int disp = branch_displacement(insn); | 76 | int disp = branch_displacement(insn); |
78 | 77 | ||
79 | regs->ARM_lr = iaddr + 4; | 78 | regs->ARM_lr = iaddr + 4; |
@@ -81,14 +80,14 @@ void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | |||
81 | regs->ARM_cpsr |= PSR_T_BIT; | 80 | regs->ARM_cpsr |= PSR_T_BIT; |
82 | } | 81 | } |
83 | 82 | ||
84 | void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | 83 | void __kprobes simulate_blx2bx(kprobe_opcode_t insn, |
84 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
85 | { | 85 | { |
86 | kprobe_opcode_t insn = p->opcode; | ||
87 | int rm = insn & 0xf; | 86 | int rm = insn & 0xf; |
88 | long rmv = regs->uregs[rm]; | 87 | long rmv = regs->uregs[rm]; |
89 | 88 | ||
90 | if (insn & (1 << 5)) | 89 | if (insn & (1 << 5)) |
91 | regs->ARM_lr = (long)p->addr + 4; | 90 | regs->ARM_lr = (long) regs->ARM_pc; |
92 | 91 | ||
93 | regs->ARM_pc = rmv & ~0x1; | 92 | regs->ARM_pc = rmv & ~0x1; |
94 | regs->ARM_cpsr &= ~PSR_T_BIT; | 93 | regs->ARM_cpsr &= ~PSR_T_BIT; |
@@ -96,15 +95,16 @@ void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | |||
96 | regs->ARM_cpsr |= PSR_T_BIT; | 95 | regs->ARM_cpsr |= PSR_T_BIT; |
97 | } | 96 | } |
98 | 97 | ||
99 | void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) | 98 | void __kprobes simulate_mrs(kprobe_opcode_t insn, |
99 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
100 | { | 100 | { |
101 | kprobe_opcode_t insn = p->opcode; | ||
102 | int rd = (insn >> 12) & 0xf; | 101 | int rd = (insn >> 12) & 0xf; |
103 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | 102 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ |
104 | regs->uregs[rd] = regs->ARM_cpsr & mask; | 103 | regs->uregs[rd] = regs->ARM_cpsr & mask; |
105 | } | 104 | } |
106 | 105 | ||
107 | void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) | 106 | void __kprobes simulate_mov_ipsp(kprobe_opcode_t insn, |
107 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
108 | { | 108 | { |
109 | regs->uregs[12] = regs->uregs[13]; | 109 | regs->uregs[12] = regs->uregs[13]; |
110 | } | 110 | } |
@@ -704,10 +704,11 @@ const union decode_item kprobe_decode_arm_table[] = { | |||
704 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); | 704 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); |
705 | #endif | 705 | #endif |
706 | 706 | ||
707 | static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) | 707 | static void __kprobes arm_singlestep(kprobe_opcode_t insn, |
708 | struct arch_specific_insn *asi, struct pt_regs *regs) | ||
708 | { | 709 | { |
709 | regs->ARM_pc += 4; | 710 | regs->ARM_pc += 4; |
710 | p->ainsn.insn_handler(p, regs); | 711 | asi->insn_handler(insn, asi, regs); |
711 | } | 712 | } |
712 | 713 | ||
713 | /* Return: | 714 | /* Return: |
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h index ef3089419a0b..d0ac8a42caa0 100644 --- a/arch/arm/kernel/probes-arm.h +++ b/arch/arm/kernel/probes-arm.h | |||
@@ -53,10 +53,15 @@ enum probes_arm_action { | |||
53 | NUM_PROBES_ARM_ACTIONS | 53 | NUM_PROBES_ARM_ACTIONS |
54 | }; | 54 | }; |
55 | 55 | ||
56 | void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs); | 56 | void __kprobes simulate_bbl(kprobe_opcode_t opcode, |
57 | void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs); | 57 | struct arch_specific_insn *asi, struct pt_regs *regs); |
58 | void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs); | 58 | void __kprobes simulate_blx1(kprobe_opcode_t opcode, |
59 | void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs); | 59 | struct arch_specific_insn *asi, struct pt_regs *regs); |
60 | void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs); | 60 | void __kprobes simulate_blx2bx(kprobe_opcode_t opcode, |
61 | struct arch_specific_insn *asi, struct pt_regs *regs); | ||
62 | void __kprobes simulate_mrs(kprobe_opcode_t opcode, | ||
63 | struct arch_specific_insn *asi, struct pt_regs *regs); | ||
64 | void __kprobes simulate_mov_ipsp(kprobe_opcode_t opcode, | ||
65 | struct arch_specific_insn *asi, struct pt_regs *regs); | ||
61 | 66 | ||
62 | #endif | 67 | #endif |
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c index 2abe8ceeb670..aa3176da1b29 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/kernel/probes-thumb.c | |||
@@ -10,10 +10,9 @@ | |||
10 | 10 | ||
11 | #include <linux/stddef.h> | 11 | #include <linux/stddef.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/kprobes.h> | ||
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | 14 | ||
16 | #include "kprobes.h" | 15 | #include "probes.h" |
17 | #include "probes-thumb.h" | 16 | #include "probes-thumb.h" |
18 | 17 | ||
19 | 18 | ||
@@ -844,17 +843,21 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) | |||
844 | return true; | 843 | return true; |
845 | } | 844 | } |
846 | 845 | ||
847 | static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) | 846 | static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode, |
847 | struct arch_specific_insn *asi, | ||
848 | struct pt_regs *regs) | ||
848 | { | 849 | { |
849 | regs->ARM_pc += 2; | 850 | regs->ARM_pc += 2; |
850 | p->ainsn.insn_handler(p, regs); | 851 | asi->insn_handler(opcode, asi, regs); |
851 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | 852 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); |
852 | } | 853 | } |
853 | 854 | ||
854 | static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) | 855 | static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode, |
856 | struct arch_specific_insn *asi, | ||
857 | struct pt_regs *regs) | ||
855 | { | 858 | { |
856 | regs->ARM_pc += 4; | 859 | regs->ARM_pc += 4; |
857 | p->ainsn.insn_handler(p, regs); | 860 | asi->insn_handler(opcode, asi, regs); |
858 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); | 861 | regs->ARM_cpsr = it_advance(regs->ARM_cpsr); |
859 | } | 862 | } |
860 | 863 | ||
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c index efd92c5b4a52..f2ab8856ba2b 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/kernel/probes.c | |||
@@ -13,12 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/kprobes.h> | ||
17 | #include <asm/system_info.h> | 16 | #include <asm/system_info.h> |
18 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
19 | #include <linux/bug.h> | 18 | #include <linux/bug.h> |
20 | 19 | ||
21 | #include "kprobes.h" | 20 | #include "probes.h" |
22 | 21 | ||
23 | 22 | ||
24 | #ifndef find_str_pc_offset | 23 | #ifndef find_str_pc_offset |
@@ -176,13 +175,17 @@ kprobe_check_cc * const kprobe_condition_checks[16] = { | |||
176 | }; | 175 | }; |
177 | 176 | ||
178 | 177 | ||
179 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) | 178 | void __kprobes kprobe_simulate_nop(kprobe_opcode_t opcode, |
179 | struct arch_specific_insn *asi, | ||
180 | struct pt_regs *regs) | ||
180 | { | 181 | { |
181 | } | 182 | } |
182 | 183 | ||
183 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) | 184 | void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode, |
185 | struct arch_specific_insn *asi, | ||
186 | struct pt_regs *regs) | ||
184 | { | 187 | { |
185 | p->ainsn.insn_fn(); | 188 | asi->insn_fn(); |
186 | } | 189 | } |
187 | 190 | ||
188 | /* | 191 | /* |
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h index 5554f161bdac..efea63c02742 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/kernel/probes.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/stddef.h> | 23 | #include <linux/stddef.h> |
24 | #include <linux/kprobes.h> | 24 | #include <linux/kprobes.h> |
25 | #include "kprobes.h" | ||
25 | 26 | ||
26 | #if __LINUX_ARM_ARCH__ >= 7 | 27 | #if __LINUX_ARM_ARCH__ >= 7 |
27 | 28 | ||
@@ -37,6 +38,7 @@ void __init find_str_pc_offset(void); | |||
37 | 38 | ||
38 | #endif | 39 | #endif |
39 | 40 | ||
41 | struct decode_header; | ||
40 | 42 | ||
41 | /* | 43 | /* |
42 | * Update ITSTATE after normal execution of an IT block instruction. | 44 | * Update ITSTATE after normal execution of an IT block instruction. |
@@ -129,8 +131,10 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | |||
129 | } | 131 | } |
130 | 132 | ||
131 | 133 | ||
132 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); | 134 | void __kprobes kprobe_simulate_nop(kprobe_opcode_t, struct arch_specific_insn *, |
133 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); | 135 | struct pt_regs *regs); |
136 | void __kprobes kprobe_emulate_none(kprobe_opcode_t, struct arch_specific_insn *, | ||
137 | struct pt_regs *regs); | ||
134 | 138 | ||
135 | enum kprobe_insn __kprobes | 139 | enum kprobe_insn __kprobes |
136 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, | 140 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, |