*/
#include <linux/sched.h>
+#include <linux/compiler.h>
typedef unsigned long kprobe_opcode_t;
unsigned long status;
};
-static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
- struct pt_regs *regs)
-{
- return &task_thread_info(p)->cpu_context.pc;
-}
-
static inline unsigned long arch_get_task_pc(struct task_struct *p)
{
return task_thread_info(p)->cpu_context.pc;
# define PTRN_ARM_INSN_AUNDEF 0x07F000F0
// branches
-# define MASK_ARM_INSN_B 0x0E000000 // xxxx111xxxxxxxxxxxxxxxxxxxxxxxxx
-# define PTRN_ARM_INSN_B 0x0A000000 // cccc101xxxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_B 0x0F000000 // xxxx1111xxxxxxxxxxxxxxxxxxxxxxxx
+# define PTRN_ARM_INSN_B 0x0A000000 // cccc1010xxxxxxxxxxxxxxxxxxxxxxxx
# define MASK_THUMB_INSN_B1 0xF000 // 1111xxxxxxxxxxxx
# define PTRN_THUMB_INSN_B1 0xD000 // 1101xxxxxxxxxxxx // b<cond> label
# define MASK_THUMB2_INSN_B2 0xD000F800 // 11x1xxxxxxxxxxxx 11111xxxxxxxxxxx // swapped
# define PTRN_THUMB2_INSN_B2 0x9000F000 // 10x1xxxxxxxxxxxx 11110xxxxxxxxxxx // swapped
-# define MASK_ARM_INSN_BL 0x0E000000 // xxxx111xxxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_BL 0x0F000000 // xxxx1111xxxxxxxxxxxxxxxxxxxxxxxx
# define PTRN_ARM_INSN_BL 0x0B000000 // cccc1011xxxxxxxxxxxxxxxxxxxxxxxx
//# define MASK_THUMB_INSN_BL 0xF800 // 11111xxxxxxxxxxx
# define MASK_THUMB2_INSN_BL 0xD000F800 // 11x1xxxxxxxxxxxx 11111xxxxxxxxxxx // swapped
# define PTRN_THUMB2_INSN_BL 0xD000F000 // 11x1xxxxxxxxxxxx 11110xxxxxxxxxxx // bl imm swapped
-# define MASK_ARM_INSN_BLX1 0xFF000000 // 11111111xxxxxxxxxxxxxxxxxxxxxxxx
-# define PTRN_ARM_INSN_BLX1 0xFA000000 // 11111011xxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_BLX1 0xFE000000 // 1111111axxxxxxxxxxxxxxxxxxxxxxxx
+# define PTRN_ARM_INSN_BLX1 0xFA000000 // 1111101axxxxxxxxxxxxxxxxxxxxxxxx
//# define MASK_THUMB_INSN_BLX1 0xF800 // 11111xxxxxxxxxxx / blx imm
//# define PTRN_THUMB_INSN_BLX1 0xF000 // 11101xxxxxxxxxxx
struct arch_specific_insn {
/* copy of the original instruction */
kprobe_opcode_t *insn;
- kprobe_opcode_t *insn_arm;
- kprobe_opcode_t *insn_thumb;
};
typedef kprobe_opcode_t (*entry_point_t) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
return 0;
}
-int arch_check_insn_arm(struct arch_specific_insn *ainsn);
+int arch_check_insn_arm(unsigned long insn);
int prep_pc_dep_insn_execbuf(kprobe_opcode_t *insns, kprobe_opcode_t insn, int uregs);
struct slot_manager;
int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs);
int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs);
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs);
void save_previous_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *cur_p);
void restore_previous_kprobe(struct kprobe_ctlblk *kcb);
void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb);
-void kretprobe_trampoline(void);
+void __naked kretprobe_trampoline(void);
+
+static inline unsigned long swap_get_karg(struct pt_regs *regs, unsigned long n)
+{
+ switch (n) {
+ case 0:
+ return regs->ARM_r0;
+ case 1:
+ return regs->ARM_r1;
+ case 2:
+ return regs->ARM_r2;
+ case 3:
+ return regs->ARM_r3;
+ }
+
+ return *((unsigned long *)regs->ARM_sp + n - 4);
+}
+
+static inline unsigned long swap_get_sarg(struct pt_regs *regs, unsigned long n)
+{
+ return swap_get_karg(regs, n);
+}
int arch_init_kprobes(void);
void arch_exit_kprobes(void);