1from abc import ABCMeta, abstractmethod
2import six
3
4import lldb
5
6@six.add_metaclass(ABCMeta)
7class ScriptedProcess:
8
9    """
10    The base class for a scripted process.
11
12    Most of the base class methods are `@abstractmethod` that need to be
13    overwritten by the inheriting class.
14
15    DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE.
16                THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE.
17    """
18
19    @abstractmethod
20    def __init__(self, target, args):
21        """ Construct a scripted process.
22
23        Args:
24            target (lldb.SBTarget): The target launching the scripted process.
25            args (lldb.SBStructuredData): A Dictionary holding arbitrary
26                key/value pairs used by the scripted process.
27        """
28        self.target = None
29        self.args = None
30        if isinstance(target, lldb.SBTarget) and target.IsValid():
31            self.target = target
32        if isinstance(args, lldb.SBStructuredData) and args.IsValid():
33            self.args = args
34
35    @abstractmethod
36    def get_memory_region_containing_address(addr):
37        """ Get the memory region for the scripted process, containing a
38            specific address.
39
40        Args:
41            addr (int): Address to look for in the scripted process memory
42                regions.
43
44        Returns:
45            lldb.SBMemoryRegionInfo: The memory region containing the address.
46                None if out of bounds.
47        """
48        pass
49
50    @abstractmethod
51    def get_thread_with_id(tid):
52        """ Get the scripted process thread with a specific ID.
53
54        Args:
55            tid (int): Thread ID to look for in the scripted process.
56
57        Returns:
58            Dict: The thread represented as a dictionary, withr the
59                tid thread ID. None if tid doesn't match any of the scripted
60                process threads.
61        """
62        pass
63
64    @abstractmethod
65    def get_registers_for_thread(tid):
66        """ Get the register context dictionary for a certain thread of
67            the scripted process.
68
69        Args:
70            tid (int): Thread ID for the thread's register context.
71
72        Returns:
73            Dict: The register context represented as a dictionary, for the
74                tid thread. None if tid doesn't match any of the scripted
75                process threads.
76        """
77        pass
78
79    @abstractmethod
80    def read_memory_at_address(addr, size):
81        """ Get a memory buffer from the scripted process at a certain address,
82            of a certain size.
83
84        Args:
85            addr (int): Address from which we should start reading.
86            size (int): Size of the memory to read.
87
88        Returns:
89            lldb.SBData: An `lldb.SBData` buffer with the target byte size and
90                byte order storing the memory read.
91        """
92        pass
93
94    @abstractmethod
95    def get_loaded_images(self):
96        """ Get the list of loaded images for the scripted process.
97
98        ```
99        class ScriptedProcessImage:
100            def __init__(name, file_spec, uuid, load_address):
101              self.name = name
102              self.file_spec = file_spec
103              self.uuid = uuid
104              self.load_address = load_address
105        ```
106
107        Returns:
108            List[ScriptedProcessImage]: A list of `ScriptedProcessImage`
109                containing for each entry, the name of the library, a UUID,
110                an `lldb.SBFileSpec` and a load address.
111                None if the list is empty.
112        """
113        pass
114
115    def get_process_id(self):
116        """ Get the scripted process identifier.
117
118        Returns:
119            int: The scripted process identifier.
120        """
121        return 0
122
123
124    def launch(self):
125        """ Simulate the scripted process launch.
126
127        Returns:
128            lldb.SBError: An `lldb.SBError` with error code 0.
129        """
130        return lldb.SBError()
131
132    def resume(self):
133        """ Simulate the scripted process resume.
134
135        Returns:
136            lldb.SBError: An `lldb.SBError` with error code 0.
137        """
138        return lldb.SBError()
139
140    @abstractmethod
141    def should_stop(self):
142        """ Check if the scripted process plugin should produce the stop event.
143
144        Returns:
145            bool: True if scripted process should broadcast a stop event.
146                  False otherwise.
147        """
148        pass
149
150    def stop(self):
151        """ Trigger the scripted process stop.
152
153        Returns:
154            lldb.SBError: An `lldb.SBError` with error code 0.
155        """
156        return lldb.SBError()
157
158    @abstractmethod
159    def is_alive(self):
160        """ Check if the scripted process is alive.
161
162        Returns:
163            bool: True if scripted process is alive. False otherwise.
164        """
165        pass
166