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