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