xref: /xnu-10063.101.15/tools/lldbmacros/core/operating_system.py (revision 94d3b452840153a99b38a3a9659680b2a006908e)
1#!/usr/bin/python
2#
3
4#source of register info is from http://opensource.apple.com/source/gdb/gdb-962/src/gdb/arm-tdep.c
5import struct
6import lldb
7
8
9osplugin_target_obj = None
10
11class PluginValue(lldb.SBValue):
12    def GetChildMemberWithName(val, name):
13        val_type = val.GetType()
14        if val_type.IsPointerType():
15            val_type = val_type.GetPointeeType()
16        for i in range(val_type.GetNumberOfFields()):
17            if name == val_type.GetFieldAtIndex(i).GetName():
18                return PluginValue(val.GetChildAtIndex(i))
19        return None
20
21class Armv8_RegisterSet(object):
22    """ register info set for armv8 64 bit architecture"""
23    register_info = { 'sets' : ['GPR'],
24                  'registers': [
25    {'name': 'x0'  , 'bitsize':64, 'offset':  0, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 0, 'dwarf': 0, 'alt-name':'arg1', 'generic':'arg1'},
26    {'name': 'x1'  , 'bitsize':64, 'offset':  8, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 1, 'dwarf': 1, 'alt-name':'arg2', 'generic':'arg2'},
27    {'name': 'x2'  , 'bitsize':64, 'offset': 16, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 2, 'dwarf': 2, 'alt-name':'arg3', 'generic':'arg3'},
28    {'name': 'x3'  , 'bitsize':64, 'offset': 24, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 3, 'dwarf': 3, 'alt-name':'arg4', 'generic':'arg4'},
29    {'name': 'x4'  , 'bitsize':64, 'offset': 32, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 4, 'dwarf': 4, 'alt-name':'arg5', 'generic':'arg5'},
30    {'name': 'x5'  , 'bitsize':64, 'offset': 40, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 5, 'dwarf': 5, 'alt-name':'arg6', 'generic':'arg6'},
31    {'name': 'x6'  , 'bitsize':64, 'offset': 48, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 6, 'dwarf': 6, 'alt-name':'arg7', 'generic':'arg7'},
32    {'name': 'x7'  , 'bitsize':64, 'offset': 56, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 7, 'dwarf': 7, 'alt-name':'arg8', 'generic':'arg8'},
33    {'name': 'x8'  , 'bitsize':64, 'offset': 64, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 8, 'dwarf': 8},
34    {'name': 'x9'  , 'bitsize':64, 'offset': 72, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 9, 'dwarf': 9},
35    {'name': 'x10' , 'bitsize':64, 'offset': 80, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':10, 'dwarf':10},
36    {'name': 'x11' , 'bitsize':64, 'offset': 88, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':11, 'dwarf':11},
37    {'name': 'x12' , 'bitsize':64, 'offset': 96, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':12, 'dwarf':12},
38    {'name': 'x13' , 'bitsize':64, 'offset':104, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':13, 'dwarf':13},
39    {'name': 'x14' , 'bitsize':64, 'offset':112, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':14, 'dwarf':14},
40    {'name': 'x15' , 'bitsize':64, 'offset':120, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':15, 'dwarf':15},
41    {'name': 'x16' , 'bitsize':64, 'offset':128, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':16, 'dwarf':16},
42    {'name': 'x17' , 'bitsize':64, 'offset':136, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':17, 'dwarf':17},
43    {'name': 'x18' , 'bitsize':64, 'offset':144, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':18, 'dwarf':18},
44    {'name': 'x19' , 'bitsize':64, 'offset':152, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':19, 'dwarf':19},
45    {'name': 'x20' , 'bitsize':64, 'offset':160, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':20, 'dwarf':20},
46    {'name': 'x21' , 'bitsize':64, 'offset':168, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':21, 'dwarf':21},
47    {'name': 'x22' , 'bitsize':64, 'offset':176, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':22, 'dwarf':22},
48    {'name': 'x23' , 'bitsize':64, 'offset':184, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':23, 'dwarf':23},
49    {'name': 'x24' , 'bitsize':64, 'offset':192, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':24, 'dwarf':24},
50    {'name': 'x25' , 'bitsize':64, 'offset':200, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':25, 'dwarf':25},
51    {'name': 'x26' , 'bitsize':64, 'offset':208, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':26, 'dwarf':26},
52    {'name': 'x27' , 'bitsize':64, 'offset':216, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':27, 'dwarf':27},
53    {'name': 'x28' , 'bitsize':64, 'offset':224, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':28, 'dwarf':28},
54    {'name': 'fp'  , 'bitsize':64, 'offset':232, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':29, 'dwarf':29, 'alt-name': 'fp', 'generic':'fp'},
55    {'name': 'lr'  , 'bitsize':64, 'offset':240, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':30, 'dwarf':30, 'alt-name': 'lr', 'generic':'lr'},
56    {'name': 'sp'  , 'bitsize':64, 'offset':248, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':31, 'dwarf':31, 'alt-name': 'sp', 'generic':'sp'},
57    {'name': 'pc'  , 'bitsize':64, 'offset':256, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':32, 'dwarf':32, 'alt-name': 'pc', 'generic':'pc'},
58    {'name': 'far' , 'bitsize':64, 'offset':264, 'encoding':'uint', 'format':'hex', 'set':0},
59    {'name': 'cpsr', 'bitsize':32, 'offset':272, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':33, 'dwarf':33, 'generic':'flags'},
60    {'name': 'esr' , 'bitsize':32, 'offset':276, 'encoding':'uint', 'format':'hex', 'set':0},
61    ]
62    }
63
64    def __init__(self):
65        self.switch_context_address = osplugin_target_obj.FindSymbols('Switch_context')[0].GetSymbol().GetStartAddress().GetLoadAddress(osplugin_target_obj)
66        self.ResetRegisterValues()
67    def ResetRegisterValues(self):
68        self.x0 = 0
69        self.x1 = 0
70        self.x2 = 0
71        self.x3 = 0
72        self.x4 = 0
73        self.x5 = 0
74        self.x6 = 0
75        self.x7 = 0
76        self.x8 = 0
77        self.x9 = 0
78        self.x10 = 0
79        self.x11 = 0
80        self.x12 = 0
81        self.x13 = 0
82        self.x14 = 0
83        self.x15 = 0
84        self.x16 = 0
85        self.x17 = 0
86        self.x18 = 0
87        self.x19 = 0
88        self.x20 = 0
89        self.x21 = 0
90        self.x22 = 0
91        self.x23 = 0
92        self.x24 = 0
93        self.x25 = 0
94        self.x26 = 0
95        self.x27 = 0
96        self.x28 = 0
97        self.fp = 0
98        self.lr = 0
99        self.sp = 0
100        self.pc = 0
101        self.far = 0
102        self.cpsr = 0
103        self.esr = 0
104
105    def __str__(self):
106        return """ pc = """
107
108    def GetPackedRegisterState(self):
109        return struct.pack('34QII', self.x0, self.x1, self.x2, self.x3, self.x4, self.x5,
110            self.x6, self.x7, self.x8, self.x9, self.x10, self.x11, self.x12, self.x13,
111            self.x14, self.x15, self.x16, self.x17, self.x18, self.x19, self.x20, self.x21,
112            self.x22, self.x23, self.x24, self.x25, self.x26, self.x27, self.x28, self.fp,
113            self.lr, self.sp, self.pc, self.far, self.cpsr, self.esr)
114
115    def ReadRegisterDataFromKDPSavedState(self, kdp_state, kernel_version):
116        """ Setup register values from KDP saved information.
117        """
118        saved_state = kernel_version.CreateValueFromExpression(None, '(struct arm_saved_state64 *) ' + str(kdp_state.GetValueAsUnsigned()))
119        saved_state = saved_state.Dereference()
120        saved_state = PluginValue(saved_state)
121        self.ResetRegisterValues()
122        self.x0 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(0).GetValueAsUnsigned()
123        self.x1 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(1).GetValueAsUnsigned()
124        self.x2 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(2).GetValueAsUnsigned()
125        self.x3 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(3).GetValueAsUnsigned()
126        self.x4 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(4).GetValueAsUnsigned()
127        self.x5 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(5).GetValueAsUnsigned()
128        self.x6 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(6).GetValueAsUnsigned()
129        self.x7 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(7).GetValueAsUnsigned()
130        self.x8 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(8).GetValueAsUnsigned()
131        self.x9 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(9).GetValueAsUnsigned()
132        self.x10 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(10).GetValueAsUnsigned()
133        self.x11 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(11).GetValueAsUnsigned()
134        self.x12 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(12).GetValueAsUnsigned()
135        self.x13 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(13).GetValueAsUnsigned()
136        self.x14 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(14).GetValueAsUnsigned()
137        self.x15 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(15).GetValueAsUnsigned()
138        self.x16 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(16).GetValueAsUnsigned()
139        self.x17 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(17).GetValueAsUnsigned()
140        self.x18 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(18).GetValueAsUnsigned()
141        self.x19 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(19).GetValueAsUnsigned()
142        self.x20 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(20).GetValueAsUnsigned()
143        self.x21 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(21).GetValueAsUnsigned()
144        self.x22 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(22).GetValueAsUnsigned()
145        self.x23 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(23).GetValueAsUnsigned()
146        self.x24 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(24).GetValueAsUnsigned()
147        self.x25 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(25).GetValueAsUnsigned()
148        self.x26 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(26).GetValueAsUnsigned()
149        self.x27 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(27).GetValueAsUnsigned()
150        self.x28 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(28).GetValueAsUnsigned()
151        self.fp = saved_state.GetChildMemberWithName('fp').GetValueAsUnsigned()
152        self.lr = saved_state.GetChildMemberWithName('lr').GetValueAsUnsigned()
153        self.sp = saved_state.GetChildMemberWithName('sp').GetValueAsUnsigned()
154        self.pc = saved_state.GetChildMemberWithName('pc').GetValueAsUnsigned()
155        self.far = saved_state.GetChildMemberWithName('far').GetValueAsUnsigned()
156        self.cpsr = saved_state.GetChildMemberWithName('cpsr').GetValueAsUnsigned()
157        self.esr = saved_state.GetChildMemberWithName('esr').GetValueAsUnsigned()
158        return self
159
160    def ReadRegisterDataFromKernelStack(self, kstack_saved_state_addr, kernel_version):
161        saved_state = kernel_version.CreateValueFromExpression(None, '(arm_kernel_saved_state_t *) '+ str(kstack_saved_state_addr))
162        saved_state = saved_state.Dereference()
163        saved_state = PluginValue(saved_state)
164        self.ResetRegisterValues()
165        self.x19 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(0).GetValueAsUnsigned()
166        self.x20 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(1).GetValueAsUnsigned()
167        self.x21 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(2).GetValueAsUnsigned()
168        self.x22 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(3).GetValueAsUnsigned()
169        self.x23 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(4).GetValueAsUnsigned()
170        self.x24 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(5).GetValueAsUnsigned()
171        self.x25 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(6).GetValueAsUnsigned()
172        self.x26 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(7).GetValueAsUnsigned()
173        self.x27 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(8).GetValueAsUnsigned()
174        self.x28 = saved_state.GetChildMemberWithName('x').GetChildAtIndex(9).GetValueAsUnsigned()
175        self.fp = saved_state.GetChildMemberWithName('fp').GetValueAsUnsigned()
176        self.lr = saved_state.GetChildMemberWithName('lr').GetValueAsUnsigned()
177        self.sp = saved_state.GetChildMemberWithName('sp').GetValueAsUnsigned()
178        # pc for a blocked thread is treated to be the next instruction it would run after thread switch.
179        self.pc = self.switch_context_address
180        return self
181
182    def ReadRegisterDataFromContinuation(self, continuation_ptr):
183        self.ResetRegisterValues()
184        self.pc = continuation_ptr
185        return self
186
187    @classmethod
188    def GetRegisterInfo(cls, regnum):
189        if regnum < 0 or regnum > len(cls.register_info['registers']):
190            return ''
191
192        reginfo = cls.register_info['registers'][regnum]
193        retval = ''
194        for i in list(reginfo.keys()):
195            v_str = str(reginfo[i])
196            if i == 'set':
197                v_str = 'General Purpose Registers'
198            retval += "%s:%s;" % (str(i), v_str)
199        return retval
200
201
202
203class Armv7_RegisterSet(object):
204    """ register info set for armv7 32 bit architecture """
205    register_info = { 'sets' : ['GPR'],
206                  'registers': [
207        { 'name':'r0'   , 'bitsize' : 32, 'offset' :  0, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 0, 'dwarf' : 0},
208        { 'name':'r1'   , 'bitsize' : 32, 'offset' :  4, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 1, 'dwarf' : 1},
209        { 'name':'r2'   , 'bitsize' : 32, 'offset' :  8, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 2, 'dwarf' : 2},
210        { 'name':'r3'   , 'bitsize' : 32, 'offset' : 12, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 3, 'dwarf' : 3},
211        { 'name':'r4'   , 'bitsize' : 32, 'offset' : 16, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 4, 'dwarf' : 4},
212        { 'name':'r5'   , 'bitsize' : 32, 'offset' : 20, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 5, 'dwarf' : 5},
213        { 'name':'r6'   , 'bitsize' : 32, 'offset' : 24, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 6, 'dwarf' : 6},
214        { 'name':'r7'   , 'bitsize' : 32, 'offset' : 28, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 7, 'dwarf' : 7},
215        { 'name':'r8'   , 'bitsize' : 32, 'offset' : 32, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 8, 'dwarf' : 8},
216        { 'name':'r9'   , 'bitsize' : 32, 'offset' : 36, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 9, 'dwarf' : 9},
217        { 'name':'r10'  , 'bitsize' : 32, 'offset' : 40, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':10, 'dwarf' :10},
218        { 'name':'r11'  , 'bitsize' : 32, 'offset' : 44, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':11, 'dwarf' :11, 'alt-name': 'fp', 'generic': 'fp'},
219        { 'name':'r12'  , 'bitsize' : 32, 'offset' : 48, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':12, 'dwarf' :12},
220        { 'name':'sp'   , 'bitsize' : 32, 'offset' : 52, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':13, 'dwarf' :13, 'generic': 'sp'},
221        { 'name':'lr'   , 'bitsize' : 32, 'offset' : 56, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':14, 'dwarf' :14, 'generic': 'lr'},
222        { 'name':'pc'   , 'bitsize' : 32, 'offset' : 60, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':15, 'dwarf' :15, 'generic': 'pc'},
223        { 'name':'cpsr' , 'bitsize' : 32, 'offset' : 64, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':16, 'dwarf' :16, 'generic':'flags'},
224        { 'name':'fsr'  , 'bitsize' : 32, 'offset' : 68, 'encoding':'uint', 'format':'hex', 'set':0},
225        { 'name':'far'  , 'bitsize' : 32, 'offset' : 72, 'encoding':'uint', 'format':'hex', 'set':0}
226        ]
227        }
228
229    def __init__(self):
230        self.switch_context_address = osplugin_target_obj.FindSymbols('load_reg')[0].GetSymbol().GetStartAddress().GetLoadAddress(osplugin_target_obj) + 8
231        self.ResetRegisterValues()
232
233    @classmethod
234    def GetRegisterInfo(cls, regnum):
235        if regnum < 0 or regnum > len(cls.register_info['registers']):
236            return ''
237
238        reginfo = cls.register_info['registers'][regnum]
239        retval = ''
240        for i in list(reginfo.keys()):
241            v_str = str(reginfo[i])
242            if i == 'set':
243                v_str = 'General Purpose Registers'
244            retval += "%s:%s;" % (str(i), v_str)
245        return retval
246
247    def ResetRegisterValues(self):
248        self.r0 = 0
249        self.r1 = 0
250        self.r2 = 0
251        self.r3 = 0
252        self.r4 = 0
253        self.r5 = 0
254        self.r6 = 0
255        self.r7 = 0
256        self.r8 = 0
257        self.r9 = 0
258        self.r10 = 0
259        self.r11 = 0
260        self.r12 = 0
261        self.sp = 0
262        self.lr = 0
263        self.pc = 0
264        self.cpsr = 0
265        self.fsr = 0
266        self.far = 0
267
268    def __str__(self):
269        return """
270            r0 = {o.r0: <#010x}
271            r1 = {o.r1: <#010x}
272            r2 = {o.r2: <#010x}
273            r3 = {o.r3: <#010x}
274            r4 = {o.r4: <#010x}
275            r5 = {o.r5: <#010x}
276            r6 = {o.r6: <#010x}
277            r7 = {o.r7: <#010x}
278            r8 = {o.r8: <#010x}
279            r9 = {o.r9: <#010x}
280            r10 = {o.r10: <#010x}
281            r11 = {o.r11: <#010x}
282            r12 = {o.r12: <#010x}
283            sp = {o.sp: <#010x}
284            lr = {o.lr: <#010x}
285            pc = {o.pc: <#010x}
286            cpsr = {o.cpsr: <#010x}
287            fsr = {o.fsr : <#010x}
288            far = {o.far : <#010x}
289            """.format(o=self)
290
291    def GetPackedRegisterState(self):
292        return struct.pack('19I', self.r0, self.r1, self.r2, self.r3,
293            self.r4, self.r5, self.r6, self.r7,
294            self.r8, self.r9, self.r10, self.r11,
295            self.r12, self.sp, self.lr, self.pc,
296            self.cpsr, self.fsr, self.far)
297
298    def ReadRegisterDataFromKDPSavedState(self, kdp_state, kernel_version):
299        saved_state = kernel_version.CreateValueFromExpression(None, '(struct arm_saved_state *) ' + str(kdp_state.GetValueAsUnsigned()))
300        saved_state = saved_state.Dereference()
301        saved_state = PluginValue(saved_state)
302        self.ResetRegisterValues()
303        self.r0 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(0).GetValueAsUnsigned()
304        self.r1 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(1).GetValueAsUnsigned()
305        self.r2 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(2).GetValueAsUnsigned()
306        self.r3 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(3).GetValueAsUnsigned()
307        self.r4 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(4).GetValueAsUnsigned()
308        self.r5 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(5).GetValueAsUnsigned()
309        self.r6 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(6).GetValueAsUnsigned()
310        self.r7 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(7).GetValueAsUnsigned()
311        self.r8 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(8).GetValueAsUnsigned()
312        self.r9 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(9).GetValueAsUnsigned()
313        self.r10 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(10).GetValueAsUnsigned()
314        self.r11 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(11).GetValueAsUnsigned()
315        self.r12 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(12).GetValueAsUnsigned()
316        self.sp = saved_state.GetChildMemberWithName('sp').GetValueAsUnsigned()
317        self.lr = saved_state.GetChildMemberWithName('lr').GetValueAsUnsigned()
318        self.pc = saved_state.GetChildMemberWithName('pc').GetValueAsUnsigned()
319        self.cpsr = saved_state.GetChildMemberWithName('cpsr').GetValueAsUnsigned()
320        self.fsr = saved_state.GetChildMemberWithName('fsr').GetValueAsUnsigned()
321        self.far = saved_state.GetChildMemberWithName('far').GetValueAsUnsigned()
322        return self
323
324    def ReadRegisterDataFromKernelStack(self, kstack_saved_state_addr, kernel_version):
325        saved_state = kernel_version.CreateValueFromExpression(None, '(struct arm_saved_state *) '+ str(kstack_saved_state_addr))
326        saved_state = saved_state.Dereference()
327        saved_state = PluginValue(saved_state)
328        self.ResetRegisterValues()
329        self.r0 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(0).GetValueAsUnsigned()
330        self.r1 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(1).GetValueAsUnsigned()
331        self.r2 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(2).GetValueAsUnsigned()
332        self.r3 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(3).GetValueAsUnsigned()
333        self.r4 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(4).GetValueAsUnsigned()
334        self.r5 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(5).GetValueAsUnsigned()
335        self.r6 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(6).GetValueAsUnsigned()
336        self.r7 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(7).GetValueAsUnsigned()
337        self.r8 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(8).GetValueAsUnsigned()
338        self.r9 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(9).GetValueAsUnsigned()
339        self.r10 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(10).GetValueAsUnsigned()
340        self.r11 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(11).GetValueAsUnsigned()
341        self.r12 = saved_state.GetChildMemberWithName('r').GetChildAtIndex(12).GetValueAsUnsigned()
342        self.sp = saved_state.GetChildMemberWithName('sp').GetValueAsUnsigned()
343        self.lr = saved_state.GetChildMemberWithName('lr').GetValueAsUnsigned()
344        # pc for a blocked thread is treated to be the next instruction it would run after thread switch.
345        self.pc = self.switch_context_address
346        self.cpsr = saved_state.GetChildMemberWithName('cpsr').GetValueAsUnsigned()
347        self.fsr = saved_state.GetChildMemberWithName('fsr').GetValueAsUnsigned()
348        self.far = saved_state.GetChildMemberWithName('far').GetValueAsUnsigned()
349        return self
350
351    def ReadRegisterDataFromContinuation(self, continuation_ptr):
352        self.ResetRegisterValues()
353        self.pc = continuation_ptr
354        return self
355
356
357class I386_RegisterSet(object):
358    """ register info set for i386 architecture
359    """
360    register_info = { 'sets' : ['GPR'],
361                  'registers': [
362        { 'name': 'eax'   , 'bitsize': 32, 'offset' : 0, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 0, 'dwarf': 0},
363        { 'name': 'ebx'   , 'bitsize': 32, 'offset' : 4, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 3, 'dwarf': 3},
364        { 'name': 'ecx'   , 'bitsize': 32, 'offset' : 8, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 1, 'dwarf': 1},
365        { 'name': 'edx'   , 'bitsize': 32, 'offset' :12, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf': 2},
366        { 'name': 'edi'   , 'bitsize': 32, 'offset' :16, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 7, 'dwarf': 7},
367        { 'name': 'esi'   , 'bitsize': 32, 'offset' :20, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 6, 'dwarf': 6},
368        { 'name': 'ebp'   , 'bitsize': 32, 'offset' :24, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 4, 'dwarf': 5, 'generic': 'fp', 'alt-name': 'fp'},
369        { 'name': 'esp'   , 'bitsize': 32, 'offset' :28, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 5, 'dwarf': 4, 'generic': 'sp', 'alt-name': 'sp'},
370        { 'name': 'ss'    , 'bitsize': 32, 'offset' :32, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
371        { 'name': 'eflags', 'bitsize': 32, 'offset' :36, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 9, 'dwarf': 9, 'generic': 'flags'},
372        { 'name': 'eip'   , 'bitsize': 32, 'offset' :40, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :8, 'dwarf':8, 'generic': 'pc', 'alt-name': 'pc'},
373        { 'name': 'cs'    , 'bitsize': 32, 'offset' :44, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
374        { 'name': 'ds'    , 'bitsize': 32, 'offset' :48, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
375        { 'name': 'es'    , 'bitsize': 32, 'offset' :52, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
376        { 'name': 'fs'    , 'bitsize': 32, 'offset' :56, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
377        { 'name': 'gs'    , 'bitsize': 32, 'offset' :60, 'encoding': 'uint' , 'format':'hex' , 'set': 0},
378        ]
379        }
380
381    def __init__(self):
382        self.ResetRegisterValues()
383
384    @classmethod
385    def GetRegisterInfo(cls, regnum):
386        if regnum < 0 or regnum > len(cls.register_info['registers']):
387            return ''
388
389        reginfo = cls.register_info['registers'][regnum]
390        retval = ''
391        for i in list(reginfo.keys()):
392            v_str = str(reginfo[i])
393            if i == 'set':
394                v_str = 'General Purpose Registers'
395            retval += "%s:%s;" % (str(i), v_str)
396        return retval
397
398    def ResetRegisterValues(self):
399        """ set all registers to zero """
400        self.eax = 0
401        self.ebx = 0
402        self.ecx = 0
403        self.edx = 0
404        self.edi = 0
405        self.esi = 0
406        self.ebp = 0
407        self.esp = 0
408        self.ss  = 0
409        self.eflags = 0
410        self.eip = 0
411        self.cs = 0
412        self.ds = 0
413        self.es = 0
414        self.fs = 0
415        self.gs = 0
416
417    def __str__(self):
418        return """
419            eax = {o.eax: #010x}
420            ebx = {o.ebx: #010x}
421            ecx = {o.ecx: #010x}
422            edx = {o.edx: #010x}
423            edi = {o.edi: #010x}
424            esi = {o.esi: #010x}
425            ebp = {o.ebp: #010x}
426            esp = {o.esp: #010x}
427            ss  = {o.ss: #010x}
428         eflags = {o.eflags: #010x}
429            eip = {o.eip: #010x}
430            cs  = {o.cs: #010x}
431            ds  = {o.ds: #010x}
432            es  = {o.es: #010x}
433            fs  = {o.fs: #010x}
434            gs  = {o.gs: #010x}
435            """.format(o=self)
436
437    def GetPackedRegisterState(self):
438        """ get a struct.pack register data """
439        return struct.pack('16I', self.eax, self.ebx, self.ecx,
440            self.edx, self.edi, self.esi,
441            self.ebp, self.esp, self.ss,
442            self.eflags, self.eip, self.cs,
443            self.ds, self.es, self.fs, self.gs
444            )
445
446    def ReadRegisterDataFromKDPSavedState(self, kdp_state, kernel_version):
447        """ to be implemented"""
448        return None
449
450    def ReadRegisterDataFromKernelStack(self, kstack_saved_state_addr, kernel_version):
451        """ to be implemented """
452        return None
453
454    def ReadRegisterDataFromContinuation(self, continuation_ptr):
455        self.ResetRegisterValues()
456        self.eip = continuation_ptr
457        return self
458
459
460class X86_64RegisterSet(object):
461    """ register info set for x86_64 architecture """
462    register_info = { 'sets' : ['GPR'],
463                  'registers': [
464        { 'name':'rax'       , 'bitsize' :  64, 'offset' :   0, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 0, 'dwarf' : 0},
465        { 'name':'rbx'       , 'bitsize' :  64, 'offset' :   8, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 3, 'dwarf' : 3},
466        { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
467        { 'name':'rdx'       , 'bitsize' :  64, 'offset' :  24, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 1, 'dwarf' : 1, 'generic':'arg3', 'alt-name':'arg3', },
468        { 'name':'rdi'       , 'bitsize' :  64, 'offset' :  32, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 5, 'dwarf' : 5, 'generic':'arg1', 'alt-name':'arg1', },
469        { 'name':'rsi'       , 'bitsize' :  64, 'offset' :  40, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 4, 'dwarf' : 4, 'generic':'arg2', 'alt-name':'arg2', },
470        { 'name':'rbp'       , 'bitsize' :  64, 'offset' :  48, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 6, 'dwarf' : 6, 'generic':'fp'  , 'alt-name':'fp', },
471        { 'name':'rsp'       , 'bitsize' :  64, 'offset' :  56, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 7, 'dwarf' : 7, 'generic':'sp'  , 'alt-name':'sp', },
472        { 'name':'r8'        , 'bitsize' :  64, 'offset' :  64, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 8, 'dwarf' : 8, 'generic':'arg5', 'alt-name':'arg5', },
473        { 'name':'r9'        , 'bitsize' :  64, 'offset' :  72, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 9, 'dwarf' : 9, 'generic':'arg6', 'alt-name':'arg6', },
474        { 'name':'r10'       , 'bitsize' :  64, 'offset' :  80, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 10, 'dwarf' : 10},
475        { 'name':'r11'       , 'bitsize' :  64, 'offset' :  88, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 11, 'dwarf' : 11},
476        { 'name':'r12'       , 'bitsize' :  64, 'offset' :  96, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 12, 'dwarf' : 12},
477        { 'name':'r13'       , 'bitsize' :  64, 'offset' : 104, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 13, 'dwarf' : 13},
478        { 'name':'r14'       , 'bitsize' :  64, 'offset' : 112, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 14, 'dwarf' : 14},
479        { 'name':'r15'       , 'bitsize' :  64, 'offset' : 120, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 15, 'dwarf' : 15},
480        { 'name':'rip'       , 'bitsize' :  64, 'offset' : 128, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 16, 'dwarf' : 16, 'generic':'pc', 'alt-name':'pc' },
481        { 'name':'rflags'    , 'bitsize' :  64, 'offset' : 136, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'generic':'flags', 'alt-name':'flags' },
482        { 'name':'cs'        , 'bitsize' :  64, 'offset' : 144, 'encoding':'uint'  , 'format':'hex'         , 'set': 0                          },
483        { 'name':'fs'        , 'bitsize' :  64, 'offset' : 152, 'encoding':'uint'  , 'format':'hex'         , 'set': 0                          },
484        { 'name':'gs'        , 'bitsize' :  64, 'offset' : 160, 'encoding':'uint'  , 'format':'hex'         , 'set': 0                          },
485        ]
486        }
487    def __init__(self):
488        self.ResetRegisterValues()
489
490    @classmethod
491    def GetRegisterInfo(cls, regnum):
492        if regnum < 0 or regnum > len(cls.register_info['registers']):
493            return ''
494
495        reginfo = cls.register_info['registers'][regnum]
496        retval = ''
497        for i in list(reginfo.keys()):
498            v_str = str(reginfo[i])
499            if i == 'set':
500                v_str = 'General Purpose Registers'
501            retval += "%s:%s;" % (str(i), v_str)
502        return retval
503
504
505    def ResetRegisterValues(self):
506        """ set all the registers to zero. """
507        self.rax = 0
508        self.rbx = 0
509        self.rcx = 0
510        self.rdx = 0
511        self.rdi = 0
512        self.rsi = 0
513        self.rbp = 0
514        self.rsp = 0
515        self.r8  = 0
516        self.r9  = 0
517        self.r10 = 0
518        self.r11 = 0
519        self.r12 = 0
520        self.r13 = 0
521        self.r14 = 0
522        self.r15 = 0
523        self.rip = 0
524        self.rflags = 0
525        self.cs  = 0
526        self.fs  = 0
527        self.gs  = 0
528
529    def __str__(self):
530        return """
531            rax = {o.rax: <#018x}
532            rbx = {o.rbx: <#018x}
533            rcx = {o.rcx: <#018x}
534            rdx = {o.rdx: <#018x}
535            rdi = {o.rdi: <#018x}
536            rsi = {o.rsi: <#018x}
537            rbp = {o.rbp: <#018x}
538            rsp = {o.rsp: <#018x}
539            r8  = {o.r8: <#018x}
540            r9  = {o.r9: <#018x}
541            r10 = {o.r10: <#018x}
542            r11 = {o.r11: <#018x}
543            r12 = {o.r12: <#018x}
544            r13 = {o.r13: <#018x}
545            r14 = {o.r14: <#018x}
546            r15 = {o.r15: <#018x}
547            rip = {o.rip: <#018x}
548            rflags =  {o.rflags: <#018x}
549            cs = {o.cs: <#018x}
550            fs = {o.fs: <#018x}
551            gs = {o.gs: <#018x}
552            """.format(o=self)
553
554    def GetPackedRegisterState(self):
555        """ get a struct.pack register data for passing to C constructs """
556        return struct.pack('21Q', self.rax, self.rbx, self.rcx, self.rdx, self.rdi,
557            self.rsi, self.rbp, self.rsp, self.r8,  self.r9,
558            self.r10, self.r11, self.r12, self.r13, self.r14,
559            self.r15, self.rip, self.rflags, self.cs, self.fs, self.gs)
560
561    def ReadRegisterDataFromKDPSavedState(self, kdp_state, kernel_version):
562        saved_state = kernel_version.CreateValueFromExpression(None, '(struct x86_saved_state64 *) '+ str(kdp_state.GetValueAsUnsigned()))
563        saved_state = saved_state.Dereference()
564        saved_state = PluginValue(saved_state)
565        self.ResetRegisterValues()
566        self.rdi = saved_state.GetChildMemberWithName('rdi').GetValueAsUnsigned()
567        self.rsi = saved_state.GetChildMemberWithName('rsi').GetValueAsUnsigned()
568        self.rdx = saved_state.GetChildMemberWithName('rdx').GetValueAsUnsigned()
569        self.r10 = saved_state.GetChildMemberWithName('r10').GetValueAsUnsigned()
570        self.r8 = saved_state.GetChildMemberWithName('r8').GetValueAsUnsigned()
571        self.r9 = saved_state.GetChildMemberWithName('r9').GetValueAsUnsigned()
572        self.r15 = saved_state.GetChildMemberWithName('r15').GetValueAsUnsigned()
573        self.r14 = saved_state.GetChildMemberWithName('r14').GetValueAsUnsigned()
574        self.r13 = saved_state.GetChildMemberWithName('r13').GetValueAsUnsigned()
575        self.r12 = saved_state.GetChildMemberWithName('r12').GetValueAsUnsigned()
576        self.r11 = saved_state.GetChildMemberWithName('r11').GetValueAsUnsigned()
577        self.rbp = saved_state.GetChildMemberWithName('rbp').GetValueAsUnsigned()
578        self.rbx = saved_state.GetChildMemberWithName('rbx').GetValueAsUnsigned()
579        self.rcx = saved_state.GetChildMemberWithName('rcx').GetValueAsUnsigned()
580        self.rax = saved_state.GetChildMemberWithName('rax').GetValueAsUnsigned()
581        self.rip = saved_state.GetChildMemberWithName('isf').GetChildMemberWithName('rip').GetValueAsUnsigned()
582        self.rflags = saved_state.GetChildMemberWithName('isf').GetChildMemberWithName('rflags').GetValueAsUnsigned()
583        self.rsp = saved_state.GetChildMemberWithName('isf').GetChildMemberWithName('rsp').GetValueAsUnsigned()
584        return self
585
586    def ReadRegisterDataFromKernelStack(self, kstack_saved_state_addr, kernel_version):
587        saved_state = kernel_version.CreateValueFromExpression(None, '(struct x86_kernel_state *) '+ str(kstack_saved_state_addr))
588        saved_state = saved_state.Dereference()
589        saved_state = PluginValue(saved_state)
590        self.ResetRegisterValues()
591        self.rbx = saved_state.GetChildMemberWithName('k_rbx').GetValueAsUnsigned()
592        self.rsp = saved_state.GetChildMemberWithName('k_rsp').GetValueAsUnsigned()
593        self.rbp = saved_state.GetChildMemberWithName('k_rbp').GetValueAsUnsigned()
594        self.r12 = saved_state.GetChildMemberWithName('k_r12').GetValueAsUnsigned()
595        self.r13 = saved_state.GetChildMemberWithName('k_r13').GetValueAsUnsigned()
596        self.r14 = saved_state.GetChildMemberWithName('k_r14').GetValueAsUnsigned()
597        self.r15 = saved_state.GetChildMemberWithName('k_r15').GetValueAsUnsigned()
598        self.rip = saved_state.GetChildMemberWithName('k_rip').GetValueAsUnsigned()
599        return self
600
601    def ReadRegisterDataFromContinuation(self, continuation_ptr):
602        self.ResetRegisterValues()
603        self.rip = continuation_ptr
604        return self
605
606
607
608
609def IterateQueue(queue_head, element_ptr_type, element_field_name):
610    """ iterate over a queue in kernel of type queue_head_t. refer to osfmk/kern/queue.h
611        params:
612            queue_head         - lldb.SBValue : Value object for queue_head.
613            element_type       - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
614            element_field_name - str : name of the field in target struct.
615        returns:
616            A generator does not return. It is used for iterating.
617            SBValue  : an object thats of type (element_type) queue_head->next. Always a pointer object
618    """
619    queue_head_addr = 0x0
620    if queue_head.TypeIsPointerType():
621        queue_head_addr = queue_head.GetValueAsUnsigned()
622    else:
623        queue_head_addr = queue_head.GetAddress().GetLoadAddress(osplugin_target_obj)
624    cur_elt = queue_head.GetChildMemberWithName('next')
625    while True:
626        if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0 or cur_elt.GetValueAsUnsigned() == queue_head_addr:
627            break
628        elt = cur_elt.Cast(element_ptr_type)
629        yield elt
630        cur_elt = elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('next')
631
632def GetUniqueSessionID(process_obj):
633    """ Create a unique session identifier.
634        params:
635          process_obj: lldb.SBProcess object refering to connected process.
636        returns:
637          int - a unique number identified by processid and stopid.
638    """
639    session_key_str = ""
640    if hasattr(process_obj, "GetUniqueID"):
641        session_key_str += str(process_obj.GetUniqueID()) + ":"
642    else:
643        session_key_str += "0:"
644
645    if hasattr(process_obj, "GetStopID"):
646        session_key_str += str(process_obj.GetStopID())
647    else:
648        session_key_str +="1"
649
650    return hash(session_key_str)
651
652
653(archX86_64, archARMv7, archI386, archARMv8) = ("x86_64", "armv7", "i386", "arm64")
654
655class OperatingSystemPlugIn(object):
656    """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
657
658    def __init__(self, process):
659        '''Initialization needs a valid.SBProcess object'''
660        self.process = None
661        self.registers = None
662        self.threads = None
663        self.thread_cache = {}
664        self.current_session_id = 0
665        self.kdp_thread = None
666        if type(process) is lldb.SBProcess and process.IsValid():
667            global osplugin_target_obj
668            self.process = process
669            self._target = process.target
670            osplugin_target_obj = self._target
671            self.current_session_id = GetUniqueSessionID(self.process)
672            self.version = self._target.FindGlobalVariables('version', 1).GetValueAtIndex(0)
673            self.kasan_tbi = self._target.FindGlobalVariables('kasan_tbi_enabled', 1).GetValueAtIndex(0)
674            self.kernel_stack_size = self._target.FindGlobalVariables('kernel_stack_size', 1).GetValueAtIndex(0).GetValueAsUnsigned()
675            self.kernel_context_size = 0
676            self.connected_over_kdp = False
677            # connected_to_debugserver signifies if we are connected to astris or other gdbserver instance
678            # that has the correct thread state for on core threads. For kdp and coredumps we rely on in memory
679            # state of threads.
680            self.connected_to_debugserver = True
681            plugin_string = self.process.GetPluginName().lower()
682            if plugin_string.find("kdp") >=0:
683                self.connected_over_kdp = True
684                self.connected_to_debugserver = False
685            #print "version", self.version, "kernel_stack_size", self.kernel_stack_size, "context_size", self.kernel_context_size
686            self.threads = None # Will be an dictionary containing info for each thread
687            triple = self.process.target.triple
688            arch = triple.split('-')[0].lower()
689            self.target_arch = ""
690            self.kernel_context_size = 0
691            if arch == archX86_64 :
692                self.target_arch = archX86_64
693                print("Target arch: x86_64")
694                self.register_set = X86_64RegisterSet()
695                self.kernel_context_size = self._target.FindFirstType('x86_kernel_state').GetByteSize()
696                self.kernel_thread_state_size = self._target.FindFirstType('struct thread_kernel_state').GetByteSize()
697            elif arch.startswith(archARMv7) :
698                self.target_arch = arch
699                print("Target arch: " + self.target_arch)
700                self.register_set = Armv7_RegisterSet()
701            elif arch.startswith(archARMv8):
702                self.target_arch = arch
703                print("Target arch: " + self.target_arch)
704                self.register_set = Armv8_RegisterSet()
705            #  connection     intel         arm
706            #  kdp            Memory        Memory
707            #  gdb            Server        Server
708            #  coredump       Memory        Server
709            if not self.connected_over_kdp :
710                if plugin_string.find('core') >= 0 and self.target_arch == archX86_64:
711                    self.connected_to_debugserver = False
712            self.registers = self.register_set.register_info
713            if self.connected_to_debugserver:
714                print("Connected to live debugserver or arm core. Will associate on-core threads to registers reported by server.")
715            else:
716                print("Instantiating threads completely from saved state in memory.")
717
718    def create_thread(self, tid, context):
719        def strip_tbi(v):
720            if self.kasan_tbi and v != 0:
721                v |= (0xFF << 56)
722            return v
723
724        # Strip TBI explicitly in case create_thread() is called externally.
725        context = strip_tbi(context)
726
727        # tid == deadbeef means its a custom thread which kernel does not know of.
728        if tid == 0xdeadbeef :
729            # tid manipulation should be the same as in "switchtoregs" code in lldbmacros/process.py .
730            tid = 0xdead0000 | (context & ~0xffff0000)
731            tid = tid & 0xdeadffff
732            thread_obj = { 'tid'   : tid,
733                           'ptr'   : context,
734                           'name'  : 'switchtoregs' + hex(context),
735                           'queue' : 'None',
736                           'state' : 'stopped',
737                           'stop_reason' : 'none'
738                         }
739            self.thread_cache[tid] = thread_obj
740            return thread_obj
741
742        th_ptr = context
743        th = self.version.CreateValueFromExpression(str(th_ptr), '(struct thread *)' + str(th_ptr))
744        thread_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
745        if tid != thread_id:
746            print("FATAL ERROR: Creating thread from memory 0x%x with tid in mem=%d when requested tid = %d " % (context, thread_id, tid))
747            return None
748
749        wait_queue = strip_tbi(th.GetChildMemberWithName('wait_queue').GetValueAsUnsigned())
750        thread_obj = { 'tid'   : thread_id,
751                       'ptr'   : th.GetValueAsUnsigned(),
752                       'name'  : hex(th.GetValueAsUnsigned()).rstrip('L'),
753                       'queue' : hex(wait_queue).rstrip('L'),
754                       'state' : 'stopped',
755                       'stop_reason' : 'none'
756                     }
757
758        if self.current_session_id != GetUniqueSessionID(self.process):
759            self.thread_cache = {}
760            self.current_session_id = GetUniqueSessionID(self.process)
761
762        self.thread_cache[tid] = thread_obj
763        return thread_obj
764
765    def get_thread_info(self):
766        self.kdp_thread = None
767        self.kdp_state = None
768        if self.connected_over_kdp :
769            kdp = self._target.FindGlobalVariables('kdp',1).GetValueAtIndex(0)
770            kdp_state = kdp.GetChildMemberWithName('saved_state')
771            kdp_thread = self._strip_thread_tbi(kdp.GetChildMemberWithName('kdp_thread'))
772            if kdp_thread and kdp_thread.GetValueAsUnsigned() != 0:
773                self.kdp_thread = kdp_thread
774                self.kdp_state = kdp_state
775                kdp_thid = kdp_thread.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
776                self.create_thread(kdp_thid, kdp_thread.GetValueAsUnsigned())
777                self.thread_cache[kdp_thid]['core']=0
778                retval = [self.thread_cache[kdp_thid]]
779                return retval
780            else:
781                print("FATAL FAILURE: Unable to find kdp_thread state for this connection.")
782                return []
783
784        num_threads = self._target.FindGlobalVariables('threads_count',1).GetValueAtIndex(0).GetValueAsUnsigned()
785        #In case we are caught before threads are initialized. Fallback to threads known by astris/gdb server.
786        if num_threads <=0 :
787            return []
788
789        self.current_session_id = GetUniqueSessionID(self.process)
790        self.threads = []
791        self.thread_cache = {}
792        self.processors = []
793        try:
794            processor_list_val = PluginValue(self._target.FindGlobalVariables('processor_list',1).GetValueAtIndex(0))
795            while processor_list_val.IsValid() and processor_list_val.GetValueAsUnsigned() !=0 :
796                th = self._strip_thread_tbi(processor_list_val.GetChildMemberWithName('active_thread'))
797                th_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
798                cpu_id = processor_list_val.GetChildMemberWithName('cpu_id').GetValueAsUnsigned()
799                self.processors.append({'active_thread': th.GetValueAsUnsigned(), 'cpu_id': cpu_id})
800                self.create_thread(th_id, th.GetValueAsUnsigned())
801                if self.connected_to_debugserver:
802                    self.thread_cache[th_id]['core'] = cpu_id
803                self.thread_cache[th_id]['queue'] = "cpu-%d" % int(cpu_id)
804                nth = self.thread_cache[th_id]
805                self.threads.append(nth)
806                self.thread_cache[nth['tid']] = nth
807                processor_list_val = processor_list_val.GetChildMemberWithName('processor_list')
808        except KeyboardInterrupt as ke:
809            print("OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate.")
810            return self.threads
811
812        if hasattr(self.process, 'CreateOSPluginThread'):
813            return self.threads
814
815        # FIXME remove legacy code
816        try:
817            thread_q_head = self._target.FindGlobalVariables('threads', 1).GetValueAtIndex(0)
818            thread_type = self._target.FindFirstType('thread')
819            thread_ptr_type = thread_type.GetPointerType()
820            for th in IterateQueue(thread_q_head, thread_ptr_type, 'threads'):
821                th = self._strip_thread_tbi(th)
822                th_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
823                self.create_thread(th_id, th.GetValueAsUnsigned())
824                nth = self.thread_cache[th_id]
825                for cputhread in self.processors:
826                    if cputhread['active_thread'] == nth['ptr']:
827                        nth['core'] = cputhread['cpu_id']
828                self.threads.append( nth )
829        except KeyboardInterrupt as ke:
830            print("OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate.")
831            return self.threads
832        # end legacy code
833        return self.threads
834
835    def get_register_info(self):
836        if self.registers == None:
837            print("Register Information not found ")
838        return self.register_set.register_info
839
840    def get_register_data(self, tid):
841        thobj = None
842        try:
843            regs = self.register_set
844            if self.current_session_id != GetUniqueSessionID(self.process):
845                self.thread_cache = {}
846                self.current_session_id = GetUniqueSessionID(self.process)
847            if tid in self.thread_cache:
848
849                #Check if the thread is a fake one. Then create and return registers directly
850                if self.thread_cache[tid]['name'].find('switchtoregs') == 0:
851                    savedstateobj = self.version.CreateValueFromExpression(None, '(uintptr_t *) ' + str(self.thread_cache[tid]['ptr']))
852                    regs.ReadRegisterDataFromKDPSavedState(savedstateobj, self.version)
853                    return regs.GetPackedRegisterState()
854
855                thobj = self.version.CreateValueFromExpression(self.thread_cache[tid]['name'], '(struct thread *)' + str(self.thread_cache[tid]['ptr']))
856
857            if thobj == None :
858                print("FATAL ERROR: Could not find thread with id %d" % tid)
859                regs.ResetRegisterValues()
860                return regs.GetPackedRegisterState()
861
862            if self.kdp_thread and self.kdp_thread.GetValueAsUnsigned() == thobj.GetValueAsUnsigned():
863                regs.ReadRegisterDataFromKDPSavedState(self.kdp_state, self.version)
864                return regs.GetPackedRegisterState()
865            if int(PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned()) != 0 :
866                if self.target_arch == archX86_64 :
867                    # we do have a stack so lets get register information
868                    saved_state_addr = PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned() + self.kernel_stack_size - self.kernel_thread_state_size
869                    regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version)
870                    return regs.GetPackedRegisterState()
871                elif self.target_arch.startswith(archARMv7) and int(PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0:
872                    #we have stack on the machine.kstackptr.
873                    saved_state_addr = PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()
874                    regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version)
875                    return regs.GetPackedRegisterState()
876                elif self.target_arch.startswith(archARMv8) and int(PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0:
877                    saved_state_addr = PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsAddress()
878                    arm_ctx = PluginValue(self.version.CreateValueFromExpression(None, '(struct arm_kernel_context *) ' + str(saved_state_addr)))
879                    arm_ss_addr = arm_ctx.GetChildMemberWithName('ss').GetLoadAddress()
880                    regs.ReadRegisterDataFromKernelStack(arm_ss_addr, self.version)
881                    return regs.GetPackedRegisterState()
882            elif self.target_arch == archX86_64 or self.target_arch.startswith(archARMv7) or self.target_arch.startswith(archARMv8):
883                regs.ReadRegisterDataFromContinuation( PluginValue(thobj).GetChildMemberWithName('continuation').GetValueAsAddress())
884                return regs.GetPackedRegisterState()
885            #incase we failed very miserably
886        except KeyboardInterrupt as ke:
887            print("OS Plugin Interrupted during thread register load. \nWARNING:Thread registers and backtraces may not be accurate. for tid = %d" % tid)
888        regs.ResetRegisterValues()
889        print("FATAL ERROR: Failed to get register state for thread id 0x%x " % tid)
890        print(thobj)
891        return regs.GetPackedRegisterState()
892
893    def _strip_thread_tbi(self, th):
894        if not self.kasan_tbi:
895            return th
896        addr = th.GetValueAsAddress()
897        return self.version.CreateValueFromExpression(str(addr), '(struct thread *)' + str(addr))