1*19c3b8c2SApple OSS Distributions""" Python I/O subsystem backed by LLDB. """ 2*19c3b8c2SApple OSS Distributions 3*19c3b8c2SApple OSS Distributionsfrom __future__ import absolute_import, division, print_function 4*19c3b8c2SApple OSS Distributions 5*19c3b8c2SApple OSS Distributionsfrom builtins import bytes 6*19c3b8c2SApple OSS Distributions 7*19c3b8c2SApple OSS Distributionsimport io 8*19c3b8c2SApple OSS Distributionsimport lldb 9*19c3b8c2SApple OSS Distributions 10*19c3b8c2SApple OSS Distributions 11*19c3b8c2SApple OSS Distributionsclass SBProcessRawIO(io.RawIOBase): 12*19c3b8c2SApple OSS Distributions """ RAW I/O implementation backed by a process memory. """ 13*19c3b8c2SApple OSS Distributions 14*19c3b8c2SApple OSS Distributions def __init__(self, sbprocess, address, size): 15*19c3b8c2SApple OSS Distributions """ Create new SBProcess I/O. 16*19c3b8c2SApple OSS Distributions 17*19c3b8c2SApple OSS Distributions sbproces: SBProcess instance to read data from. 18*19c3b8c2SApple OSS Distributions address: Starting memory address in process' VA. 19*19c3b8c2SApple OSS Distributions size: Size of the memory range. 20*19c3b8c2SApple OSS Distributions """ 21*19c3b8c2SApple OSS Distributions super(SBProcessRawIO, self).__init__() 22*19c3b8c2SApple OSS Distributions 23*19c3b8c2SApple OSS Distributions self._sbprocess = sbprocess 24*19c3b8c2SApple OSS Distributions self._start = address 25*19c3b8c2SApple OSS Distributions self._offset = 0 26*19c3b8c2SApple OSS Distributions self._end = address + size 27*19c3b8c2SApple OSS Distributions 28*19c3b8c2SApple OSS Distributions # Base I/O methods 29*19c3b8c2SApple OSS Distributions 30*19c3b8c2SApple OSS Distributions def readable(self): 31*19c3b8c2SApple OSS Distributions return True 32*19c3b8c2SApple OSS Distributions 33*19c3b8c2SApple OSS Distributions def writable(self): 34*19c3b8c2SApple OSS Distributions # This is a lie that allows using BufferedRandom on top of this I/O. 35*19c3b8c2SApple OSS Distributions return True 36*19c3b8c2SApple OSS Distributions 37*19c3b8c2SApple OSS Distributions def seekable(self): 38*19c3b8c2SApple OSS Distributions return True 39*19c3b8c2SApple OSS Distributions 40*19c3b8c2SApple OSS Distributions # Raw I/O methods 41*19c3b8c2SApple OSS Distributions 42*19c3b8c2SApple OSS Distributions def tell(self): 43*19c3b8c2SApple OSS Distributions return self._offset 44*19c3b8c2SApple OSS Distributions 45*19c3b8c2SApple OSS Distributions def seek(self, offset, whence=0): 46*19c3b8c2SApple OSS Distributions seekto = offset 47*19c3b8c2SApple OSS Distributions if whence == 0: 48*19c3b8c2SApple OSS Distributions seekto += 0 49*19c3b8c2SApple OSS Distributions elif whence == 1: 50*19c3b8c2SApple OSS Distributions seekto += self.tell() 51*19c3b8c2SApple OSS Distributions elif whence == 2: 52*19c3b8c2SApple OSS Distributions seekto += self._end - self._start 53*19c3b8c2SApple OSS Distributions else: 54*19c3b8c2SApple OSS Distributions raise IOError("Invalid whence argument to seek: %r" % (whence,)) 55*19c3b8c2SApple OSS Distributions 56*19c3b8c2SApple OSS Distributions self._offset = seekto 57*19c3b8c2SApple OSS Distributions return seekto 58*19c3b8c2SApple OSS Distributions 59*19c3b8c2SApple OSS Distributions def read(self, size=-1): 60*19c3b8c2SApple OSS Distributions if size < 0: 61*19c3b8c2SApple OSS Distributions return self.readall() 62*19c3b8c2SApple OSS Distributions 63*19c3b8c2SApple OSS Distributions # Do not read past the end of the data range. 64*19c3b8c2SApple OSS Distributions read_size = min(size, self._end - (self._start + self._offset)) 65*19c3b8c2SApple OSS Distributions 66*19c3b8c2SApple OSS Distributions err = lldb.SBError() 67*19c3b8c2SApple OSS Distributions data = self._sbprocess.ReadMemory(self._start + self._offset, read_size, err) 68*19c3b8c2SApple OSS Distributions 69*19c3b8c2SApple OSS Distributions # EOF on failure 70*19c3b8c2SApple OSS Distributions if not err.Success(): 71*19c3b8c2SApple OSS Distributions return bytes() 72*19c3b8c2SApple OSS Distributions 73*19c3b8c2SApple OSS Distributions self._offset += len(data) 74*19c3b8c2SApple OSS Distributions return bytes(data) 75*19c3b8c2SApple OSS Distributions 76*19c3b8c2SApple OSS Distributions def readall(self): 77*19c3b8c2SApple OSS Distributions err = lldb.SBError() 78*19c3b8c2SApple OSS Distributions data = self._sbprocess.ReadMemory(self._start, self._end - self._start, err) 79*19c3b8c2SApple OSS Distributions 80*19c3b8c2SApple OSS Distributions if not err.Success(): 81*19c3b8c2SApple OSS Distributions return bytes() 82*19c3b8c2SApple OSS Distributions 83*19c3b8c2SApple OSS Distributions return bytes(data) 84*19c3b8c2SApple OSS Distributions 85*19c3b8c2SApple OSS Distributions def readinto(self, bytes): 86*19c3b8c2SApple OSS Distributions """ Reads data into existing object. """ 87*19c3b8c2SApple OSS Distributions data = self.read(len(bytes)) 88*19c3b8c2SApple OSS Distributions if data: 89*19c3b8c2SApple OSS Distributions bytes[:len(data)] = data 90*19c3b8c2SApple OSS Distributions return len(data) 91*19c3b8c2SApple OSS Distributions 92*19c3b8c2SApple OSS Distributions def readlines(self, hint=-1): 93*19c3b8c2SApple OSS Distributions raise NotImplementedError("Can't read lines yet.") 94*19c3b8c2SApple OSS Distributions 95*19c3b8c2SApple OSS Distributions def write(self, bytes): 96*19c3b8c2SApple OSS Distributions raise NotImplementedError("Can't write through LLDB yet.") 97