xref: /xnu-12377.41.6/tools/lldbmacros/core/operating_system.py (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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
8osplugin_target_obj = None
9
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, f"(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, f"(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: lldb.SBValue, element_ptr_type: lldb.SBType, element_field_name: str):
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: lldb.SBValue = queue_head.GetChildMemberWithName('next')
625    while True:
626        if not (cur_elt.IsValid() and cur_elt.error.success) 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        self.struct_arm_kernel_context_type = None
667        if type(process) is lldb.SBProcess and process.IsValid():
668            global osplugin_target_obj
669            self.process = process
670            self._target = process.target
671            osplugin_target_obj = self._target
672            self.current_session_id = GetUniqueSessionID(self.process)
673            self.version = self._target.FindGlobalVariables('version', 1).GetValueAtIndex(0)
674
675            # Configure explicit pointer stripping
676            is_tagged = self._target.FindFirstGlobalVariable('kasan_tbi_enabled').IsValid()
677
678            if is_tagged:
679
680                def strip_ptr(ptr):
681                    if ptr != 0:
682                        ptr |= (0xFF << 56)
683                    return ptr
684                self._strip_ptr = strip_ptr
685
686                def strip_thread_sbval(th):
687                    addr = th.GetValueAsAddress()
688                    return self.version.CreateValueFromExpression(str(addr), f"(struct thread *) {str(addr)}")
689                self._strip_thread_sbval = strip_thread_sbval
690
691            else:
692                self._strip_ptr = lambda ptr: ptr
693                self._strip_thread_sbval = lambda val: val
694
695            self.kernel_stack_size = self._target.FindGlobalVariables('kernel_stack_size', 1).GetValueAtIndex(0).GetValueAsUnsigned()
696            self.kernel_context_size = 0
697            self.connected_over_kdp = False
698            # connected_to_debugserver signifies if we are connected to astris or other gdbserver instance
699            # that has the correct thread state for on core threads. For kdp and coredumps we rely on in memory
700            # state of threads.
701            self.connected_to_debugserver = True
702            plugin_string = self.process.GetPluginName().lower()
703            if plugin_string.find("kdp") >=0:
704                self.connected_over_kdp = True
705                self.connected_to_debugserver = False
706            #print "version", self.version, "kernel_stack_size", self.kernel_stack_size, "context_size", self.kernel_context_size
707            self.threads = None # Will be an dictionary containing info for each thread
708            triple = self.process.target.triple
709            arch = triple.split('-')[0].lower()
710            self.target_arch = ""
711            self.kernel_context_size = 0
712            if arch == archX86_64 :
713                self.target_arch = archX86_64
714                print("Target arch: x86_64")
715                self.register_set = X86_64RegisterSet()
716                self.kernel_context_size = self._target.FindFirstType('x86_kernel_state').GetByteSize()
717                self.kernel_thread_state_size = self._target.FindFirstType('struct thread_kernel_state').GetByteSize()
718            elif arch.startswith(archARMv7) :
719                self.target_arch = arch
720                print("Target arch: " + self.target_arch)
721                self.register_set = Armv7_RegisterSet()
722            elif arch.startswith(archARMv8):
723                self.target_arch = arch
724                print("Target arch: " + self.target_arch)
725                self.register_set = Armv8_RegisterSet()
726            #  connection     intel         arm
727            #  kdp            Memory        Memory
728            #  gdb            Server        Server
729            #  coredump       Memory        Server
730            if not self.connected_over_kdp :
731                if plugin_string.find('core') >= 0 and self.target_arch == archX86_64:
732                    self.connected_to_debugserver = False
733            self.registers = self.register_set.register_info
734            if self.connected_to_debugserver:
735                print("Connected to live debugserver or arm core. Will associate on-core threads to registers reported by server.")
736            else:
737                print("Instantiating threads completely from saved state in memory.")
738
739    def create_thread(self, tid, context):
740        # Strip TBI explicitly in case create_thread() is called externally.
741        context = self._strip_ptr(context)
742
743        # tid == deadbeef means its a custom thread which kernel does not know of.
744        if tid == 0xdeadbeef :
745            # tid manipulation should be the same as in "switchtoregs" code in lldbmacros/process.py .
746            tid = 0xdead0000 | (context & ~0xffff0000)
747            tid = tid & 0xdeadffff
748            thread_obj = { 'tid'   : tid,
749                           'ptr'   : context,
750                           'name'  : 'switchtoregs' + hex(context),
751                           'queue' : 'None',
752                           'state' : 'stopped',
753                           'stop_reason' : 'none'
754                         }
755            self.thread_cache[tid] = thread_obj
756            return thread_obj
757
758        th_ptr = context
759        th = self.version.CreateValueFromExpression(str(th_ptr), f"(struct thread *) {str(th_ptr)}")
760        thread_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
761        # thread_unique_id starts at 100. If we're reading bogus memory, something's wrong
762        if tid != thread_id or tid == 0:
763            print(f"FATAL ERROR: Creating thread from memory 0x{context:x} with tid in mem={thread_id:d} when requested tid = {tid:d} ")
764            print(th)
765            return None
766
767        wait_queue = self._strip_ptr(th.GetChildMemberWithName('wait_queue').GetValueAsUnsigned())
768        thread_obj = { 'tid'   : thread_id,
769                       'ptr'   : th.GetValueAsUnsigned(),
770                       'name'  : hex(th.GetValueAsUnsigned()).rstrip('L'),
771                       'queue' : hex(wait_queue).rstrip('L'),
772                       'state' : 'stopped',
773                       'stop_reason' : 'none'
774                     }
775
776        if self.current_session_id != GetUniqueSessionID(self.process):
777            self.thread_cache = {}
778            self.current_session_id = GetUniqueSessionID(self.process)
779
780        self.thread_cache[tid] = thread_obj
781        return thread_obj
782
783    def populate_info_from_cores(self):
784        """
785        Populates info from active cores, including creating LLDB threads for
786        active threads
787        """
788
789        self.current_session_id = GetUniqueSessionID(self.process)
790        self.threads = []
791        self.thread_cache = {}
792        self.processors = []
793
794        processor_list_val = PluginValue(self._target.FindGlobalVariables('processor_list',1).GetValueAtIndex(0))
795        while processor_list_val.IsValid() and processor_list_val.error.success and processor_list_val.GetValueAsUnsigned() !=0:
796            cpu_id = processor_list_val.GetChildMemberWithName('cpu_id').GetValueAsUnsigned()
797            th = self._strip_thread_sbval(processor_list_val.GetChildMemberWithName('active_thread'))
798            th_id_val = th.GetChildMemberWithName('thread_id')
799            if th_id_val.IsValid() and th_id_val.error.success:
800                th_id = th_id_val.GetValueAsUnsigned()
801                self.processors.append({'active_thread': th.GetValueAsUnsigned(), 'cpu_id': cpu_id})
802                thread_obj = self.create_thread(th_id, th.GetValueAsUnsigned())
803                if thread_obj is None:
804                    print(f"Error creating LLDB thread for thread\n{th}\nDo not trust register state and backtrace for this thread.\n")
805                else:
806                    if self.connected_to_debugserver:
807                        self.thread_cache[th_id]['core'] = cpu_id
808                    self.thread_cache[th_id]['queue'] = "cpu-%d" % int(cpu_id)
809                    nth = self.thread_cache[th_id]
810                    self.threads.append(nth)
811                    self.thread_cache[nth['tid']] = nth
812            else:
813                print(f"Invalid active core thread SBValue:\n{th_id_val}Do not trust register state and backtrace for this thread.\n")
814            processor_list_val = processor_list_val.GetChildMemberWithName('processor_list')
815
816
817    def get_thread_info(self):
818        self.kdp_thread = None
819        self.kdp_state = None
820        if self.connected_over_kdp :
821            kdp = self._target.FindGlobalVariables('kdp',1).GetValueAtIndex(0)
822            kdp_state = kdp.GetChildMemberWithName('saved_state')
823            kdp_thread = self._strip_thread_sbval(kdp.GetChildMemberWithName('kdp_thread'))
824            if kdp_thread and kdp_thread.GetValueAsUnsigned() != 0:
825                self.kdp_thread = kdp_thread
826                self.kdp_state = kdp_state
827                kdp_thid = kdp_thread.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
828                self.create_thread(kdp_thid, kdp_thread.GetValueAsUnsigned())
829                self.thread_cache[kdp_thid]['core']=0
830                retval = [self.thread_cache[kdp_thid]]
831                return retval
832            else:
833                print("FATAL FAILURE: Unable to find kdp_thread state for this connection.")
834                return []
835
836        num_threads = self._target.FindGlobalVariables('threads_count',1).GetValueAtIndex(0).GetValueAsUnsigned()
837        # In case we are caught before threads are initialized. Fallback to threads known by astris/gdb server.
838        if num_threads <=0 :
839            return []
840
841        self.populate_info_from_cores()
842        return self.threads
843
844    def get_register_info(self):
845        if self.registers == None:
846            print("Register Information not found ")
847        return self.register_set.register_info
848
849    def get_register_data(self, tid):
850        thobj = None
851        try:
852            regs = self.register_set
853            if self.current_session_id != GetUniqueSessionID(self.process):
854                self.thread_cache = {}
855                self.current_session_id = GetUniqueSessionID(self.process)
856            if tid in self.thread_cache:
857
858                #Check if the thread is a fake one. Then create and return registers directly
859                if self.thread_cache[tid]['name'].find('switchtoregs') == 0:
860                    savedstateobj = self.version.CreateValueFromExpression(None, '(uintptr_t *) ' + str(self.thread_cache[tid]['ptr']))
861                    regs.ReadRegisterDataFromKDPSavedState(savedstateobj, self.version)
862                    return regs.GetPackedRegisterState()
863
864                thobj = self.version.CreateValueFromExpression(self.thread_cache[tid]['name'], f"(struct thread *) {self.thread_cache[tid]['ptr']}")
865
866            if thobj == None :
867                print("FATAL ERROR: Could not find thread with id %d" % tid)
868                regs.ResetRegisterValues()
869                return regs.GetPackedRegisterState()
870
871            if self.kdp_thread and self.kdp_thread.GetValueAsUnsigned() == thobj.GetValueAsUnsigned():
872                regs.ReadRegisterDataFromKDPSavedState(self.kdp_state, self.version)
873                return regs.GetPackedRegisterState()
874            if int(PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned()) != 0 :
875                if self.target_arch == archX86_64 :
876                    # we do have a stack so lets get register information
877                    saved_state_addr = PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned() + self.kernel_stack_size - self.kernel_thread_state_size
878                    regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version)
879                    return regs.GetPackedRegisterState()
880                elif self.target_arch.startswith(archARMv7) and int(PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0:
881                    #we have stack on the machine.kstackptr.
882                    saved_state_addr = PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()
883                    regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version)
884                    return regs.GetPackedRegisterState()
885                elif self.target_arch.startswith(archARMv8) and int((kstackptr := PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr')).GetValueAsUnsigned()) != 0:
886                    saved_state_addr = kstackptr.GetValueAsAddress()
887
888                    if self.struct_arm_kernel_context_type is not None:
889                        arm_ctx = self.version.CreateValueFromAddress(None, saved_state_addr, self.struct_arm_kernel_context_type)
890                    else:
891                        arm_ctx = self.version.CreateValueFromExpression(None, '(struct arm_kernel_context *) ' + str(saved_state_addr))
892                        arm_ctx = PluginValue(arm_ctx)
893                        self.struct_arm_kernel_context_type = arm_ctx.GetType().GetPointeeType()
894
895                    arm_ss_addr = arm_ctx.GetChildMemberWithName('ss').GetLoadAddress()
896                    regs.ReadRegisterDataFromKernelStack(arm_ss_addr, self.version)
897                    return regs.GetPackedRegisterState()
898            elif self.target_arch == archX86_64 or self.target_arch.startswith(archARMv7) or self.target_arch.startswith(archARMv8):
899                regs.ReadRegisterDataFromContinuation(PluginValue(thobj).GetChildMemberWithName('continuation').GetValueAsAddress())
900                return regs.GetPackedRegisterState()
901            #incase we failed very miserably
902        except KeyboardInterrupt as ke:
903            print("OS Plugin Interrupted during thread register load. \nWARNING:Thread registers and backtraces may not be accurate. for tid = %d" % tid)
904        regs.ResetRegisterValues()
905        print("FATAL ERROR: Failed to get register state for thread id 0x%x " % tid)
906        print(thobj)
907        return regs.GetPackedRegisterState()
908