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