]> git.saurik.com Git - apple/xnu.git/blame_incremental - tools/lldbmacros/core/operating_system.py
xnu-2422.115.4.tar.gz
[apple/xnu.git] / tools / lldbmacros / core / operating_system.py
... / ...
CommitLineData
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
19
20class Armv7_RegisterSet(object):
21 """ register info set for armv7 32 bit architecture """
22 def __init__(self):
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'}
45 ]
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):
49 self.r0 = 0
50 self.r1 = 0
51 self.r2 = 0
52 self.r3 = 0
53 self.r4 = 0
54 self.r5 = 0
55 self.r6 = 0
56 self.r7 = 0
57 self.r8 = 0
58 self.r9 = 0
59 self.r10 = 0
60 self.r11 = 0
61 self.r12 = 0
62 self.sp = 0
63 self.lr = 0
64 self.pc = 0
65 self.cpsr = 0
66 self.fsr = 0
67 self.far = 0
68
69 def __str__(self):
70 return """
71 r0 = {o.r0: <#010x}
72 r1 = {o.r1: <#010x}
73 r2 = {o.r2: <#010x}
74 r3 = {o.r3: <#010x}
75 r4 = {o.r4: <#010x}
76 r5 = {o.r5: <#010x}
77 r6 = {o.r6: <#010x}
78 r7 = {o.r7: <#010x}
79 r8 = {o.r8: <#010x}
80 r9 = {o.r9: <#010x}
81 r10 = {o.r10: <#010x}
82 r11 = {o.r11: <#010x}
83 r12 = {o.r12: <#010x}
84 sp = {o.sp: <#010x}
85 lr = {o.lr: <#010x}
86 pc = {o.pc: <#010x}
87 cpsr = {o.cpsr: <#010x}
88 fsr = {o.fsr : <#010x}
89 far = {o.far : <#010x}
90 """.format(o=self)
91
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)
98
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()
123 return self
124
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()
150 return self
151
152 def ReadRegisterDataFromContinuation(self, continuation_ptr):
153 self.ResetRegisterValues()
154 self.pc = continuation_ptr
155 return self
156
157
158class I386_RegisterSet(object):
159 """ register info set for i386 architecture
160 """
161 def __init__(self):
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},
181 ]
182 self.ResetRegisterValues()
183 def ResetRegisterValues(self):
184 """ set all registers to zero """
185 self.eax = 0
186 self.ebx = 0
187 self.ecx = 0
188 self.edx = 0
189 self.edi = 0
190 self.esi = 0
191 self.ebp = 0
192 self.esp = 0
193 self.ss = 0
194 self.eflags = 0
195 self.eip = 0
196 self.cs = 0
197 self.ds = 0
198 self.es = 0
199 self.fs = 0
200 self.gs = 0
201
202 def __str__(self):
203 return """
204 eax = {o.eax: #010x}
205 ebx = {o.ebx: #010x}
206 ecx = {o.ecx: #010x}
207 edx = {o.edx: #010x}
208 edi = {o.edi: #010x}
209 esi = {o.esi: #010x}
210 ebp = {o.ebp: #010x}
211 esp = {o.esp: #010x}
212 ss = {o.ss: #010x}
213 eflags = {o.eflags: #010x}
214 eip = {o.eip: #010x}
215 cs = {o.cs: #010x}
216 ds = {o.ds: #010x}
217 es = {o.es: #010x}
218 fs = {o.fs: #010x}
219 gs = {o.gs: #010x}
220 """.format(o=self)
221
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
229 )
230 def ReadRegisterDataFromKDPSavedState(self, kdp_state, kernel_version):
231 """ to be implemented"""
232 return None
233 def ReadRegisterDataFromKernelStack(self, kstack_saved_state_addr, kernel_version):
234 """ to be implemented """
235 return None
236
237 def ReadRegisterDataFromContinuation(self, continuation_ptr):
238 self.ResetRegisterValues()
239 self.eip = continuation_ptr
240 return self
241
242
243class X86_64RegisterSet(object):
244 """ register info set for x86_64 architecture """
245 def __init__(self):
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 },
270 ]
271 self.ResetRegisterValues()
272
273 def ResetRegisterValues(self):
274 """ set all the registers to zero. """
275 self.rax = 0
276 self.rbx = 0
277 self.rcx = 0
278 self.rdx = 0
279 self.rdi = 0
280 self.rsi = 0
281 self.rbp = 0
282 self.rsp = 0
283 self.r8 = 0
284 self.r9 = 0
285 self.r10 = 0
286 self.r11 = 0
287 self.r12 = 0
288 self.r13 = 0
289 self.r14 = 0
290 self.r15 = 0
291 self.rip = 0
292 self.rflags = 0
293 self.cs = 0
294 self.fs = 0
295 self.gs = 0
296 def __str__(self):
297 return """
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}
306 r8 = {o.r8: <#018x}
307 r9 = {o.r9: <#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}
316 cs = {o.cs: <#018x}
317 fs = {o.fs: <#018x}
318 gs = {o.gs: <#018x}
319 """.format(o=self)
320
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)
327
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()
351 return self
352
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()
366 return self
367
368 def ReadRegisterDataFromContinuation(self, continuation_ptr):
369 self.ResetRegisterValues()
370 self.rip = continuation_ptr
371 return self
372
373
374
375
376def 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
378 params:
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.
382 returns:
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
385 """
386 queue_head_addr = 0x0
387 if queue_head.TypeIsPointerType():
388 queue_head_addr = queue_head.GetValueAsUnsigned()
389 else:
390 queue_head_addr = queue_head.GetAddress().GetLoadAddress(osplugin_target_obj)
391 cur_elt = queue_head.GetChildMemberWithName('next')
392 while True:
393
394 if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0 or cur_elt.GetValueAsUnsigned() == queue_head_addr:
395 break
396 elt = cur_elt.Cast(element_ptr_type)
397 yield elt
398 cur_elt = elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('next')
399
400def GetUniqueSessionID(process_obj):
401 """ Create a unique session identifier.
402 params:
403 process_obj: lldb.SBProcess object refering to connected process.
404 returns:
405 int - a unique number identified by processid and stopid.
406 """
407 session_key_str = ""
408 if hasattr(process_obj, "GetUniqueID"):
409 session_key_str += str(process_obj.GetUniqueID()) + ":"
410 else:
411 session_key_str += "0:"
412
413 if hasattr(process_obj, "GetStopID"):
414 session_key_str += str(process_obj.GetStopID())
415 else:
416 session_key_str +="1"
417
418 return hash(session_key_str)
419
420
421(archX86_64, archARMv7_family, archI386) = ("x86_64", ("armv7", "armv7s") , "i386")
422
423class OperatingSystemPlugIn(object):
424 """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
425
426 def __init__(self, process):
427 '''Initialization needs a valid.SBProcess object'''
428 self.process = None
429 self.registers = None
430 self.threads = 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
463
464 def create_thread(self, tid, context):
465 th_ptr = context
466 th = self.version.CreateValueFromExpression(str(th_ptr),'(struct thread *)' + str(th_ptr))
467 thread_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned()
468 if tid != thread_id:
469 print "FATAL ERROR: Creating thread from memory 0x%x with tid in mem=%d when requested tid = %d " % (context, thread_id, tid)
470 return None
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'),
475 'state' : 'stopped',
476 'stop_reason' : 'none'
477 }
478 if self.current_session_id != GetUniqueSessionID(self.process):
479 self.thread_cache = {}
480 self.current_session_id = GetUniqueSessionID(self.process)
481
482 self.thread_cache[tid] = thread_obj
483 return thread_obj
484
485
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]]
500 return retval
501 else:
502 print "FATAL FAILURE: Unable to find kdp_thread state for this connection."
503 return []
504
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.
507 if num_threads <=0 :
508 return []
509
510 self.current_session_id = GetUniqueSessionID(self.process)
511 self.threads = []
512 self.thread_cache = {}
513 self.processors = []
514 try:
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."
530 return self.threads
531
532 if hasattr(self.process, 'CreateOSPluginThread'):
533 return self.threads
534
535 # FIXME remove legacy code
536 try:
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."
551 return self.threads
552 # end legacy code
553 return self.threads
554
555 def get_register_info(self):
556 if self.registers == None:
557 print "Register Information not found "
558 return self.register_set.register_info
559
560 def get_register_data(self, tid):
561 #print "searching for tid", tid
562 thobj = None
563 try:
564 if self.current_session_id != GetUniqueSessionID(self.process):
565 self.thread_cache = {}
566 self.current_session_id = GetUniqueSessionID(self.process)
567
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
571 if thobj == None :
572 print "FATAL ERROR: Could not find thread with id %d" % tid
573 regs.ResetRegisterValues()
574 return regs.GetPackedRegisterState()
575
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
598 print thobj
599 return regs.GetPackedRegisterState()
600