xref: /xnu-11417.140.69/tools/lldbmacros/core/io.py (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
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().__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