4 #source of register info is from http://opensource.apple.com/source/gdb/gdb-962/src/gdb/arm-tdep.c
7 osplugin_target_obj
= None
9 class 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
))
20 class Armv7_RegisterSet(object):
21 """ register info set for armv7 32 bit architecture """
23 self
.register_info
= {}
24 self
.register_info
['sets'] = ['GPR']
25 self
.register_info
['registers'] = [
26 { 'name':'r0' , 'bitsize' : 32, 'offset' : 0, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 0, 'dwarf' : 0}
,
27 { 'name':'r1' , 'bitsize' : 32, 'offset' : 4, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 1, 'dwarf' : 1}
,
28 { 'name':'r2' , 'bitsize' : 32, 'offset' : 8, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 2, 'dwarf' : 2}
,
29 { 'name':'r3' , 'bitsize' : 32, 'offset' : 12, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 3, 'dwarf' : 3}
,
30 { 'name':'r4' , 'bitsize' : 32, 'offset' : 16, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 4, 'dwarf' : 4}
,
31 { 'name':'r5' , 'bitsize' : 32, 'offset' : 20, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 5, 'dwarf' : 5}
,
32 { 'name':'r6' , 'bitsize' : 32, 'offset' : 24, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 6, 'dwarf' : 6}
,
33 { 'name':'r7' , 'bitsize' : 32, 'offset' : 28, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 7, 'dwarf' : 7}
,
34 { 'name':'r8' , 'bitsize' : 32, 'offset' : 32, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 8, 'dwarf' : 8}
,
35 { 'name':'r9' , 'bitsize' : 32, 'offset' : 36, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc': 9, 'dwarf' : 9}
,
36 { 'name':'r10' , 'bitsize' : 32, 'offset' : 40, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':10, 'dwarf' :10}
,
37 { 'name':'r11' , 'bitsize' : 32, 'offset' : 44, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':11, 'dwarf' :11, 'alt-name': 'fp', 'generic': 'fp'}
,
38 { 'name':'r12' , 'bitsize' : 32, 'offset' : 48, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':12, 'dwarf' :12}
,
39 { 'name':'sp' , 'bitsize' : 32, 'offset' : 52, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':13, 'dwarf' :13, 'alt-name': 'sp', 'generic': 'sp'}
,
40 { 'name':'lr' , 'bitsize' : 32, 'offset' : 56, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':14, 'dwarf' :14, 'alt-name': 'lr', 'generic': 'lr'}
,
41 { 'name':'pc' , 'bitsize' : 32, 'offset' : 60, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':15, 'dwarf' :15, 'alt-name': 'pc', 'generic': 'pc'}
,
42 { 'name':'cpsr' , 'bitsize' : 32, 'offset' : 64, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':25, 'dwarf' :16, 'alt-name':'cpsr','generic':'cpsr'}
,
43 { 'name':'fsr' , 'bitsize' : 32, 'offset' : 68, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':17, 'dwarf' :17, 'alt-name':'fsr', 'generic': 'fsr'}
,
44 { 'name':'far' , 'bitsize' : 32, 'offset' : 72, 'encoding':'uint', 'format':'hex', 'set':0, 'gcc':18, 'dwarf' :18, 'alt-name': 'far', 'generic': 'far'}
46 self
.switch_context_address
= osplugin_target_obj
.FindSymbols('load_reg')[0].GetSymbol().GetStartAddress().GetLoadAddress(osplugin_target_obj
) + 8
47 self
.ResetRegisterValues()
48 def ResetRegisterValues(self
):
87 cpsr = {o.cpsr: <#010x}
88 fsr = {o.fsr : <#010x}
89 far = {o.far : <#010x}
92 def GetPackedRegisterState(self
):
93 return struct
.pack('19I', self
.r0
, self
.r1
, self
.r2
, self
.r3
,
94 self
.r4
, self
.r5
, self
.r6
, self
.r7
,
95 self
.r8
, self
.r9
, self
.r10
, self
.r11
,
96 self
.r12
, self
.sp
, self
.lr
, self
.pc
,
97 self
.cpsr
, self
.fsr
, self
.far
)
99 def ReadRegisterDataFromKDPSavedState(self
, kdp_state
, kernel_version
):
100 saved_state
= kernel_version
.CreateValueFromExpression(None, '(struct arm_saved_state *) ' + str(kdp_state
.GetValueAsUnsigned()))
101 saved_state
= saved_state
.Dereference()
102 saved_state
= PluginValue(saved_state
)
103 self
.ResetRegisterValues()
104 self
.r0
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(0).GetValueAsUnsigned()
105 self
.r1
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(1).GetValueAsUnsigned()
106 self
.r2
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(2).GetValueAsUnsigned()
107 self
.r3
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(3).GetValueAsUnsigned()
108 self
.r4
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(4).GetValueAsUnsigned()
109 self
.r5
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(5).GetValueAsUnsigned()
110 self
.r6
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(6).GetValueAsUnsigned()
111 self
.r7
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(7).GetValueAsUnsigned()
112 self
.r8
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(8).GetValueAsUnsigned()
113 self
.r9
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(9).GetValueAsUnsigned()
114 self
.r10
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(10).GetValueAsUnsigned()
115 self
.r11
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(11).GetValueAsUnsigned()
116 self
.r12
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(12).GetValueAsUnsigned()
117 self
.sp
= saved_state
.GetChildMemberWithName('sp').GetValueAsUnsigned()
118 self
.lr
= saved_state
.GetChildMemberWithName('lr').GetValueAsUnsigned()
119 self
.pc
= saved_state
.GetChildMemberWithName('pc').GetValueAsUnsigned()
120 self
.cpsr
= saved_state
.GetChildMemberWithName('cpsr').GetValueAsUnsigned()
121 self
.fsr
= saved_state
.GetChildMemberWithName('fsr').GetValueAsUnsigned()
122 self
.far
= saved_state
.GetChildMemberWithName('far').GetValueAsUnsigned()
125 def ReadRegisterDataFromKernelStack(self
, kstack_saved_state_addr
, kernel_version
):
126 saved_state
= kernel_version
.CreateValueFromExpression(None, '(struct arm_saved_state *) '+ str(kstack_saved_state_addr
))
127 saved_state
= saved_state
.Dereference()
128 saved_state
= PluginValue(saved_state
)
129 self
.ResetRegisterValues()
130 self
.r0
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(0).GetValueAsUnsigned()
131 self
.r1
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(1).GetValueAsUnsigned()
132 self
.r2
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(2).GetValueAsUnsigned()
133 self
.r3
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(3).GetValueAsUnsigned()
134 self
.r4
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(4).GetValueAsUnsigned()
135 self
.r5
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(5).GetValueAsUnsigned()
136 self
.r6
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(6).GetValueAsUnsigned()
137 self
.r7
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(7).GetValueAsUnsigned()
138 self
.r8
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(8).GetValueAsUnsigned()
139 self
.r9
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(9).GetValueAsUnsigned()
140 self
.r10
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(10).GetValueAsUnsigned()
141 self
.r11
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(11).GetValueAsUnsigned()
142 self
.r12
= saved_state
.GetChildMemberWithName('r').GetChildAtIndex(12).GetValueAsUnsigned()
143 self
.sp
= saved_state
.GetChildMemberWithName('sp').GetValueAsUnsigned()
144 self
.lr
= saved_state
.GetChildMemberWithName('lr').GetValueAsUnsigned()
145 # pc for a blocked thread is treated to be the next instruction it would run after thread switch.
146 self
.pc
= self
.switch_context_address
147 self
.cpsr
= saved_state
.GetChildMemberWithName('cpsr').GetValueAsUnsigned()
148 self
.fsr
= saved_state
.GetChildMemberWithName('fsr').GetValueAsUnsigned()
149 self
.far
= saved_state
.GetChildMemberWithName('far').GetValueAsUnsigned()
152 def ReadRegisterDataFromContinuation(self
, continuation_ptr
):
153 self
.ResetRegisterValues()
154 self
.pc
= continuation_ptr
158 class I386_RegisterSet(object):
159 """ register info set for i386 architecture
162 self
.register_info
= []
163 self
.register_info
['sets'] = ['GPR']
164 self
.register_info
['registers'] = [
165 { 'name': 'eax' , 'bitsize': 32, 'offset' : 0, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 0, 'dwarf': 0}
,
166 { 'name': 'ebx' , 'bitsize': 32, 'offset' : 4, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 1, 'dwarf': 1}
,
167 { 'name': 'ecx' , 'bitsize': 32, 'offset' : 8, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf': 2}
,
168 { 'name': 'edx' , 'bitsize': 32, 'offset' :12, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 3, 'dwarf': 3}
,
169 { 'name': 'edi' , 'bitsize': 32, 'offset' :16, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 4, 'dwarf': 4}
,
170 { 'name': 'esi' , 'bitsize': 32, 'offset' :20, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 5, 'dwarf': 5}
,
171 { 'name': 'ebp' , 'bitsize': 32, 'offset' :24, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 6, 'dwarf': 6}
,
172 { 'name': 'esp' , 'bitsize': 32, 'offset' :28, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 7, 'dwarf': 7}
,
173 { 'name': 'ss' , 'bitsize': 32, 'offset' :32, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 8, 'dwarf': 8}
,
174 { 'name': 'eflags', 'bitsize': 32, 'offset' :36, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' : 9, 'dwarf': 9}
,
175 { 'name': 'eip' , 'bitsize': 32, 'offset' :40, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :10, 'dwarf':10}
,
176 { 'name': 'cs' , 'bitsize': 32, 'offset' :44, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :11, 'dwarf':11}
,
177 { 'name': 'ds' , 'bitsize': 32, 'offset' :48, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :12, 'dwarf':12}
,
178 { 'name': 'es' , 'bitsize': 32, 'offset' :52, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :13, 'dwarf':13}
,
179 { 'name': 'fs' , 'bitsize': 32, 'offset' :56, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :14, 'dwarf':14}
,
180 { 'name': 'gs' , 'bitsize': 32, 'offset' :60, 'encoding': 'uint' , 'format':'hex' , 'set': 0, 'gcc' :15, 'dwarf':15}
,
182 self
.ResetRegisterValues()
183 def ResetRegisterValues(self
):
184 """ set all registers to zero """
213 eflags = {o.eflags: #010x}
222 def GetPackedRegisterState(self
):
223 """ get a struct.pack register data """
224 return struct
.pack('16I', self
.eax
, self
.ebx
, self
.ecx
,
225 self
.edx
, self
.edi
, self
.esi
,
226 self
.ebp
, self
.esp
, self
.ss
,
227 self
.eflags
, self
.eip
, self
.cs
,
228 self
.ds
, self
.es
, self
.fs
, self
.gs
230 def ReadRegisterDataFromKDPSavedState(self
, kdp_state
, kernel_version
):
231 """ to be implemented"""
233 def ReadRegisterDataFromKernelStack(self
, kstack_saved_state_addr
, kernel_version
):
234 """ to be implemented """
237 def ReadRegisterDataFromContinuation(self
, continuation_ptr
):
238 self
.ResetRegisterValues()
239 self
.eip
= continuation_ptr
243 class X86_64RegisterSet(object):
244 """ register info set for x86_64 architecture """
246 self
.register_info
= {}
247 self
.register_info
['sets'] = ['GPR', 'FPU', 'EXC']
248 self
.register_info
['registers'] = [
249 { 'name':'rax' , 'bitsize' : 64, 'offset' : 0, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 0, 'dwarf' : 0}
,
250 { 'name':'rbx' , 'bitsize' : 64, 'offset' : 8, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 3, 'dwarf' : 3}
,
251 { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }
,
252 { 'name':'rdx' , 'bitsize' : 64, 'offset' : 24, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 1, 'dwarf' : 1, 'generic':'arg3', 'alt-name':'arg3', }
,
253 { 'name':'rdi' , 'bitsize' : 64, 'offset' : 32, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 5, 'dwarf' : 5, 'generic':'arg1', 'alt-name':'arg1', }
,
254 { 'name':'rsi' , 'bitsize' : 64, 'offset' : 40, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 4, 'dwarf' : 4, 'generic':'arg2', 'alt-name':'arg2', }
,
255 { 'name':'rbp' , 'bitsize' : 64, 'offset' : 48, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 6, 'dwarf' : 6, 'generic':'fp' , 'alt-name':'fp', }
,
256 { 'name':'rsp' , 'bitsize' : 64, 'offset' : 56, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 7, 'dwarf' : 7, 'generic':'sp' , 'alt-name':'sp', }
,
257 { 'name':'r8' , 'bitsize' : 64, 'offset' : 64, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 8, 'dwarf' : 8, 'generic':'arg5', 'alt-name':'arg5', }
,
258 { 'name':'r9' , 'bitsize' : 64, 'offset' : 72, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 9, 'dwarf' : 9, 'generic':'arg6', 'alt-name':'arg6', }
,
259 { 'name':'r10' , 'bitsize' : 64, 'offset' : 80, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 10, 'dwarf' : 10}
,
260 { 'name':'r11' , 'bitsize' : 64, 'offset' : 88, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 11, 'dwarf' : 11}
,
261 { 'name':'r12' , 'bitsize' : 64, 'offset' : 96, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 12, 'dwarf' : 12}
,
262 { 'name':'r13' , 'bitsize' : 64, 'offset' : 104, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 13, 'dwarf' : 13}
,
263 { 'name':'r14' , 'bitsize' : 64, 'offset' : 112, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 14, 'dwarf' : 14}
,
264 { 'name':'r15' , 'bitsize' : 64, 'offset' : 120, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 15, 'dwarf' : 15}
,
265 { 'name':'rip' , 'bitsize' : 64, 'offset' : 128, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 16, 'dwarf' : 16, 'generic':'pc', 'alt-name':'pc' }
,
266 { 'name':'rflags' , 'bitsize' : 64, 'offset' : 136, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'generic':'flags', 'alt-name':'flags' }
,
267 { 'name':'cs' , 'bitsize' : 64, 'offset' : 144, 'encoding':'uint' , 'format':'hex' , 'set': 0 }
,
268 { 'name':'fs' , 'bitsize' : 64, 'offset' : 152, 'encoding':'uint' , 'format':'hex' , 'set': 0 }
,
269 { 'name':'gs' , 'bitsize' : 64, 'offset' : 160, 'encoding':'uint' , 'format':'hex' , 'set': 0 }
,
271 self
.ResetRegisterValues()
273 def ResetRegisterValues(self
):
274 """ set all the registers to zero. """
298 rax = {o.rax: <#018x}
299 rbx = {o.rbx: <#018x}
300 rcx = {o.rcx: <#018x}
301 rdx = {o.rdx: <#018x}
302 rdi = {o.rdi: <#018x}
303 rsi = {o.rsi: <#018x}
304 rbp = {o.rbp: <#018x}
305 rsp = {o.rsp: <#018x}
308 r10 = {o.r10: <#018x}
309 r11 = {o.r11: <#018x}
310 r12 = {o.r12: <#018x}
311 r13 = {o.r13: <#018x}
312 r14 = {o.r14: <#018x}
313 r15 = {o.r15: <#018x}
314 rip = {o.rip: <#018x}
315 rflags = {o.rflags: <#018x}
321 def GetPackedRegisterState(self
):
322 """ get a struct.pack register data for passing to C constructs """
323 return struct
.pack('21Q', self
.rax
, self
.rbx
, self
.rcx
, self
.rdx
, self
.rdi
,
324 self
.rsi
, self
.rbp
, self
.rsp
, self
.r8
, self
.r9
,
325 self
.r10
, self
.r11
, self
.r12
, self
.r13
, self
.r14
,
326 self
.r15
, self
.rip
, self
.rflags
, self
.cs
, self
.fs
, self
.gs
)
328 def ReadRegisterDataFromKDPSavedState(self
, kdp_state
, kernel_version
):
329 saved_state
= kernel_version
.CreateValueFromExpression(None, '(struct x86_saved_state64 *) '+ str(kdp_state
.GetValueAsUnsigned()))
330 saved_state
= saved_state
.Dereference()
331 saved_state
= PluginValue(saved_state
)
332 self
.ResetRegisterValues()
333 self
.rdi
= saved_state
.GetChildMemberWithName('rdi').GetValueAsUnsigned()
334 self
.rsi
= saved_state
.GetChildMemberWithName('rsi').GetValueAsUnsigned()
335 self
.rdx
= saved_state
.GetChildMemberWithName('rdx').GetValueAsUnsigned()
336 self
.r10
= saved_state
.GetChildMemberWithName('r10').GetValueAsUnsigned()
337 self
.r8
= saved_state
.GetChildMemberWithName('r8').GetValueAsUnsigned()
338 self
.r9
= saved_state
.GetChildMemberWithName('r9').GetValueAsUnsigned()
339 self
.r15
= saved_state
.GetChildMemberWithName('r15').GetValueAsUnsigned()
340 self
.r14
= saved_state
.GetChildMemberWithName('r14').GetValueAsUnsigned()
341 self
.r13
= saved_state
.GetChildMemberWithName('r13').GetValueAsUnsigned()
342 self
.r12
= saved_state
.GetChildMemberWithName('r12').GetValueAsUnsigned()
343 self
.r11
= saved_state
.GetChildMemberWithName('r11').GetValueAsUnsigned()
344 self
.rbp
= saved_state
.GetChildMemberWithName('rbp').GetValueAsUnsigned()
345 self
.rbx
= saved_state
.GetChildMemberWithName('rbx').GetValueAsUnsigned()
346 self
.rcx
= saved_state
.GetChildMemberWithName('rcx').GetValueAsUnsigned()
347 self
.rax
= saved_state
.GetChildMemberWithName('rax').GetValueAsUnsigned()
348 self
.rip
= saved_state
.GetChildMemberWithName('isf').GetChildMemberWithName('rip').GetValueAsUnsigned()
349 self
.rflags
= saved_state
.GetChildMemberWithName('isf').GetChildMemberWithName('rflags').GetValueAsUnsigned()
350 self
.rsp
= saved_state
.GetChildMemberWithName('isf').GetChildMemberWithName('rsp').GetValueAsUnsigned()
353 def ReadRegisterDataFromKernelStack(self
, kstack_saved_state_addr
, kernel_version
):
354 saved_state
= kernel_version
.CreateValueFromExpression(None, '(struct x86_kernel_state *) '+ str(kstack_saved_state_addr
))
355 saved_state
= saved_state
.Dereference()
356 saved_state
= PluginValue(saved_state
)
357 self
.ResetRegisterValues()
358 self
.rbx
= saved_state
.GetChildMemberWithName('k_rbx').GetValueAsUnsigned()
359 self
.rsp
= saved_state
.GetChildMemberWithName('k_rsp').GetValueAsUnsigned()
360 self
.rbp
= saved_state
.GetChildMemberWithName('k_rbp').GetValueAsUnsigned()
361 self
.r12
= saved_state
.GetChildMemberWithName('k_r12').GetValueAsUnsigned()
362 self
.r13
= saved_state
.GetChildMemberWithName('k_r13').GetValueAsUnsigned()
363 self
.r14
= saved_state
.GetChildMemberWithName('k_r14').GetValueAsUnsigned()
364 self
.r15
= saved_state
.GetChildMemberWithName('k_r15').GetValueAsUnsigned()
365 self
.rip
= saved_state
.GetChildMemberWithName('k_rip').GetValueAsUnsigned()
368 def ReadRegisterDataFromContinuation(self
, continuation_ptr
):
369 self
.ResetRegisterValues()
370 self
.rip
= continuation_ptr
376 def IterateQueue(queue_head
, element_ptr_type
, element_field_name
):
377 """ iterate over a queue in kernel of type queue_head_t. refer to osfmk/kern/queue.h
379 queue_head - lldb.SBValue : Value object for queue_head.
380 element_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
381 element_field_name - str : name of the field in target struct.
383 A generator does not return. It is used for iterating.
384 SBValue : an object thats of type (element_type) queue_head->next. Always a pointer object
386 queue_head_addr
= 0x0
387 if queue_head
.TypeIsPointerType():
388 queue_head_addr
= queue_head
.GetValueAsUnsigned()
390 queue_head_addr
= queue_head
.GetAddress().GetLoadAddress(osplugin_target_obj
)
391 cur_elt
= queue_head
.GetChildMemberWithName('next')
394 if not cur_elt
.IsValid() or cur_elt
.GetValueAsUnsigned() == 0 or cur_elt
.GetValueAsUnsigned() == queue_head_addr
:
396 elt
= cur_elt
.Cast(element_ptr_type
)
398 cur_elt
= elt
.GetChildMemberWithName(element_field_name
).GetChildMemberWithName('next')
400 def GetUniqueSessionID(process_obj
):
401 """ Create a unique session identifier.
403 process_obj: lldb.SBProcess object refering to connected process.
405 int - a unique number identified by processid and stopid.
408 if hasattr(process_obj
, "GetUniqueID"):
409 session_key_str
+= str(process_obj
.GetUniqueID()) + ":"
411 session_key_str
+= "0:"
413 if hasattr(process_obj
, "GetStopID"):
414 session_key_str
+= str(process_obj
.GetStopID())
416 session_key_str
+="1"
418 return hash(session_key_str
)
421 (archX86_64
, archARMv7_family
, archI386
) = ("x86_64", ("armv7", "armv7s") , "i386")
423 class OperatingSystemPlugIn(object):
424 """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
426 def __init__(self
, process
):
427 '''Initialization needs a valid.SBProcess object'''
429 self
.registers
= None
431 self
.thread_cache
= {}
432 self
.current_session_id
= 0
433 self
.kdp_thread
= None
434 if type(process
) is lldb
.SBProcess
and process
.IsValid():
435 global osplugin_target_obj
436 self
.process
= process
437 self
._target
= process
.target
438 osplugin_target_obj
= self
._target
439 self
.current_session_id
= GetUniqueSessionID(self
.process
)
440 self
.version
= self
._target
.FindGlobalVariables('version', 0).GetValueAtIndex(0)
441 self
.kernel_stack_size
= self
._target
.FindGlobalVariables('kernel_stack_size', 0).GetValueAtIndex(0).GetValueAsUnsigned()
442 self
.kernel_context_size
= 0
443 self
.connected_over_kdp
= False
444 plugin_string
= self
.process
.GetPluginName().lower()
445 if plugin_string
.find("kdp") >=0:
446 self
.connected_over_kdp
= True
447 #print "version", self.version, "kernel_stack_size", self.kernel_stack_size, "context_size", self.kernel_context_size
448 self
.threads
= None # Will be an dictionary containing info for each thread
449 triple
= self
.process
.target
.triple
450 arch
= triple
.split('-')[0].lower()
451 self
.target_arch
= ""
452 self
.kernel_context_size
= 0
453 if arch
== archX86_64
:
454 self
.target_arch
= archX86_64
455 print "Target arch: x86_64"
456 self
.register_set
= X86_64RegisterSet()
457 self
.kernel_context_size
= self
._target
.FindFirstType('x86_kernel_state').GetByteSize()
458 elif arch
in archARMv7_family
:
459 self
.target_arch
= arch
460 print "Target arch: " + self
.target_arch
461 self
.register_set
= Armv7_RegisterSet()
462 self
.registers
= self
.register_set
.register_info
464 def create_thread(self
, tid
, context
):
466 th
= self
.version
.CreateValueFromExpression(str(th_ptr
),'(struct thread *)' + str(th_ptr
))
467 thread_id
= th
.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
469 print "FATAL ERROR: Creating thread from memory 0x%x with tid in mem=%d when requested tid = %d " % (context
, thread_id
, tid
)
471 thread_obj
= { 'tid' : thread_id
,
472 'ptr' : th
.GetValueAsUnsigned(),
473 'name' : hex(th
.GetValueAsUnsigned()).rstrip('L'),
474 'queue' : hex(th
.GetChildMemberWithName('wait_queue').GetValueAsUnsigned()).rstrip('L'),
476 'stop_reason' : 'none'
478 if self
.current_session_id
!= GetUniqueSessionID(self
.process
):
479 self
.thread_cache
= {}
480 self
.current_session_id
= GetUniqueSessionID(self
.process
)
482 self
.thread_cache
[tid
] = thread_obj
486 def get_thread_info(self
):
487 self
.kdp_thread
= None
488 self
.kdp_state
= None
489 if self
.connected_over_kdp
:
490 kdp
= self
._target
.FindGlobalVariables('kdp',1).GetValueAtIndex(0)
491 kdp_state
= kdp
.GetChildMemberWithName('saved_state')
492 kdp_thread
= kdp
.GetChildMemberWithName('kdp_thread')
493 if kdp_thread
and kdp_thread
.GetValueAsUnsigned() != 0:
494 self
.kdp_thread
= kdp_thread
495 self
.kdp_state
= kdp_state
496 kdp_thid
= kdp_thread
.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
497 self
.create_thread(kdp_thid
, kdp_thread
.GetValueAsUnsigned())
498 self
.thread_cache
[kdp_thid
]['core']=0
499 retval
= [self
.thread_cache
[kdp_thid
]]
502 print "FATAL FAILURE: Unable to find kdp_thread state for this connection."
505 num_threads
= self
._target
.FindGlobalVariables('threads_count',1).GetValueAtIndex(0).GetValueAsUnsigned()
506 #In case we are caught before threads are initialized. Fallback to threads known by astris/gdb server.
510 self
.current_session_id
= GetUniqueSessionID(self
.process
)
512 self
.thread_cache
= {}
515 processor_list_val
= PluginValue(self
._target
.FindGlobalVariables('processor_list',1).GetValueAtIndex(0))
516 while processor_list_val
.IsValid() and processor_list_val
.GetValueAsUnsigned() !=0 :
517 th
= processor_list_val
.GetChildMemberWithName('active_thread')
518 th_id
= th
.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
519 cpu_id
= processor_list_val
.GetChildMemberWithName('cpu_id').GetValueAsUnsigned()
520 self
.processors
.append({'active_thread': th.GetValueAsUnsigned(), 'cpu_id': cpu_id}
)
521 self
.create_thread(th_id
, th
.GetValueAsUnsigned())
522 self
.thread_cache
[th_id
]['core'] = cpu_id
523 nth
= self
.thread_cache
[th_id
]
524 print "Found 0x%x on logical cpu %d" % ( nth
['ptr'], nth
['core'])
525 self
.threads
.append(nth
)
526 self
.thread_cache
[nth
['tid']] = nth
527 processor_list_val
= processor_list_val
.GetChildMemberWithName('processor_list')
528 except KeyboardInterrupt, ke
:
529 print "OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate."
532 if hasattr(self
.process
, 'CreateOSPluginThread'):
535 # FIXME remove legacy code
537 thread_q_head
= self
._target
.FindGlobalVariables('threads', 0).GetValueAtIndex(0)
538 thread_type
= self
._target
.FindFirstType('thread')
539 thread_ptr_type
= thread_type
.GetPointerType()
540 for th
in IterateQueue(thread_q_head
, thread_ptr_type
, 'threads'):
541 th_id
= th
.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
542 self
.create_thread(th_id
, th
.GetValueAsUnsigned())
543 nth
= self
.thread_cache
[th_id
]
544 for cputhread
in self
.processors
:
545 if cputhread
['active_thread'] == nth
['ptr']:
546 nth
['core'] = cputhread
['cpu_id']
547 #print "Found 0x%x on logical cpu %d" % ( nth['ptr'], cputhread['cpu_id'])
548 self
.threads
.append( nth
)
549 except KeyboardInterrupt, ke
:
550 print "OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate."
555 def get_register_info(self
):
556 if self
.registers
== None:
557 print "Register Information not found "
558 return self
.register_set
.register_info
560 def get_register_data(self
, tid
):
561 #print "searching for tid", tid
564 if self
.current_session_id
!= GetUniqueSessionID(self
.process
):
565 self
.thread_cache
= {}
566 self
.current_session_id
= GetUniqueSessionID(self
.process
)
568 if tid
in self
.thread_cache
.keys():
569 thobj
= self
.version
.CreateValueFromExpression(self
.thread_cache
[tid
]['name'], '(struct thread *)' + str(self
.thread_cache
[tid
]['ptr']))
570 regs
= self
.register_set
572 print "FATAL ERROR: Could not find thread with id %d" % tid
573 regs
.ResetRegisterValues()
574 return regs
.GetPackedRegisterState()
576 if self
.kdp_thread
and self
.kdp_thread
.GetValueAsUnsigned() == thobj
.GetValueAsUnsigned():
577 regs
.ReadRegisterDataFromKDPSavedState(self
.kdp_state
, self
.version
)
578 return regs
.GetPackedRegisterState()
579 if int(PluginValue(thobj
).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned()) != 0 :
580 if self
.target_arch
== archX86_64
:
581 # we do have a stack so lets get register information
582 saved_state_addr
= PluginValue(thobj
).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned() + self
.kernel_stack_size
- self
.kernel_context_size
583 regs
.ReadRegisterDataFromKernelStack(saved_state_addr
, self
.version
)
584 return regs
.GetPackedRegisterState()
585 elif self
.target_arch
in archARMv7_family
and int(PluginValue(thobj
).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0:
586 #we have stack on the machine.kstackptr.
587 saved_state_addr
= PluginValue(thobj
).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()
588 regs
.ReadRegisterDataFromKernelStack(saved_state_addr
, self
.version
)
589 return regs
.GetPackedRegisterState()
590 elif self
.target_arch
== archX86_64
or self
.target_arch
in archARMv7_family
:
591 regs
.ReadRegisterDataFromContinuation( PluginValue(thobj
).GetChildMemberWithName('continuation').GetValueAsUnsigned())
592 return regs
.GetPackedRegisterState()
593 #incase we failed very miserably
594 except KeyboardInterrupt, ke
:
595 print "OS Plugin Interrupted during thread register load. \nWARNING:Thread registers and backtraces may not be accurate. for tid = %d" % tid
596 regs
.ResetRegisterValues()
597 print "FATAL ERROR: Failed to get register state for thread id 0x%x " % tid
599 return regs
.GetPackedRegisterState()