From 87abef63ead5ac9e2c67f0c07c461eda6be16aeb Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Wed, 5 Mar 2014 21:06:29 -0500 Subject: ARM: move generic thumb instruction parsing code to new files for use by other feature Move the thumb version of the kprobes instruction parsing code into more generic files from where it can be used by uprobes and possibly other subsystems. The symbol names will be made more generic in a subsequent part of this patchset. Signed-off-by: David A. Long Acked-by: Jon Medhurst --- arch/arm/kernel/probes-thumb.h | 81 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 arch/arm/kernel/probes-thumb.h (limited to 'arch/arm/kernel/probes-thumb.h') diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h new file mode 100644 index 000000000000..98709c40b659 --- /dev/null +++ b/arch/arm/kernel/probes-thumb.h @@ -0,0 +1,81 @@ +/* + * arch/arm/kernel/probes-thumb.h + * + * Copyright 2013 Linaro Ltd. + * Written by: David A. Long + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _ARM_KERNEL_PROBES_THUMB_H +#define _ARM_KERNEL_PROBES_THUMB_H + +/* + * True if current instruction is in an IT block. + */ +#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000) + +/* + * Return the condition code to check for the currently executing instruction. + * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if + * in_it_block returns true. + */ +#define current_cond(cpsr) ((cpsr >> 12) & 0xf) + +void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs); +void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn, + struct arch_specific_insn *asi); + +void __kprobes t32_simulate_table_branch(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs); +void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs); +void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); +enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn, + struct arch_specific_insn *asi); +void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs); +void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs); +void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p, + struct pt_regs *regs); +void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, + struct pt_regs *regs); + +#endif -- cgit v1.2.3 From 3e6cd394bb10c2d65322e5f5d2ff0a9074d903a1 Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Thu, 6 Mar 2014 18:06:43 -0500 Subject: ARM: use a function table for determining instruction interpreter action Make the instruction interpreter call back to semantic action functions through a function pointer array provided by the invoker. The interpreter decodes the instructions into groups and uses the group number to index into the supplied array. kprobes and uprobes code will each supply their own array of functions. Signed-off-by: David A. Long Acked-by: Jon Medhurst --- arch/arm/kernel/probes-thumb.h | 104 ++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 49 deletions(-) (limited to 'arch/arm/kernel/probes-thumb.h') diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index 98709c40b659..8d6b4eefa706 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h @@ -27,55 +27,61 @@ */ #define current_cond(cpsr) ((cpsr >> 12) & 0xf) -void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn, - struct arch_specific_insn *asi); +enum probes_t32_action { + PROBES_T32_EMULATE_NONE, + PROBES_T32_SIMULATE_NOP, + PROBES_T32_LDMSTM, + PROBES_T32_LDRDSTRD, + PROBES_T32_TABLE_BRANCH, + PROBES_T32_TST, + PROBES_T32_CMP, + PROBES_T32_MOV, + PROBES_T32_ADDSUB, + PROBES_T32_LOGICAL, + PROBES_T32_ADDWSUBW_PC, + PROBES_T32_ADDWSUBW, + PROBES_T32_MOVW, + PROBES_T32_SAT, + PROBES_T32_BITFIELD, + PROBES_T32_SEV, + PROBES_T32_WFE, + PROBES_T32_MRS, + PROBES_T32_BRANCH_COND, + PROBES_T32_BRANCH, + PROBES_T32_PLDI, + PROBES_T32_LDR_LIT, + PROBES_T32_LDRSTR, + PROBES_T32_SIGN_EXTEND, + PROBES_T32_MEDIA, + PROBES_T32_REVERSE, + PROBES_T32_MUL_ADD, + PROBES_T32_MUL_ADD2, + PROBES_T32_MUL_ADD_LONG, + NUM_PROBES_T32_ACTIONS +}; -void __kprobes t32_simulate_table_branch(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, - struct pt_regs *regs); +enum probes_t16_action { + PROBES_T16_ADD_SP, + PROBES_T16_CBZ, + PROBES_T16_SIGN_EXTEND, + PROBES_T16_PUSH, + PROBES_T16_POP, + PROBES_T16_SEV, + PROBES_T16_WFE, + PROBES_T16_IT, + PROBES_T16_CMP, + PROBES_T16_ADDSUB, + PROBES_T16_LOGICAL, + PROBES_T16_BLX, + PROBES_T16_HIREGOPS, + PROBES_T16_LDR_LIT, + PROBES_T16_LDRHSTRH, + PROBES_T16_LDRSTR, + PROBES_T16_ADR, + PROBES_T16_LDMSTM, + PROBES_T16_BRANCH_COND, + PROBES_T16_BRANCH, + NUM_PROBES_T16_ACTIONS +}; #endif -- cgit v1.2.3 From 47e190fafde49ff8ca732fa137e39cb2b8baba8c Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Thu, 6 Mar 2014 18:12:07 -0500 Subject: ARM: Change the remaining shared kprobes/uprobes symbols to something generic Any more ARM kprobes/uprobes symbols which have "kprobe" in the name must be changed to the more generic "probes" or other non-kprobes specific symbol. Signed-off-by: David A. Long Acked-by: Jon Medhurst --- arch/arm/kernel/probes-thumb.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/arm/kernel/probes-thumb.h') diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index 8d6b4eefa706..d6f67c1df7af 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h @@ -84,4 +84,14 @@ enum probes_t16_action { NUM_PROBES_T16_ACTIONS }; +extern const union decode_item probes_decode_thumb32_table[]; +extern const union decode_item probes_decode_thumb16_table[]; + +enum probes_insn __kprobes +thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, + const union decode_action *actions); +enum probes_insn __kprobes +thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, + const union decode_action *actions); + #endif -- cgit v1.2.3 From 602cd2609eee92d338a83e400774e97c60535ba2 Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Wed, 5 Mar 2014 21:40:12 -0500 Subject: ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions Add an emulate flag into the instruction interpreter, primarily for uprobes support. Signed-off-by: David A. Long Acked-by: Jon Medhurst --- arch/arm/kernel/probes-thumb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/kernel/probes-thumb.h') diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index d6f67c1df7af..65e4250e9b78 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h @@ -89,9 +89,9 @@ extern const union decode_item probes_decode_thumb16_table[]; enum probes_insn __kprobes thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, - const union decode_action *actions); + bool emulate, const union decode_action *actions); enum probes_insn __kprobes thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, - const union decode_action *actions); + bool emulate, const union decode_action *actions); #endif -- cgit v1.2.3 From b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97 Mon Sep 17 00:00:00 2001 From: "David A. Long" Date: Wed, 5 Mar 2014 21:41:29 -0500 Subject: ARM: Make arch_specific_insn a define for new arch_probes_insn structure Because the common underlying code for ARM kprobes and uprobes needs to share a common architecrure-specific context structure, and because the generic kprobes include file insists on defining this to a dummy structure when kprobes is not configured, a new common structure is required which can exist when uprobes is configured without kprobes. In this case kprobes will define a dummy structure, but without the define aliasing the two structure tags it will not affect uprobes and the shared probes code. Signed-off-by: David A. Long Acked-by: Jon Medhurst --- arch/arm/kernel/probes-thumb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/kernel/probes-thumb.h') diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index 65e4250e9b78..7c6f6ebe514f 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h @@ -88,10 +88,10 @@ extern const union decode_item probes_decode_thumb32_table[]; extern const union decode_item probes_decode_thumb16_table[]; enum probes_insn __kprobes -thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, +thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, bool emulate, const union decode_action *actions); enum probes_insn __kprobes -thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, +thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, bool emulate, const union decode_action *actions); #endif -- cgit v1.2.3