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