diff options
| -rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 57 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-common.c | 3 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-thumb.c | 149 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes.c | 9 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes.h | 15 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.c | 114 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-arm.h | 52 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-thumb.c | 145 | ||||
| -rw-r--r-- | arch/arm/kernel/probes-thumb.h | 104 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.c | 9 | ||||
| -rw-r--r-- | arch/arm/kernel/probes.h | 55 |
11 files changed, 441 insertions, 271 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index a1d0a8f00f9e..8ebd84c48867 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
| @@ -73,7 +73,7 @@ | |||
| 73 | #endif | 73 | #endif |
| 74 | 74 | ||
| 75 | 75 | ||
| 76 | void __kprobes | 76 | static void __kprobes |
| 77 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 77 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) |
| 78 | { | 78 | { |
| 79 | kprobe_opcode_t insn = p->opcode; | 79 | kprobe_opcode_t insn = p->opcode; |
| @@ -102,7 +102,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
| 102 | regs->uregs[rn] = rnv; | 102 | regs->uregs[rn] = rnv; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void __kprobes | 105 | static void __kprobes |
| 106 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) | 106 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) |
| 107 | { | 107 | { |
| 108 | kprobe_opcode_t insn = p->opcode; | 108 | kprobe_opcode_t insn = p->opcode; |
| @@ -132,7 +132,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
| 132 | regs->uregs[rn] = rnv; | 132 | regs->uregs[rn] = rnv; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | void __kprobes | 135 | static void __kprobes |
| 136 | emulate_str(struct kprobe *p, struct pt_regs *regs) | 136 | emulate_str(struct kprobe *p, struct pt_regs *regs) |
| 137 | { | 137 | { |
| 138 | kprobe_opcode_t insn = p->opcode; | 138 | kprobe_opcode_t insn = p->opcode; |
| @@ -159,7 +159,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
| 159 | regs->uregs[rn] = rnv; | 159 | regs->uregs[rn] = rnv; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | void __kprobes | 162 | static void __kprobes |
| 163 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | 163 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) |
| 164 | { | 164 | { |
| 165 | kprobe_opcode_t insn = p->opcode; | 165 | kprobe_opcode_t insn = p->opcode; |
| @@ -194,7 +194,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
| 194 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 194 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | void __kprobes | 197 | static void __kprobes |
| 198 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 198 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
| 199 | { | 199 | { |
| 200 | kprobe_opcode_t insn = p->opcode; | 200 | kprobe_opcode_t insn = p->opcode; |
| @@ -221,7 +221,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 221 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 221 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | void __kprobes | 224 | static void __kprobes |
| 225 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 225 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
| 226 | { | 226 | { |
| 227 | kprobe_opcode_t insn = p->opcode; | 227 | kprobe_opcode_t insn = p->opcode; |
| @@ -250,7 +250,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 250 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 250 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | void __kprobes | 253 | static void __kprobes |
| 254 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | 254 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) |
| 255 | { | 255 | { |
| 256 | kprobe_opcode_t insn = p->opcode; | 256 | kprobe_opcode_t insn = p->opcode; |
| @@ -270,7 +270,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 270 | regs->uregs[rd] = rdv; | 270 | regs->uregs[rd] = rdv; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | void __kprobes | 273 | static void __kprobes |
| 274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
| 275 | { | 275 | { |
| 276 | kprobe_opcode_t insn = p->opcode; | 276 | kprobe_opcode_t insn = p->opcode; |
| @@ -299,3 +299,44 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
| 299 | regs->uregs[rdhi] = rdhiv; | 299 | regs->uregs[rdhi] = rdhiv; |
| 300 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 300 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
| 301 | } | 301 | } |
| 302 | |||
| 303 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { | ||
| 304 | [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none}, | ||
| 305 | [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop}, | ||
| 306 | [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop}, | ||
| 307 | [PROBES_PRELOAD_REG] = {.handler = kprobe_simulate_nop}, | ||
| 308 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | ||
| 309 | [PROBES_MRS] = {.handler = simulate_mrs}, | ||
| 310 | [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, | ||
| 311 | [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, | ||
| 312 | [PROBES_SATURATING_ARITHMETIC] = { | ||
| 313 | .handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 314 | [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, | ||
| 315 | [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, | ||
| 316 | [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 317 | [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, | ||
| 318 | [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, | ||
| 319 | [PROBES_LOAD] = {.handler = emulate_ldr}, | ||
| 320 | [PROBES_STORE_EXTRA] = {.handler = emulate_str}, | ||
| 321 | [PROBES_STORE] = {.handler = emulate_str}, | ||
| 322 | [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, | ||
| 323 | [PROBES_DATA_PROCESSING_REG] = { | ||
| 324 | .handler = emulate_rd12rn16rm0rs8_rwflags}, | ||
| 325 | [PROBES_DATA_PROCESSING_IMM] = { | ||
| 326 | .handler = emulate_rd12rn16rm0rs8_rwflags}, | ||
| 327 | [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, | ||
| 328 | [PROBES_SEV] = {.handler = kprobe_emulate_none}, | ||
| 329 | [PROBES_WFE] = {.handler = kprobe_simulate_nop}, | ||
| 330 | [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 331 | [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, | ||
| 332 | [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 333 | [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 334 | [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, | ||
| 335 | [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, | ||
| 336 | [PROBES_MUL_ADD_LONG] = { | ||
| 337 | .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, | ||
| 338 | [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, | ||
| 339 | [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, | ||
| 340 | [PROBES_BRANCH] = {.handler = simulate_bbl}, | ||
| 341 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} | ||
| 342 | }; | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index f02c038059c3..029b79c6face 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c | |||
| @@ -112,7 +112,8 @@ emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | enum kprobe_insn __kprobes | 114 | enum kprobe_insn __kprobes |
| 115 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 115 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, |
| 116 | const struct decode_header *h) | ||
| 116 | { | 117 | { |
| 117 | kprobe_insn_handler_t *handler = 0; | 118 | kprobe_insn_handler_t *handler = 0; |
| 118 | unsigned reglist = insn & 0xffff; | 119 | unsigned reglist = insn & 0xffff; |
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 977f21723a9c..d83f6092920a 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c | |||
| @@ -16,6 +16,10 @@ | |||
| 16 | #include "kprobes.h" | 16 | #include "kprobes.h" |
| 17 | #include "probes-thumb.h" | 17 | #include "probes-thumb.h" |
| 18 | 18 | ||
| 19 | /* These emulation encodings are functionally equivalent... */ | ||
| 20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | ||
| 21 | t32_emulate_rdlo12rdhi8rn16rm0_noflags | ||
| 22 | |||
| 19 | /* | 23 | /* |
| 20 | * Return the PC value for a probe in thumb code. | 24 | * Return the PC value for a probe in thumb code. |
| 21 | * This is the address of the probed instruction plus 4. | 25 | * This is the address of the probed instruction plus 4. |
| @@ -29,7 +33,7 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) | |||
| 29 | 33 | ||
| 30 | /* t32 thumb actions */ | 34 | /* t32 thumb actions */ |
| 31 | 35 | ||
| 32 | void __kprobes | 36 | static void __kprobes |
| 33 | t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | 37 | t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) |
| 34 | { | 38 | { |
| 35 | kprobe_opcode_t insn = p->opcode; | 39 | kprobe_opcode_t insn = p->opcode; |
| @@ -49,7 +53,7 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | |||
| 49 | regs->ARM_pc = pc + 2 * halfwords; | 53 | regs->ARM_pc = pc + 2 * halfword |
