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