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