diff options
author | Petr Machata <pmachata@redhat.com> | 2013-02-06 20:01:53 +0100 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2013-03-12 00:08:53 +0100 |
commit | f25af517a06521f69fbc53eaf3c245a7a2298c75 (patch) | |
tree | 67234374eb1632f7880ccfd4ef1321a1a96fb10f /sysdeps | |
parent | 8a7a9f59e75c8605ca8206294b7729d0fd70f11f (diff) | |
download | ltrace-f25af517a06521f69fbc53eaf3c245a7a2298c75.tar.gz |
ARM cleanups
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/linux-gnu/arm/regs.c | 36 | ||||
-rw-r--r-- | sysdeps/linux-gnu/arm/regs.h | 2 | ||||
-rw-r--r-- | sysdeps/linux-gnu/arm/trace.c | 21 |
3 files changed, 34 insertions, 25 deletions
diff --git a/sysdeps/linux-gnu/arm/regs.c b/sysdeps/linux-gnu/arm/regs.c index bd86370..e9e825e 100644 --- a/sysdeps/linux-gnu/arm/regs.c +++ b/sysdeps/linux-gnu/arm/regs.c @@ -39,9 +39,6 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -#define off_pc ((void *)60) -#define off_sp ((void *)52) - int arm_get_register(struct process *proc, enum arm_register reg, uint32_t *lp) { @@ -54,6 +51,13 @@ arm_get_register(struct process *proc, enum arm_register reg, uint32_t *lp) } int +arm_set_register(struct process *proc, enum arm_register reg, uint32_t lp) +{ + return ptrace(PTRACE_PEEKUSER, proc->pid, + (void *)(reg * 4L), (void *)lp); +} + +int arm_get_register_offpc(struct process *proc, enum arm_register reg, uint32_t *lp) { @@ -116,36 +120,38 @@ arm_get_shifted_register(struct process *proc, uint32_t inst, int carry, return 0; } -arch_addr_t -get_instruction_pointer(struct process *proc) +static arch_addr_t +get_register_nocheck(struct process *proc, enum arm_register r) { uint32_t reg; - if (arm_get_register(proc, ARM_REG_PC, ®) < 0) + if (arm_get_register(proc, r, ®) < 0) /* XXX double cast. */ return (arch_addr_t)-1; /* XXX double cast. */ return (arch_addr_t)(uintptr_t)reg; } +arch_addr_t +get_instruction_pointer(struct process *proc) +{ + return get_register_nocheck(proc, ARM_REG_PC); +} + void -set_instruction_pointer(struct process *proc, void *addr) +set_instruction_pointer(struct process *proc, arch_addr_t addr) { - ptrace(PTRACE_POKEUSER, proc->pid, off_pc, addr); + /* XXX double cast. */ + arm_set_register(proc, ARM_REG_PC, (uint32_t)addr); } void * get_stack_pointer(struct process *proc) { - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_sp, 0); + return get_register_nocheck(proc, ARM_REG_SP); } arch_addr_t get_return_addr(struct process *proc, arch_addr_t stack_pointer) { - uint32_t reg; - if (arm_get_register(proc, ARM_REG_LR, ®) < 0) - /* XXX double cast. */ - return (arch_addr_t)-1; - /* XXX double cast. */ - return (arch_addr_t)(uintptr_t)reg; + return get_register_nocheck(proc, ARM_REG_LR); } diff --git a/sysdeps/linux-gnu/arm/regs.h b/sysdeps/linux-gnu/arm/regs.h index 1566f92..f9a5a86 100644 --- a/sysdeps/linux-gnu/arm/regs.h +++ b/sysdeps/linux-gnu/arm/regs.h @@ -25,6 +25,8 @@ ((long) (BITS(obj,st,fn) | ((long) BIT(obj,fn) * ~ SUBMASK(fn - st)))) enum arm_register { + ARM_REG_R7 = 7, + ARM_REG_IP = 12, ARM_REG_SP = 13, ARM_REG_LR = 14, ARM_REG_PC = 15, diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c index a4d82ac..5e51e91 100644 --- a/sysdeps/linux-gnu/arm/trace.c +++ b/sysdeps/linux-gnu/arm/trace.c @@ -35,6 +35,7 @@ #include "output.h" #include "ptrace.h" #include "regs.h" +#include "type.h" #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) # define PTRACE_PEEKUSER PTRACE_PEEKUSR @@ -44,12 +45,6 @@ # define PTRACE_POKEUSER PTRACE_POKEUSR #endif -#define off_r0 ((void *)0) -#define off_r7 ((void *)28) -#define off_ip ((void *)48) -#define off_pc ((void *)60) -#define off_cpsr ((void *)64) - void get_arch_dep(struct process *proc) { @@ -71,18 +66,24 @@ syscall_p(struct process *proc, int status, int *sysnum) { if (WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { - /* get the user's pc (plus 8) */ - unsigned pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); + uint32_t pc, ip; + if (arm_get_register(proc, ARM_REG_PC, &pc) < 0 + || arm_get_register(proc, ARM_REG_IP, &ip) < 0) + return -1; + pc = pc - 4; + /* fetch the SWI instruction */ unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid, (void *)pc, 0); - int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0); if (insn == 0xef000000 || insn == 0x0f000000 || (insn & 0xffff0000) == 0xdf000000) { /* EABI syscall */ - *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0); + uint32_t r7; + if (arm_get_register(proc, ARM_REG_R7, &r7) < 0) + return -1; + *sysnum = r7; } else if ((insn & 0xfff00000) == 0xef900000) { /* old ABI syscall */ *sysnum = insn & 0xfffff; |