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