1 """ Please make sure you read the README file COMPLETELY BEFORE reading anything below.
2 It is very critical that you read coding guidelines in Section E in README file.
14 @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
15 def GetTaskIPCSummary(task
):
16 """ Display a task's ipc summary.
18 task : core.value represeting a Task in kernel
20 str - string of ipc info for the task
23 format_string
= "{0: <#020x} {1: <6d} {2: <6d} {3: <10d} {4: <15s}"
24 pval
= Cast(task
.bsd_info
, 'proc *')
25 table_size
= int(task
.itk_space
.is_table_size
)
26 proc_name
= str(pval
.p_comm
)
27 out_string
+= format_string
.format(task
, pval
.p_pid
, task
.thread_count
, table_size
, proc_name
)
30 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s} {5: <20s} {6: <4s}\n".format(
31 "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
32 def PrintPortSummary(port
, show_kmsg_summary
=True, prefix
=""):
33 """ Display a port's summary
35 port : core.value representing a port in the kernel
37 str : string of ipc info for the given port
40 portp
= Cast(port
, 'struct ipc_port *')
41 destspacep
= kern
.GetValueFromAddress(0, 'struct ipc_space *')
42 spacep
= portp
.data
.receiver
43 format_string
= "{0: #019x} {1: #019x} {2: <8s} {3: #011x} {4: <5s} {5: #05x} {6: #019x} {7: <16s}\n"
44 if portp
.ip_object
.io_bits
& 0x80000000:
45 out_string
+= prefix
+ format_string
.format(
46 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
47 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
48 "APort", portp
.ip_object
.io_references
,
49 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
50 GetPortDestProc(portp
))
52 out_string
+= prefix
+ format_string
.format(
53 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
54 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
55 "DPort", portp
.ip_object
.io_references
, unsigned(portp
),
59 kmsgp
= Cast(portp
.ip_messages
.data
.port
.messages
.ikmq_base
, 'ipc_kmsg_t')
61 print prefix
+ GetKMsgSummary
.header
+ prefix
+ GetKMsgSummary(kmsgp
, prefix
)
63 kmsgp
= kmsgp
.ikm_next
64 while (kmsgp
) != (kmsgheadp
):
65 print prefix
+ GetKMsgSummary(kmsgp
, prefix
)
66 kmsgp
= kmsgp
.ikm_next
69 def GetPortDestProc(portp
):
70 """ Display the name and pid of a given port's receiver
72 portp : core.value representing a pointer to a port in the kernel
73 destspacep : core.value representing a pointer to an ipc_space
75 str : string containing receiver's name and pid
77 spacep
= portp
.data
.receiver
79 for tsk
in kern
.tasks
:
80 if tsk
.itk_space
== spacep
:
82 destprocp
= Cast(tsk
.bsd_info
, 'struct proc *')
83 out_str
= "{0:s}({1: <d})".format(destprocp
.p_comm
, destprocp
.p_pid
)
90 @header("{:<20s} {:<28s} {:<12s} {:<8s} {:<6s} {:<19s} {:<26s} {:<26s}\n".format(
91 "", "kmsg", "msgid", "disp", "size", "reply-port", "source", "destination"))
92 def GetKMsgSummary(kmsgp
, prefix_str
=""):
93 """ Display a summary for type ipc_kmsg_t
95 kmsgp : core.value representing the given ipc_kmsg_t struct
97 str : string of summary info for the given ipc_kmsg_t instance
99 kmsghp
= kmsgp
.ikm_header
100 kmsgh
= dereference(kmsghp
)
102 out_string
+= "{0: <20s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
103 ' ', unsigned(kmsgp
), ' '*8, kmsgh
.msgh_id
)
104 prefix_str
= "{0: <20s} ".format(' ') + prefix_str
106 bits
= kmsgh
.msgh_bits
& 0xff
114 disposition
= "rX" # invalid
116 out_string
+= "{0: <2s}".format(disposition
)
120 bits
= (kmsgh
.msgh_bits
& 0xff00) >> 8
129 disposition
= "lX" # invalid
131 out_string
+= "{0: <2s}".format(disposition
)
135 bits
= (kmsgh
.msgh_bits
& 0xff0000) >> 16
144 out_string
+= "{0: <2s}".format(disposition
)
147 if kmsgh
.msgh_bits
& 0x80000000:
148 out_string
+= "{0: <1s}".format("c")
150 out_string
+= "{0: <1s}".format("s")
153 if kmsgh
.msgh_bits
& 0x20000000:
154 out_string
+= "{0: <1s}".format("I")
156 out_string
+= "{0: <1s}".format("-")
159 if kmsgp
.ikm_header
.msgh_remote_port
:
160 dest_proc_name
= GetDestinationProcessFromPort(kmsgp
.ikm_header
.msgh_remote_port
)
162 out_string
+= "{0: ^6d} {1: <#019x} {2: <26s} {3: <26s}\n".format(
163 unsigned(kmsgh
.msgh_size
), unsigned(kmsgh
.msgh_local_port
),
164 GetKMsgSrc(kmsgp
), dest_proc_name
)
166 if kmsgh
.msgh_bits
& 0x80000000:
167 out_string
+= prefix_str
+ "\t" + GetKMsgBody
.header
+ "\n"
168 out_string
+= prefix_str
+ "\t" + GetKMsgBody(kmsgp
, prefix_str
+ "\t") + "\n"
172 @header("{: <20s} {: <20s} {: <10s}".format("descriptor", "address", "size"))
173 def GetMachMsgOOLDescriptorSummary(desc
):
174 """ Returns description for mach_msg_ool_descriptor_t * object
176 format_string
= "{: <#020x} {: <#020x} {: <#010x}"
177 out_string
= format_string
.format(desc
, desc
.address
, desc
.size
)
180 @header("{: <20s} {: <8s} {: <20s} {: <10s} {: <20s}".format("kmsgheader", "size", "body", "ds_count", "dsc_head"))
181 def GetKMsgBody(kmsgp
, prefix_str
=""):
182 """ Routine that prints a complex kmsg's body
184 kmsghp
= kmsgp
.ikm_header
185 kmsgh
= dereference(kmsghp
)
186 format_string
= "{: <#020x} {: <#08x} {: <#020x} {: <#010x} {: <#020x}"
188 body
= Cast(addressof(kmsghp
[1]), 'mach_msg_body_t *')
189 dsc_count
= body
.msgh_descriptor_count
191 dschead
= Cast(addressof(body
[1]), 'mach_msg_descriptor_t *')
192 out_string
+= format_string
.format(kmsghp
, sizeof(dereference(kmsghp
)), body
, unsigned(dsc_count
), dschead
)
194 for i
in range(dsc_count
):
196 out_string
+= "\n" + prefix_str
+ "Descriptor: " + xnudefines
.mach_msg_type_descriptor_strings
[unsigned(dsc
.type.type)]
197 if unsigned(dsc
.type.type) == 0:
200 out_string
+= " name: {: <#20x}".format(p
)
201 elif unsigned(dsc
.type.type) in (1,3):
202 # its OOL DESCRIPTOR or OOL VOLATILE DESCRIPTOR
203 ool
= dsc
.out_of_line
204 out_string
+= " " + GetMachMsgOOLDescriptorSummary(addressof(ool
))
207 def GetKMsgSrc(kmsgp
):
208 """ Routine that prints a kmsg's source process and pid details
210 kmsgp : core.value representing the given ipc_kmsg_t struct
212 str : string containing the name and pid of the kmsg's source proc
214 kmsgsrchp
= Cast(kmsgp
, 'ipc_kmsg_t').ikm_header
215 kmsgpid
= int(Cast(kern
.GetValueFromAddress(unsigned(kmsgsrchp
) + kmsgsrchp
.msgh_size
, 'uint *')[10], 'pid_t'))
217 return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid
), kmsgpid
)
220 def PrintPortSetMembers(space
, setid
, show_kmsg_summary
):
221 """ Print out the members of a given IPC PSet
223 num_entries
= int(space
.is_table_size
)
224 is_tableval
= space
.is_table
225 setid_str
= GetWaitqSetidString(setid
)
227 prefix_str
= "{0:<21s}".format(' '*21)
230 if config
['verbosity'] > vHUMAN
:
234 while idx
< num_entries
:
235 entryval
= GetObjectAtIndexFromArray(is_tableval
, idx
)
236 ie_bits
= unsigned(entryval
.ie_bits
)
237 if not (ie_bits
& 0x00180000):
238 # It's a port entry that's _not_ dead
239 portval
= Cast(entryval
.ie_object
, 'ipc_port_t')
240 waitq
= addressof(portval
.ip_messages
.data
.port
.waitq
)
241 psets
= GetWaitqSets(addressof(portval
.ip_messages
.data
.port
.waitq
))
246 print "{:s}\n{:s}{:s}".format(GetPortDestProc(portval
), prefix_str
, PrintPortSummary
.header
)
247 PrintPortSummary(portval
, show_kmsg_summary
, prefix_str
)
249 sys
.stderr
.write('{:d}/{:d}... \r'.format(idx
, num_entries
))
253 def FindEntryName(obj
, space
):
254 """ Routine to locate a port/ipc_object in an ipc_space
255 and return the name within that space.
260 num_entries
= int(space
.is_table_size
)
261 is_tableval
= space
.is_table
263 while idx
< num_entries
:
264 entry_val
= GetObjectAtIndexFromArray(is_tableval
, idx
)
265 entry_bits
= unsigned(entry_val
.ie_bits
)
267 if (int(entry_bits
) & 0x001f0000) != 0: ## it's a valid entry
268 entry_obj
= unsigned(entry_val
.ie_object
)
269 if entry_obj
== unsigned(obj
):
270 nm
= (idx
<< 8) |
(entry_bits
>> 24)
276 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
277 "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
278 def PrintPortSetSummary(pset
, space
= 0):
279 """ Display summary for a given struct ipc_pset *
281 pset : core.value representing a pset in the kernel
283 str : string of summary information for the given pset
286 show_kmsg_summary
= False
287 if config
['verbosity'] > vHUMAN
:
288 show_kmsg_summary
= True
290 local_name
= FindEntryName(pset
, space
)
292 if pset
.ips_object
.io_bits
& 0x80000000:
293 setid
= pset
.ips_messages
.data
.pset
.setq
.wqset_id
294 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
295 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
297 pset
.ips_object
.io_references
,
301 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
302 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
304 pset
.ips_object
.io_references
,
308 if setid
!= 0 and space
!= 0:
309 PrintPortSetMembers(space
, setid
, show_kmsg_summary
)
315 @lldb_command('showipc')
316 def ShowIPC(cmd_args
=None):
317 """ Routine to print data for the given IPC space
318 Usage: showipc <address of ipc space>
321 print "No arguments passed"
322 print ShowIPC
.__doc
__
324 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
326 print "unknown arguments:", str(cmd_args
)
328 print PrintIPCInformation
.header
329 PrintIPCInformation(ipc
, False, False)
335 @lldb_command('showtaskipc')
336 def ShowTaskIPC(cmd_args
=None):
337 """ Routine to print IPC summary of given task
338 Usage: showtaskipc <address of task>
341 print "No arguments passed"
342 print ShowTaskIPC
.__doc
__
344 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
346 print "unknown arguments:", str(cmd_args
)
348 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
349 pval
= Cast(tval
.bsd_info
, 'proc *')
350 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
351 print GetTaskIPCSummary
.header
352 print GetTaskIPCSummary(tval
)
354 # EndMacro: showtaskipc
358 @lldb_command('showallipc')
359 def ShowAllIPC(cmd_args
=None):
360 """ Routine to print IPC summary of all tasks
364 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
365 pval
= Cast(t
.bsd_info
, 'proc *')
366 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
367 print PrintIPCInformation
.header
368 PrintIPCInformation(t
.itk_space
, False, False) + "\n\n"
370 # EndMacro: showallipc
372 @lldb_command('showipcsummary')
373 def ShowIPCSummary(cmd_args
=None):
374 """ Summarizes the IPC state of all tasks.
375 This is a convenient way to dump some basic clues about IPC messaging. You can use the output to determine
376 tasks that are candidates for further investigation.
378 print GetTaskIPCSummary
.header
380 print GetTaskIPCSummary(t
)
383 def GetKObjectFromPort(portval
):
384 """ Get Kobject description from the port.
385 params: portval - core.value representation of 'ipc_port *' object
386 returns: str - string of kobject information
388 kobject_str
= "{0: <#020x}".format(portval
.kdata
.kobject
)
389 io_bits
= unsigned(portval
.ip_object
.io_bits
)
390 objtype_index
= io_bits
& 0xfff
391 if objtype_index
< len(xnudefines
.kobject_types
) :
392 objtype_str
= xnudefines
.kobject_types
[objtype_index
]
393 if objtype_str
== 'IOKIT_OBJ':
394 iokit_classnm
= GetObjectTypeStr(portval
.kdata
.kobject
)
395 if not iokit_classnm
:
396 iokit_classnm
= "<unknown class>"
398 iokit_classnm
= re
.sub(r
'vtable for ', r
'', iokit_classnm
)
399 desc_str
= "kobject({:s}:{:s})".format(objtype_str
, iokit_classnm
)
401 desc_str
= "kobject({0:s})".format(objtype_str
)
402 if xnudefines
.kobject_types
[objtype_index
] in ('TASK_RESUME', 'TASK'):
403 desc_str
+= " " + GetProcNameForTask(Cast(portval
.kdata
.kobject
, 'task *'))
405 desc_str
= "kobject(UNKNOWN) {:d}".format(objtype_index
)
406 return kobject_str
+ " " + desc_str
408 @static_var('destcache', {})
409 def GetDestinationProcessFromPort(port
):
411 params: port - core.value representation of 'ipc_port *' object
412 returns: str - name of process
415 dest_space
= port
.data
.receiver
417 #update destcache if data is not found
418 if hex(dest_space
) not in GetDestinationProcessFromPort
.destcache
:
420 if hex(t
.itk_space
) == hex(dest_space
):
421 pval
= Cast(t
.bsd_info
, 'proc *')
422 GetDestinationProcessFromPort
.destcache
[hex(dest_space
)] = (t
, pval
)
426 else: found_dest
= True
429 (ftask
, fproc
) = GetDestinationProcessFromPort
.destcache
[hex(dest_space
)]
431 out_str
= "{0:s}({1:d})".format(fproc
.p_comm
, fproc
.p_pid
)
433 out_str
= "task {0: <#020x}".format(ftask
)
438 @header("{0: <20s} {1: <20s}".format("destname", "destination") )
439 def GetPortDestinationSummary(port
):
440 """ Get destination information for a port.
441 params: port - core.value representation of 'ipc_port *' object
442 returns: str - string of info about ports destination
445 format_string
= "{0: <20s} {1: <20s}"
448 ipc_space_kernel
= unsigned(kern
.globals.ipc_space_kernel
)
449 target_spaceval
= port
.data
.receiver
450 if unsigned(target_spaceval
) == ipc_space_kernel
:
451 destname_str
= GetKObjectFromPort(port
)
453 if int(port
.ip_object
.io_bits
) & 0x80000000 :
454 destname_str
= "{0: <#020x}".format(port
.ip_messages
.data
.port
.receiver_name
)
455 destination_str
= GetDestinationProcessFromPort(port
)
457 destname_str
= "{0: <#020x}".format(port
)
458 destination_str
= "inactive-port"
460 out_str
+= format_string
.format(destname_str
, destination_str
)
463 @lldb_type_summary(['ipc_entry_t'])
464 @header("{: <20s} {: <20s} {: <8s} {: <8s} {: <8s} {: <8s} {: <20s} {: <20s}".format("object", "name","rite", "urefs", "nsets", "nmsgs", "destname", "destination"))
465 def GetIPCEntrySummary(entry
, ipc_name
='', rights_filter
=0):
466 """ Get summary of a ipc entry.
468 entry - core.value representing ipc_entry_t in the kernel
469 ipc_name - str of format '0x0123' for display in summary.
471 str - string of ipc entry related information
478 'O' : Send-once right
479 types of notifications:
480 's' : Send-Possible notification armed
481 'd' : Send-Possible notification requested
482 'n' : Dead-Name notification requested
484 'x' : No-Senders notification requested
487 entry_ptr
= int(hex(entry
), 16)
488 format_string
= "{: <#020x} {: <12s} {: <8s} {: <8d} {: <8d} {: <8d} {: <20s} {: <20s}"
493 ie_object
= entry
.ie_object
494 ie_bits
= int(entry
.ie_bits
)
495 urefs
= int(ie_bits
& 0xffff)
498 if ie_bits
& 0x00100000 :
500 elif ie_bits
& 0x00080000:
502 psetval
= Cast(ie_object
, 'ipc_pset *')
503 set_str
= GetWaitqSets(addressof(psetval
.ips_messages
.data
.pset
.setq
.wqset_q
))
507 if ie_bits
& 0x00010000 :
508 if ie_bits
& 0x00020000 :
514 elif ie_bits
& 0x00020000:
517 elif ie_bits
& 0x00040000 :
520 portval
= Cast(ie_object
, 'ipc_port_t')
521 if int(entry
.index
.request
) != 0:
522 requestsval
= portval
.ip_requests
523 sorightval
= requestsval
[int(entry
.index
.request
)].notify
.port
524 soright_ptr
= unsigned(sorightval
)
526 # send-possible armed
527 if soright_ptr
& 0x1 : right_str
+='s'
528 # send-possible requested
529 elif soright_ptr
& 0x2 : right_str
+='d'
530 # dead-name notification requested
531 else : right_str
+='n'
532 # XXX: What does this bit mean?
533 if ie_bits
& 0x00800000 : right_str
+='c'
534 # No-senders notification requested
535 if portval
.ip_nsrequest
!= 0: right_str
+='x'
536 # now show the port destination part
537 destname_str
= GetPortDestinationSummary(Cast(ie_object
, 'ipc_port_t'))
538 # Get the number of sets to which this port belongs
539 set_str
= GetWaitqSets(addressof(portval
.ip_messages
.data
.port
.waitq
))
541 nmsgs
= portval
.ip_messages
.data
.port
.msgcount
542 if rights_filter
== 0 or rights_filter
== right_str
:
543 out_str
= format_string
.format(ie_object
, ipc_name
, right_str
, urefs
, nsets
, nmsgs
, destname_str
, destination_str
)
546 @header("{0: >20s}".format("user bt") )
547 def GetPortUserStack(port
, task
):
548 """ Get UserStack information for the given port & task.
549 params: port - core.value representation of 'ipc_port *' object
550 task - value representing 'task *' object
551 returns: str - string information on port's userstack
554 ie_port_callstack
= port
.ip_callstack
555 ie_port_spares
= port
.ip_spares
[0]
556 proc_val
= Cast(task
.bsd_info
, 'proc *')
557 if ie_port_callstack
[0]:
558 out_str
+= "{: <10x}".format(ie_port_callstack
[0])
560 while count
< 16 and ie_port_callstack
[count
]:
561 out_str
+= ": <10x".format(ie_port_callstack
[count
])
563 if ie_port_spares
!= proc_val
.p_pid
:
564 out_str
+= " ({:<10d})".format(ie_port_spares
)
568 @lldb_type_summary(['ipc_space *'])
569 @header("{0: <20s} {1: <20s} {2: <20s} {3: <8s} {4: <10s} {5: <18s} {6: >8s} {7: <8s}".format('ipc_space', 'is_task', 'is_table', 'flags', 'ports', 'table_next', 'low_mod', 'high_mod'))
570 def PrintIPCInformation(space
, show_entries
=False, show_userstack
=False, rights_filter
=0):
571 """ Provide a summary of the ipc space
574 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#18x} {6: >8d} {7: <8d}"
575 is_tableval
= space
.is_table
576 ports
= int(space
.is_table_size
)
578 is_bits
= int(space
.is_bits
)
579 if (is_bits
& 0x40000000) == 0: flags
+='A'
581 if (is_bits
& 0x20000000) != 0: flags
+='G'
582 print format_string
.format(space
, space
.is_task
, space
.is_table
, flags
, space
.is_table_size
, space
.is_table_next
, space
.is_low_mod
, space
.is_high_mod
)
584 #should show the each individual entries if asked.
585 if show_entries
== True:
586 print "\t" + GetIPCEntrySummary
.header
589 while index
< num_entries
:
590 entryval
= GetObjectAtIndexFromArray(is_tableval
, index
)
591 entry_ie_bits
= unsigned(entryval
.ie_bits
)
592 if (int(entry_ie_bits
) & 0x001f0000 ) != 0:
593 entry_name
= "{0: <#020x}".format( (index
<<8 | entry_ie_bits
>> 24) )
594 entry_str
= GetIPCEntrySummary(entryval
, entry_name
, rights_filter
)
595 if len(entry_str
) > 0:
596 print " \r\t" + entry_str
597 if show_userstack
== True:
598 entryport
= Cast(entryval
.ie_object
, 'ipc_port *')
599 if entryval
.ie_object
and (int(entry_ie_bits
) & 0x00070000) and entryport
.ip_callstack
[0]:
600 print GetPortUserStack
.header
+ GetPortUserStack(entryport
, space
.is_task
)
602 # give some progress indication (this is especially
603 # helpful for tasks with large sets of rights)
604 sys
.stderr
.write(' {:d}/{:d}...\r'.format(index
, num_entries
))
606 #done with showing entries
611 @lldb_command('showrights', 'R:')
612 def ShowRights(cmd_args
=None, cmd_options
={}):
613 """ Routine to print rights information for the given IPC space
614 Usage: showrights [-R rights_type] <address of ipc space>
615 -R rights_type : only display rights matching the string 'rights_type'
622 'O' : Send-once right
623 types of notifications (append to rights type string):
624 's' : Send-Possible notification armed
625 'd' : Send-Possible notification requested
626 'n' : Dead-Name notification requested
628 'x' : No-Senders notification requested
631 print "No arguments passed"
632 print ShowRights
.__doc
__
634 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
636 print "unknown arguments:", str(cmd_args
)
639 if "-R" in cmd_options
:
640 rights_type
= cmd_options
["-R"]
641 print PrintIPCInformation
.header
642 PrintIPCInformation(ipc
, True, False, rights_type
)
644 # EndMacro: showrights
646 @lldb_command('showtaskrights','R:')
647 def ShowTaskRights(cmd_args
=None, cmd_options
={}):
648 """ Routine to ipc rights information for a task
649 Usage: showtaskrights [-R rights_type] <task address>
650 -R rights_type : only display rights matching the string 'rights_type'
657 'O' : Send-once right
658 types of notifications (append to rights type string):
659 's' : Send-Possible notification armed
660 'd' : Send-Possible notification requested
661 'n' : Dead-Name notification requested
663 'x' : No-Senders notification requested
666 print "No arguments passed"
667 print ShowTaskStacksCmdHelper
.__doc
__
669 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
671 print "unknown arguments:", str(cmd_args
)
674 if "-R" in cmd_options
:
675 rights_type
= cmd_options
["-R"]
676 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
677 pval
= Cast(tval
.bsd_info
, 'proc *')
678 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
679 print PrintIPCInformation
.header
680 PrintIPCInformation(tval
.itk_space
, True, False, rights_type
)
682 # Macro: showataskrightsbt
684 @lldb_command('showtaskrightsbt', 'R:')
685 def ShowTaskRightsBt(cmd_args
=None, cmd_options
={}):
686 """ Routine to ipc rights information with userstacks for a task
687 Usage: showtaskrightsbt [-R rights_type] <task address>
688 -R rights_type : only display rights matching the string 'rights_type'
695 'O' : Send-once right
696 types of notifications (append to rights type string):
697 's' : Send-Possible notification armed
698 'd' : Send-Possible notification requested
699 'n' : Dead-Name notification requested
701 'x' : No-Senders notification requested
704 print "No arguments passed"
705 print ShowTaskRightsBt
.__doc
__
707 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
709 print "unknown arguments:", str(cmd_args
)
712 if "-R" in cmd_options
:
713 rights_type
= cmd_options
["-R"]
714 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
715 pval
= Cast(tval
.bsd_info
, 'proc *')
716 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
717 print PrintIPCInformation
.header
718 PrintIPCInformation(tval
.itk_space
, True, True, rights_type
)
720 # EndMacro: showtaskrightsbt
722 # Macro: showallrights
724 @lldb_command('showallrights', 'R:')
725 def ShowAllRights(cmd_args
=None, cmd_options
={}):
726 """ Routine to print rights information for IPC space of all tasks
727 Usage: showallrights [-R rights_type]
728 -R rights_type : only display rights matching the string 'rights_type'
735 'O' : Send-once right
736 types of notifications (append to rights type string):
737 's' : Send-Possible notification armed
738 'd' : Send-Possible notification requested
739 'n' : Dead-Name notification requested
741 'x' : No-Senders notification requested
744 if "-R" in cmd_options
:
745 rights_type
= cmd_options
["-R"]
747 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
748 pval
= Cast(t
.bsd_info
, 'proc *')
749 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
751 print PrintIPCInformation
.header
752 PrintIPCInformation(t
.itk_space
, True, False, rights_type
) + "\n\n"
753 except (KeyboardInterrupt, SystemExit):
756 print "Failed to get IPC information. Do individual showtaskrights <task> to find the error. \n\n"
758 # EndMacro: showallrights
760 # Macro: showpipestats
761 @lldb_command('showpipestats')
762 def ShowPipeStats(cmd_args
=None):
763 """ Display pipes usage information in the kernel
765 print "Number of pipes: {: d}".format(kern
.globals.amountpipes
)
766 print "Memory used by pipes: {:s}".format(sizeof_fmt(int(kern
.globals.amountpipekva
)))
767 print "Max memory allowed for pipes: {:s}".format(sizeof_fmt(int(kern
.globals.maxpipekva
)))
768 # EndMacro: showpipestats
770 # Macro: showtaskbusyports
771 @lldb_command('showtaskbusyports')
772 def ShowTaskBusyPorts(cmd_args
=None):
773 """ Routine to print information about receive rights belonging to this task that
774 have enqueued messages. This is oten a sign of a blocked or hung process
775 Usage: showtaskbusyports <task address>
778 print "No arguments passed. Please pass in the address of a task"
779 print ShowTaskBusyPorts
.__doc
__
781 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
782 PrintTaskBusyPorts(task
)
785 def PrintTaskBusyPorts(task
):
786 """ Prints all busy ports for a given task. ie. all receive rights belonging
787 to this task that have enqueued messages.
789 task : core.value representing a task in kernel
791 str : String containing information about the given task's busy ports
795 while i
< isp
.is_table_size
:
796 iep
= addressof(isp
.is_table
[i
])
797 if iep
.ie_bits
& 0x00020000:
798 port
= Cast(iep
.ie_object
, 'ipc_port_t')
799 if port
.ip_messages
.data
.port
.msgcount
> 0:
800 print PrintPortSummary
.header
801 PrintPortSummary(port
)
804 # EndMacro: showtaskbusyports
806 # Macro: showallbusyports
807 @lldb_command('showallbusyports')
808 def ShowAllBusyPorts(cmd_args
=None):
809 """ Routine to print information about all receive rights on the system that
810 have enqueued messages.
812 task_queue_head
= kern
.globals.tasks
814 for tsk
in kern
.tasks
:
815 PrintTaskBusyPorts(tsk
)
817 # EndMacro: showallbusyports
820 @lldb_command('showport','K')
821 def ShowPort(cmd_args
=None, cmd_options
={}):
822 """ Routine that lists details about a given IPC port
823 Syntax: (lldb) showport 0xaddr
826 if "-K" in cmd_options
:
829 print "Please specify the address of the port whose details you want to print"
830 print ShowPort
.__doc
__
832 port
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_port *')
833 print PrintPortSummary
.header
834 PrintPortSummary(port
, show_kmsgs
)
838 @lldb_command('showmqueue', "S:")
839 def ShowMQueue(cmd_args
=None, cmd_options
={}):
840 """ Routine that lists details about a given mqueue
841 Syntax: (lldb) showmqueue 0xaddr [-S ipc_space]
844 print "Please specify the address of the ipc_mqueue whose details you want to print"
845 print ShowMQueue
.__doc
__
848 if "-S" in cmd_options
:
849 space
= kern
.GetValueFromAddress(cmd_options
["-S"], 'struct ipc_space *')
850 mqueue
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_mqueue *')
851 wq_type
= mqueue
.data
.pset
.setq
.wqset_q
.waitq_type
852 if int(wq_type
) == 3:
853 psetoff
= getfieldoffset('struct ipc_pset', 'ips_messages')
854 pset
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(psetoff
)
855 print PrintPortSetSummary
.header
856 PrintPortSetSummary(kern
.GetValueFromAddress(pset
, 'struct ipc_pset *'), space
)
857 elif int(wq_type
) == 2:
858 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
859 port
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(portoff
)
860 print PrintPortSummary
.header
861 PrintPortSummary(kern
.GetValueFromAddress(port
, 'struct ipc_port *'))
863 print "Invalid mqueue? (waitq type {:d} is invalid)".format(int(wq_type
))
864 # EndMacro: showmqueue
867 @lldb_command('showkmsg')
868 def ShowKMSG(cmd_args
=[]):
869 """ Show detail information about a <ipc_kmsg_t> structure
870 Usage: (lldb) showkmsg <ipc_kmsg_t>
873 raise ArgumentError('Invalid arguments')
874 kmsg
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_kmsg_t')
875 print GetKMsgSummary
.header
876 print GetKMsgSummary(kmsg
)
881 @lldb_command('showpset', "S:")
882 def ShowPSet(cmd_args
=None, cmd_options
={}):
883 """ Routine that prints details for a given ipc_pset *
884 Syntax: (lldb) showpset 0xaddr [-S ipc_space]
887 print "Please specify the address of the pset whose details you want to print"
888 print ShowPSet
.__doc
__
891 if "-S" in cmd_options
:
892 space
= kern
.GetValueFromAddress(cmd_options
["-S"], 'struct ipc_space *')
894 print PrintPortSetSummary
.header
895 PrintPortSetSummary(kern
.GetValueFromAddress(cmd_args
[0], 'ipc_pset *'), space
)
898 # IPC importance inheritance related macros.
900 @lldb_command('showalliits')
901 def ShowAllIITs(cmd_args
=[], cmd_options
={}):
902 """ Development only macro. Show list of all iits allocated in the system. """
904 iit_queue
= kern
.globals.global_iit_alloc_queue
906 print "This debug macro is only available in development or debug kernels"
909 print GetIPCImportantTaskSummary
.header
910 for iit
in IterateQueue(iit_queue
, 'struct ipc_importance_task *', 'iit_allocation'):
911 print GetIPCImportantTaskSummary(iit
)
914 @header("{: <18s} {: <3s} {: <18s} {: <20s} {: <18s} {: <8s}".format("ipc_imp_inherit", "don", "to_task", "proc_name", "from_elem", "depth"))
915 @lldb_type_summary(['ipc_importance_inherit *', 'ipc_importance_inherit_t'])
916 def GetIPCImportanceInheritSummary(iii
):
917 """ describes iii object of type ipc_importance_inherit_t * """
919 fmt
= "{o: <#018x} {don: <3s} {o.iii_to_task.iit_task: <#018x} {task_name: <20s} {o.iii_from_elem: <#018x} {o.iii_depth: <#08x}"
921 if unsigned(iii
.iii_donating
):
923 taskname
= GetProcNameForTask(iii
.iii_to_task
.iit_task
)
924 if hasattr(iii
.iii_to_task
, 'iit_bsd_pid'):
925 taskname
= "({:d}) {:s}".format(iii
.iii_to_task
.iit_bsd_pid
, iii
.iii_to_task
.iit_procname
)
926 out_str
+= fmt
.format(o
=iii
, task_name
= taskname
, don
=donating_str
)
929 @static_var('recursion_count', 0)
930 @header("{: <18s} {: <4s} {: <8s} {: <8s} {: <18s} {: <18s}".format("iie", "type", "refs", "made", "#kmsgs", "#inherits"))
931 @lldb_type_summary(['ipc_importance_elem *'])
932 def GetIPCImportanceElemSummary(iie
):
933 """ describes an ipc_importance_elem * object """
935 if GetIPCImportanceElemSummary
.recursion_count
> 500:
936 GetIPCImportanceElemSummary
.recursion_count
= 0
937 return "Recursion of 500 reached"
940 fmt
= "{: <#018x} {: <4s} {: <8d} {: <8d} {: <#018x} {: <#018x}"
941 if unsigned(iie
.iie_bits
) & 0x80000000:
946 iit
= Cast(iie
, 'struct ipc_importance_task *')
947 inherit_count
= sum(1 for i
in IterateQueue(iit
.iit_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'))
949 refs
= unsigned(iie
.iie_bits
) & 0x7fffffff
950 made_refs
= unsigned(iie
.iie_made
)
951 kmsg_count
= sum(1 for i
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'))
952 out_str
+= fmt
.format(iie
, type_str
, refs
, made_refs
, kmsg_count
, inherit_count
)
953 if config
['verbosity'] > vHUMAN
:
955 out_str
+= "\n\t"+ GetKMsgSummary
.header
956 for k
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'):
957 out_str
+= "\t" + "{: <#018x}".format(k
.ikm_header
.msgh_remote_port
) + ' ' + GetKMsgSummary(k
, "\t").lstrip()
959 if inherit_count
> 0:
960 out_str
+= "\n\t" + GetIPCImportanceInheritSummary
.header
+ "\n"
961 for i
in IterateQueue(iit
.iit_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'):
962 out_str
+= "\t" + GetIPCImportanceInheritSummary(i
) + "\n"
964 if type_str
== "INH":
965 iii
= Cast(iie
, 'struct ipc_importance_inherit *')
966 out_str
+= "Inherit from: " + GetIPCImportanceElemSummary(iii
.iii_from_elem
)
970 @header("{: <18s} {: <18s} {: <20s}".format("iit", "task", "name"))
971 @lldb_type_summary(['ipc_importance_task *'])
972 def GetIPCImportantTaskSummary(iit
):
973 """ iit is a ipc_importance_task value object.
975 fmt
= "{: <#018x} {: <#018x} {: <20s}"
977 pname
= GetProcNameForTask(iit
.iit_task
)
978 if hasattr(iit
, 'iit_bsd_pid'):
979 pname
= "({:d}) {:s}".format(iit
.iit_bsd_pid
, iit
.iit_procname
)
980 out_str
+= fmt
.format(iit
, iit
.iit_task
, pname
)
983 @lldb_command('showallimportancetasks')
984 def ShowIPCImportanceTasks(cmd_args
=[], cmd_options
={}):
985 """ display a list of all tasks with ipc importance information.
986 Usage: (lldb) showallimportancetasks
987 Tip: add "-v" to see detailed information on each kmsg or inherit elems
989 print ' ' + GetIPCImportantTaskSummary
.header
+ ' ' + GetIPCImportanceElemSummary
.header
992 if unsigned(t
.task_imp_base
):
993 s
+= ' ' + GetIPCImportantTaskSummary(t
.task_imp_base
)
994 s
+= ' ' + GetIPCImportanceElemSummary(addressof(t
.task_imp_base
.iit_elem
))
997 @lldb_command('showipcimportance', '')
998 def ShowIPCImportance(cmd_args
=[], cmd_options
={}):
999 """ Describe an importance from <ipc_importance_elem_t> argument.
1000 Usage: (lldb) showimportance <ipc_importance_elem_t>
1003 raise ArgumentError("Please provide valid argument")
1005 elem
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_importance_elem_t')
1006 print GetIPCImportanceElemSummary
.header
1007 print GetIPCImportanceElemSummary(elem
)
1009 @header("{: <18s} {: <10s} {: <18s} {: <18s} {: <8s} {: <5s} {: <5s} {: <5s}".format("ivac", "refs", "port", "tbl", "tblsize", "index", "Grow", "freelist"))
1010 @lldb_type_summary(['ipc_voucher_attr_control *', 'ipc_voucher_attr_control_t'])
1011 def GetIPCVoucherAttrControlSummary(ivac
):
1012 """ describes a voucher attribute control settings """
1014 fmt
= "{c: <#018x} {c.ivac_refs: <10d} {c.ivac_port: <#018x} {c.ivac_table: <#018x} {c.ivac_table_size: <8d} {c.ivac_key_index: <5d} {growing: <5s} {c.ivac_freelist: <5d}"
1017 if unsigned(ivac
) == 0:
1018 return "{: <#018x}".format(ivac
)
1020 if unsigned(ivac
.ivac_is_growing
):
1022 out_str
+= fmt
.format(c
=ivac
, growing
= growing_str
)
1025 @lldb_command('showivac','')
1026 def ShowIPCVoucherAttributeControl(cmd_args
=[], cmd_options
={}):
1027 """ Show summary of voucher attribute contols.
1028 Usage: (lldb) showivac <ipc_voucher_attr_control_t>
1031 raise ArgumentError("Please provide correct arguments.")
1032 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
1033 print GetIPCVoucherAttrControlSummary
.header
1034 print GetIPCVoucherAttrControlSummary(ivac
)
1035 if config
['verbosity'] > vHUMAN
:
1037 last_entry_index
= unsigned(ivac
.ivac_table_size
)
1038 print "index " + GetIPCVoucherAttributeEntrySummary
.header
1039 while cur_entry_index
< last_entry_index
:
1040 print "{: <5d} ".format(cur_entry_index
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[cur_entry_index
]))
1041 cur_entry_index
+= 1
1046 @header("{: <18s} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}".format("ivam", "get_value_fn", "extract_fn", "release_value_fn", "command_fn", "release_fn"))
1047 @lldb_type_summary(['ipc_voucher_attr_manager *', 'ipc_voucher_attr_manager_t'])
1048 def GetIPCVoucherAttrManagerSummary(ivam
):
1049 """ describes a voucher attribute manager settings """
1051 fmt
= "{: <#018x} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}"
1053 if unsigned(ivam
) == 0 :
1054 return "{: <#018x}".format(ivam
)
1056 get_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_get_value
))
1057 extract_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_extract_content
))
1058 release_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release_value
))
1059 command_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_command
))
1060 release_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release
))
1061 out_str
+= fmt
.format(ivam
, get_value_fn
, extract_fn
, release_value_fn
, command_fn
, release_fn
)
1066 @header("{: <18s} {: <10s} {:s} {:s}".format("ivgte", "key", GetIPCVoucherAttrControlSummary
.header
.strip(), GetIPCVoucherAttrManagerSummary
.header
.strip()))
1067 @lldb_type_summary(['ipc_voucher_global_table_element *', 'ipc_voucher_global_table_element_t'])
1068 def GetIPCVoucherGlobalTableElementSummary(ivgte
):
1069 """ describes a ipc_voucher_global_table_element object """
1071 fmt
= "{g: <#018x} {g.ivgte_key: <10d} {ctrl_s:s} {mgr_s:s}"
1072 out_str
+= fmt
.format(g
=ivgte
, ctrl_s
=GetIPCVoucherAttrControlSummary(ivgte
.ivgte_control
), mgr_s
=GetIPCVoucherAttrManagerSummary(ivgte
.ivgte_manager
))
1075 @lldb_command('showglobalvouchertable', '')
1076 def ShowGlobalVoucherTable(cmd_args
=[], cmd_options
={}):
1077 """ show detailed information of all voucher attribute managers registered with vouchers system
1078 Usage: (lldb) showglobalvouchertable
1080 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1081 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1082 print GetIPCVoucherGlobalTableElementSummary
.header
1083 for i
in range(elems
):
1084 elt
= addressof(kern
.globals.iv_global_table
[i
])
1085 print GetIPCVoucherGlobalTableElementSummary(elt
)
1087 # Type summaries for Bag of Bits.
1089 @lldb_type_summary(['user_data_value_element', 'user_data_element_t'])
1090 @header("{0: <20s} {1: <16s} {2: <20s} {3: <20s} {4: <16s} {5: <20s}".format("user_data_ve", "maderefs", "checksum", "hash value", "size", "data"))
1091 def GetBagofBitsElementSummary(data_element
):
1092 """ Summarizes the Bag of Bits element
1093 params: data_element = value of the object of type user_data_value_element_t
1094 returns: String with summary of the type.
1096 format_str
= "{0: <#020x} {1: <16d} {2: <#020x} {3: <#020x} {4: <16d}"
1097 out_string
= format_str
.format(data_element
, unsigned(data_element
.e_made
), data_element
.e_sum
, data_element
.e_hash
, unsigned(data_element
.e_size
))
1100 for i
in range(0, (unsigned(data_element
.e_size
) - 1)):
1101 out_string
+= "{:02x}".format(int(data_element
.e_data
[i
]))
1104 def GetIPCHandleSummary(handle_ptr
):
1105 """ converts a handle value inside a voucher attribute table to ipc element and returns appropriate summary.
1106 params: handle_ptr - uint64 number stored in handle of voucher.
1107 returns: str - string summary of the element held in internal structure
1109 elem
= kern
.GetValueFromAddress(handle_ptr
, 'ipc_importance_elem_t')
1110 if elem
.iie_bits
& 0x80000000 :
1111 iie
= Cast(elem
, 'struct ipc_importance_inherit *')
1112 return GetIPCImportanceInheritSummary(iie
)
1114 iit
= Cast(elem
, 'struct ipc_importance_task *')
1115 return GetIPCImportantTaskSummary(iit
)
1117 def GetATMHandleSummary(handle_ptr
):
1118 """ Convert a handle value to atm value and returns corresponding summary of its fields.
1119 params: handle_ptr - uint64 number stored in handle of voucher
1120 returns: str - summary of atm value
1122 elem
= kern
.GetValueFromAddress(handle_ptr
, 'atm_value *')
1123 return GetATMValueSummary(elem
)
1125 def GetBankHandleSummary(handle_ptr
):
1126 """ converts a handle value inside a voucher attribute table to bank element and returns appropriate summary.
1127 params: handle_ptr - uint64 number stored in handle of voucher.
1128 returns: str - summary of bank element
1130 if handle_ptr
== 1 :
1131 return "Bank task of Current task"
1132 elem
= kern
.GetValueFromAddress(handle_ptr
, 'bank_element_t')
1133 if elem
.be_type
& 1 :
1134 ba
= Cast(elem
, 'struct bank_account *')
1135 return GetBankAccountSummary(ba
)
1137 bt
= Cast(elem
, 'struct bank_task *')
1138 return GetBankTaskSummary(bt
)
1140 def GetBagofBitsHandleSummary(handle_ptr
):
1141 """ Convert a handle value to bag of bits value and returns corresponding summary of its fields.
1142 params: handle_ptr - uint64 number stored in handle of voucher
1143 returns: str - summary of bag of bits element
1145 elem
= kern
.GetValueFromAddress(handle_ptr
, 'user_data_element_t')
1146 return GetBagofBitsElementSummary(elem
)
1148 @static_var('attr_managers',{1: GetATMHandleSummary, 2: GetIPCHandleSummary, 3: GetBankHandleSummary, 7: GetBagofBitsHandleSummary}
)
1149 def GetHandleSummaryForKey(handle_ptr
, key_num
):
1150 """ Get a summary of handle pointer from the voucher attribute manager.
1151 For example key 1 -> ATM and it puts atm_value_t in the handle. So summary of it would be atm value and refs etc.
1152 key 2 -> ipc and it puts either ipc_importance_inherit_t or ipc_important_task_t.
1153 key 3 -> Bank and it puts either bank_task_t or bank_account_t.
1154 key 7 -> Bag of Bits and it puts user_data_element_t in handle. So summary of it would be Bag of Bits content and refs etc.
1156 key_num
= int(key_num
)
1157 if key_num
not in GetHandleSummaryForKey
.attr_managers
:
1158 return "Unknown key %d" % key_num
1159 return GetHandleSummaryForKey
.attr_managers
[key_num
](handle_ptr
)
1162 @header("{: <18s} {: <18s} {: <10s} {: <4s} {: <18s} {: <18s}".format("ivace", "value_handle", "#refs", "rel?", "maderefs", "next_layer"))
1163 @lldb_type_summary(['ivac_entry *', 'ivac_entry_t'])
1164 def GetIPCVoucherAttributeEntrySummary(ivace
, manager_key_num
= 0):
1165 """ Get summary for voucher attribute entry.
1168 fmt
= "{e: <#018x} {e.ivace_value: <#018x} {e.ivace_refs: <10d} {release: <4s} {made_refs: <18s} {next_layer: <18s}"
1174 if unsigned(ivace
.ivace_releasing
):
1176 if unsigned(ivace
.ivace_free
):
1178 if unsigned(ivace
.ivace_layered
):
1179 next_layer
= "{: <#018x}".format(ivace
.ivace_u
.ivaceu_layer
)
1181 made_refs
= "{: <18d}".format(ivace
.ivace_u
.ivaceu_made
)
1183 out_str
+= fmt
.format(e
=ivace
, release
=release_str
, made_refs
=made_refs
, next_layer
=next_layer
)
1184 if config
['verbosity'] > vHUMAN
and manager_key_num
> 0:
1185 out_str
+= " " + GetHandleSummaryForKey(unsigned(ivace
.ivace_value
), manager_key_num
)
1186 if config
['verbosity'] > vHUMAN
:
1187 out_str
+= ' {: <2s} {: <4d} {: <4d}'.format(free_str
, ivace
.ivace_next
, ivace
.ivace_index
)
1190 @lldb_command('showivacfreelist','')
1191 def ShowIVACFreeList(cmd_args
=[], cmd_options
={}):
1192 """ Walk the free list and print every entry in the list.
1193 usage: (lldb) showivacfreelist <ipc_voucher_attr_control_t>
1196 raise ArgumentError('Please provide <ipc_voucher_attr_control_t>')
1197 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
1198 print GetIPCVoucherAttrControlSummary
.header
1199 print GetIPCVoucherAttrControlSummary(ivac
)
1200 if unsigned(ivac
.ivac_freelist
) == 0:
1201 print "ivac table is full"
1203 print "index " + GetIPCVoucherAttributeEntrySummary
.header
1204 next_free
= unsigned(ivac
.ivac_freelist
)
1205 while next_free
!= 0:
1206 print "{: <5d} ".format(next_free
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[next_free
]))
1207 next_free
= unsigned(ivac
.ivac_table
[next_free
].ivace_next
)
1211 @header('{: <18s} {: <8s} {: <18s} {: <18s} {: <18s} {: <18s} {: <18s}'.format("ipc_voucher", "refs", "checksum", "hash", "tbl_size", "table", "voucher_port"))
1212 @lldb_type_summary(['ipc_voucher *', 'ipc_voucher_t'])
1213 def GetIPCVoucherSummary(voucher
, show_entries
=False):
1214 """ describe a voucher from its ipc_voucher * object """
1216 fmt
= "{v: <#018x} {v.iv_refs: <8d} {v.iv_sum: <#018x} {v.iv_hash: <#018x} {v.iv_table_size: <#018x} {v.iv_table: <#018x} {v.iv_port: <#018x}"
1217 out_str
+= fmt
.format(v
= voucher
)
1219 if show_entries
or config
['verbosity'] > vHUMAN
:
1220 elems
= unsigned(voucher
.iv_table_size
)
1221 entries_header_str
= "\n\t" + "{: <5s} {: <3s} {: <16s} {: <30s}".format("index", "key", "value_index", "manager") + " " + GetIPCVoucherAttributeEntrySummary
.header
1222 fmt
= "{: <5d} {: <3d} {: <16d} {: <30s}"
1223 for i
in range(elems
):
1224 voucher_entry_index
= unsigned(voucher
.iv_inline_table
[i
])
1225 if voucher_entry_index
:
1226 s
= fmt
.format(i
, GetVoucherManagerKeyForIndex(i
), voucher_entry_index
, GetVoucherAttributeManagerNameForIndex(i
))
1227 e
= GetVoucherValueHandleFromVoucherForIndex(voucher
, i
)
1229 s
+= " " + GetIPCVoucherAttributeEntrySummary(addressof(e
), GetVoucherManagerKeyForIndex(i
) )
1230 if entries_header_str
:
1231 entries_str
= entries_header_str
1232 entries_header_str
= ''
1233 entries_str
+= "\n\t" + s
1234 if not entries_header_str
:
1235 entries_str
+= "\n\t"
1236 out_str
+= entries_str
1239 def GetVoucherManagerKeyForIndex(idx
):
1240 """ Returns key number for index based on global table. Will raise index error if value is incorrect
1242 return unsigned(kern
.globals.iv_global_table
[idx
].ivgte_key
)
1244 def GetVoucherAttributeManagerForKey(k
):
1245 """ Walks through the iv_global_table and finds the attribute manager name
1246 params: k - int key number of the manager
1247 return: cvalue - the attribute manager object.
1251 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1252 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1253 for i
in range(elems
):
1254 elt
= addressof(kern
.globals.iv_global_table
[i
])
1255 if k
== unsigned(elt
.ivgte_key
):
1256 retval
= elt
.ivgte_manager
1260 def GetVoucherAttributeControllerForKey(k
):
1261 """ Walks through the iv_global_table and finds the attribute controller
1262 params: k - int key number of the manager
1263 return: cvalue - the attribute controller object.
1267 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1268 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1269 for i
in range(elems
):
1270 elt
= addressof(kern
.globals.iv_global_table
[i
])
1271 if k
== unsigned(elt
.ivgte_key
):
1272 retval
= elt
.ivgte_control
1277 def GetVoucherAttributeManagerName(ivam
):
1278 """ find the name of the ivam object
1279 param: ivam - cvalue object of type ipc_voucher_attr_manager_t
1280 returns: str - name of the manager
1282 return kern
.Symbolicate(unsigned(ivam
))
1284 def GetVoucherAttributeManagerNameForIndex(idx
):
1285 """ get voucher attribute manager name for index
1286 return: str - name of the attribute manager object
1288 return GetVoucherAttributeManagerName(GetVoucherAttributeManagerForKey(GetVoucherManagerKeyForIndex(idx
)))
1290 def GetVoucherValueHandleFromVoucherForIndex(voucher
, idx
):
1291 """ traverse the voucher attrs and get value_handle in the voucher attr controls table
1293 voucher - cvalue object of type ipc_voucher_t
1294 idx - int index in the entries for which you wish to get actual handle for
1295 returns: cvalue object of type ivac_entry_t
1296 None if no handle found.
1298 manager_key
= GetVoucherManagerKeyForIndex(idx
)
1299 voucher_num_elems
= unsigned(voucher
.iv_table_size
)
1300 if idx
>= voucher_num_elems
:
1301 debuglog("idx %d is out of range max: %d" % (idx
, voucher_num_elems
))
1303 voucher_entry_value
= unsigned(voucher
.iv_inline_table
[idx
])
1304 debuglog("manager_key %d" % manager_key
)
1305 ivac
= GetVoucherAttributeControllerForKey(manager_key
)
1306 if ivac
is None or unsigned(ivac
) == 0:
1307 debuglog("No voucher attribute controller for idx %d" % idx
)
1310 ivac
= kern
.GetValueFromAddress(unsigned(ivac
), 'ipc_voucher_attr_control_t') # ??? No idea why lldb does not addressof directly
1311 ivace_table
= ivac
.ivac_table
1312 if voucher_entry_value
>= unsigned(ivac
.ivac_table_size
):
1313 print "Failed to get ivace for value %d in table of size %d" % (voucher_entry_value
, unsigned(ivac
.ivac_table_size
))
1315 return ivace_table
[voucher_entry_value
]
1319 @lldb_command('showallvouchers')
1320 def ShowAllVouchers(cmd_args
=[], cmd_options
={}):
1321 """ Display a list of all vouchers in the global voucher hash table
1322 Usage: (lldb) showallvouchers
1324 iv_hash_table
= kern
.globals.ivht_bucket
1325 num_buckets
= sizeof(kern
.globals.ivht_bucket
) / sizeof(kern
.globals.ivht_bucket
[0])
1326 print GetIPCVoucherSummary
.header
1327 for i
in range(num_buckets
):
1328 for v
in IterateQueue(iv_hash_table
[i
], 'ipc_voucher_t', 'iv_hash_link'):
1329 print GetIPCVoucherSummary(v
)
1331 @lldb_command('showvoucher', '')
1332 def ShowVoucher(cmd_args
=[], cmd_options
={}):
1333 """ Describe a voucher from <ipc_voucher_t> argument.
1334 Usage: (lldb) showvoucher <ipc_voucher_t>
1337 raise ArgumentError("Please provide valid argument")
1339 voucher
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_t')
1340 print GetIPCVoucherSummary
.header
1341 print GetIPCVoucherSummary(voucher
, show_entries
=True)
1343 def GetSpaceSendRightEntries(space
, port
):
1344 """ Get entry summaries for all send rights to port address in an IPC space.
1346 space - the IPC space to search for send rights
1347 port_addr - the port address to match, or 0 to get all send rights
1348 returns: an array of IPC entries
1350 entry_table
= space
.is_table
1351 ports
= int(space
.is_table_size
)
1356 entry
= GetObjectAtIndexFromArray(entry_table
, i
)
1358 entry_ie_bits
= unsigned(entry
.ie_bits
)
1359 if (entry_ie_bits
& 0x00010000) != 0 and (not port
or entry
.ie_object
== port
):
1360 entries
.append(entry
)
1365 @lldb_command('showportsendrights')
1366 def ShowPortSendRights(cmd_args
=[], cmd_options
={}):
1367 """ Display a list of send rights across all tasks for a given port.
1368 Usage: (lldb) showportsendrights <ipc_port_t>
1371 raise ArgumentError("no port address provided")
1372 port
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_port *')
1375 for t
in kern
.tasks
:
1376 # Write a progress line. Using stderr avoids automatic newline when
1377 # writing to stdout from lldb. Blank spaces at the end clear out long
1379 sys
.stderr
.write("checking {:s} ({}/{})...{:30s}\r".format(Cast(t
.bsd_info
, 'proc_t').p_name
, i
, len(kern
.tasks
), ''))
1381 entries
= GetSpaceSendRightEntries(t
.itk_space
, port
)
1384 print GetTaskIPCSummary
.header
1385 print GetTaskIPCSummary(t
)
1386 print '\t' + GetIPCEntrySummary
.header
1388 for entry
in entries
:
1389 print "\t" + GetIPCEntrySummary(entry
)
1391 @lldb_command('showtasksuspenders')
1392 def ShowTaskSuspenders(cmd_args
=[], cmd_options
={}):
1393 """ Display the tasks and send rights that are holding a target task suspended.
1394 Usage: (lldb) showtasksuspenders <task_t>
1397 raise ArgumentError("no task address provided")
1398 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1400 if task
.suspend_count
== 0:
1401 print "task {:#x} ({:s}) is not suspended".format(unsigned(task
), Cast(task
.bsd_info
, 'proc_t').p_name
)
1404 # If the task has been suspended by the kernel (potentially by
1405 # kperf, using task_suspend_internal) or a client of task_suspend2
1406 # that does not convert its task suspension token to a port using
1407 # convert_task_suspension_token_to_port, then it's impossible to determine
1408 # which task did the suspension.
1409 port
= task
.itk_resume
1411 print "task {:#x} ({:s}) is suspended but no resume port exists".format(unsigned(task
), Cast(task
.bsd_info
, 'proc_t').p_name
)
1414 return ShowPortSendRights(cmd_args
=[unsigned(port
)], cmd_options
=cmd_options
)