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.
10 @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
11 def GetTaskIPCSummary(task
):
12 """ Display a task's ipc summary.
14 task : core.value represeting a Task in kernel
16 str - string of ipc info for the task
19 format_string
= "{0: <#020x} {1: <6d} {2: <6d} {3: <10d} {4: <15s}"
20 pval
= Cast(task
.bsd_info
, 'proc *')
21 table_size
= int(task
.itk_space
.is_table_size
)
22 proc_name
= str(pval
.p_comm
)
23 out_string
+= format_string
.format(task
, pval
.p_pid
, task
.thread_count
, table_size
, proc_name
)
26 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s} {5: <20s} {6: <4s}\n".format(
27 "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
28 def GetPortSummary(port
, show_kmsg_summary
=True, prefix
=""):
29 """ Display a port's summary
31 port : core.value representing a port in the kernel
33 str : string of ipc info for the given port
36 portp
= Cast(port
, 'struct ipc_port *')
37 destspacep
= kern
.GetValueFromAddress(0, 'struct ipc_space *')
38 spacep
= portp
.data
.receiver
39 format_string
= "{0: #019x} {1: #019x} {2: <8s} {3: #011x} {4: <5s} {5: #05x} {6: #019x} {7: <16s}\n"
40 if portp
.ip_object
.io_bits
& 0x80000000:
41 out_string
+= prefix
+ format_string
.format(
42 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
43 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
44 "APort", portp
.ip_object
.io_references
,
45 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
46 GetPortDestProc(portp
))
48 out_string
+= prefix
+ format_string
.format(
49 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
50 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
51 "DPort", portp
.ip_object
.io_references
, unsigned(portp
),
55 kmsgp
= Cast(portp
.ip_messages
.data
.port
.messages
.ikmq_base
, 'ipc_kmsg_t')
56 out_string
+= prefix
+ GetKMsgSummary
.header
+ prefix
+ GetKMsgSummary(kmsgp
)
59 kmsgp
= kmsgp
.ikm_next
60 while (kmsgp
) != (kmsgheadp
):
61 out_string
+= prefix
+ GetKMsgSummary(kmsgp
)
62 kmsgp
= kmsgp
.ikm_next
65 def GetPortDestProc(portp
):
66 """ Display the name and pid of a given port's receiver
68 portp : core.value representing a pointer to a port in the kernel
69 destspacep : core.value representing a pointer to an ipc_space
71 str : string containing receiver's name and pid
73 spacep
= portp
.data
.receiver
75 for tsk
in kern
.tasks
:
76 if tsk
.itk_space
== spacep
:
78 destprocp
= Cast(tsk
.bsd_info
, 'struct proc *')
79 out_str
= "{0:s}({1: <d})".format(destprocp
.p_comm
, destprocp
.p_pid
)
81 out_str
= "task {0: #019x}".format(desttaskp
)
86 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <19s} {6: <6s}\n".format(
87 "dest-port", "kmsg", "msgid", "disp", "size", "reply-port", "source"))
88 def GetKMsgSummary(kmsgp
):
89 """ Display a summary for type ipc_kmsg_t
91 kmsgp : core.value representing the given ipc_kmsg_t struct
93 str : string of summary info for the given ipc_kmsg_t instance
95 kmsghp
= kmsgp
.ikm_header
96 kmsgh
= dereference(kmsghp
)
98 out_string
+= "{0: <19s} {1: #019x} {2: <8s} {3: #011x} ".format(
99 ' '*19, unsigned(kmsgp
), ' '*8, kmsgh
.msgh_id
)
101 if (kmsgh
.msgh_bits
& 0xff) == 19:
102 out_string
+= "{0: <2s}".format("rC")
104 out_string
+= "{0: <2s}".format("rM")
106 if (kmsgh
.msgh_bits
& 0xff00) == (19 << 8):
107 out_string
+= "{0: <2s}".format("lC")
109 out_string
+= "{0: <2s}".format("lM")
110 if kmsgh
.msgh_bits
& 0xf0000000:
111 out_string
+= "{0: <2s}".format("c")
113 out_string
+= "{0: <2s}".format("s")
115 out_string
+= "{0: >5d} {1: #019x} {2: <16s}\n".format(
116 unsigned(kmsgh
.msgh_size
), kmsgh
.msgh_local_port
,
120 def GetKMsgSrc(kmsgp
):
121 """ Routine that prints a kmsg's source process and pid details
123 kmsgp : core.value representing the given ipc_kmsg_t struct
125 str : string containing the name and pid of the kmsg's source proc
127 kmsgsrchp
= Cast(kmsgp
, 'ipc_kmsg_t').ikm_header
128 kmsgpid
= int(Cast(kern
.GetValueFromAddress(unsigned(kmsgsrchp
) + kmsgsrchp
.msgh_size
, 'uint *')[10], 'pid_t'))
130 return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid
), kmsgpid
)
132 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
133 "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
134 def GetPortSetSummary(pset
):
135 """ Display summary for a given struct ipc_pset *
137 pset : core.value representing a pset in the kernel
139 str : string of summary information for the given pset
142 if pset
.ips_object
.io_bits
& 0x80000000:
143 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
144 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
145 pset
.ips_messages
.data
.pset
.local_name
, "ASet",
146 pset
.ips_object
.io_references
,
147 pset
.ips_messages
.data
.pset
.local_name
)
150 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
151 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
152 pset
.ips_messages
.data
.pset
.local_name
, "DSet",
153 pset
.ips_object
.io_references
,
154 pset
.ips_messages
.data
.pset
.local_name
)
157 setlinksp
= addressof(pset
.ips_messages
.data
.pset
.set_queue
.wqs_setlinks
)
158 wql
= Cast(pset
.ips_messages
.data
.pset
.set_queue
.wqs_setlinks
.next
, 'WaitQueueLink *')
159 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
160 prefix_str
= "{0:<21s}".format(' '*21)
161 while unsigned(wql
) != unsigned(Cast(setlinksp
, 'void *')):
162 portp
= kern
.GetValueFromAddress(unsigned(wql
.wql_element
.wqe_queue
) - portoff
, 'ipc_port *')
165 out_str
+= "{0:s}\n{1:s}{2:s}".format(GetPortDestProc(portp
), prefix_str
, GetPortSummary
.header
)
166 out_str
+= GetPortSummary(portp
, False, prefix_str
)
167 wql
= Cast(wql
.wql_setlinks
.next
, 'WaitQueueLink *')
172 @lldb_command('showipc')
173 def ShowIPC(cmd_args
=None):
174 """ Routine to print data for the given IPC space
175 Usage: showipc <address of ipc space>
178 print "No arguments passed"
179 print ShowIPC
.__doc
__
181 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
183 print "unknown arguments:", str(cmd_args
)
185 print GetIPCInformation
.header
186 print GetIPCInformation(ipc
, False, False)
192 @lldb_command('showtaskipc')
193 def ShowTaskIPC(cmd_args
=None):
194 """ Routine to print IPC summary of given task
195 Usage: showtaskipc <address of task>
198 print "No arguments passed"
199 print ShowTaskIPC
.__doc
__
201 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
203 print "unknown arguments:", str(cmd_args
)
205 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
206 pval
= Cast(tval
.bsd_info
, 'proc *')
207 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
208 print GetTaskIPCSummary
.header
209 print GetTaskIPCSummary(tval
)
211 # EndMacro: showtaskipc
215 @lldb_command('showallipc')
216 def ShowAllIPC(cmd_args
=None):
217 """ Routine to print IPC summary of all tasks
221 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
222 pval
= Cast(t
.bsd_info
, 'proc *')
223 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
224 print GetIPCInformation
.header
225 print GetIPCInformation(t
.itk_space
, False, False) + "\n\n"
227 # EndMacro: showallipc
229 @lldb_command('showipcsummary')
230 def ShowIPCSummary(cmd_args
=None):
231 """ Summarizes the IPC state of all tasks.
232 This is a convenient way to dump some basic clues about IPC messaging. You can use the output to determine
233 tasks that are candidates for further investigation.
235 print GetTaskIPCSummary
.header
237 print GetTaskIPCSummary(t
)
240 def GetKObjectFromPort(portval
):
241 """ Get Kobject description from the port.
242 params: portval - core.value representation of 'ipc_port *' object
243 returns: str - string of kobject information
245 kobject_str
= "{0: <#020x}".format(portval
.kdata
.kobject
)
246 io_bits
= unsigned(portval
.ip_object
.io_bits
)
247 objtype_index
= io_bits
& 0xfff
248 if objtype_index
< len(xnudefines
.kobject_types
) :
249 desc_str
= "kobject({0:s})".format(xnudefines
.kobject_types
[objtype_index
])
251 desc_str
= "kobject(UNKNOWN) {:d}".format(objtype_index
)
252 return kobject_str
+ " " + desc_str
254 @static_var('destcache', {})
255 def GetDestinationProcessFromPort(port
):
257 params: port - core.value representation of 'ipc_port *' object
258 returns: str - name of process
261 dest_space
= port
.data
.receiver
263 #update destcache if data is not found
264 if hex(dest_space
) not in GetDestinationProcessFromPort
.destcache
:
266 if hex(t
.itk_space
) == hex(dest_space
):
267 pval
= Cast(t
.bsd_info
, 'proc *')
268 GetDestinationProcessFromPort
.destcache
[hex(dest_space
)] = (t
, pval
)
272 else: found_dest
= True
275 (ftask
, fproc
) = GetDestinationProcessFromPort
.destcache
[hex(dest_space
)]
277 out_str
= "{0:s}({1:d})".format(fproc
.p_comm
, fproc
.p_pid
)
279 out_str
= "task {0: <#020x}".format(ftask
)
284 @header("{0: <20s} {1: <20s}".format("destname", "destination") )
285 def GetPortDestinationSummary(port
):
286 """ Get destination information for a port.
287 params: port - core.value representation of 'ipc_port *' object
288 returns: str - string of info about ports destination
291 format_string
= "{0: <20s} {1: <20s}"
294 ipc_space_kernel
= unsigned(kern
.globals.ipc_space_kernel
)
295 target_spaceval
= port
.data
.receiver
296 if unsigned(target_spaceval
) == ipc_space_kernel
:
297 destname_str
= GetKObjectFromPort(port
)
299 if int(port
.ip_object
.io_bits
) & 0x80000000 :
300 destname_str
= "{0: <#020x}".format(port
.ip_messages
.data
.port
.receiver_name
)
301 destination_str
= GetDestinationProcessFromPort(port
)
303 destname_str
= "{0: <#020x}".format(port
)
304 destination_str
= "inactive-port"
306 out_str
+= format_string
.format(destname_str
, destination_str
)
309 @lldb_type_summary(['ipc_entry_t'])
310 @header("{0: <20s} {1: <20s} {2: <8s} {3: <8s} {4: <20s} {5: <20s}".format("object", "name","rite", "urefs", "destname", "destination"))
311 def GetIPCEntrySummary(entry
, ipc_name
=''):
312 """ Get summary of a ipc entry.
314 entry - core.value representing ipc_entry_t in the kernel
315 ipc_name - str of format '0x0123' for display in summary.
317 str - string of ipc entry related information
320 entry_ptr
= int(hex(entry
), 16)
321 format_string
= "{0: <#020x} {1: <12s} {2: <8s} {3: <8d} {4: <20s} {5: <20s}"
326 ie_object
= entry
.ie_object
327 ie_bits
= int(entry
.ie_bits
)
328 urefs
= int(ie_bits
& 0xffff)
329 if ie_bits
& 0x00100000 :
331 elif ie_bits
& 0x00080000:
334 if ie_bits
& 0x00010000 :
335 if ie_bits
& 0x00020000 :
339 elif ie_bits
& 0x00020000:
341 elif ie_bits
& 0x00040000 :
343 if int(entry
.index
.request
) != 0:
344 portval
= Cast(ie_object
, 'ipc_port_t')
345 requestsval
= portval
.ip_requests
346 sorightval
= requestsval
[int(entry
.index
.request
)].notify
.port
347 soright_ptr
= unsigned(sorightval
)
349 if soright_ptr
& 0x1 : right_str
+='s'
350 elif soright_ptr
& 0x2 : right_str
+='d'
351 else : right_str
+='n'
352 if ie_bits
& 0x00800000 : right_str
+='c'
353 # now show the port destination part
354 destname_str
= GetPortDestinationSummary(Cast(ie_object
, 'ipc_port_t'))
356 out_str
= format_string
.format(ie_object
, ipc_name
, right_str
, urefs
, destname_str
, destination_str
)
359 @header("{0: >20s}".format("user bt") )
360 def GetPortUserStack(port
, task
):
361 """ Get UserStack information for the given port & task.
362 params: port - core.value representation of 'ipc_port *' object
363 task - value representing 'task *' object
364 returns: str - string information on port's userstack
367 ie_port_callstack
= port
.ip_callstack
368 ie_port_spares
= port
.ip_spares
[0]
369 proc_val
= Cast(task
.bsd_info
, 'proc *')
370 if ie_port_callstack
[0]:
371 out_str
+= "{: <10x}".format(ie_port_callstack
[0])
373 while count
< 16 and ie_port_callstack
[count
]:
374 out_str
+= ": <10x".format(ie_port_callstack
[count
])
376 if ie_port_spares
!= proc_val
.p_pid
:
377 out_str
+= " ({:<10d})".format(ie_port_spares
)
381 @lldb_type_summary(['ipc_space *'])
382 @header("{0: <20s} {1: <20s} {2: <20s} {3: <8s} {4: <10s} {5: <16s} {6: <10s} {7: <7s}".format('ipc_space', 'is_task', 'is_table', 'flags', 'ports', 'table_next', 'low_mod', 'high_mod'))
383 def GetIPCInformation(space
, show_entries
=False, show_userstack
=False):
384 """ Provide a summary of the ipc space
387 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#01x} {6: >10d} {7: >10d}"
388 is_tableval
= space
.is_table
389 ports
= int(space
.is_table_size
)
391 is_bits
= int(space
.is_bits
)
392 if (is_bits
& 0x40000000) == 0: flags
+='A'
394 if (is_bits
& 0x20000000) != 0: flags
+='G'
395 out_str
+= 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
)
397 #should show the each individual entries if asked.
398 if show_entries
== True:
399 out_str
+= "\n\t" + GetIPCEntrySummary
.header
+ "\n"
402 while index
< num_entries
:
403 entryval
= GetObjectAtIndexFromArray(is_tableval
, index
)
404 entry_ie_bits
= unsigned(entryval
.ie_bits
)
405 if (int(entry_ie_bits
) & 0x001f0000 ) != 0:
406 entry_name
= "{0: <#020x}".format( (index
<<8 | entry_ie_bits
>> 24) )
407 out_str
+= "\t" + GetIPCEntrySummary(entryval
, entry_name
) + "\n"
408 if show_userstack
== True:
409 entryport
= Cast(entryval
.ie_object
, 'ipc_port *')
410 if entryval
.ie_object
and (int(entry_ie_bits
) & 0x00070000) and entryport
.ip_callstack
[0]:
411 out_str
+= GetPortUserStack
.header
412 out_str
+= GetPortUserStack(entryport
, space
.is_task
)
414 #done with showing entries
419 @lldb_command('showrights')
420 def ShowRights(cmd_args
=None):
421 """ Routine to print rights information for the given IPC space
422 Usage: showrights <address of ipc space>
425 print "No arguments passed"
426 print ShowRights
.__doc
__
428 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
430 print "unknown arguments:", str(cmd_args
)
432 print GetIPCInformation
.header
433 print GetIPCInformation(ipc
, True, False)
435 # EndMacro: showrights
437 @lldb_command('showtaskrights')
438 def ShowTaskRights(cmd_args
=None):
439 """ Routine to ipc rights information for a task
440 Usage: showtaskrights <task address>
443 print "No arguments passed"
444 print ShowTaskStacksCmdHelper
.__doc
__
446 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
448 print "unknown arguments:", str(cmd_args
)
450 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
451 pval
= Cast(tval
.bsd_info
, 'proc *')
452 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
453 print GetIPCInformation
.header
454 print GetIPCInformation(tval
.itk_space
, True, False)
456 # Macro: showataskrightsbt
458 @lldb_command('showtaskrightsbt')
459 def ShowTaskRightsBt(cmd_args
=None):
460 """ Routine to ipc rights information with userstacks for a task
461 Usage: showtaskrightsbt <task address>
464 print "No arguments passed"
465 print ShowTaskRightsBt
.__doc
__
467 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
469 print "unknown arguments:", str(cmd_args
)
471 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
472 pval
= Cast(tval
.bsd_info
, 'proc *')
473 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
474 print GetIPCInformation
.header
475 print GetIPCInformation(tval
.itk_space
, True, True)
477 # EndMacro: showtaskrightsbt
479 # Macro: showallrights
481 @lldb_command('showallrights')
482 def ShowAllRights(cmd_args
=None):
483 """ Routine to print rights information for IPC space of all tasks
487 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
488 pval
= Cast(t
.bsd_info
, 'proc *')
489 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
490 print GetIPCInformation
.header
491 print GetIPCInformation(t
.itk_space
, True, False) + "\n\n"
493 # EndMacro: showallrights
495 # Macro: showpipestats
496 @lldb_command('showpipestats')
497 def ShowPipeStats(cmd_args
=None):
498 """ Display pipes usage information in the kernel
500 print "Number of pipes: {: d}".format(kern
.globals.amountpipes
)
501 print "Memory used by pipes: {:s}".format(sizeof_fmt(int(kern
.globals.amountpipekva
)))
502 print "Max memory allowed for pipes: {:s}".format(sizeof_fmt(int(kern
.globals.maxpipekva
)))
503 # EndMacro: showpipestats
505 # Macro: showtaskbusyports
506 @lldb_command('showtaskbusyports')
507 def ShowTaskBusyPorts(cmd_args
=None):
508 """ Routine to print information about receive rights belonging to this task that
509 have enqueued messages. This is oten a sign of a blocked or hung process
510 Usage: showtaskbusyports <task address>
513 print "No arguments passed. Please pass in the address of a task"
514 print ShowTaskBusyPorts
.__doc
__
516 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
517 print GetTaskBusyPorts(task
)
520 def GetTaskBusyPorts(task
):
521 """ Prints all busy ports for a given task. ie. all receive rights belonging
522 to this task that have enqueued messages.
524 task : core.value representing a task in kernel
526 str : String containing information about the given task's busy ports
531 while i
< isp
.is_table_size
:
532 iep
= addressof(isp
.is_table
[i
])
533 if iep
.ie_bits
& 0x00020000:
534 port
= Cast(iep
.ie_object
, 'ipc_port_t')
535 if port
.ip_messages
.data
.port
.msgcount
> 0:
536 out_string
+= GetPortSummary
.header
+ GetPortSummary(port
)
539 # EndMacro: showtaskbusyports
541 # Macro: showallbusyports
542 @lldb_command('showallbusyports')
543 def ShowAllBusyPorts(cmd_args
=None):
544 """ Routine to print information about all receive rights on the system that
545 have enqueued messages.
547 task_queue_head
= kern
.globals.tasks
549 for tsk
in kern
.tasks
:
550 print GetTaskBusyPorts(tsk
)
552 # EndMacro: showallbusyports
555 @lldb_command('showmqueue')
556 def ShowMQueue(cmd_args
=None):
557 """ Routine that lists details about a given mqueue
558 Syntax: (lldb) showmqueue 0xaddr
561 print "Please specify the address of the ipc_mqueue whose details you want to print"
562 print ShowMQueue
.__doc
__
564 mqueue
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_mqueue *')
565 wq_type
= mqueue
.data
.pset
.set_queue
.wqs_wait_queue
.wq_type
566 if int(wq_type
) == 3:
567 psetoff
= getfieldoffset('struct ipc_pset *', 'ips_messages')
568 pset
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(psetoff
)
569 print GetPortSetSummary
.header
+ GetPortSetSummary(kern
.GetValueFromAddress(pset
, 'struct ipc_pset *'))
570 if int(wq_type
) == 2:
571 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
572 port
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(portoff
)
573 print GetPortSummary
.header
+ GetPortSummary(kern
.GetValueFromAddress(port
, 'struct ipc_port *'))
574 # EndMacro: showmqueue
577 @lldb_command('showpset')
578 def ShowPSet(cmd_args
=None):
579 """ Routine that prints details for a given ipc_pset *
580 Syntax: (lldb) showpset 0xaddr
583 print "Please specify the address of the pset whose details you want to print"
584 print ShowPSet
.__doc
__
587 print GetPortSetSummary
.header
+ GetPortSetSummary(kern
.GetValueFromAddress(cmd_args
[0], 'ipc_pset *'))