]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/kevent.py
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / kevent.py
1 from xnu import *
2 from workqueue import GetWorkqueueThreadRequestSummary
3 from memory import vm_unpack_pointer
4
5 def IterateProcKqueues(proc):
6 """ Iterate through all kqueues in the given process
7
8 params:
9 proc - the proc object
10 returns: nothing, this is meant to be used as a generator function
11 kq - yields each kqueue in the process
12 """
13 for kqf in IterateProcKqfiles(proc):
14 yield kern.GetValueFromAddress(int(kqf), 'struct kqueue *')
15 if int(proc.p_fd.fd_wqkqueue) != 0:
16 yield kern.GetValueFromAddress(int(proc.p_fd.fd_wqkqueue), 'struct kqueue *')
17 for kqwl in IterateProcKqworkloops(proc):
18 yield kern.GetValueFromAddress(int(kqwl), 'struct kqueue *')
19
20 def IterateProcKqfiles(proc):
21 """ Iterate through all kqfiles in the given process
22
23 params:
24 proc - the proc object
25 returns: nothing, this is meant to be used as a generator function
26 kqf - yields each kqfile in the process
27 """
28 filetype_KQUEUE = 5
29
30 proc_filedesc = proc.p_fd
31 proc_lastfile = unsigned(proc_filedesc.fd_lastfile)
32 proc_ofiles = proc_filedesc.fd_ofiles
33 queues = list()
34 count = 0
35
36 if unsigned(proc_ofiles) == 0:
37 return
38
39 while count <= proc_lastfile:
40 if unsigned(proc_ofiles[count]) != 0:
41 proc_fd_flags = proc_ofiles[count].fp_flags
42 proc_fd_fglob = proc_ofiles[count].fp_glob
43 proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type)
44 if proc_fd_ftype == xnudefines.DTYPE_KQUEUE:
45 yield kern.GetValueFromAddress(int(proc_fd_fglob.fg_data), 'struct kqfile *')
46 count += 1
47
48 def IterateProcKqworkloops(proc):
49 """ Iterate through all kqworkloops in the given process
50
51 params:
52 proc - the proc object
53 returns: nothing, this is meant to be used as a generator function
54 kqwl - yields each kqworkloop in the process
55 """
56 proc_filedesc = proc.p_fd
57 if int(proc_filedesc.fd_kqhash) == 0:
58 return
59
60 hash_mask = proc_filedesc.fd_kqhashmask
61 for i in xrange(hash_mask + 1):
62 for kqwl in IterateListEntry(proc_filedesc.fd_kqhash[i], 'struct kqworkloop *', 'kqwl_hashlink'):
63 yield kqwl
64
65 def IterateAllKqueues():
66 """ Iterate through all kqueues in the system
67
68 returns: nothing, this is meant to be used as a generator function
69 kq - yields each kqueue in the system
70 """
71 for t in kern.tasks:
72 proc = unsigned(t.bsd_info)
73 if proc == 0:
74 continue
75 proc = kern.GetValueFromAddress(proc, 'proc_t')
76 for kq in IterateProcKqueues(proc):
77 yield kq
78
79 def IterateProcKnotes(proc):
80 """ Iterate through all knotes in the given process
81
82 params:
83 proc - the proc object
84 returns: nothing, this is meant to be used as a generator function
85 kn - yields each knote in the process
86 """
87 proc_filedesc = proc.p_fd
88
89 if int(proc.p_fd.fd_knlist) != 0:
90 for i in xrange(proc.p_fd.fd_knlistsize):
91 for kn in IterateListEntry(proc.p_fd.fd_knlist[i], 'struct knote *', 'kn_link', list_prefix='s'):
92 yield kn
93 if int(proc.p_fd.fd_knhash) != 0:
94 for i in xrange(proc.p_fd.fd_knhashmask + 1):
95 for kn in IterateListEntry(proc.p_fd.fd_knhash[i], 'struct knote *', 'kn_link', list_prefix='s'):
96 yield kn
97
98 def GetKnoteKqueue(kn):
99 """ Get the kqueue corresponding to a given knote
100
101 params:
102 kn - the knote object
103 returns: kq - the kqueue corresponding to the knote
104 """
105
106 return vm_unpack_pointer(kn.kn_kq_packed, kern.globals.kn_kq_packing_params, 'struct kqueue *')
107
108
109 @lldb_type_summary(['knote *'])
110 @header('{:<20s} {:<20s} {:<10s} {:<20s} {:<20s} {:<30s} {:<10} {:<10} {:<10} {:<20s}'.format('knote', 'ident', 'kev_flags', 'kqueue', 'udata', 'filtops', 'qos_req', 'qos_use', 'qos_ovr', 'status'))
111 def GetKnoteSummary(kn):
112 """ Summarizes a knote and related information
113
114 returns: str - summary of knote
115 """
116 format_string = '{o: <#020x} {o.kn_kevent.kei_ident: <#020x} {o.kn_kevent.kei_flags: <#010x} {kq_ptr: <#020x} {o.kn_kevent.kei_udata: <#020x} {ops_str: <30s} {qos_req: <10s} {qos_use: <10s} {qos_ovr: <10s} {st_str: <20s}'
117 state = unsigned(kn.kn_status)
118 fops_str = kern.Symbolicate(kern.globals.sysfilt_ops[unsigned(kn.kn_kevent.kei_filtid)])
119 qos_index = int(kn.kn_qos_index)
120 if qos_index > 6:
121 qos_req = qos_index
122 else:
123 qos_req = int((kn.kn_kevent.kei_qos & 0x003fff00) >> 8).bit_length()
124 return format_string.format(
125 o=kn,
126 qos_req=xnudefines.thread_qos_short_strings[qos_req],
127 qos_use=xnudefines.thread_qos_short_strings[qos_index],
128 qos_ovr=xnudefines.thread_qos_short_strings[int(kn.kn_qos_override)],
129 st_str=xnudefines.GetStateString(xnudefines.kn_state_strings, state),
130 kq_ptr=int(GetKnoteKqueue(kn)),
131 ops_str=fops_str)
132
133 @lldb_command('showknote', fancy=True)
134 def ShowKnote(cmd_args=None, cmd_options={}, O=None):
135 """ Show information about a knote
136
137 usage: showknote <struct knote *>
138 """
139 if not cmd_args:
140 return O.error('missing struct knote * argument')
141
142 kn = kern.GetValueFromAddress(cmd_args[0], 'struct knote *')
143 with O.table(GetKnoteSummary.header):
144 print GetKnoteSummary(kn)
145
146 def IterateKqueueKnotes(kq):
147 """ Iterate through all knotes of a given kqueue
148
149 params:
150 kq - the kqueue to iterate the knotes of
151 returns: nothing, this is meant to be used as a generator function
152 kn - yields each knote in the kqueue
153 """
154 proc = kq.kq_p
155 for kn in IterateProcKnotes(proc):
156 if unsigned(GetKnoteKqueue(kn)) != unsigned(addressof(kq)):
157 continue
158 yield kn
159
160 kqueue_summary_fmt = '{ptr: <#020x} {o.kq_p: <#020x} {dyn_id: <#020x} {servicer: <#20x} {owner: <#20x} {o.kq_count: <6d} {wqs: <#020x} {st_str: <10s}'
161
162 def GetServicer(req):
163 if req.tr_state in [3, 4]: # [ BINDING , BOUND ]
164 return int(req.tr_thread)
165 return 0
166
167 @lldb_type_summary(['struct kqueue *'])
168 @header('{: <20s} {: <20s} {: <20s} {: <20s} {: <20s} {: <6s} {: <20s} {: <10s}'.format('kqueue', 'process', 'dynamic_id', 'servicer', 'owner', '#evts', 'wqs', 'state'))
169 def GetKqueueSummary(kq):
170 """ Summarize kqueue information
171
172 params:
173 kq - the kqueue object
174 returns: str - summary of kqueue
175 """
176 if kq.kq_state & xnudefines.KQ_WORKLOOP:
177 return GetKqworkloopSummary(kern.GetValueFromAddress(int(kq), 'struct kqworkloop *'))
178 elif kq.kq_state & xnudefines.KQ_WORKQ:
179 return GetKqworkqSummary(kern.GetValueFromAddress(int(kq), 'struct kqworkq *'))
180 else:
181 return GetKqfileSummary(kern.GetValueFromAddress(int(kq), 'struct kqfile *'))
182
183 @lldb_type_summary(['struct kqfile *'])
184 @header(GetKqueueSummary.header)
185 def GetKqfileSummary(kqf):
186 kq = kern.GetValueFromAddress(int(kqf), 'struct kqueue *')
187 state = int(kq.kq_state)
188 return kqueue_summary_fmt.format(
189 o=kq,
190 ptr=int(kq),
191 wqs=int(kq.kq_wqs),
192 dyn_id=0,
193 st_str=xnudefines.GetStateString(xnudefines.kq_state_strings, state),
194 servicer=0,
195 owner=0)
196
197 @lldb_command('showkqfile', fancy=True)
198 def ShowKqfile(cmd_args=None, cmd_options={}, O=None):
199 """ Display information about a kqfile object.
200
201 usage: showkqfile <struct kqfile *>
202 """
203 if len(cmd_args) < 1:
204 return O.error('missing struct kqfile * argument')
205
206 kqf = kern.GetValueFromAddress(cmd_args[0], 'kqfile *')
207
208 with O.table(GetKqfileSummary.header):
209 print GetKqfileSummary(kqf)
210 with O.table(GetKnoteSummary.header):
211 for kn in IterateKqueueKnotes(kqf.kqf_kqueue):
212 print GetKnoteSummary(kn)
213 for kn in IterateTAILQ_HEAD(kqf.kqf_suppressed, 'kn_tqe'):
214 print GetKnoteSummary(kn)
215
216 @lldb_type_summary(['struct kqworkq *'])
217 @header(GetKqueueSummary.header)
218 def GetKqworkqSummary(kqwq):
219 """ Summarize workqueue kqueue information
220
221 params:
222 kqwq - the kqworkq object
223 returns: str - summary of workqueue kqueue
224 """
225 return GetKqfileSummary(kern.GetValueFromAddress(int(kqwq), 'struct kqfile *'))
226
227 @lldb_command('showkqworkq', fancy=True)
228 def ShowKqworkq(cmd_args=None, cmd_options={}, O=None):
229 """ Display summary and knote information about a kqworkq.
230
231 usage: showkqworkq <struct kqworkq *>
232 """
233 if len(cmd_args) < 1:
234 return O.error('missing struct kqworkq * argument')
235
236 kqwq = kern.GetValueFromAddress(cmd_args[0], 'struct kqworkq *')
237 kq = kqwq.kqwq_kqueue
238 with O.table(GetKqueueSummary.header):
239 print GetKqworkqSummary(kqwq)
240
241 with O.table(GetWorkqueueThreadRequestSummary.header):
242 for i in range(1, 8):
243 print GetWorkqueueThreadRequestSummary(kq.kq_p, kqwq.kqwq_request[i])
244
245 with O.table(GetKnoteSummary.header):
246 for kn in IterateKqueueKnotes(kq):
247 print GetKnoteSummary(kn)
248 for i in xrange(0, xnudefines.KQWQ_NBUCKETS):
249 for kn in IterateTAILQ_HEAD(kq.kq_queue[i], 'kn_tqe'):
250 print GetKnoteSummary(kn)
251
252 @lldb_type_summary(['struct kqworkloop *'])
253 @header(GetKqueueSummary.header)
254 def GetKqworkloopSummary(kqwl):
255 """ Summarize workloop kqueue information
256
257 params:
258 kqwl - the kqworkloop object
259 returns: str - summary of workloop kqueue
260 """
261 state = int(kqwl.kqwl_kqueue.kq_state)
262 return kqueue_summary_fmt.format(
263 ptr=int(kqwl),
264 o=kqwl.kqwl_kqueue,
265 wqs=int(kqwl.kqwl_kqueue.kq_wqs),
266 dyn_id=kqwl.kqwl_dynamicid,
267 st_str=xnudefines.GetStateString(xnudefines.kq_state_strings, state),
268 servicer=GetServicer(kqwl.kqwl_request),
269 owner=int(kqwl.kqwl_owner)
270 )
271
272 @lldb_command('showkqworkloop', fancy=True)
273 def ShowKqworkloop(cmd_args=None, cmd_options={}, O=None):
274 """ Display information about a kqworkloop.
275
276 usage: showkqworkloop <struct kqworkloop *>
277 """
278 if len(cmd_args) < 1:
279 return O.error('missing struct kqworkloop * argument')
280
281 kqwl = kern.GetValueFromAddress(cmd_args[0], 'struct kqworkloop *')
282
283 with O.table(GetKqworkloopSummary.header):
284 print GetKqworkloopSummary(kqwl)
285
286 with O.table(GetWorkqueueThreadRequestSummary.header):
287 print GetWorkqueueThreadRequestSummary(kqwl.kqwl_kqueue.kq_p, kqwl.kqwl_request)
288
289 with O.table(GetKnoteSummary.header):
290 for kn in IterateKqueueKnotes(kqwl.kqwl_kqueue):
291 print GetKnoteSummary(kn)
292
293 @lldb_command('showkqueue', fancy=True)
294 def ShowKqueue(cmd_args=None, cmd_options={}, O=None):
295 """ Given a struct kqueue pointer, display the summary of the kqueue
296
297 usage: showkqueue <struct kqueue *>
298 """
299 if not cmd_args:
300 return O.error('missing struct kqueue * argument')
301
302 kq = kern.GetValueFromAddress(cmd_args[0], 'struct kqueue *')
303 if int(kq.kq_state) & xnudefines.KQ_WORKQ:
304 ShowKqworkq(cmd_args, cmd_options, O)
305 elif int(kq.kq_state) & xnudefines.KQ_WORKLOOP:
306 ShowKqworkloop(cmd_args, cmd_options, O)
307 else:
308 ShowKqfile(cmd_args, cmd_options, O)
309
310 @lldb_command('showprocworkqkqueue', fancy=True)
311 def ShowProcWorkqKqueue(cmd_args=None, cmd_options={}, O=None):
312 """ Show the workqueue kqueue for a given process.
313
314 usage: showprocworkqkqueue <proc_t>
315 """
316 if not cmd_args:
317 return O.error('missing struct proc * argument')
318
319 proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t')
320 ShowKqworkq(cmd_args=[str(int(proc.p_fd.fd_wqkqueue))])
321
322 @lldb_command('showprockqueues', fancy=True)
323 def ShowProcKqueues(cmd_args=None, cmd_options={}, O=None):
324 """ Show the kqueues for a given process.
325
326 usage: showprockqueues <proc_t>
327 """
328 if not cmd_args:
329 return O.error('missing struct proc * argument')
330
331 proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t')
332
333 with O.table(GetKqueueSummary.header):
334 for kq in IterateProcKqueues(proc):
335 print GetKqueueSummary(kq)
336
337 @lldb_command('showprocknotes', fancy=True)
338 def ShowProcKnotes(cmd_args=None, cmd_options={}, O=None):
339 """ Show the knotes for a given process.
340
341 usage: showprocknotes <proc_t>
342 """
343
344 if not cmd_args:
345 return O.error('missing struct proc * argument')
346
347 proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t')
348
349 with O.table(GetKnoteSummary.header):
350 for kn in IterateProcKnotes(proc):
351 print GetKnoteSummary(kn)
352
353 @lldb_command('showallkqueues', fancy=True)
354 def ShowAllKqueues(cmd_args=None, cmd_options={}, O=None):
355 """ Display a summary of all the kqueues in the system
356
357 usage: showallkqueues
358 """
359 with O.table(GetKqueueSummary.header):
360 for kq in IterateAllKqueues():
361 print GetKqueueSummary(kq)