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