]>
Commit | Line | Data |
---|---|---|
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) |