2 * arch/arm/kernel/kprobes-decode.c
4 * Copyright (C) 2006, 2007 Motorola Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
17 * We do not have hardware single-stepping on ARM, This
18 * effort is further complicated by the ARM not having a
19 * "next PC" register. Instructions that change the PC
20 * can't be safely single-stepped in a MP environment, so
21 * we have a lot of work to do:
23 * In the prepare phase:
24 * *) If it is an instruction that does anything
25 * with the CPU mode, we reject it for a kprobe.
26 * (This is out of laziness rather than need. The
27 * instructions could be simulated.)
29 * *) Otherwise, decode the instruction rewriting its
30 * registers to take fixed, ordered registers and
31 * setting a handler for it to run the instruction.
33 * In the execution phase by an instruction's handler:
35 * *) If the PC is written to by the instruction, the
36 * instruction must be fully simulated in software.
38 * *) Otherwise, a modified form of the instruction is
39 * directly executed. Its handler calls the
40 * instruction in insn[0]. In insn[1] is a
41 * "mov pc, lr" to return.
43 * Before calling, load up the reordered registers
44 * from the original instruction's registers. If one
45 * of the original input registers is the PC, compute
46 * and adjust the appropriate input register.
48 * After call completes, copy the output registers to
49 * the original instruction's original registers.
51 * We don't use a real breakpoint instruction since that
52 * would have us in the kernel go from SVC mode to SVC
53 * mode losing the link register. Instead we use an
54 * undefined instruction. To simplify processing, the
55 * undefined instruction used for kprobes must be reserved
56 * exclusively for kprobes use.
58 * TODO: ifdef out some instruction decoding based on architecture.
61 #include <linux/kernel.h>
62 #include <linux/kprobes.h>
63 #include <linux/ptrace.h>
66 #include "probes-arm.h"
68 #if __LINUX_ARM_ARCH__ >= 6
69 #define BLX(reg) "blx "reg" \n\t"
71 #define BLX(reg) "mov lr, pc \n\t" \
76 emulate_ldrdstrd(probes_opcode_t insn
,
77 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
79 unsigned long pc
= regs
->ARM_pc
+ 4;
80 int rt
= (insn
>> 12) & 0xf;
81 int rn
= (insn
>> 16) & 0xf;
84 register unsigned long rtv
asm("r0") = regs
->uregs
[rt
];
85 register unsigned long rt2v
asm("r1") = regs
->uregs
[rt
+1];
86 register unsigned long rnv
asm("r2") = (rn
== 15) ? pc
88 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
90 __asm__
__volatile__ (
92 : "=r" (rtv
), "=r" (rt2v
), "=r" (rnv
)
93 : "0" (rtv
), "1" (rt2v
), "2" (rnv
), "r" (rmv
),
94 [fn
] "r" (asi
->insn_fn
)
95 : "lr", "memory", "cc"
98 regs
->uregs
[rt
] = rtv
;
99 regs
->uregs
[rt
+1] = rt2v
;
100 if (is_writeback(insn
))
101 regs
->uregs
[rn
] = rnv
;
104 static void __kprobes
105 emulate_ldr(probes_opcode_t insn
,
106 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
108 unsigned long pc
= regs
->ARM_pc
+ 4;
109 int rt
= (insn
>> 12) & 0xf;
110 int rn
= (insn
>> 16) & 0xf;
113 register unsigned long rtv
asm("r0");
114 register unsigned long rnv
asm("r2") = (rn
== 15) ? pc
116 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
118 __asm__
__volatile__ (
120 : "=r" (rtv
), "=r" (rnv
)
121 : "1" (rnv
), "r" (rmv
), [fn
] "r" (asi
->insn_fn
)
122 : "lr", "memory", "cc"
126 load_write_pc(rtv
, regs
);
128 regs
->uregs
[rt
] = rtv
;
130 if (is_writeback(insn
))
131 regs
->uregs
[rn
] = rnv
;
134 static void __kprobes
135 emulate_str(probes_opcode_t insn
,
136 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
138 unsigned long rtpc
= regs
->ARM_pc
- 4 + str_pc_offset
;
139 unsigned long rnpc
= regs
->ARM_pc
+ 4;
140 int rt
= (insn
>> 12) & 0xf;
141 int rn
= (insn
>> 16) & 0xf;
144 register unsigned long rtv
asm("r0") = (rt
== 15) ? rtpc
146 register unsigned long rnv
asm("r2") = (rn
== 15) ? rnpc
148 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
150 __asm__
__volatile__ (
153 : "r" (rtv
), "0" (rnv
), "r" (rmv
), [fn
] "r" (asi
->insn_fn
)
154 : "lr", "memory", "cc"
157 if (is_writeback(insn
))
158 regs
->uregs
[rn
] = rnv
;
161 static void __kprobes
162 emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn
,
163 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
165 unsigned long pc
= regs
->ARM_pc
+ 4;
166 int rd
= (insn
>> 12) & 0xf;
167 int rn
= (insn
>> 16) & 0xf;
169 int rs
= (insn
>> 8) & 0xf;
171 register unsigned long rdv
asm("r0") = regs
->uregs
[rd
];
172 register unsigned long rnv
asm("r2") = (rn
== 15) ? pc
174 register unsigned long rmv
asm("r3") = (rm
== 15) ? pc
176 register unsigned long rsv
asm("r1") = regs
->uregs
[rs
];
177 unsigned long cpsr
= regs
->ARM_cpsr
;
179 __asm__
__volatile__ (
180 "msr cpsr_fs, %[cpsr] \n\t"
182 "mrs %[cpsr], cpsr \n\t"
183 : "=r" (rdv
), [cpsr
] "=r" (cpsr
)
184 : "0" (rdv
), "r" (rnv
), "r" (rmv
), "r" (rsv
),
185 "1" (cpsr
), [fn
] "r" (asi
->insn_fn
)
186 : "lr", "memory", "cc"
190 alu_write_pc(rdv
, regs
);
192 regs
->uregs
[rd
] = rdv
;
193 regs
->ARM_cpsr
= (regs
->ARM_cpsr
& ~APSR_MASK
) | (cpsr
& APSR_MASK
);
196 static void __kprobes
197 emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn
,
198 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
200 int rd
= (insn
>> 12) & 0xf;
201 int rn
= (insn
>> 16) & 0xf;
204 register unsigned long rdv
asm("r0") = regs
->uregs
[rd
];
205 register unsigned long rnv
asm("r2") = regs
->uregs
[rn
];
206 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
207 unsigned long cpsr
= regs
->ARM_cpsr
;
209 __asm__
__volatile__ (
210 "msr cpsr_fs, %[cpsr] \n\t"
212 "mrs %[cpsr], cpsr \n\t"
213 : "=r" (rdv
), [cpsr
] "=r" (cpsr
)
214 : "0" (rdv
), "r" (rnv
), "r" (rmv
),
215 "1" (cpsr
), [fn
] "r" (asi
->insn_fn
)
216 : "lr", "memory", "cc"
219 regs
->uregs
[rd
] = rdv
;
220 regs
->ARM_cpsr
= (regs
->ARM_cpsr
& ~APSR_MASK
) | (cpsr
& APSR_MASK
);
223 static void __kprobes
224 emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn
,
225 struct arch_probes_insn
*asi
,
226 struct pt_regs
*regs
)
228 int rd
= (insn
>> 16) & 0xf;
229 int rn
= (insn
>> 12) & 0xf;
231 int rs
= (insn
>> 8) & 0xf;
233 register unsigned long rdv
asm("r2") = regs
->uregs
[rd
];
234 register unsigned long rnv
asm("r0") = regs
->uregs
[rn
];
235 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
236 register unsigned long rsv
asm("r1") = regs
->uregs
[rs
];
237 unsigned long cpsr
= regs
->ARM_cpsr
;
239 __asm__
__volatile__ (
240 "msr cpsr_fs, %[cpsr] \n\t"
242 "mrs %[cpsr], cpsr \n\t"
243 : "=r" (rdv
), [cpsr
] "=r" (cpsr
)
244 : "0" (rdv
), "r" (rnv
), "r" (rmv
), "r" (rsv
),
245 "1" (cpsr
), [fn
] "r" (asi
->insn_fn
)
246 : "lr", "memory", "cc"
249 regs
->uregs
[rd
] = rdv
;
250 regs
->ARM_cpsr
= (regs
->ARM_cpsr
& ~APSR_MASK
) | (cpsr
& APSR_MASK
);
253 static void __kprobes
254 emulate_rd12rm0_noflags_nopc(probes_opcode_t insn
,
255 struct arch_probes_insn
*asi
, struct pt_regs
*regs
)
257 int rd
= (insn
>> 12) & 0xf;
260 register unsigned long rdv
asm("r0") = regs
->uregs
[rd
];
261 register unsigned long rmv
asm("r3") = regs
->uregs
[rm
];
263 __asm__
__volatile__ (
266 : "0" (rdv
), "r" (rmv
), [fn
] "r" (asi
->insn_fn
)
267 : "lr", "memory", "cc"
270 regs
->uregs
[rd
] = rdv
;
273 static void __kprobes
274 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn
,
275 struct arch_probes_insn
*asi
,
276 struct pt_regs
*regs
)
278 int rdlo
= (insn
>> 12) & 0xf;
279 int rdhi
= (insn
>> 16) & 0xf;
281 int rm
= (insn
>> 8) & 0xf;
283 register unsigned long rdlov
asm("r0") = regs
->uregs
[rdlo
];
284 register unsigned long rdhiv
asm("r2") = regs
->uregs
[rdhi
];
285 register unsigned long rnv
asm("r3") = regs
->uregs
[rn
];
286 register unsigned long rmv
asm("r1") = regs
->uregs
[rm
];
287 unsigned long cpsr
= regs
->ARM_cpsr
;
289 __asm__
__volatile__ (
290 "msr cpsr_fs, %[cpsr] \n\t"
292 "mrs %[cpsr], cpsr \n\t"
293 : "=r" (rdlov
), "=r" (rdhiv
), [cpsr
] "=r" (cpsr
)
294 : "0" (rdlov
), "1" (rdhiv
), "r" (rnv
), "r" (rmv
),
295 "2" (cpsr
), [fn
] "r" (asi
->insn_fn
)
296 : "lr", "memory", "cc"
299 regs
->uregs
[rdlo
] = rdlov
;
300 regs
->uregs
[rdhi
] = rdhiv
;
301 regs
->ARM_cpsr
= (regs
->ARM_cpsr
& ~APSR_MASK
) | (cpsr
& APSR_MASK
);
304 const union decode_action kprobes_arm_actions
[NUM_PROBES_ARM_ACTIONS
] = {
305 [PROBES_EMULATE_NONE
] = {.handler
= probes_emulate_none
},
306 [PROBES_SIMULATE_NOP
] = {.handler
= probes_simulate_nop
},
307 [PROBES_PRELOAD_IMM
] = {.handler
= probes_simulate_nop
},
308 [PROBES_PRELOAD_REG
] = {.handler
= probes_simulate_nop
},
309 [PROBES_BRANCH_IMM
] = {.handler
= simulate_blx1
},
310 [PROBES_MRS
] = {.handler
= simulate_mrs
},
311 [PROBES_BRANCH_REG
] = {.handler
= simulate_blx2bx
},
312 [PROBES_CLZ
] = {.handler
= emulate_rd12rm0_noflags_nopc
},
313 [PROBES_SATURATING_ARITHMETIC
] = {
314 .handler
= emulate_rd12rn16rm0_rwflags_nopc
},
315 [PROBES_MUL1
] = {.handler
= emulate_rdlo12rdhi16rn0rm8_rwflags_nopc
},
316 [PROBES_MUL2
] = {.handler
= emulate_rd16rn12rm0rs8_rwflags_nopc
},
317 [PROBES_SWP
] = {.handler
= emulate_rd12rn16rm0_rwflags_nopc
},
318 [PROBES_LDRSTRD
] = {.handler
= emulate_ldrdstrd
},
319 [PROBES_LOAD_EXTRA
] = {.handler
= emulate_ldr
},
320 [PROBES_LOAD
] = {.handler
= emulate_ldr
},
321 [PROBES_STORE_EXTRA
] = {.handler
= emulate_str
},
322 [PROBES_STORE
] = {.handler
= emulate_str
},
323 [PROBES_MOV_IP_SP
] = {.handler
= simulate_mov_ipsp
},
324 [PROBES_DATA_PROCESSING_REG
] = {
325 .handler
= emulate_rd12rn16rm0rs8_rwflags
},
326 [PROBES_DATA_PROCESSING_IMM
] = {
327 .handler
= emulate_rd12rn16rm0rs8_rwflags
},
328 [PROBES_MOV_HALFWORD
] = {.handler
= emulate_rd12rm0_noflags_nopc
},
329 [PROBES_SEV
] = {.handler
= probes_emulate_none
},
330 [PROBES_WFE
] = {.handler
= probes_simulate_nop
},
331 [PROBES_SATURATE
] = {.handler
= emulate_rd12rn16rm0_rwflags_nopc
},
332 [PROBES_REV
] = {.handler
= emulate_rd12rm0_noflags_nopc
},
333 [PROBES_MMI
] = {.handler
= emulate_rd12rn16rm0_rwflags_nopc
},
334 [PROBES_PACK
] = {.handler
= emulate_rd12rn16rm0_rwflags_nopc
},
335 [PROBES_EXTEND
] = {.handler
= emulate_rd12rm0_noflags_nopc
},
336 [PROBES_EXTEND_ADD
] = {.handler
= emulate_rd12rn16rm0_rwflags_nopc
},
337 [PROBES_MUL_ADD_LONG
] = {
338 .handler
= emulate_rdlo12rdhi16rn0rm8_rwflags_nopc
},
339 [PROBES_MUL_ADD
] = {.handler
= emulate_rd16rn12rm0rs8_rwflags_nopc
},
340 [PROBES_BITFIELD
] = {.handler
= emulate_rd12rm0_noflags_nopc
},
341 [PROBES_BRANCH
] = {.handler
= simulate_bbl
},
342 [PROBES_LDMSTM
] = {.decoder
= kprobe_decode_ldmstm
}