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