]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/usertaskdebugging/userprocess.py
xnu-4903.221.2.tar.gz
[apple/xnu.git] / tools / lldbmacros / usertaskdebugging / userprocess.py
CommitLineData
39037602
A
1import logging
2import target
3import struct
4
5from xnu import *
6from core.operating_system import Armv8_RegisterSet, Armv7_RegisterSet, I386_RegisterSet, X86_64RegisterSet
7
5ba3f43e 8""" these defines should come from an authoritative header file """
39037602
A
9CPU_TYPE_I386 = 0x00000007
10CPU_TYPE_X86_64 = 0x01000007
11CPU_TYPE_ARM = 0x0000000c
12CPU_TYPE_ARM64 = 0x0100000c
13
39037602 14def GetRegisterSetForCPU(cputype, subtype):
d9a64523 15 if cputype == CPU_TYPE_ARM64:
5ba3f43e
A
16 retval = Armv8_RegisterSet
17 elif cputype == CPU_TYPE_ARM:
18 retval = Armv7_RegisterSet
39037602
A
19 elif cputype == CPU_TYPE_I386:
20 retval = I386_RegisterSet
5ba3f43e
A
21 elif cputype == CPU_TYPE_X86_64:
22 retval = X86_64RegisterSet
23
24 """ crash if unknown cputype """
39037602
A
25
26 return retval.register_info['registers']
27
28
29class UserThreadObject(object):
30 """representation of userspace thread"""
d9a64523 31 def __init__(self, thr_obj, cputype, cpusubtype, is_kern_64bit):
39037602
A
32 super(UserThreadObject, self).__init__()
33 self.thread = thr_obj
34 self.registerset = GetRegisterSetForCPU(cputype, cpusubtype)
35 self.thread_id = unsigned(self.thread.thread_id)
36 self.is64Bit = bool(cputype & 0x01000000)
39037602
A
37
38 if self.is64Bit:
39 if cputype == CPU_TYPE_X86_64:
40 self.reg_type = "x86_64"
41 self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_64
42 if cputype == CPU_TYPE_ARM64:
43 self.reg_type = "arm64"
44 self.saved_state = self.thread.machine.upcb.uss.ss_64
45 else:
46 if cputype == CPU_TYPE_I386:
47 self.reg_type = "i386"
48 self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_32
49 if cputype == CPU_TYPE_ARM:
50 self.reg_type = "arm"
d9a64523 51 if not is_kern_64bit:
39037602
A
52 self.saved_state = self.thread.machine.PcbData
53 else:
54 self.saved_state = self.thread.machine.contextData.ss.uss.ss_32
d9a64523
A
55
56 logging.debug("created thread id 0x%x of type %s, is_kern_64bit 0x%x cputype 0x%x"
57 % (self.thread_id, self.reg_type, is_kern_64bit, cputype))
39037602
A
58
59 def getRegisterValueByName(self, name):
60 if self.reg_type == 'arm64':
61 if name in ('x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18', 'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27', 'x28'):
62 return unsigned(getattr(self.saved_state, 'x')[int(name.strip('x'))])
63
64 return unsigned(getattr(self.saved_state, name))
65
66 if self.reg_type == "x86_64":
67 if name in ('rip', 'rflags', 'cs', 'rsp', 'cpu'):
68 return unsigned(getattr(self.saved_state.isf, name))
69 return unsigned(getattr(self.saved_state, name))
70
71 if self.reg_type == "arm":
72 if name in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'):
73 retval = unsigned(getattr(self.saved_state, 'r')[int(name.strip('r'))])
74 else:
75 retval = unsigned(getattr(self.saved_state, name))
76 return retval
77
78 #TODO for i386
79
80 def getName(self):
81 return str(self.thread_id)
82
83 def getRegisterData(self, reg_num):
84 """ returns None if there is error """
85 if reg_num < 0 or reg_num >= len(self.registerset):
86 logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, self.thread_id))
87 return None
88 return self.getRegisterValueByName(self.registerset[reg_num]['name'])
89
90
91class UserProcess(target.Process):
92 """ Represent a user process and thread states """
93 def __init__(self, task):
94 self.task = task
95 self.proc = Cast(task.bsd_info, 'proc_t')
96 dataregisters64bit = False
97 ptrsize = 4
98
99 if task.t_flags & 0x1:
100 ptrsize = 8
101 if task.t_flags & 0x2:
d9a64523 102 dataregisters64bit = True
39037602 103
d9a64523
A
104 is_kern_64bit = kern.arch in ['x86_64', 'x86_64h', 'arm64'
105 ]
5ba3f43e 106
d9a64523
A
107 self.cputype = unsigned(self.proc.p_cputype)
108 self.cpusubtype = unsigned(self.proc.p_cpusubtype)
39037602 109
d9a64523 110 super(UserProcess, self).__init__(self.cputype, self.cpusubtype, ptrsize)
39037602
A
111
112 self.hinfo['ostype'] = 'macosx'
d9a64523 113 if self.cputype != CPU_TYPE_X86_64 and self.cputype != CPU_TYPE_I386:
39037602
A
114 self.hinfo['ostype'] = 'ios'
115
d9a64523 116 self.registerset = GetRegisterSetForCPU(self.cputype, self.cpusubtype)
39037602
A
117 logging.debug("process %s is64bit: %d ptrsize: %d cputype: %d cpusubtype:%d",
118 hex(self.proc), int(dataregisters64bit), ptrsize,
119 self.cputype, self.cpusubtype
120 )
121 self.threads = {}
122 self.threads_ids_list = []
123 logging.debug("iterating over threads in process")
124 for thval in IterateQueue(task.threads, 'thread *', 'task_threads'):
d9a64523 125 self.threads[unsigned(thval.thread_id)] = UserThreadObject(thval, self.cputype, self.cpusubtype, is_kern_64bit)
39037602
A
126 self.threads_ids_list.append(unsigned(thval.thread_id))
127
128 def getRegisterDataForThread(self, th_id, reg_num):
129 if th_id not in self.threads:
130 logging.critical("0x%x thread id is not found in this task")
131 return ''
132 if reg_num < 0 or reg_num >= len(self.registerset):
133 logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, th_id))
134 return ''
135 value = self.threads[th_id].getRegisterData(reg_num)
136 return self.encodeRegisterData(value, bytesize=self.registerset[reg_num]['bitsize']/8)
137
138 def getRegisterCombinedDataForThread(self, th_id):
139 if th_id not in self.threads:
140 logging.critical("0x%x thread id is not found in this task" % th_id)
141 return ''
142 cur_thread = self.threads[th_id]
143 retval = 'thread:%s;name:%s;' % (self.encodeThreadID(th_id), cur_thread.getName())
144 pos = 0
145 for rinfo in self.registerset:
146 name = rinfo['name']
147 format = "%02x:%s;"
148 value = cur_thread.getRegisterValueByName(name)
149 value_endian_correct_str = self.encodeRegisterData(value, bytesize=(rinfo['bitsize']/8))
150 retval += format % (pos, value_endian_correct_str)
151 pos += 1
152 return retval
153
154 def getThreadStopInfo(self, th_id):
155 if th_id not in self.threads:
156 logging.critical("0x%x thread id is not found in this task")
157 return ''
158 return 'T02' + self.getRegisterCombinedDataForThread(th_id) + 'threads:' + self.getThreadsInfo()+';'
159
160 def getRegisterInfo(self, regnum):
161 #something similar to
162 #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;"
163 if regnum > len(self.registerset):
164 logging.debug("No register_info for number %d." % regnum)
165 return 'E45'
166
167 rinfo = self.registerset[regnum]
168 retval = ''
169 for i in rinfo.keys():
170 i_val = str(rinfo[i])
171 if i == 'set':
172 i_val = 'General Purpose Registers'
173 retval += '%s:%s;' % (str(i), i_val)
174
175 return retval
176
177 def getProcessInfo(self):
178 retval = ''
179 #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;
180 #ostype:macosx;vendor:apple;endian:little;ptrsize:8;
181 pinfo = {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'}
182 pinfo['pid'] = "%x" % (GetProcPIDForTask(self.task))
183 pinfo['parent-pid'] = "%x" % (unsigned(self.proc.p_ppid))
184 pinfo['ptrsize'] = str(self.ptrsize)
185 pinfo['ostype'] = 'macosx'
186 pinfo['cputype'] = "%x" % self.cputype
187 pinfo['cpusubtype'] = "%x" % self.cpusubtype
188 pinfo['real-uid'] = "%x" % (unsigned(self.proc.p_ruid))
189 pinfo['real-gid'] = "%x" % (unsigned(self.proc.p_rgid))
190 if str(kern.arch).find('arm') >= 0:
191 pinfo['ostype'] = 'ios'
192 for i in pinfo.keys():
193 i_val = str(pinfo[i])
194 retval += '%s:%s;' % (str(i), i_val)
195 return retval
196
197 def readMemory(self, address, size):
198 data = GetUserDataAsString(self.task, address, size)
199 if not data:
200 logging.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self.task, address, size))
201 return self.encodeByteString(data)
202
203 def getSharedLibInfoAddress(self):
204 return unsigned(self.task.all_image_info_addr)