Source code for vtrace.platforms.android

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 adbCommand(*argv): return subprocess.check_output(argv, stderr=subprocess.PIPE)
[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 platformDetach(self): if self.gdbserver: self.gdbserver.kill() self.gdbserver = None
[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)