xref: /xnu-8020.140.41/tools/lldbmacros/core/io.py (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
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