ptrace on ARM
vstinner opened this issue · 8 comments
Originally reported by: Peter Saveliev (Bitbucket: svinota, GitHub: svinota)
root@localhost:~# ./strace.py ps
execve(/bin/ps, ['/bin/ps'], [/* 40 vars */]) = 19393
Debugger error: [NotImplementedError]
Traceback (most recent call last):
File "./strace.py", line 247, in _main
self.runDebugger()
File "./strace.py", line 235, in runDebugger
self.syscallTrace(process)
File "./strace.py", line 181, in syscallTrace
self.syscall(process)
File "./strace.py", line 185, in syscall
syscall = state.event(self.syscall_options)
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/syscall_state.py", line 15, in event
return self.enter(options)
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/syscall_state.py", line 24, in enter
self.syscall.enter(regs)
File "/usr/lib/python2.7/dist-packages/ptrace/syscall/ptrace_syscall.py", line 33, in enter
argument_values = self.readArgumentValues(regs)
File "/usr/lib/python2.7/dist-packages/ptrace/syscall/ptrace_syscall.py", line 74, in readArgumentValues
raise NotImplementedError()
NotImplementedError
Terminate <PtraceProcess #19393>
*** Error in `python': double free or corruption (!prev): 0x02340d90 ***
Aborted
root@localhost:~# cat /proc/cpuinfo
Processor : ARMv7 Processor rev 9 (v7l)
processor : 0
BogoMIPS : 1993.93
processor : 1
BogoMIPS : 1993.93
processor : 2
BogoMIPS : 1993.93
processor : 3
BogoMIPS : 1993.93
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 9
Hardware : cardhu
Revision : 0000
Serial : 02458200e04f4300
root@localhost:~#
Platform -- Debian sid on asus transformer pad tf300t, using Android kernel:
root@localhost:~# uname -a
Linux localhost 3.1.10-00003-gb0003ba #1 SMP PREEMPT Fri Dec 28 17:34:15 CST 2012 armv7l GNU/Linux
If ARM platform is not supported, it would be better to raise an exception on import for non-distribution installations AND restrict platforms for distribution packaging.
If it is supported, it would be nice to have it fixed.
Original comment by Victor Stinner (Bitbucket: haypo, GitHub: haypo):
Oh, I don't have access to an ARM device to test python-ptrace. I never tested python-ptrace on ARM. According to the traceback: ptrace() is supported, but not tracing syscalls.
You have to patch PtraceSyscall.readSyscall() and PtraceSyscall.readArgumentValues() for your platform. It's quite easy, you "just" have to find the calling convention for syscalls: where system call arguments are stored? In registers? On the stack?
See for example http://stackoverflow.com/questions/12946958/system-call-in-arm
"Register R8 is used to pass the system call number that is whenever you use a system call through an API, the function being called does not do any specific work. It acts as an interface between the user and the system call system routine.
the registers R9,R10,R11,R12 are used to pass the parameters to the system call. if the system call needs more than 4 parameters then the first 4 are placed on the registers and the others are placed on the stack (This approach can vary with the Compiler being used to compile the kernel)."
Original comment by hex_m_hell (Bitbucket: hex_m_hell, GitHub: Unknown):
I will buy you a raspberry pi if you will be willing to use it to fix this.
Original comment by Victor Stinner (Bitbucket: haypo, GitHub: haypo):
Thanks hex_m_hell! I received the Raspberry Pi this morning. I plugged the USB cable to power it, plugged an ethernet cable and... it works!
I made the following changes to port python-ptrace on ARM:
16f3a48
613417e
610608c
PTRACE_SINGLESTEP was implemented in software in the Linux kernel, but it was removed for different reasons.
http://comments.gmane.org/gmane.linux.ports.arm.kernel/105658
HAS_PTRACE_SINGLESTEP should maybe be set to False in ptrace/binding/func.py, but I would prefer that someone else confirms that it doesn't work.
I tried to implement breakpoint using "FE DE FF E7" instruction ("UND" instruction on Linux?), but it looks like the kernel freezes. It looks like debugging is very different from ptrace on Intel. I'm not sure that stack and frame pointer registers are correct.
So please test it!
Original comment by Victor Stinner (Bitbucket: haypo, GitHub: haypo):
Patch for breakpoint which freezes the board:
diff -r 16f3a48a7f5a ptrace/debugger/breakpoint.py
--- a/ptrace/debugger/breakpoint.py Mon Jan 20 17:07:55 2014 +0100
+++ b/ptrace/debugger/breakpoint.py Mon Jan 20 16:24:25 2014 +0000
@@ -2,10 +2,13 @@
from ptrace import PtraceError
from logging import info
from weakref import ref
-from ptrace.cpu_info import CPU_POWERPC, CPU_WORD_SIZE
+from ptrace.cpu_info import CPU_POWERPC, CPU_WORD_SIZE, CPU_ARM
from ptrace.ctypes_tools import word2bytes
from ptrace.six import b
+# UND opcode on Linux
+ARM_BREAKPOINT = b('\xFE\xDE\xFF\xE7')
+
class Breakpoint(object):
"""
Software breakpoint.
@@ -18,6 +21,8 @@
self.address = address
if CPU_POWERPC:
size = CPU_WORD_SIZE
+ elif CPU_ARM:
+ size = len(ARM_BREAKPOINT)
elif size is None:
size = 1
self.size = size
@@ -29,6 +34,8 @@
if CPU_POWERPC:
# Replace instruction with "TRAP"
new_bytes = word2bytes(0x0cc00000)
+ elif CPU_ARM:
+ new_bytes = ARM_BREAKPOINT
else:
# Replace instruction with "INT 3"
new_bytes = b("\xCC") * size