diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-06-06 11:52:50 -0400 |
---|---|---|
committer | Tixy <tixy@medhuaa1.miniserver.com> | 2011-07-13 13:32:48 -0400 |
commit | 3535a89ab26db6b69603abf04420ec0b6c9ac387 (patch) | |
tree | 9604e87c6d7f224435191d9289207460a110ba1d /arch/arm/kernel/kprobes-arm.c | |
parent | 9f596e51261f96d602aa4eaf6db7f12ce53260d6 (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.c | 111 |
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 | ||
971 | static 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 | |||
971 | static enum kprobe_insn __kprobes | 1033 | static enum kprobe_insn __kprobes |
972 | space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 1034 | space_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 | ||
1179 | static enum kprobe_insn __kprobes | 1194 | static enum kprobe_insn __kprobes |