import os
import tempfile
import threading
import subprocess
import envi.memory as e_mem
import vtrace
import vtrace.archs.arm as v_arm
import vtrace.platforms.base as v_base
import vtrace.platforms.posix as v_posix
import vtrace.platforms.gdbstub as v_gdbstub
from cStringIO import StringIO
platdir = os.path.dirname(__file__)
targdir = '/data/local/tmp/'
gdbserver_arm = 'gdbserver_arm_4.3.3'
gdbserver_arm_path = os.path.join(platdir, 'gdbbins', gdbserver_arm)
gdbserver_arm_targ = targdir + gdbserver_arm
[docs]def checkGdbServer():
t = adbCommand('adb','shell','ls',targdir)
if t.find(gdbserver_arm) == -1:
adbCommand('adb','push',gdbserver_arm_path,targdir)
adbCommand('adb','shell','chmod','755', gdbserver_arm_targ)
[docs]def openAndroidFile(fname):
fd = tempfile.NamedTemporaryFile()
adbCommand('adb','pull', fname, fd.name)
return file(fd.name, 'r+b')
arm_regfmt = '<16I96sI'
arm_regnames = ["r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","sl","fp","ip","sp", "lr","pc", None, "cpsr"]
[docs]class AndroidArmTrace(
vtrace.Trace,
v_gdbstub.GdbStubMixin,
v_arm.ArmMixin,
v_posix.ElfMixin,
v_base.TracerBase):
def __init__(self, avd=None):
vtrace.Trace.__init__(self, archname='arm')
v_base.TracerBase.__init__(self)
v_gdbstub.GdbStubMixin.__init__(self)
v_arm.ArmMixin.__init__(self)
v_posix.ElfMixin.__init__(self)
self._gdbSetRegisterInfo(arm_regfmt, arm_regnames)
self._gdb_filemagic = '\x7fELF'
self.setMeta('Platform', 'android')
self.avd = avd
self.gdbserver = None
[docs] def platformAttach(self, pid):
port = 33221
checkGdbServer()
gserver = ['adb','shell',gdbserver_arm_targ,'0.0.0.0:%d' % port, '--attach', str(pid) ]
try:
self.gdbserver = subprocess.Popen(gserver,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
# Read the "Attached" and "Listening" output (which delays us long
# enough to connect correctly....)
# FIXME error check this stuff!
l1 = self.gdbserver.stdout.readline()
l2 = self.gdbserver.stdout.readline()
adbCommand('adb','forward','tcp:%d' % port, 'tcp:%d' % port)
self._gdb_host = 'localhost'
self._gdb_port = port
return v_gdbstub.GdbStubMixin.platformAttach(self, pid)
except Exception, e:
if self.gdbserver:
self.gdbserver.kill()
self.gdbserver = None
raise
[docs] def platformGetMaps(self):
maps = []
mapsbuf = adbCommand('adb','shell','cat','/proc/%d/maps' % self.pid)
for line in mapsbuf.splitlines():
if not line:
continue
perms = 0
sline = line.split(" ")
addrs = sline[0]
permstr = sline[1]
fname = sline[-1].strip()
addrs = addrs.split("-")
base = long(addrs[0],16)
max = long(addrs[1],16)
mlen = max-base
if "r" in permstr:
perms |= e_mem.MM_READ
if "w" in permstr:
perms |= e_mem.MM_WRITE
if "x" in permstr:
perms |= e_mem.MM_EXEC
maps.append((base,mlen,perms,fname))
return maps
[docs] def platformPs(self):
ret = []
output = adbCommand('adb','shell','ps')
for line in output.split('\n'):
line = line.strip()
if not line:
continue
if line.startswith('USER'):
continue
parts = line.split(None, 8)
ret.append( (int(parts[1]), parts[8]) )
return ret
[docs] def platformOpenFile(self, filename):
return openAndroidFile(filename)
#output = adbCommand('adb','shell','cat',filename)
#return StringIO(output)
[docs]def getTrace(avd=None):
# Check for adb in path...
try:
output = adbCommand('adb', 'devices')
lines = output.splitlines()
if len(lines) <= 2:
print('Warning: "adb devices" didnt see an Android device, start/attach one!')
except Exception, e:
raise Exception('Android "adb" command *must* be in your path!')
return AndroidArmTrace(avd)