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