]>
Commit | Line | Data |
---|---|---|
d9a64523 A |
1 | |
2 | """ Please make sure you read the README COMPLETELY BEFORE reading anything below. | |
3 | It is very critical that you read coding guidelines in Section E in README file. | |
4 | """ | |
5 | ||
6 | from xnu import * | |
7 | from utils import * | |
8 | from string import * | |
9 | ||
10 | import xnudefines | |
11 | ||
12 | def IterateProcChannels(proc): | |
13 | """ Iterate through all channels in the given process | |
14 | ||
15 | params: | |
16 | proc - the proc object | |
17 | returns: nothing, this is meant to be used as a generator function | |
18 | kc - yields each kern_channel in the process | |
19 | """ | |
20 | ||
21 | proc_filedesc = proc.p_fd | |
22 | proc_lastfile = unsigned(proc_filedesc.fd_lastfile) | |
23 | proc_ofiles = proc_filedesc.fd_ofiles | |
24 | ||
25 | count = 0 | |
26 | while count <= proc_lastfile: | |
27 | if unsigned(proc_ofiles[count]) != 0: | |
28 | proc_fd_fglob = proc_ofiles[count].f_fglob | |
29 | if (unsigned(proc_fd_fglob.fg_ops.fo_type) == 10): | |
30 | yield Cast(proc_fd_fglob.fg_data, 'kern_channel *') | |
31 | count += 1 | |
32 | ||
33 | def IterateKernChannelRings(kc, kind): | |
34 | """ Iterate through all rings on a given channel | |
35 | """ | |
36 | ||
37 | NR_RX = 0 | |
38 | NR_TX = 1 | |
39 | NR_A = 2 | |
40 | NR_F = 3 | |
41 | ||
42 | if kind == NR_RX: | |
43 | rings = kc.ch_na.na_rx_rings | |
44 | elif kind == NR_TX : | |
45 | rings = kc.ch_na.na_tx_rings | |
46 | elif kind == NR_A : | |
47 | rings = kc.ch_na.na_alloc_rings | |
48 | else : | |
49 | rings = kc.ch_na.na_free_rings | |
50 | ||
51 | # note that ch_last is actually one greater than the last | |
52 | # as per the comment in ch_connect | |
53 | for i in xrange(kc.ch_first[kind], kc.ch_last[kind]): | |
54 | yield addressof(rings[i]) | |
55 | ||
56 | # Note this is broken if you have type summaries enabled | |
57 | # because we are summarizing the pointer to the structure | |
58 | # and not the structure itself. Unfortunately, that's | |
59 | # the pattern used elsewhere. | |
60 | # Trying to actually use the type summary will blow up | |
61 | # because it has a linked list pointer to itself | |
62 | # | |
63 | @lldb_type_summary(['kern_channel_t', 'kern_channel *']) | |
64 | @header('{:<20s} {:<36s}'.format('kern_channel', 'uuid')) | |
65 | def GetKernChannelSummary(kc): | |
66 | """ Summarizes a kern_channel and related information | |
67 | ||
68 | returns: str - summary of kern_channel | |
69 | """ | |
70 | ||
71 | format_string = '{o: <#020x} {u: <36s}' | |
72 | return format_string.format( | |
73 | o=kc, | |
74 | u=GetUUIDSummary(kc.ch_info.cinfo_ch_id)) | |
75 | ||
76 | @lldb_type_summary(['__kern_channel_ring *']) | |
77 | @header('{:<20s} {:<65s} {:>10s} | {:<5s} {:<5s} | {:<5s} {:<5s} {:<5s} | {:<5s} {:<5s} {:<5s}'.format( | |
78 | 'kernchannelring', 'name', 'flags', 'kc', 'kt', 'rc', 'rh', 'rt', 'c', 'h', 't')) | |
79 | def GetKernChannelRingSummary(kring): | |
80 | """ Summarizes a __kern_channel_ring and related information | |
81 | ||
82 | returns: str - summary of kern_channel_ring | |
83 | """ | |
84 | ||
85 | format_string = '{o: <#020x} "{name: <63s}" {flags: >#010x} | {kh: <5d} {kt: <5d} | {rh: <5d} {rt: <5d} | {h: <5d} {t: <5d}' | |
86 | return format_string.format( | |
87 | o=kring, | |
88 | name=kring.ckr_name, | |
89 | flags=kring.ckr_flags, | |
90 | kh=kring.ckr_khead, | |
91 | kt=kring.ckr_ktail, | |
92 | rh=kring.ckr_rhead, | |
93 | rt=kring.ckr_rtail, | |
94 | h=kring.ckr_ring.ring_head, | |
95 | t=kring.ckr_ring.ring_tail) | |
96 | ||
97 | @lldb_command('showprocchannels') | |
98 | def ShowProcChannels(cmd_args=None): | |
99 | """ Show the skywalk channels for a given process. | |
100 | ||
101 | usage: showprocchannels <proc_t> | |
102 | """ | |
103 | ||
104 | if not cmd_args: | |
105 | raise ArgumentError('missing struct proc * argument') | |
106 | ||
107 | proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t') | |
108 | ||
109 | print GetKernChannelSummary.header | |
110 | for kc in IterateProcChannels(proc): | |
111 | print GetKernChannelSummary(kc) | |
112 | ||
113 | @lldb_command('showchannelrings') | |
114 | def ShowChannelRings(cmd_args=None): | |
115 | """ Show the skywalk rings for a given channel. | |
116 | ||
117 | usage: showchannelrings <struct kern_channel *> | |
118 | """ | |
119 | ||
120 | if not cmd_args: | |
121 | raise ArgumentError('missing struct kern_channel * argument') | |
122 | ||
123 | kc = kern.GetValueFromAddress(cmd_args[0], 'kern_channel *') | |
124 | ||
125 | print "RX rings:" | |
126 | print GetKernChannelRingSummary.header | |
127 | for ring in IterateKernChannelRings(kc, 0) : | |
128 | print GetKernChannelRingSummary(ring) | |
129 | ||
130 | print "TX rings:" | |
131 | print GetKernChannelRingSummary.header | |
132 | for ring in IterateKernChannelRings(kc, 1) : | |
133 | print GetKernChannelRingSummary(ring) | |
134 | ||
135 | print "ALLOC rings:" | |
136 | print GetKernChannelRingSummary.header | |
137 | for ring in IterateKernChannelRings(kc, 2) : | |
138 | print GetKernChannelRingSummary(ring) | |
139 | ||
140 | print "FREE rings:" | |
141 | print GetKernChannelRingSummary.header | |
142 | for ring in IterateKernChannelRings(kc, 3) : | |
143 | print GetKernChannelRingSummary(ring) | |
144 | ||
145 | def SkmemCacheModeAsString(mode) : | |
146 | out_string = "" | |
147 | SKM_MODE_NOCACHE = 0x1 | |
148 | SKM_MODE_AUDIT = 0x2 | |
149 | ||
150 | if (mode & SKM_MODE_NOCACHE) : | |
151 | out_string += "n" | |
152 | else : | |
153 | out_string += "-" | |
154 | if (mode & SKM_MODE_AUDIT) : | |
155 | out_string += "a" | |
156 | else : | |
157 | out_string += "-" | |
158 | ||
159 | return out_string | |
160 | ||
161 | @lldb_command('showskmemcache') | |
162 | def ShowSkmemCache(cmd_args=None) : | |
163 | """ Show the global list of skmem caches | |
164 | """ | |
165 | ||
166 | format_string = "{:<4s} {:<18s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<s}" | |
167 | print format_string.format("", "ADDR", "BUFI", "BUFM", "RESC", "SLCR", "SLDE", "SLAL", "SLFR", "DECO", "MODE", "NAME") | |
168 | ||
169 | i = 1 | |
170 | skmhead = kern.globals.skmem_cache_head | |
171 | ||
172 | for skm in IterateTAILQ_HEAD(skmhead, "skm_link") : | |
173 | format_string = "{:>4d}: 0x{:<08x} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4s} \"{:<s}\"" | |
174 | print format_string.format(i, skm, skm.skm_bufinuse, skm.skm_bufmax, skm.skm_rescale, skm.skm_sl_create, skm.skm_sl_destroy, skm.skm_sl_alloc, skm.skm_sl_free, skm.skm_depot_contention, SkmemCacheModeAsString(skm.skm_mode), str(skm.skm_name)) | |
175 | i += 1 | |
176 | ||
177 | @lldb_command('showskmemslab') | |
178 | def ShowBufCtl(cmd_args=None) : | |
179 | """ Show slabs and bufctls of a skmem cache | |
180 | """ | |
181 | ||
182 | if (cmd_args == None or len(cmd_args) == 0) : | |
183 | print "Missing argument 0 (skmem_cache address)." | |
184 | return | |
185 | ||
186 | skm = kern.GetValueFromAddress(cmd_args[0], 'skmem_cache *') | |
187 | ||
188 | for slab in IterateTAILQ_HEAD(skm.skm_sl_partial, "sl_link") : | |
189 | format_string = "{:<08x} {:<4d} 0x{:<08x} 0x{:08x}" | |
190 | print format_string.format(slab, slab.sl_refcnt, slab.sl_base, slab.sl_basem) | |
191 | ||
192 | for slab in IterateTAILQ_HEAD(skm.skm_sl_empty, "sl_link") : | |
193 | format_string = "{:<08x} {:<4d} 0x{:<08x} 0x{:08x}" | |
194 | print format_string.format(slab, slab.sl_refcnt, slab.sl_base, slab.sl_basem) | |
195 | ||
196 | def SkmemArenaTypeAsString(type) : | |
197 | out_string = "" | |
198 | SKMEM_ARENA_TYPE_NEXUS = 0 | |
199 | SKMEM_ARENA_TYPE_NECP = 1 | |
200 | SKMEM_ARENA_TYPE_SYSTEM = 2 | |
201 | ||
202 | if (type == SKMEM_ARENA_TYPE_NEXUS) : | |
203 | out_string += "NEXUS" | |
204 | elif (type == SKMEM_ARENA_TYPE_NECP) : | |
205 | out_string += "NECP" | |
206 | elif (type == SKMEM_ARENA_TYPE_SYSTEM) : | |
207 | out_string += "SYSTEM" | |
208 | else : | |
209 | out_string += "?" | |
210 | ||
211 | return out_string | |
212 | ||
213 | @lldb_command('showskmemarena') | |
214 | def ShowSkmemArena(cmd_args=None) : | |
215 | """ Show the global list of skmem arenas | |
216 | """ | |
217 | ||
218 | i = 1 | |
219 | arhead = kern.globals.skmem_arena_head | |
220 | ||
221 | for ar in IterateTAILQ_HEAD(arhead, "ar_link") : | |
222 | format_string = "{:>4d}: 0x{:<08x} {:<6s} {:>5d} KB \"{:<s}\"" | |
223 | print format_string.format(i, ar, SkmemArenaTypeAsString(ar.ar_type), ar.ar_mapsize >> 10, str(ar.ar_name)) | |
224 | i += 1 | |
225 | ||
226 | @lldb_command('showskmemregion') | |
227 | def ShowSkmemRegion(cmd_args=None) : | |
228 | """ Show the global list of skmem regions | |
229 | """ | |
230 | ||
231 | i = 1 | |
232 | skrhead = kern.globals.skmem_region_head | |
233 | ||
234 | for skr in IterateTAILQ_HEAD(skrhead, "skr_link") : | |
235 | format_string = "{:>4d}: 0x{:<08x} \"{:<s}\"" | |
236 | print format_string.format(i, skr, str(skr.skr_name)) | |
237 | i += 1 | |
238 | ||
239 | @lldb_command('showchannelupphash') | |
240 | def ShowChannelUppHash(cmd_args=None) : | |
241 | """ Show channel user packet pool hash chain | |
242 | """ | |
243 | ||
244 | if (cmd_args == None or len(cmd_args) == 0) : | |
245 | print "Missing argument 0 (skmem_cache address)." | |
246 | return | |
247 | ||
248 | ch = kern.GetValueFromAddress(cmd_args[0], 'kern_channel *') | |
249 | KERN_CHANNEL_UPP_HTBL_SIZE = 256 | |
250 | ||
251 | for i in range(KERN_CHANNEL_UPP_HTBL_SIZE) : | |
252 | bkt = addressof(ch.ch_upp_hash_table[i]) | |
253 | format_string = "{:>4d} 0x{:<08x}" | |
254 | print format_string.format(i, bkt) | |
255 | for kqum in IterateListEntry(bkt.upp_head, 'struct __kern_quantum *', | |
256 | 'qum_upp_link', list_prefix='s') : | |
257 | format_string = "0x{:<08x}" | |
258 | print format_string.format(kqum) | |
259 | ||
260 | @lldb_type_summary(['struct ns *']) | |
261 | @header('{:<20s} {:<5s} {:<48s} {:<4s}'.format('ns', 'proto', 'addr', 'nreservations')) | |
262 | def GetStructNsSummary(ns): | |
263 | """ Summarizes a struct ns from the netns | |
264 | ||
265 | returns: str - summary of struct ns | |
266 | """ | |
267 | ||
268 | if (ns.ns_proto == IPPROTO_TCP): | |
269 | proto = "tcp" | |
270 | elif (ns.ns_proto == IPPROTO_UDP): | |
271 | proto = "udp" | |
272 | else: | |
273 | proto = str(ns.ns_proto) | |
274 | ||
275 | if (ns.ns_addr_len == sizeof('struct in_addr')): | |
276 | addr = GetInAddrAsString(addressof(ns.ns_inaddr)) | |
277 | elif (ns.ns_addr_len == sizeof('struct in6_addr')): | |
278 | addr = GetIn6AddrAsString(ns.ns_in6addr.__u6_addr.__u6_addr8) | |
279 | else: | |
280 | addr = str(ns_addr) + " bad len {:u}".format(ns.ns_addr_len) | |
281 | ||
282 | format_string = '{o:#020x} {p:<5s} {a:<48s} {n:<4d}' | |
283 | ||
284 | """ show ports and refs, one per line | |
285 | """ | |
286 | ports_string = "ports & refs\n" | |
287 | for f in IterateRBTreeEntry(ns.ns_reservations, 'struct ns_reservation *', 'nsr_link'): | |
288 | ports_string += "\t%u" % f.nsr_port | |
289 | ports_string += "\tlisten %d\tskywalk %d\tbsd %d\tpf %d\n" % (f.nsr_refs[0], f.nsr_refs[1], f.nsr_refs[2], f.nsr_refs[3]) | |
290 | """ show just the ports, not refs | |
291 | offs = 0 | |
292 | ports_string = "\nports:\t" | |
293 | for f in IterateRBTreeEntry(ns.ns_reservations, 'struct ns_reservation *', 'nsr_link'): | |
294 | if (len(ports_string)-offs > 70): | |
295 | ports_string += "\n\t" | |
296 | offs = len(ports_string) | |
297 | ports_string += " %u" % f.nsr_port | |
298 | """ | |
299 | ||
300 | return format_string.format( | |
301 | o=ns, | |
302 | p=proto, | |
303 | a=addr, | |
304 | n=ns.ns_n_reservations) + ports_string | |
305 | ||
306 | @lldb_command('shownetns') | |
307 | def ShowNetNS(cmd_args=None): | |
308 | """ Show the netns table | |
309 | """ | |
310 | print"\nnetns_namespaces:" | |
311 | print GetStructNsSummary.header | |
312 | ||
313 | namespaces = kern.globals.netns_namespaces | |
314 | for ns in IterateRBTreeEntry(namespaces, 'struct ns *', 'ns_link'): | |
315 | print GetStructNsSummary(ns) | |
316 | ||
317 | print "\nwild: (these should be duplicated above)" | |
318 | print GetStructNsSummary.header | |
319 | for i in range(0,4): | |
320 | print GetStructNsSummary(kern.globals.netns_global_wild[i]) | |
321 | ||
322 | print "\nnon wild:" | |
323 | print GetStructNsSummary.header | |
324 | for i in range(0,4): | |
325 | print GetStructNsSummary(kern.globals.netns_global_non_wild[i]) | |
326 | ||
327 | ||
328 | @lldb_type_summary(['struct ns_token *']) | |
329 | @header('{:<20s} {:<5s} {:<48s} {:<12s} {:<8s} {:<38s} {:<38s} {:<12s}'.format('nt', 'proto', 'addr', 'port', 'owner', 'ifp', 'parent', 'flags')) | |
330 | def GetNsTokenSummary(nt): | |
331 | """ Summarizes a struct ns from the netns | |
332 | ||
333 | returns: str - summary of struct ns | |
334 | """ | |
335 | ||
336 | if (nt.nt_proto == IPPROTO_TCP): | |
337 | proto = "tcp" | |
338 | elif (nt.nt_proto == IPPROTO_UDP): | |
339 | proto = "udp" | |
340 | else: | |
341 | proto = str(nt.nt_proto) | |
342 | ||
343 | if (nt.nt_addr_len == sizeof('struct in_addr')): | |
344 | addr = GetInAddrAsString(addressof(nt.nt_inaddr)) | |
345 | elif (nt.nt_addr_len == sizeof('struct in6_addr')): | |
346 | addr = GetIn6AddrAsString(nt.nt_in6addr.__u6_addr.__u6_addr8) | |
347 | else: | |
348 | addr = str(nt_addr) + " bad len {:u}".format(nt.nt_addr_len) | |
349 | ||
350 | format_string = '{o:#020x} {p:<5s} {a:<48s} {pt:<12s} {wn:<8s} {ifp:38s} {pa:38s} {f:#012x}' | |
351 | ||
352 | ports = "%u" % nt.nt_port | |
353 | ||
354 | ifp = "(struct ifnet *)" + hex(nt.nt_ifp) | |
355 | ||
356 | if ((nt.nt_flags & 0x7) == 0x00): | |
357 | owner = "LISTENER" | |
358 | parent = "(void *)" + hex(nt.nt_parent) | |
359 | elif ((nt.nt_flags & 0x7) == 0x01): | |
360 | owner = "SKYWALK" | |
361 | parent = "(struct flow_entry *)" + hex(nt.nt_parent_skywalk) | |
362 | elif ((nt.nt_flags & 0x7) == 0x02): # XXX xnudefines? | |
363 | owner = "BSD" | |
364 | parent = "(struct inpcb *)" + hex(nt.nt_parent_bsd) | |
365 | elif ((nt.nt_flags & 0x7) == 0x03): # XXX xnudefines? | |
366 | owner = "PF" | |
367 | parent = "(void *)" + hex(nt.nt_parent) | |
368 | ||
369 | return format_string.format( | |
370 | o=nt, | |
371 | p=proto, | |
372 | a=addr, | |
373 | pt=ports, | |
374 | wn=owner, | |
375 | ifp=ifp, | |
376 | pa=parent, | |
377 | f=nt.nt_flags) | |
378 | ||
379 | @lldb_command("showallnetnstokens") | |
380 | def ShowAllNetNSTokens(cmd_args=None): | |
381 | """ show all netns tokens | |
382 | """ | |
383 | ||
384 | tokenhead = kern.globals.netns_all_tokens | |
385 | print GetNsTokenSummary.header | |
386 | for nt in IterateListEntry(tokenhead, 'struct ns_token *', 'nt_all_link', list_prefix='s'): | |
387 | print GetNsTokenSummary(nt) | |
388 | ||
389 | @lldb_command("shownetnstokens") | |
390 | def ShowNetNSTokens(cmd_args=None): | |
391 | """ show netns tokens attached to an ifp | |
392 | with no args, shows unbound tokens | |
393 | """ | |
394 | ||
395 | if (cmd_args == None or len(cmd_args) == 0): | |
396 | print "No ifp argument provided, showing unbound tokens" | |
397 | tokenhead = kern.globals.netns_unbound_tokens | |
398 | elif len(cmd_args) > 0: | |
399 | ifp = kern.GetValueFromAddress(cmd_args[0], 'ifnet *') | |
400 | print "Showing tokens for ifp %r" % ifp | |
401 | tokenhead = ifp.if_netns_tokens | |
402 | else: | |
403 | print "Missing ifp argument 0 in shownetnstokens" | |
404 | print cmd_args | |
405 | return | |
406 | ||
407 | print GetNsTokenSummary.header | |
408 | for nt in IterateListEntry(tokenhead, 'struct ns_token *', 'nt_ifp_link', list_prefix='s'): | |
409 | print GetNsTokenSummary(nt) | |
410 | ||
411 | def IterateSTAILQ_HEAD(headval, element_name): | |
412 | iter_val = headval.stqh_first | |
413 | while unsigned(iter_val) != 0 : | |
414 | yield iter_val | |
415 | iter_val = iter_val.__getattr__(element_name).stqe_next | |
416 | #end of yield loop | |
417 | ||
418 | @lldb_command("shownexuschannels") | |
419 | def ShowNexusChannels(cmd_args=None): | |
420 | """ show nexus channels | |
421 | """ | |
422 | if (cmd_args == None or len(cmd_args) == 0): | |
423 | print "Missing argument 0 (kern_nexus address)." | |
424 | return | |
425 | ||
426 | nx = kern.GetValueFromAddress(cmd_args[0], 'kern_nexus *') | |
427 | i = 1 | |
428 | ||
429 | format_string = "{:>4s} {:<18s} {:>4s} {:<7s} {:<7s} {:<18s} {:<18s} {:<18s} {:>8s} {:6s} {:<18s} {:>4s} {:s}" | |
430 | print format_string.format("", "addr", "refs", "txrings", "rxrings", "arena", "ioskmap", "mapaddr", "mapsize", "maprdr", "na", "fd", "process") | |
431 | ||
432 | for ch in IterateSTAILQ_HEAD(nx.nx_ch_head, "ch_link"): | |
433 | format_string = "{:>4d}: 0x{:<08x} {:>4d} [{:2d},{:2d}] [{:2d},{:2d}] 0x{:<08x} 0x{:<08x} 0x{:<16x} {:>8d} {:>6d} 0x{:<08x} {:>4d} {:s}({:d})" | |
434 | print format_string.format(i, ch, ch.ch_refcnt, ch.ch_first[0], ch.ch_last[0], ch.ch_first[1], ch.ch_last[1], ch.ch_mmap.ami_arena, ch.ch_mmap.ami_mapref, ch.ch_mmap.ami_mapaddr, ch.ch_mmap.ami_mapsize, ch.ch_mmap.ami_redirect, ch.ch_na, ch.ch_fd, ch.ch_name, ch.ch_pid) | |
435 | i += 1 | |
436 | ||
437 | for ch in IterateSTAILQ_HEAD(nx.nx_ch_nonxref_head, "ch_link"): | |
438 | format_string = "{:>4d}: 0x{:<08x} {:>4d} [{:2d},{:2d}] [{:2d},{:2d}] 0x{:<08x} 0x{:<08x} 0x{:<16x} {:>8d} {:>6d} 0x{:<08x} {:>4d} {:s}({:d})" | |
439 | print format_string.format(i, ch, ch.ch_refcnt, ch.ch_first[0], ch.ch_last[0], ch.ch_first[1], ch.ch_last[1], ch.ch_mmap.ami_arena, ch.ch_mmap.ami_mapref, ch.ch_mmap.ami_mapaddr, ch.ch_mmap.ami_mapsize, ch.ch_mmap.ami_redirect, ch.ch_na, ch.ch_fd, ch.ch_name, ch.ch_pid) | |
440 | i += 1 | |
441 | ||
442 | def IterateProcNECP(proc): | |
443 | """ Iterate through all NECP descriptors in the given process | |
444 | ||
445 | params: | |
446 | proc - the proc object | |
447 | returns: nothing, this is meant to be used as a generator function | |
448 | necp - yields each necp_fd_data in the process | |
449 | """ | |
450 | ||
451 | proc_filedesc = proc.p_fd | |
452 | proc_lastfile = unsigned(proc_filedesc.fd_lastfile) | |
453 | proc_ofiles = proc_filedesc.fd_ofiles | |
454 | ||
455 | count = 0 | |
456 | while count <= proc_lastfile: | |
457 | if unsigned(proc_ofiles[count]) != 0: | |
458 | proc_fd_fglob = proc_ofiles[count].f_fglob | |
459 | if (unsigned(proc_fd_fglob.fg_ops.fo_type) == 9): | |
460 | yield Cast(proc_fd_fglob.fg_data, 'necp_fd_data *') | |
461 | count += 1 | |
462 | ||
463 | def GetNECPClientBitFields(necp): | |
464 | """ Return the bit fields in necp_client as string | |
465 | ||
466 | returns: str - string representation of necp_client bit fields | |
467 | """ | |
468 | ||
469 | bitfields_string = '' | |
470 | if necp.result_read != 0: | |
471 | bitfields_string += 'r' | |
472 | else: | |
473 | bitfields_string += '-' | |
474 | if necp.allow_multiple_flows != 0: | |
475 | bitfields_string += 'm' | |
476 | else: | |
477 | bitfields_string += '-' | |
478 | if necp.background != 0: | |
479 | bitfields_string += 'b' | |
480 | else: | |
481 | bitfields_string += '-' | |
482 | if necp.background_update != 0: | |
483 | bitfields_string += 'B' | |
484 | else: | |
485 | bitfields_string += '-' | |
486 | if necp.platform_binary != 0: | |
487 | bitfields_string += 'p' | |
488 | else: | |
489 | bitfields_string += '-' | |
490 | ||
491 | return bitfields_string | |
492 | ||
493 | def GetNECPFlowBitFields(flow_registration): | |
494 | """ Return the bit fields in necp_client_flow_registration as string | |
495 | ||
496 | returns: str - string representation of necp_client_flow_registration bit fields | |
497 | """ | |
498 | ||
499 | bitfields_string = '' | |
500 | if flow_registration.flow_result_read != 0: | |
501 | bitfields_string += 'r' | |
502 | else: | |
503 | bitfields_string += '-' | |
504 | if flow_registration.defunct != 0: | |
505 | bitfields_string += 'd' | |
506 | else: | |
507 | bitfields_string += '-' | |
508 | ||
509 | return bitfields_string | |
510 | ||
511 | @lldb_type_summary(['necp_fd_data *']) | |
512 | @header('{:<20s} {:<8s}'.format('necp_fd_data', "flags")) | |
513 | def GetNECPSummary(necp): | |
514 | """ Summarizes a necp_fd_data and related information | |
515 | ||
516 | returns: str - summary of necp_fd_data | |
517 | """ | |
518 | ||
519 | format_string = '{o: <#020x} {u:<#08x}' | |
520 | ||
521 | stats_arenas_string = "\n\n\t%-18s %-39s %-4s %-10s\n" % ("stats_arenas", "mmap", "refs", "flags") | |
522 | for sa in IterateListEntry(necp.stats_arena_list, 'struct necp_arena_info *', 'nai_chain'): | |
523 | stats_arenas_string += "\t0x%016x " % sa | |
524 | stats_arenas_string += "[0x%016x-0x%016x) " % (sa.nai_mmap.ami_mapaddr,(sa.nai_mmap.ami_mapaddr+sa.nai_mmap.ami_mapsize)) | |
525 | stats_arenas_string += "%4u " % sa.nai_use_count | |
526 | stats_arenas_string += "0x%08x " % sa.nai_flags | |
527 | stats_arenas_string += "\n" | |
528 | ||
529 | clients_string = "" | |
530 | for c in IterateRBTreeEntry(necp.clients, 'struct necp_client *', 'link'): | |
531 | clients_string += "\n\t%-18s %-36s %-4s %-5s\n" % ("necp_clients", "client_id", "refs", "flags") | |
532 | clients_string += "\t0x%016x " % c | |
533 | clients_string += "%36s " % GetUUIDSummary(c.client_id) | |
534 | clients_string += "%4u " % c.reference_count | |
535 | clients_string += "%5s " % GetNECPClientBitFields(c) | |
536 | count = 0; | |
537 | for f in IterateRBTreeEntry(c.flow_registrations, 'struct necp_client_flow_registration *', 'client_link'): | |
538 | if count == 0: | |
539 | clients_string += "\n\t\t%-18s %-36s %-2s %-18s %-18s %-18s\n" % ("flow_registration", "registraton_id", "flags", "stats_arena", "kstats_obj", "ustats_obj") | |
540 | clients_string += "\t\t0x%016x " % f | |
541 | clients_string += "%36s " % GetUUIDSummary(f.registration_id) | |
542 | clients_string += "%2s " % GetNECPFlowBitFields(f) | |
543 | clients_string += "0x%016x " % f.stats_arena | |
544 | clients_string += "0x%016x " % f.kstats_kaddr | |
545 | clients_string += "0x%016x " % f.ustats_uaddr | |
546 | clients_string += "\n" | |
547 | ||
548 | return format_string.format( | |
549 | o=necp, | |
550 | u=necp.flags) + stats_arenas_string + clients_string | |
551 | ||
552 | @lldb_command('showprocnecp') | |
553 | def ShowProcNECP(cmd_args=None): | |
554 | """ Show NECP descriptors for a given process. | |
555 | ||
556 | usage: showprocnecp <proc_t> | |
557 | """ | |
558 | ||
559 | if not cmd_args: | |
560 | raise ArgumentError('missing struct proc * argument') | |
561 | ||
562 | proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t') | |
563 | ||
564 | print GetNECPSummary.header | |
565 | for kc in IterateProcNECP(proc): | |
566 | print GetNECPSummary(kc) |