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