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