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