summaryrefslogtreecommitdiff
path: root/uprobe
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2013-04-02 16:50:25 +0400
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2013-04-02 16:50:25 +0400
commit14eef18ad1a0953c73c5e6ca32ffa8bf5ee7a814 (patch)
treeb0e9ee90c172e787461755a4c0a6c396bc7f0858 /uprobe
parenta70e8ac65c9c19cf16549a061c23ad9ee698095f (diff)
downloadswap-modules-14eef18ad1a0953c73c5e6ca32ffa8bf5ee7a814.tar.gz
swap-modules-14eef18ad1a0953c73c5e6ca32ffa8bf5ee7a814.tar.bz2
swap-modules-14eef18ad1a0953c73c5e6ca32ffa8bf5ee7a814.zip
[REFACTOR] create restore_opcode_for_thumb()
Diffstat (limited to 'uprobe')
-rw-r--r--uprobe/arch/asm-arm/swap_uprobes.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/uprobe/arch/asm-arm/swap_uprobes.c b/uprobe/arch/asm-arm/swap_uprobes.c
index f0097a66..08b47741 100644
--- a/uprobe/arch/asm-arm/swap_uprobes.c
+++ b/uprobe/arch/asm-arm/swap_uprobes.c
@@ -12,6 +12,10 @@
extern struct hlist_head uprobe_insn_pages;
+#define flush_insns(addr, size) \
+ flush_icache_range((unsigned long)(addr), \
+ (unsigned long)(addr) + (size))
+
#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
@@ -683,6 +687,16 @@ disarm:
return -1;
}
+static void restore_opcode_for_thumb(struct kprobe *p, struct pt_regs *regs)
+{
+ if (thumb_mode(regs) && !is_thumb2(p->opcode)) {
+ u16 tmp = p->opcode >> 16;
+ write_proc_vm_atomic(current,
+ (unsigned long)((u16*)p->addr + 1), &tmp, 2);
+ flush_insns(p->addr, 4);
+ }
+}
+
static int uprobe_handler(struct pt_regs *regs)
{
kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->ARM_pc);
@@ -708,16 +722,7 @@ static int uprobe_handler(struct pt_regs *regs)
return 0;
}
- /* restore opcode for thumb app */
- if (thumb_mode(regs)) {
- if (!is_thumb2(p->opcode)) {
- unsigned long tmp = p->opcode >> 16;
- write_proc_vm_atomic(task, (unsigned long)((unsigned short*)p->addr + 1), &tmp, 2);
-
- // "2*sizeof(kprobe_opcode_t)" - strange. Should be "sizeof(kprobe_opcode_t)", need to test
- flush_icache_range((unsigned int)p->addr, ((unsigned int)p->addr) + (2 * sizeof(kprobe_opcode_t)));
- }
- }
+ restore_opcode_for_thumb(p, regs);
if (!p->pre_handler || !p->pre_handler(p, regs)) {
prepare_singlestep(p, regs);