1#!/usr/bin/env python
2
3import lldb
4import struct
5
6
7class OperatingSystemPlugIn(object):
8    """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
9
10    def __init__(self, process):
11        '''Initialization needs a valid.SBProcess object.
12
13        This plug-in will get created after a live process is valid and has stopped for the
14        first time.'''
15        self.process = None
16        self.registers = None
17        self.threads = None
18        if isinstance(process, lldb.SBProcess) and process.IsValid():
19            self.process = process
20            self.threads = None  # Will be an dictionary containing info for each thread
21
22    def get_target(self):
23        # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target"
24        # tracks the current target in the LLDB command interpreter which isn't the
25        # correct thing to use for this plug-in.
26        return self.process.target
27
28    def create_thread(self, tid, context):
29        if tid == 0x444444444:
30            thread_info = {
31                'tid': tid,
32                'name': 'four',
33                'queue': 'queue4',
34                'state': 'stopped',
35                'stop_reason': 'none'}
36            self.threads.append(thread_info)
37            return thread_info
38        return None
39
40    def get_thread_info(self):
41        if not self.threads:
42            # The sample dictionary below shows the values that can be returned for a thread
43            # tid => thread ID (mandatory)
44            # name => thread name (optional key/value pair)
45            # queue => thread dispatch queue name (optional key/value pair)
46            # state => thred state (mandatory, set to 'stopped' for now)
47            # stop_reason => thread stop reason. (mandatory, usually set to 'none')
48            #  Possible values include:
49            #   'breakpoint' if the thread is stopped at a breakpoint
50            #   'none' thread is just stopped because the process is stopped
51            #   'trace' the thread just single stepped
52            #   The usual value for this while threads are in memory is 'none'
53            # register_data_addr => the address of the register data in memory (optional key/value pair)
54            #   Specifying this key/value pair for a thread will avoid a call to get_register_data()
55            #   and can be used when your registers are in a thread context structure that is contiguous
56            #   in memory. Don't specify this if your register layout in memory doesn't match the layout
57            # described by the dictionary returned from a call to the
58            # get_register_info() method.
59            self.threads = [{'tid': 0x111111111,
60                             'name': 'one',
61                             'queue': 'queue1',
62                             'state': 'stopped',
63                             'stop_reason': 'breakpoint'},
64                            {'tid': 0x222222222,
65                             'name': 'two',
66                             'queue': 'queue2',
67                             'state': 'stopped',
68                             'stop_reason': 'none'},
69                            {'tid': 0x333333333,
70                             'name': 'three',
71                             'queue': 'queue3',
72                             'state': 'stopped',
73                             'stop_reason': 'trace',
74                             'register_data_addr': 0x100000000}]
75        return self.threads
76
77    def get_register_info(self):
78        if self.registers is None:
79            self.registers = dict()
80            triple = self.process.target.triple
81            if triple:
82                arch = triple.split('-')[0]
83                if arch == 'x86_64':
84                    self.registers['sets'] = ['GPR', 'FPU', 'EXC']
85                    self.registers['registers'] = [
86                        {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0},
87                        {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3},
88                        {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', },
89                        {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', },
90                        {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', },
91                        {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', },
92                        {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', },
93                        {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', },
94                        {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', },
95                        {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', },
96                        {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
97                        {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
98                        {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
99                        {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13},
100                        {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14},
101                        {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15},
102                        {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'},
103                        {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'},
104                        {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0},
105                        {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0},
106                        {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0},
107                    ]
108        return self.registers
109
110    def get_register_data(self, tid):
111        if tid == 0x111111111:
112            return struct.pack(
113                '21Q',
114                1,
115                2,
116                3,
117                4,
118                5,
119                6,
120                7,
121                8,
122                9,
123                10,
124                11,
125                12,
126                13,
127                14,
128                15,
129                16,
130                17,
131                18,
132                19,
133                20,
134                21)
135        elif tid == 0x222222222:
136            return struct.pack(
137                '21Q',
138                11,
139                12,
140                13,
141                14,
142                15,
143                16,
144                17,
145                18,
146                19,
147                110,
148                111,
149                112,
150                113,
151                114,
152                115,
153                116,
154                117,
155                118,
156                119,
157                120,
158                121)
159        elif tid == 0x333333333:
160            return struct.pack(
161                '21Q',
162                21,
163                22,
164                23,
165                24,
166                25,
167                26,
168                27,
169                28,
170                29,
171                210,
172                211,
173                212,
174                213,
175                214,
176                215,
177                216,
178                217,
179                218,
180                219,
181                220,
182                221)
183        elif tid == 0x444444444:
184            return struct.pack(
185                '21Q',
186                31,
187                32,
188                33,
189                34,
190                35,
191                36,
192                37,
193                38,
194                39,
195                310,
196                311,
197                312,
198                313,
199                314,
200                315,
201                316,
202                317,
203                318,
204                319,
205                320,
206                321)
207        else:
208            return struct.pack(
209                '21Q',
210                41,
211                42,
212                43,
213                44,
214                45,
215                46,
216                47,
217                48,
218                49,
219                410,
220                411,
221                412,
222                413,
223                414,
224                415,
225                416,
226                417,
227                418,
228                419,
229                420,
230                421)
231        return None
232