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, element_ptr_type, element_field_name): 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 = queue_head.GetChildMemberWithName('next') 625 while True: 626 if not cur_elt.IsValid() 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 self.kasan_tbi = self._target.FindGlobalVariables('kasan_tbi_enabled', 1).GetValueAtIndex(0) 674 self.kernel_stack_size = self._target.FindGlobalVariables('kernel_stack_size', 1).GetValueAtIndex(0).GetValueAsUnsigned() 675 self.kernel_context_size = 0 676 self.connected_over_kdp = False 677 # connected_to_debugserver signifies if we are connected to astris or other gdbserver instance 678 # that has the correct thread state for on core threads. For kdp and coredumps we rely on in memory 679 # state of threads. 680 self.connected_to_debugserver = True 681 plugin_string = self.process.GetPluginName().lower() 682 if plugin_string.find("kdp") >=0: 683 self.connected_over_kdp = True 684 self.connected_to_debugserver = False 685 #print "version", self.version, "kernel_stack_size", self.kernel_stack_size, "context_size", self.kernel_context_size 686 self.threads = None # Will be an dictionary containing info for each thread 687 triple = self.process.target.triple 688 arch = triple.split('-')[0].lower() 689 self.target_arch = "" 690 self.kernel_context_size = 0 691 if arch == archX86_64 : 692 self.target_arch = archX86_64 693 print("Target arch: x86_64") 694 self.register_set = X86_64RegisterSet() 695 self.kernel_context_size = self._target.FindFirstType('x86_kernel_state').GetByteSize() 696 self.kernel_thread_state_size = self._target.FindFirstType('struct thread_kernel_state').GetByteSize() 697 elif arch.startswith(archARMv7) : 698 self.target_arch = arch 699 print("Target arch: " + self.target_arch) 700 self.register_set = Armv7_RegisterSet() 701 elif arch.startswith(archARMv8): 702 self.target_arch = arch 703 print("Target arch: " + self.target_arch) 704 self.register_set = Armv8_RegisterSet() 705 # connection intel arm 706 # kdp Memory Memory 707 # gdb Server Server 708 # coredump Memory Server 709 if not self.connected_over_kdp : 710 if plugin_string.find('core') >= 0 and self.target_arch == archX86_64: 711 self.connected_to_debugserver = False 712 self.registers = self.register_set.register_info 713 if self.connected_to_debugserver: 714 print("Connected to live debugserver or arm core. Will associate on-core threads to registers reported by server.") 715 else: 716 print("Instantiating threads completely from saved state in memory.") 717 718 def create_thread(self, tid, context): 719 def strip_tbi(v): 720 if self.kasan_tbi and v != 0: 721 v |= (0xFF << 56) 722 return v 723 724 # Strip TBI explicitly in case create_thread() is called externally. 725 context = strip_tbi(context) 726 727 # tid == deadbeef means its a custom thread which kernel does not know of. 728 if tid == 0xdeadbeef : 729 # tid manipulation should be the same as in "switchtoregs" code in lldbmacros/process.py . 730 tid = 0xdead0000 | (context & ~0xffff0000) 731 tid = tid & 0xdeadffff 732 thread_obj = { 'tid' : tid, 733 'ptr' : context, 734 'name' : 'switchtoregs' + hex(context), 735 'queue' : 'None', 736 'state' : 'stopped', 737 'stop_reason' : 'none' 738 } 739 self.thread_cache[tid] = thread_obj 740 return thread_obj 741 742 th_ptr = context 743 th = self.version.CreateValueFromExpression(str(th_ptr), '(struct thread *)' + str(th_ptr)) 744 thread_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned() 745 if tid != thread_id: 746 print("FATAL ERROR: Creating thread from memory 0x%x with tid in mem=%d when requested tid = %d " % (context, thread_id, tid)) 747 return None 748 749 wait_queue = strip_tbi(th.GetChildMemberWithName('wait_queue').GetValueAsUnsigned()) 750 thread_obj = { 'tid' : thread_id, 751 'ptr' : th.GetValueAsUnsigned(), 752 'name' : hex(th.GetValueAsUnsigned()).rstrip('L'), 753 'queue' : hex(wait_queue).rstrip('L'), 754 'state' : 'stopped', 755 'stop_reason' : 'none' 756 } 757 758 if self.current_session_id != GetUniqueSessionID(self.process): 759 self.thread_cache = {} 760 self.current_session_id = GetUniqueSessionID(self.process) 761 762 self.thread_cache[tid] = thread_obj 763 return thread_obj 764 765 def get_thread_info(self): 766 self.kdp_thread = None 767 self.kdp_state = None 768 if self.connected_over_kdp : 769 kdp = self._target.FindGlobalVariables('kdp',1).GetValueAtIndex(0) 770 kdp_state = kdp.GetChildMemberWithName('saved_state') 771 kdp_thread = self._strip_thread_tbi(kdp.GetChildMemberWithName('kdp_thread')) 772 if kdp_thread and kdp_thread.GetValueAsUnsigned() != 0: 773 self.kdp_thread = kdp_thread 774 self.kdp_state = kdp_state 775 kdp_thid = kdp_thread.GetChildMemberWithName('thread_id').GetValueAsUnsigned() 776 self.create_thread(kdp_thid, kdp_thread.GetValueAsUnsigned()) 777 self.thread_cache[kdp_thid]['core']=0 778 retval = [self.thread_cache[kdp_thid]] 779 return retval 780 else: 781 print("FATAL FAILURE: Unable to find kdp_thread state for this connection.") 782 return [] 783 784 num_threads = self._target.FindGlobalVariables('threads_count',1).GetValueAtIndex(0).GetValueAsUnsigned() 785 #In case we are caught before threads are initialized. Fallback to threads known by astris/gdb server. 786 if num_threads <=0 : 787 return [] 788 789 self.current_session_id = GetUniqueSessionID(self.process) 790 self.threads = [] 791 self.thread_cache = {} 792 self.processors = [] 793 try: 794 processor_list_val = PluginValue(self._target.FindGlobalVariables('processor_list',1).GetValueAtIndex(0)) 795 while processor_list_val.IsValid() and processor_list_val.GetValueAsUnsigned() !=0 : 796 th = self._strip_thread_tbi(processor_list_val.GetChildMemberWithName('active_thread')) 797 th_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned() 798 cpu_id = processor_list_val.GetChildMemberWithName('cpu_id').GetValueAsUnsigned() 799 self.processors.append({'active_thread': th.GetValueAsUnsigned(), 'cpu_id': cpu_id}) 800 self.create_thread(th_id, th.GetValueAsUnsigned()) 801 if self.connected_to_debugserver: 802 self.thread_cache[th_id]['core'] = cpu_id 803 self.thread_cache[th_id]['queue'] = "cpu-%d" % int(cpu_id) 804 nth = self.thread_cache[th_id] 805 self.threads.append(nth) 806 self.thread_cache[nth['tid']] = nth 807 processor_list_val = processor_list_val.GetChildMemberWithName('processor_list') 808 except KeyboardInterrupt as ke: 809 print("OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate.") 810 return self.threads 811 812 if hasattr(self.process, 'CreateOSPluginThread'): 813 return self.threads 814 815 # FIXME remove legacy code 816 try: 817 thread_q_head = self._target.FindGlobalVariables('threads', 1).GetValueAtIndex(0) 818 thread_type = self._target.FindFirstType('thread') 819 thread_ptr_type = thread_type.GetPointerType() 820 for th in IterateQueue(thread_q_head, thread_ptr_type, 'threads'): 821 th = self._strip_thread_tbi(th) 822 th_id = th.GetChildMemberWithName('thread_id').GetValueAsUnsigned() 823 self.create_thread(th_id, th.GetValueAsUnsigned()) 824 nth = self.thread_cache[th_id] 825 for cputhread in self.processors: 826 if cputhread['active_thread'] == nth['ptr']: 827 nth['core'] = cputhread['cpu_id'] 828 self.threads.append( nth ) 829 except KeyboardInterrupt as ke: 830 print("OS Plugin Interrupted during thread loading process. \nWARNING:Thread registers and backtraces may not be accurate.") 831 return self.threads 832 # end legacy code 833 return self.threads 834 835 def get_register_info(self): 836 if self.registers == None: 837 print("Register Information not found ") 838 return self.register_set.register_info 839 840 def get_register_data(self, tid): 841 thobj = None 842 try: 843 regs = self.register_set 844 if self.current_session_id != GetUniqueSessionID(self.process): 845 self.thread_cache = {} 846 self.current_session_id = GetUniqueSessionID(self.process) 847 if tid in self.thread_cache: 848 849 #Check if the thread is a fake one. Then create and return registers directly 850 if self.thread_cache[tid]['name'].find('switchtoregs') == 0: 851 savedstateobj = self.version.CreateValueFromExpression(None, '(uintptr_t *) ' + str(self.thread_cache[tid]['ptr'])) 852 regs.ReadRegisterDataFromKDPSavedState(savedstateobj, self.version) 853 return regs.GetPackedRegisterState() 854 855 thobj = self.version.CreateValueFromExpression(self.thread_cache[tid]['name'], '(struct thread *)' + str(self.thread_cache[tid]['ptr'])) 856 857 if thobj == None : 858 print("FATAL ERROR: Could not find thread with id %d" % tid) 859 regs.ResetRegisterValues() 860 return regs.GetPackedRegisterState() 861 862 if self.kdp_thread and self.kdp_thread.GetValueAsUnsigned() == thobj.GetValueAsUnsigned(): 863 regs.ReadRegisterDataFromKDPSavedState(self.kdp_state, self.version) 864 return regs.GetPackedRegisterState() 865 if int(PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned()) != 0 : 866 if self.target_arch == archX86_64 : 867 # we do have a stack so lets get register information 868 saved_state_addr = PluginValue(thobj).GetChildMemberWithName('kernel_stack').GetValueAsUnsigned() + self.kernel_stack_size - self.kernel_thread_state_size 869 regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version) 870 return regs.GetPackedRegisterState() 871 elif self.target_arch.startswith(archARMv7) and int(PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0: 872 #we have stack on the machine.kstackptr. 873 saved_state_addr = PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned() 874 regs.ReadRegisterDataFromKernelStack(saved_state_addr, self.version) 875 return regs.GetPackedRegisterState() 876 elif self.target_arch.startswith(archARMv8) and int(PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsUnsigned()) != 0: 877 saved_state_addr = PluginValue(thobj).GetChildMemberWithName('machine').GetChildMemberWithName('kstackptr').GetValueAsAddress() 878 arm_ctx = PluginValue(self.version.CreateValueFromExpression(None, '(struct arm_kernel_context *) ' + str(saved_state_addr))) 879 arm_ss_addr = arm_ctx.GetChildMemberWithName('ss').GetLoadAddress() 880 regs.ReadRegisterDataFromKernelStack(arm_ss_addr, self.version) 881 return regs.GetPackedRegisterState() 882 elif self.target_arch == archX86_64 or self.target_arch.startswith(archARMv7) or self.target_arch.startswith(archARMv8): 883 regs.ReadRegisterDataFromContinuation( PluginValue(thobj).GetChildMemberWithName('continuation').GetValueAsAddress()) 884 return regs.GetPackedRegisterState() 885 #incase we failed very miserably 886 except KeyboardInterrupt as ke: 887 print("OS Plugin Interrupted during thread register load. \nWARNING:Thread registers and backtraces may not be accurate. for tid = %d" % tid) 888 regs.ResetRegisterValues() 889 print("FATAL ERROR: Failed to get register state for thread id 0x%x " % tid) 890 print(thobj) 891 return regs.GetPackedRegisterState() 892 893 def _strip_thread_tbi(self, th): 894 if not self.kasan_tbi: 895 return th 896 addr = th.GetValueAsAddress() 897 return self.version.CreateValueFromExpression(str(addr), '(struct thread *)' + str(addr))