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