2 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/stddef.h>
12 #include <linux/wait.h>
13 #include <linux/uprobes.h>
14 #include <linux/module.h>
17 #include "probes-arm.h"
20 static int uprobes_substitute_pc(unsigned long *pinsn
, u32 oregs
)
22 probes_opcode_t insn
= __mem_to_opcode_arm(*pinsn
);
29 for (regs
= oregs
; regs
; regs
>>= 4, insn
>>= 4) {
30 if ((regs
& 0xf) == REG_TYPE_NONE
)
33 free
&= ~(1 << (insn
& 0xf));
36 /* No PC, no problem */
44 * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
45 * pick LR instead of R1.
47 freereg
= free
= fls(free
) - 1;
49 temp
= __mem_to_opcode_arm(*pinsn
);
54 for (; regs
; regs
>>= 4, mask
<<= 4, free
<<= 4, temp
>>= 4) {
55 if ((regs
& 0xf) == REG_TYPE_NONE
)
58 if ((temp
& 0xf) != 15)
65 *pinsn
= __opcode_to_mem_arm(insn
);
69 static void uprobe_set_pc(struct arch_uprobe
*auprobe
,
70 struct arch_uprobe_task
*autask
,
73 u32 pcreg
= auprobe
->pcreg
;
75 autask
->backup
= regs
->uregs
[pcreg
];
76 regs
->uregs
[pcreg
] = regs
->ARM_pc
+ 8;
79 static void uprobe_unset_pc(struct arch_uprobe
*auprobe
,
80 struct arch_uprobe_task
*autask
,
83 /* PC will be taken care of by common code */
84 regs
->uregs
[auprobe
->pcreg
] = autask
->backup
;
87 static void uprobe_aluwrite_pc(struct arch_uprobe
*auprobe
,
88 struct arch_uprobe_task
*autask
,
91 u32 pcreg
= auprobe
->pcreg
;
93 alu_write_pc(regs
->uregs
[pcreg
], regs
);
94 regs
->uregs
[pcreg
] = autask
->backup
;
97 static void uprobe_write_pc(struct arch_uprobe
*auprobe
,
98 struct arch_uprobe_task
*autask
,
101 u32 pcreg
= auprobe
->pcreg
;
103 load_write_pc(regs
->uregs
[pcreg
], regs
);
104 regs
->uregs
[pcreg
] = autask
->backup
;
108 decode_pc_ro(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
109 const struct decode_header
*d
)
111 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
113 struct decode_emulate
*decode
= (struct decode_emulate
*) d
;
114 u32 regs
= decode
->header
.type_regs
.bits
>> DECODE_TYPE_BITS
;
117 reg
= uprobes_substitute_pc(&auprobe
->ixol
[0], regs
);
122 return INSN_REJECTED
;
124 auprobe
->pcreg
= reg
;
125 auprobe
->prehandler
= uprobe_set_pc
;
126 auprobe
->posthandler
= uprobe_unset_pc
;
132 decode_wb_pc(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
133 const struct decode_header
*d
, bool alu
)
135 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
137 enum probes_insn ret
= decode_pc_ro(insn
, asi
, d
);
139 if (((insn
>> 12) & 0xf) == 15)
140 auprobe
->posthandler
= alu
? uprobe_aluwrite_pc
147 decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn
,
148 struct arch_probes_insn
*asi
,
149 const struct decode_header
*d
)
151 return decode_wb_pc(insn
, asi
, d
, true);
155 decode_ldr(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
156 const struct decode_header
*d
)
158 return decode_wb_pc(insn
, asi
, d
, false);
162 uprobe_decode_ldmstm(probes_opcode_t insn
,
163 struct arch_probes_insn
*asi
,
164 const struct decode_header
*d
)
166 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
168 unsigned reglist
= insn
& 0xffff;
169 int rn
= (insn
>> 16) & 0xf;
170 int lbit
= insn
& (1 << 20);
171 unsigned used
= reglist
| (1 << rn
);
174 return INSN_REJECTED
;
176 if (!(used
& (1 << 15)))
179 if (used
& (1 << 14))
180 return INSN_REJECTED
;
182 /* Use LR instead of PC */
186 auprobe
->ixol
[0] = __opcode_to_mem_arm(insn
);
188 auprobe
->prehandler
= uprobe_set_pc
;
190 auprobe
->posthandler
= uprobe_write_pc
;
192 auprobe
->posthandler
= uprobe_unset_pc
;
197 const union decode_action uprobes_probes_actions
[] = {
198 [PROBES_EMULATE_NONE
] = {.handler
= probes_simulate_nop
},
199 [PROBES_SIMULATE_NOP
] = {.handler
= probes_simulate_nop
},
200 [PROBES_PRELOAD_IMM
] = {.handler
= probes_simulate_nop
},
201 [PROBES_PRELOAD_REG
] = {.handler
= probes_simulate_nop
},
202 [PROBES_BRANCH_IMM
] = {.handler
= simulate_blx1
},
203 [PROBES_MRS
] = {.handler
= simulate_mrs
},
204 [PROBES_BRANCH_REG
] = {.handler
= simulate_blx2bx
},
205 [PROBES_CLZ
] = {.handler
= probes_simulate_nop
},
206 [PROBES_SATURATING_ARITHMETIC
] = {.handler
= probes_simulate_nop
},
207 [PROBES_MUL1
] = {.handler
= probes_simulate_nop
},
208 [PROBES_MUL2
] = {.handler
= probes_simulate_nop
},
209 [PROBES_SWP
] = {.handler
= probes_simulate_nop
},
210 [PROBES_LDRSTRD
] = {.decoder
= decode_pc_ro
},
211 [PROBES_LOAD_EXTRA
] = {.decoder
= decode_pc_ro
},
212 [PROBES_LOAD
] = {.decoder
= decode_ldr
},
213 [PROBES_STORE_EXTRA
] = {.decoder
= decode_pc_ro
},
214 [PROBES_STORE
] = {.decoder
= decode_pc_ro
},
215 [PROBES_MOV_IP_SP
] = {.handler
= simulate_mov_ipsp
},
216 [PROBES_DATA_PROCESSING_REG
] = {
217 .decoder
= decode_rd12rn16rm0rs8_rwflags
},
218 [PROBES_DATA_PROCESSING_IMM
] = {
219 .decoder
= decode_rd12rn16rm0rs8_rwflags
},
220 [PROBES_MOV_HALFWORD
] = {.handler
= probes_simulate_nop
},
221 [PROBES_SEV
] = {.handler
= probes_simulate_nop
},
222 [PROBES_WFE
] = {.handler
= probes_simulate_nop
},
223 [PROBES_SATURATE
] = {.handler
= probes_simulate_nop
},
224 [PROBES_REV
] = {.handler
= probes_simulate_nop
},
225 [PROBES_MMI
] = {.handler
= probes_simulate_nop
},
226 [PROBES_PACK
] = {.handler
= probes_simulate_nop
},
227 [PROBES_EXTEND
] = {.handler
= probes_simulate_nop
},
228 [PROBES_EXTEND_ADD
] = {.handler
= probes_simulate_nop
},
229 [PROBES_MUL_ADD_LONG
] = {.handler
= probes_simulate_nop
},
230 [PROBES_MUL_ADD
] = {.handler
= probes_simulate_nop
},
231 [PROBES_BITFIELD
] = {.handler
= probes_simulate_nop
},
232 [PROBES_BRANCH
] = {.handler
= simulate_bbl
},
233 [PROBES_LDMSTM
] = {.decoder
= uprobe_decode_ldmstm
}