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