diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2013-04-02 16:50:25 +0400 |
---|---|---|
committer | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2013-04-02 16:50:25 +0400 |
commit | 14eef18ad1a0953c73c5e6ca32ffa8bf5ee7a814 (patch) | |
tree | b0e9ee90c172e787461755a4c0a6c396bc7f0858 /uprobe | |
parent | a70e8ac65c9c19cf16549a061c23ad9ee698095f (diff) | |
download | swap-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.c | 25 |
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); |