aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes-arm.c
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-06-06 11:52:50 -0400
committerTixy <tixy@medhuaa1.miniserver.com>2011-07-13 13:32:48 -0400
commit3535a89ab26db6b69603abf04420ec0b6c9ac387 (patch)
tree9604e87c6d7f224435191d9289207460a110ba1d /arch/arm/kernel/kprobes-arm.c
parent9f596e51261f96d602aa4eaf6db7f12ce53260d6 (diff)
ARM: kprobes: Migrate ARM data-processing (register) instructions to decoding tables
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel/kprobes-arm.c')
-rw-r--r--arch/arm/kernel/kprobes-arm.c111
1 files changed, 63 insertions, 48 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 6e38bd4f7efd..8e4b7185f9fb 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -968,6 +968,68 @@ static const union decode_item arm_1111_table[] = {
968 DECODE_END 968 DECODE_END
969}; 969};
970 970
971static const union decode_item arm_cccc_000x_table[] = {
972 /* Data-processing (register) */
973
974 /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
975 DECODE_REJECT (0x0e10f000, 0x0010f000),
976
977 /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
978 DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
979
980 /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
981 /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
982 /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
983 /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
984 DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
985 REGS(ANY, 0, 0, 0, ANY)),
986
987 /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
988 /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
989 DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
990 REGS(0, ANY, 0, 0, ANY)),
991
992 /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
993 /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
994 /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
995 /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
996 /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
997 /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
998 /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
999 /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
1000 /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
1001 /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
1002 DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
1003 REGS(ANY, ANY, 0, 0, ANY)),
1004
1005 /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
1006 /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
1007 /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
1008 /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
1009 DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
1010 REGS(ANY, 0, NOPC, 0, ANY)),
1011
1012 /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
1013 /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
1014 DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
1015 REGS(0, ANY, NOPC, 0, ANY)),
1016
1017 /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
1018 /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
1019 /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
1020 /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
1021 /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
1022 /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
1023 /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
1024 /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
1025 /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
1026 /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
1027 DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
1028 REGS(ANY, ANY, NOPC, 0, ANY)),
1029
1030 DECODE_END
1031};
1032
971static enum kprobe_insn __kprobes 1033static enum kprobe_insn __kprobes
972space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) 1034space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
973{ 1035{
@@ -1126,54 +1188,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1126 return prep_emulate_ldr_str(insn, asi); 1188 return prep_emulate_ldr_str(insn, asi);
1127 } 1189 }
1128 1190
1129 /* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */ 1191 return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false);
1130
1131 /*
1132 * ALU op with S bit and Rd == 15 :
1133 * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
1134 */
1135 if ((insn & 0x0e10f000) == 0x0010f000)
1136 return INSN_REJECTED;
1137
1138 /*
1139 * "mov ip, sp" is the most common kprobe'd instruction by far.
1140 * Check and optimize for it explicitly.
1141 */
1142 if (insn == 0xe1a0c00d) {
1143 asi->insn_handler = simulate_mov_ipsp;
1144 return INSN_GOOD_NO_SLOT;
1145 }
1146
1147 /*
1148 * Data processing: Immediate-shift / Register-shift
1149 * ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx
1150 * CPY : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx
1151 * MOV : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx
1152 * *S (bit 20) updates condition codes
1153 * ADC/SBC/RSC reads the C flag
1154 */
1155 insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */
1156 insn |= 0x00000001; /* Rm = r1 */
1157 if (insn & 0x010) {
1158 insn &= 0xfffff0ff; /* register shift */
1159 insn |= 0x00000200; /* Rs = r2 */
1160 }
1161 asi->insn[0] = insn;
1162
1163 if ((insn & 0x0f900000) == 0x01100000) {
1164 /*
1165 * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
1166 * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
1167 * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
1168 * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
1169 */
1170 asi->insn_handler = emulate_alu_tests;
1171 } else {
1172 /* ALU ops which write to Rd */
1173 asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
1174 emulate_alu_rwflags : emulate_alu_rflags;
1175 }
1176 return INSN_GOOD;
1177} 1192}
1178 1193
1179static enum kprobe_insn __kprobes 1194static enum kprobe_insn __kprobes