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