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.
12 @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
13 def GetTaskIPCSummary(task
):
14 """ Display a task's ipc summary.
16 task : core.value represeting a Task in kernel
18 str - string of ipc info for the task
21 format_string
= "{0: <#020x} {1: <6d} {2: <6d} {3: <10d} {4: <15s}"
22 pval
= Cast(task
.bsd_info
, 'proc *')
23 table_size
= int(task
.itk_space
.is_table_size
)
24 proc_name
= str(pval
.p_comm
)
25 out_string
+= format_string
.format(task
, pval
.p_pid
, task
.thread_count
, table_size
, proc_name
)
28 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s} {5: <20s} {6: <4s}\n".format(
29 "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
30 def GetPortSummary(port
, show_kmsg_summary
=True, prefix
=""):
31 """ Display a port's summary
33 port : core.value representing a port in the kernel
35 str : string of ipc info for the given port
38 portp
= Cast(port
, 'struct ipc_port *')
39 destspacep
= kern
.GetValueFromAddress(0, 'struct ipc_space *')
40 spacep
= portp
.data
.receiver
41 format_string
= "{0: #019x} {1: #019x} {2: <8s} {3: #011x} {4: <5s} {5: #05x} {6: #019x} {7: <16s}\n"
42 if portp
.ip_object
.io_bits
& 0x80000000:
43 out_string
+= prefix
+ format_string
.format(
44 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
45 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
46 "APort", portp
.ip_object
.io_references
,
47 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
48 GetPortDestProc(portp
))
50 out_string
+= prefix
+ format_string
.format(
51 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
52 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
53 "DPort", portp
.ip_object
.io_references
, unsigned(portp
),
57 kmsgp
= Cast(portp
.ip_messages
.data
.port
.messages
.ikmq_base
, 'ipc_kmsg_t')
58 out_string
+= prefix
+ GetKMsgSummary
.header
+ prefix
+ GetKMsgSummary(kmsgp
)
61 kmsgp
= kmsgp
.ikm_next
62 while (kmsgp
) != (kmsgheadp
):
63 out_string
+= prefix
+ GetKMsgSummary(kmsgp
)
64 kmsgp
= kmsgp
.ikm_next
67 def GetPortDestProc(portp
):
68 """ Display the name and pid of a given port's receiver
70 portp : core.value representing a pointer to a port in the kernel
71 destspacep : core.value representing a pointer to an ipc_space
73 str : string containing receiver's name and pid
75 spacep
= portp
.data
.receiver
77 for tsk
in kern
.tasks
:
78 if tsk
.itk_space
== spacep
:
80 destprocp
= Cast(tsk
.bsd_info
, 'struct proc *')
81 out_str
= "{0:s}({1: <d})".format(destprocp
.p_comm
, destprocp
.p_pid
)
88 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <19s} {6: <26s} {7: <26s}\n".format(
89 "dest-port", "kmsg", "msgid", "disp", "size", "reply-port", "source", "destination"))
90 def GetKMsgSummary(kmsgp
):
91 """ Display a summary for type ipc_kmsg_t
93 kmsgp : core.value representing the given ipc_kmsg_t struct
95 str : string of summary info for the given ipc_kmsg_t instance
97 kmsghp
= kmsgp
.ikm_header
98 kmsgh
= dereference(kmsghp
)
100 out_string
+= "{0: <19s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
101 ' '*19, unsigned(kmsgp
), ' '*8, kmsgh
.msgh_id
)
103 if (kmsgh
.msgh_bits
& 0xff) == 17:
104 out_string
+= "{0: <2s}".format("rS")
106 out_string
+= "{0: <2s}".format("rO")
108 if (kmsgh
.msgh_bits
& 0xff00) == (17 << 8):
109 out_string
+= "{0: <2s}".format("lS")
111 if (kmsgh
.msgh_bits
& 0xff00) == (18 << 8):
112 out_string
+= "{0: <2s}".format("lO")
114 out_string
+= "{0: <2s}".format("l-")
115 if kmsgh
.msgh_bits
& 0xf0000000:
116 out_string
+= "{0: <2s}".format("c")
118 out_string
+= "{0: <2s}".format("s")
121 if kmsgp
.ikm_header
.msgh_remote_port
:
122 dest_proc_name
= GetDestinationProcessFromPort(kmsgp
.ikm_header
.msgh_remote_port
)
124 out_string
+= "{0: ^6d} {1: <#019x} {2: <26s} {3: <26s}\n".format(
125 unsigned(kmsgh
.msgh_size
), unsigned(kmsgh
.msgh_local_port
),
126 GetKMsgSrc(kmsgp
), dest_proc_name
)
129 def GetKMsgSrc(kmsgp
):
130 """ Routine that prints a kmsg's source process and pid details
132 kmsgp : core.value representing the given ipc_kmsg_t struct
134 str : string containing the name and pid of the kmsg's source proc
136 kmsgsrchp
= Cast(kmsgp
, 'ipc_kmsg_t').ikm_header
137 kmsgpid
= int(Cast(kern
.GetValueFromAddress(unsigned(kmsgsrchp
) + kmsgsrchp
.msgh_size
, 'uint *')[10], 'pid_t'))
139 return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid
), kmsgpid
)
141 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
142 "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
143 def GetPortSetSummary(pset
):
144 """ Display summary for a given struct ipc_pset *
146 pset : core.value representing a pset in the kernel
148 str : string of summary information for the given pset
151 if pset
.ips_object
.io_bits
& 0x80000000:
152 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
153 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
154 pset
.ips_messages
.data
.pset
.local_name
, "ASet",
155 pset
.ips_object
.io_references
,
156 pset
.ips_messages
.data
.pset
.local_name
)
159 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
160 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
161 pset
.ips_messages
.data
.pset
.local_name
, "DSet",
162 pset
.ips_object
.io_references
,
163 pset
.ips_messages
.data
.pset
.local_name
)
166 setlinksp
= addressof(pset
.ips_messages
.data
.pset
.set_queue
.wqs_setlinks
)
167 wql
= Cast(pset
.ips_messages
.data
.pset
.set_queue
.wqs_setlinks
.next
, 'WaitQueueLink *')
168 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
169 prefix_str
= "{0:<21s}".format(' '*21)
170 while unsigned(wql
) != unsigned(Cast(setlinksp
, 'void *')):
171 portp
= kern
.GetValueFromAddress(unsigned(wql
.wql_element
.wqe_queue
) - portoff
, 'ipc_port *')
174 out_str
+= "{0:s}\n{1:s}{2:s}".format(GetPortDestProc(portp
), prefix_str
, GetPortSummary
.header
)
175 out_str
+= GetPortSummary(portp
, False, prefix_str
)
176 wql
= Cast(wql
.wql_setlinks
.next
, 'WaitQueueLink *')
181 @lldb_command('showipc')
182 def ShowIPC(cmd_args
=None):
183 """ Routine to print data for the given IPC space
184 Usage: showipc <address of ipc space>
187 print "No arguments passed"
188 print ShowIPC
.__doc
__
190 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
192 print "unknown arguments:", str(cmd_args
)
194 print GetIPCInformation
.header
195 print GetIPCInformation(ipc
, False, False)
201 @lldb_command('showtaskipc')
202 def ShowTaskIPC(cmd_args
=None):
203 """ Routine to print IPC summary of given task
204 Usage: showtaskipc <address of task>
207 print "No arguments passed"
208 print ShowTaskIPC
.__doc
__
210 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
212 print "unknown arguments:", str(cmd_args
)
214 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
215 pval
= Cast(tval
.bsd_info
, 'proc *')
216 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
217 print GetTaskIPCSummary
.header
218 print GetTaskIPCSummary(tval
)
220 # EndMacro: showtaskipc
224 @lldb_command('showallipc')
225 def ShowAllIPC(cmd_args
=None):
226 """ Routine to print IPC summary of all tasks
230 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
231 pval
= Cast(t
.bsd_info
, 'proc *')
232 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
233 print GetIPCInformation
.header
234 print GetIPCInformation(t
.itk_space
, False, False) + "\n\n"
236 # EndMacro: showallipc
238 @lldb_command('showipcsummary')
239 def ShowIPCSummary(cmd_args
=None):
240 """ Summarizes the IPC state of all tasks.
241 This is a convenient way to dump some basic clues about IPC messaging. You can use the output to determine
242 tasks that are candidates for further investigation.
244 print GetTaskIPCSummary
.header
246 print GetTaskIPCSummary(t
)
249 def GetKObjectFromPort(portval
):
250 """ Get Kobject description from the port.
251 params: portval - core.value representation of 'ipc_port *' object
252 returns: str - string of kobject information
254 kobject_str
= "{0: <#020x}".format(portval
.kdata
.kobject
)
255 io_bits
= unsigned(portval
.ip_object
.io_bits
)
256 objtype_index
= io_bits
& 0xfff
257 if objtype_index
< len(xnudefines
.kobject_types
) :
258 desc_str
= "kobject({0:s})".format(xnudefines
.kobject_types
[objtype_index
])
259 if xnudefines
.kobject_types
[objtype_index
] in ('TASK_RESUME', 'TASK'):
260 desc_str
+= " " + GetProcNameForTask(Cast(portval
.kdata
.kobject
, 'task *'))
262 desc_str
= "kobject(UNKNOWN) {:d}".format(objtype_index
)
263 return kobject_str
+ " " + desc_str
265 @static_var('destcache', {})
266 def GetDestinationProcessFromPort(port
):
268 params: port - core.value representation of 'ipc_port *' object
269 returns: str - name of process
272 dest_space
= port
.data
.receiver
274 #update destcache if data is not found
275 if hex(dest_space
) not in GetDestinationProcessFromPort
.destcache
:
277 if hex(t
.itk_space
) == hex(dest_space
):
278 pval
= Cast(t
.bsd_info
, 'proc *')
279 GetDestinationProcessFromPort
.destcache
[hex(dest_space
)] = (t
, pval
)
283 else: found_dest
= True
286 (ftask
, fproc
) = GetDestinationProcessFromPort
.destcache
[hex(dest_space
)]
288 out_str
= "{0:s}({1:d})".format(fproc
.p_comm
, fproc
.p_pid
)
290 out_str
= "task {0: <#020x}".format(ftask
)
295 @header("{0: <20s} {1: <20s}".format("destname", "destination") )
296 def GetPortDestinationSummary(port
):
297 """ Get destination information for a port.
298 params: port - core.value representation of 'ipc_port *' object
299 returns: str - string of info about ports destination
302 format_string
= "{0: <20s} {1: <20s}"
305 ipc_space_kernel
= unsigned(kern
.globals.ipc_space_kernel
)
306 target_spaceval
= port
.data
.receiver
307 if unsigned(target_spaceval
) == ipc_space_kernel
:
308 destname_str
= GetKObjectFromPort(port
)
310 if int(port
.ip_object
.io_bits
) & 0x80000000 :
311 destname_str
= "{0: <#020x}".format(port
.ip_messages
.data
.port
.receiver_name
)
312 destination_str
= GetDestinationProcessFromPort(port
)
314 destname_str
= "{0: <#020x}".format(port
)
315 destination_str
= "inactive-port"
317 out_str
+= format_string
.format(destname_str
, destination_str
)
320 @lldb_type_summary(['ipc_entry_t'])
321 @header("{0: <20s} {1: <20s} {2: <8s} {3: <8s} {4: <20s} {5: <20s}".format("object", "name","rite", "urefs", "destname", "destination"))
322 def GetIPCEntrySummary(entry
, ipc_name
=''):
323 """ Get summary of a ipc entry.
325 entry - core.value representing ipc_entry_t in the kernel
326 ipc_name - str of format '0x0123' for display in summary.
328 str - string of ipc entry related information
331 entry_ptr
= int(hex(entry
), 16)
332 format_string
= "{0: <#020x} {1: <12s} {2: <8s} {3: <8d} {4: <20s} {5: <20s}"
337 ie_object
= entry
.ie_object
338 ie_bits
= int(entry
.ie_bits
)
339 urefs
= int(ie_bits
& 0xffff)
340 if ie_bits
& 0x00100000 :
342 elif ie_bits
& 0x00080000:
345 if ie_bits
& 0x00010000 :
346 if ie_bits
& 0x00020000 :
350 elif ie_bits
& 0x00020000:
352 elif ie_bits
& 0x00040000 :
354 portval
= Cast(ie_object
, 'ipc_port_t')
355 if int(entry
.index
.request
) != 0:
356 requestsval
= portval
.ip_requests
357 sorightval
= requestsval
[int(entry
.index
.request
)].notify
.port
358 soright_ptr
= unsigned(sorightval
)
360 if soright_ptr
& 0x1 : right_str
+='s'
361 elif soright_ptr
& 0x2 : right_str
+='d'
362 else : right_str
+='n'
363 if ie_bits
& 0x00800000 : right_str
+='c'
364 if portval
.ip_nsrequest
!= 0: right_str
+='x'
365 # now show the port destination part
366 destname_str
= GetPortDestinationSummary(Cast(ie_object
, 'ipc_port_t'))
368 out_str
= format_string
.format(ie_object
, ipc_name
, right_str
, urefs
, destname_str
, destination_str
)
371 @header("{0: >20s}".format("user bt") )
372 def GetPortUserStack(port
, task
):
373 """ Get UserStack information for the given port & task.
374 params: port - core.value representation of 'ipc_port *' object
375 task - value representing 'task *' object
376 returns: str - string information on port's userstack
379 ie_port_callstack
= port
.ip_callstack
380 ie_port_spares
= port
.ip_spares
[0]
381 proc_val
= Cast(task
.bsd_info
, 'proc *')
382 if ie_port_callstack
[0]:
383 out_str
+= "{: <10x}".format(ie_port_callstack
[0])
385 while count
< 16 and ie_port_callstack
[count
]:
386 out_str
+= ": <10x".format(ie_port_callstack
[count
])
388 if ie_port_spares
!= proc_val
.p_pid
:
389 out_str
+= " ({:<10d})".format(ie_port_spares
)
393 @lldb_type_summary(['ipc_space *'])
394 @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'))
395 def GetIPCInformation(space
, show_entries
=False, show_userstack
=False):
396 """ Provide a summary of the ipc space
399 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#01x} {6: >10d} {7: >10d}"
400 is_tableval
= space
.is_table
401 ports
= int(space
.is_table_size
)
403 is_bits
= int(space
.is_bits
)
404 if (is_bits
& 0x40000000) == 0: flags
+='A'
406 if (is_bits
& 0x20000000) != 0: flags
+='G'
407 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
)
409 #should show the each individual entries if asked.
410 if show_entries
== True:
411 out_str
+= "\n\t" + GetIPCEntrySummary
.header
+ "\n"
414 while index
< num_entries
:
415 entryval
= GetObjectAtIndexFromArray(is_tableval
, index
)
416 entry_ie_bits
= unsigned(entryval
.ie_bits
)
417 if (int(entry_ie_bits
) & 0x001f0000 ) != 0:
418 entry_name
= "{0: <#020x}".format( (index
<<8 | entry_ie_bits
>> 24) )
419 out_str
+= "\t" + GetIPCEntrySummary(entryval
, entry_name
) + "\n"
420 if show_userstack
== True:
421 entryport
= Cast(entryval
.ie_object
, 'ipc_port *')
422 if entryval
.ie_object
and (int(entry_ie_bits
) & 0x00070000) and entryport
.ip_callstack
[0]:
423 out_str
+= GetPortUserStack
.header
424 out_str
+= GetPortUserStack(entryport
, space
.is_task
)
426 #done with showing entries
431 @lldb_command('showrights')
432 def ShowRights(cmd_args
=None):
433 """ Routine to print rights information for the given IPC space
434 Usage: showrights <address of ipc space>
437 print "No arguments passed"
438 print ShowRights
.__doc
__
440 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
442 print "unknown arguments:", str(cmd_args
)
444 print GetIPCInformation
.header
445 print GetIPCInformation(ipc
, True, False)
447 # EndMacro: showrights
449 @lldb_command('showtaskrights')
450 def ShowTaskRights(cmd_args
=None):
451 """ Routine to ipc rights information for a task
452 Usage: showtaskrights <task address>
455 print "No arguments passed"
456 print ShowTaskStacksCmdHelper
.__doc
__
458 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
460 print "unknown arguments:", str(cmd_args
)
462 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
463 pval
= Cast(tval
.bsd_info
, 'proc *')
464 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
465 print GetIPCInformation
.header
466 print GetIPCInformation(tval
.itk_space
, True, False)
468 # Macro: showataskrightsbt
470 @lldb_command('showtaskrightsbt')
471 def ShowTaskRightsBt(cmd_args
=None):
472 """ Routine to ipc rights information with userstacks for a task
473 Usage: showtaskrightsbt <task address>
476 print "No arguments passed"
477 print ShowTaskRightsBt
.__doc
__
479 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
481 print "unknown arguments:", str(cmd_args
)
483 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
484 pval
= Cast(tval
.bsd_info
, 'proc *')
485 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
486 print GetIPCInformation
.header
487 print GetIPCInformation(tval
.itk_space
, True, True)
489 # EndMacro: showtaskrightsbt
491 # Macro: showallrights
493 @lldb_command('showallrights')
494 def ShowAllRights(cmd_args
=None):
495 """ Routine to print rights information for IPC space of all tasks
499 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
500 pval
= Cast(t
.bsd_info
, 'proc *')
501 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
503 print GetIPCInformation
.header
504 print GetIPCInformation(t
.itk_space
, True, False) + "\n\n"
505 except (KeyboardInterrupt, SystemExit):
508 print "Failed to get IPC information. Do individual showtaskrights <task> to find the error. \n\n"
510 # EndMacro: showallrights
512 # Macro: showpipestats
513 @lldb_command('showpipestats')
514 def ShowPipeStats(cmd_args
=None):
515 """ Display pipes usage information in the kernel
517 print "Number of pipes: {: d}".format(kern
.globals.amountpipes
)
518 print "Memory used by pipes: {:s}".format(sizeof_fmt(int(kern
.globals.amountpipekva
)))
519 print "Max memory allowed for pipes: {:s}".format(sizeof_fmt(int(kern
.globals.maxpipekva
)))
520 # EndMacro: showpipestats
522 # Macro: showtaskbusyports
523 @lldb_command('showtaskbusyports')
524 def ShowTaskBusyPorts(cmd_args
=None):
525 """ Routine to print information about receive rights belonging to this task that
526 have enqueued messages. This is oten a sign of a blocked or hung process
527 Usage: showtaskbusyports <task address>
530 print "No arguments passed. Please pass in the address of a task"
531 print ShowTaskBusyPorts
.__doc
__
533 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
534 print GetTaskBusyPorts(task
)
537 def GetTaskBusyPorts(task
):
538 """ Prints all busy ports for a given task. ie. all receive rights belonging
539 to this task that have enqueued messages.
541 task : core.value representing a task in kernel
543 str : String containing information about the given task's busy ports
548 while i
< isp
.is_table_size
:
549 iep
= addressof(isp
.is_table
[i
])
550 if iep
.ie_bits
& 0x00020000:
551 port
= Cast(iep
.ie_object
, 'ipc_port_t')
552 if port
.ip_messages
.data
.port
.msgcount
> 0:
553 out_string
+= GetPortSummary
.header
+ GetPortSummary(port
)
556 # EndMacro: showtaskbusyports
558 # Macro: showallbusyports
559 @lldb_command('showallbusyports')
560 def ShowAllBusyPorts(cmd_args
=None):
561 """ Routine to print information about all receive rights on the system that
562 have enqueued messages.
564 task_queue_head
= kern
.globals.tasks
566 for tsk
in kern
.tasks
:
567 print GetTaskBusyPorts(tsk
)
569 # EndMacro: showallbusyports
572 @lldb_command('showmqueue')
573 def ShowMQueue(cmd_args
=None):
574 """ Routine that lists details about a given mqueue
575 Syntax: (lldb) showmqueue 0xaddr
578 print "Please specify the address of the ipc_mqueue whose details you want to print"
579 print ShowMQueue
.__doc
__
581 mqueue
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_mqueue *')
582 wq_type
= mqueue
.data
.pset
.set_queue
.wqs_wait_queue
.wq_type
583 if int(wq_type
) == 3:
584 psetoff
= getfieldoffset('struct ipc_pset', 'ips_messages')
585 pset
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(psetoff
)
586 print GetPortSetSummary
.header
+ GetPortSetSummary(kern
.GetValueFromAddress(pset
, 'struct ipc_pset *'))
587 if int(wq_type
) == 2:
588 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
589 port
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(portoff
)
590 print GetPortSummary
.header
+ GetPortSummary(kern
.GetValueFromAddress(port
, 'struct ipc_port *'))
591 # EndMacro: showmqueue
594 @lldb_command('showkmsg')
595 def ShowKMSG(cmd_args
=[]):
596 """ Show detail information about a <ipc_kmsg_t> structure
597 Usage: (lldb) showkmsg <ipc_kmsg_t>
600 raise ArgumentError('Invalid arguments')
601 kmsg
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_kmsg_t')
602 print GetKMsgSummary
.header
603 print GetKMsgSummary(kmsg
)
608 @lldb_command('showpset')
609 def ShowPSet(cmd_args
=None):
610 """ Routine that prints details for a given ipc_pset *
611 Syntax: (lldb) showpset 0xaddr
614 print "Please specify the address of the pset whose details you want to print"
615 print ShowPSet
.__doc
__
618 print GetPortSetSummary
.header
+ GetPortSetSummary(kern
.GetValueFromAddress(cmd_args
[0], 'ipc_pset *'))
621 # IPC importance inheritance related macros.
623 @lldb_command('showalliits')
624 def ShowAllIITs(cmd_args
=[], cmd_options
={}):
625 """ Development only macro. Show list of all iits allocated in the system. """
627 iit_queue
= kern
.globals.global_iit_alloc_queue
629 print "This debug macro is only available in development or debug kernels"
632 print GetIPCImportantTaskSummary
.header
633 for iit
in IterateQueue(iit_queue
, 'struct ipc_importance_task *', 'iit_allocation'):
634 print GetIPCImportantTaskSummary(iit
)
637 @header("{: <18s} {: <3s} {: <18s} {: <20s} {: <18s} {: <8s}".format("ipc_imp_inherit", "don", "to_task", "proc_name", "from_elem", "depth"))
638 @lldb_type_summary(['ipc_importance_inherit *', 'ipc_importance_inherit_t'])
639 def GetIPCImportanceInheritSummary(iii
):
640 """ describes iii object of type ipc_importance_inherit_t * """
642 fmt
= "{o: <#018x} {don: <3s} {o.iii_to_task.iit_task: <#018x} {task_name: <20s} {o.iii_from_elem: <#018x} {o.iii_depth: <#08x}"
644 if unsigned(iii
.iii_donating
):
646 taskname
= GetProcNameForTask(iii
.iii_to_task
.iit_task
)
647 if hasattr(iii
.iii_to_task
, 'iit_bsd_pid'):
648 taskname
= "({:d}) {:s}".format(iii
.iii_to_task
.iit_bsd_pid
, iii
.iii_to_task
.iit_procname
)
649 out_str
+= fmt
.format(o
=iii
, task_name
= taskname
, don
=donating_str
)
652 @static_var('recursion_count', 0)
653 @header("{: <18s} {: <4s} {: <8s} {: <8s} {: <18s} {: <18s}".format("iie", "type", "refs", "made", "#kmsgs", "#inherits"))
654 @lldb_type_summary(['ipc_importance_elem *'])
655 def GetIPCImportanceElemSummary(iie
):
656 """ describes an ipc_importance_elem * object """
658 if GetIPCImportanceElemSummary
.recursion_count
> 500:
659 GetIPCImportanceElemSummary
.recursion_count
= 0
660 return "Recursion of 500 reached"
663 fmt
= "{: <#018x} {: <4s} {: <8d} {: <8d} {: <#018x} {: <#018x}"
665 if unsigned(iie
.iie_bits
) & 0x80000000:
667 refs
= unsigned(iie
.iie_bits
) & 0x7fffffff
668 made_refs
= unsigned(iie
.iie_made
)
669 kmsg_count
= sum(1 for i
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'))
670 inherit_count
= sum(1 for i
in IterateQueue(iie
.iie_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'))
671 out_str
+= fmt
.format(iie
, type_str
, refs
, made_refs
, kmsg_count
, inherit_count
)
672 if config
['verbosity'] > vHUMAN
:
674 out_str
+= "\n\t"+ GetKMsgSummary
.header
675 for k
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'):
676 out_str
+= "\t" + "{: <#018x}".format(k
.ikm_header
.msgh_remote_port
) + ' ' + GetKMsgSummary(k
).lstrip()
678 if inherit_count
> 0:
679 out_str
+= "\n\t" + GetIPCImportanceInheritSummary
.header
+ "\n"
680 for i
in IterateQueue(iie
.iie_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'):
681 out_str
+= "\t" + GetIPCImportanceInheritSummary(i
) + "\n"
683 if type_str
== "INH":
684 iii
= Cast(iie
, 'struct ipc_importance_inherit *')
685 out_str
+= "Inherit from: " + GetIPCImportanceElemSummary(iii
.iii_from_elem
)
689 @header("{: <18s} {: <18s} {: <20s}".format("iit", "task", "name"))
690 @lldb_type_summary(['ipc_importance_task *'])
691 def GetIPCImportantTaskSummary(iit
):
692 """ iit is a ipc_importance_task value object.
694 fmt
= "{: <#018x} {: <#018x} {: <20s}"
696 pname
= GetProcNameForTask(iit
.iit_task
)
697 if hasattr(iit
, 'iit_bsd_pid'):
698 pname
= "({:d}) {:s}".format(iit
.iit_bsd_pid
, iit
.iit_procname
)
699 out_str
+= fmt
.format(iit
, iit
.iit_task
, pname
)
702 @lldb_command('showallimportancetasks')
703 def ShowIPCImportanceTasks(cmd_args
=[], cmd_options
={}):
704 """ display a list of all tasks with ipc importance information.
705 Usage: (lldb) showallimportancetasks
706 Tip: add "-v" to see detailed information on each kmsg or inherit elems
708 print ' ' + GetIPCImportantTaskSummary
.header
+ ' ' + GetIPCImportanceElemSummary
.header
711 if unsigned(t
.task_imp_base
):
712 s
+= ' ' + GetIPCImportantTaskSummary(t
.task_imp_base
)
713 s
+= ' ' + GetIPCImportanceElemSummary(addressof(t
.task_imp_base
.iit_elem
))
716 @lldb_command('showipcimportance', '')
717 def ShowIPCImportance(cmd_args
=[], cmd_options
={}):
718 """ Describe an importance from <ipc_importance_elem_t> argument.
719 Usage: (lldb) showimportance <ipc_importance_elem_t>
722 raise ArgumentError("Please provide valid argument")
724 elem
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_importance_elem_t')
725 print GetIPCImportanceElemSummary
.header
726 print GetIPCImportanceElemSummary(elem
)
728 @header("{: <18s} {: <10s} {: <18s} {: <18s} {: <8s} {: <5s} {: <5s} {: <5s}".format("ivac", "refs", "port", "tbl", "tblsize", "index", "Grow", "freelist"))
729 @lldb_type_summary(['ipc_voucher_attr_control *', 'ipc_voucher_attr_control_t'])
730 def GetIPCVoucherAttrControlSummary(ivac
):
731 """ describes a voucher attribute control settings """
733 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}"
736 if unsigned(ivac
) == 0:
737 return "{: <#018x}".format(ivac
)
739 if unsigned(ivac
.ivac_is_growing
):
741 out_str
+= fmt
.format(c
=ivac
, growing
= growing_str
)
744 @lldb_command('showivac','')
745 def ShowIPCVoucherAttributeControl(cmd_args
=[], cmd_options
={}):
746 """ Show summary of voucher attribute contols.
747 Usage: (lldb) showivac <ipc_voucher_attr_control_t>
750 raise ArgumentError("Please provide correct arguments.")
751 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
752 print GetIPCVoucherAttrControlSummary
.header
753 print GetIPCVoucherAttrControlSummary(ivac
)
754 if config
['verbosity'] > vHUMAN
:
756 last_entry_index
= unsigned(ivac
.ivac_table_size
)
757 print "index " + GetIPCVoucherAttributeEntrySummary
.header
758 while cur_entry_index
< last_entry_index
:
759 print "{: <5d} ".format(cur_entry_index
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[cur_entry_index
]))
765 @header("{: <18s} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}".format("ivam", "get_value_fn", "extract_fn", "release_value_fn", "command_fn", "release_fn"))
766 @lldb_type_summary(['ipc_voucher_attr_manager *', 'ipc_voucher_attr_manager_t'])
767 def GetIPCVoucherAttrManagerSummary(ivam
):
768 """ describes a voucher attribute manager settings """
770 fmt
= "{: <#018x} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}"
772 if unsigned(ivam
) == 0 :
773 return "{: <#018x}".format(ivam
)
775 get_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_get_value
))
776 extract_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_extract_content
))
777 release_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release_value
))
778 command_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_command
))
779 release_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release
))
780 out_str
+= fmt
.format(ivam
, get_value_fn
, extract_fn
, release_value_fn
, command_fn
, release_fn
)
785 @header("{: <18s} {: <10s} {:s} {:s}".format("ivgte", "key", GetIPCVoucherAttrControlSummary
.header
.strip(), GetIPCVoucherAttrManagerSummary
.header
.strip()))
786 @lldb_type_summary(['ipc_voucher_global_table_element *', 'ipc_voucher_global_table_element_t'])
787 def GetIPCVoucherGlobalTableElementSummary(ivgte
):
788 """ describes a ipc_voucher_global_table_element object """
790 fmt
= "{g: <#018x} {g.ivgte_key: <10d} {ctrl_s:s} {mgr_s:s}"
791 out_str
+= fmt
.format(g
=ivgte
, ctrl_s
=GetIPCVoucherAttrControlSummary(ivgte
.ivgte_control
), mgr_s
=GetIPCVoucherAttrManagerSummary(ivgte
.ivgte_manager
))
794 @lldb_command('showglobalvouchertable', '')
795 def ShowGlobalVoucherTable(cmd_args
=[], cmd_options
={}):
796 """ show detailed information of all voucher attribute managers registered with vouchers system
797 Usage: (lldb) showglobalvouchertable
799 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
800 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
801 print GetIPCVoucherGlobalTableElementSummary
.header
802 for i
in range(elems
):
803 elt
= addressof(kern
.globals.iv_global_table
[i
])
804 print GetIPCVoucherGlobalTableElementSummary(elt
)
806 # Type summaries for Bag of Bits.
808 @lldb_type_summary(['user_data_value_element', 'user_data_element_t'])
809 @header("{0: <20s} {1: <16s} {2: <20s} {3: <20s} {4: <16s} {5: <20s}".format("user_data_ve", "maderefs", "checksum", "hash value", "size", "data"))
810 def GetBagofBitsElementSummary(data_element
):
811 """ Summarizes the Bag of Bits element
812 params: data_element = value of the object of type user_data_value_element_t
813 returns: String with summary of the type.
815 format_str
= "{0: <#020x} {1: <16d} {2: <#020x} {3: <#020x} {4: <16d}"
816 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
))
819 for i
in range(0, (unsigned(data_element
.e_size
) - 1)):
820 out_string
+= "{:02x}".format(int(data_element
.e_data
[i
]))
823 def GetIPCHandleSummary(handle_ptr
):
824 """ converts a handle value inside a voucher attribute table to ipc element and returns appropriate summary.
825 params: handle_ptr - uint64 number stored in handle of voucher.
826 returns: str - string summary of the element held in internal structure
828 elem
= kern
.GetValueFromAddress(handle_ptr
, 'ipc_importance_elem_t')
829 if elem
.iie_bits
& 0x80000000 :
830 iie
= Cast(elem
, 'struct ipc_importance_inherit *')
831 return GetIPCImportanceInheritSummary(iie
)
833 iit
= Cast(elem
, 'struct ipc_importance_task *')
834 return GetIPCImportantTaskSummary(iit
)
836 def GetATMHandleSummary(handle_ptr
):
837 """ Convert a handle value to atm value and returns corresponding summary of its fields.
838 params: handle_ptr - uint64 number stored in handle of voucher
839 returns: str - summary of atm value
841 elem
= kern
.GetValueFromAddress(handle_ptr
, 'atm_value *')
842 return GetATMValueSummary(elem
)
844 def GetBankHandleSummary(handle_ptr
):
845 """ converts a handle value inside a voucher attribute table to bank element and returns appropriate summary.
846 params: handle_ptr - uint64 number stored in handle of voucher.
847 returns: str - summary of bank element
849 elem
= kern
.GetValueFromAddress(handle_ptr
, 'bank_element_t')
850 if elem
.be_type
& 1 :
851 ba
= Cast(elem
, 'struct bank_account *')
852 return GetBankAccountSummary(ba
)
854 bt
= Cast(elem
, 'struct bank_task *')
855 return GetBankTaskSummary(bt
)
857 def GetBagofBitsHandleSummary(handle_ptr
):
858 """ Convert a handle value to bag of bits value and returns corresponding summary of its fields.
859 params: handle_ptr - uint64 number stored in handle of voucher
860 returns: str - summary of bag of bits element
862 elem
= kern
.GetValueFromAddress(handle_ptr
, 'user_data_element_t')
863 return GetBagofBitsElementSummary(elem
)
865 @static_var('attr_managers',{1: GetATMHandleSummary, 2: GetIPCHandleSummary, 3: GetBankHandleSummary, 7: GetBagofBitsHandleSummary}
)
866 def GetHandleSummaryForKey(handle_ptr
, key_num
):
867 """ Get a summary of handle pointer from the voucher attribute manager.
868 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.
869 key 2 -> ipc and it puts either ipc_importance_inherit_t or ipc_important_task_t.
870 key 3 -> Bank and it puts either bank_task_t or bank_account_t.
871 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.
873 key_num
= int(key_num
)
874 if key_num
not in GetHandleSummaryForKey
.attr_managers
:
875 return "Unknown key %d" % key_num
876 return GetHandleSummaryForKey
.attr_managers
[key_num
](handle_ptr
)
879 @header("{: <18s} {: <18s} {: <10s} {: <4s} {: <18s} {: <18s}".format("ivace", "value_handle", "#refs", "rel?", "maderefs", "next_layer"))
880 @lldb_type_summary(['ivac_entry *', 'ivac_entry_t'])
881 def GetIPCVoucherAttributeEntrySummary(ivace
, manager_key_num
= 0):
882 """ Get summary for voucher attribute entry.
885 fmt
= "{e: <#018x} {e.ivace_value: <#018x} {e.ivace_refs: <10d} {release: <4s} {made_refs: <18s} {next_layer: <18s}"
891 if unsigned(ivace
.ivace_releasing
):
893 if unsigned(ivace
.ivace_free
):
895 if unsigned(ivace
.ivace_layered
):
896 next_layer
= "{: <#018x}".format(ivace
.ivace_u
.ivaceu_layer
)
898 made_refs
= "{: <18d}".format(ivace
.ivace_u
.ivaceu_made
)
900 out_str
+= fmt
.format(e
=ivace
, release
=release_str
, made_refs
=made_refs
, next_layer
=next_layer
)
901 if config
['verbosity'] > vHUMAN
and manager_key_num
> 0:
902 out_str
+= " " + GetHandleSummaryForKey(unsigned(ivace
.ivace_value
), manager_key_num
)
903 if config
['verbosity'] > vHUMAN
:
904 out_str
+= ' {: <2s} {: <4d} {: <4d}'.format(free_str
, ivace
.ivace_next
, ivace
.ivace_index
)
907 @lldb_command('showivacfreelist','')
908 def ShowIVACFreeList(cmd_args
=[], cmd_options
={}):
909 """ Walk the free list and print every entry in the list.
910 usage: (lldb) showivacfreelist <ipc_voucher_attr_control_t>
913 raise ArgumentError('Please provide <ipc_voucher_attr_control_t>')
914 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
915 print GetIPCVoucherAttrControlSummary
.header
916 print GetIPCVoucherAttrControlSummary(ivac
)
917 if unsigned(ivac
.ivac_freelist
) == 0:
918 print "ivac table is full"
920 print "index " + GetIPCVoucherAttributeEntrySummary
.header
921 next_free
= unsigned(ivac
.ivac_freelist
)
922 while next_free
!= 0:
923 print "{: <5d} ".format(next_free
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[next_free
]))
924 next_free
= unsigned(ivac
.ivac_table
[next_free
].ivace_next
)
928 @header('{: <18s} {: <8s} {: <18s} {: <18s} {: <18s} {: <18s} {: <18s}'.format("ipc_voucher", "refs", "checksum", "hash", "tbl_size", "table", "voucher_port"))
929 @lldb_type_summary(['ipc_voucher *', 'ipc_voucher_t'])
930 def GetIPCVoucherSummary(voucher
, show_entries
=False):
931 """ describe a voucher from its ipc_voucher * object """
933 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}"
934 out_str
+= fmt
.format(v
= voucher
)
936 if show_entries
or config
['verbosity'] > vHUMAN
:
937 elems
= unsigned(voucher
.iv_table_size
)
938 entries_header_str
= "\n\t" + "{: <5s} {: <3s} {: <16s} {: <30s}".format("index", "key", "value_index", "manager") + " " + GetIPCVoucherAttributeEntrySummary
.header
939 fmt
= "{: <5d} {: <3d} {: <16d} {: <30s}"
940 for i
in range(elems
):
941 voucher_entry_index
= unsigned(voucher
.iv_inline_table
[i
])
942 if voucher_entry_index
:
943 s
= fmt
.format(i
, GetVoucherManagerKeyForIndex(i
), voucher_entry_index
, GetVoucherAttributeManagerNameForIndex(i
))
944 e
= GetVoucherValueHandleFromVoucherForIndex(voucher
, i
)
946 s
+= " " + GetIPCVoucherAttributeEntrySummary(addressof(e
), GetVoucherManagerKeyForIndex(i
) )
947 if entries_header_str
:
948 entries_str
= entries_header_str
949 entries_header_str
= ''
950 entries_str
+= "\n\t" + s
951 if not entries_header_str
:
952 entries_str
+= "\n\t"
953 out_str
+= entries_str
956 def GetVoucherManagerKeyForIndex(idx
):
957 """ Returns key number for index based on global table. Will raise index error if value is incorrect
959 return unsigned(kern
.globals.iv_global_table
[idx
].ivgte_key
)
961 def GetVoucherAttributeManagerForKey(k
):
962 """ Walks through the iv_global_table and finds the attribute manager name
963 params: k - int key number of the manager
964 return: cvalue - the attribute manager object.
968 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
969 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
970 for i
in range(elems
):
971 elt
= addressof(kern
.globals.iv_global_table
[i
])
972 if k
== unsigned(elt
.ivgte_key
):
973 retval
= elt
.ivgte_manager
977 def GetVoucherAttributeControllerForKey(k
):
978 """ Walks through the iv_global_table and finds the attribute controller
979 params: k - int key number of the manager
980 return: cvalue - the attribute controller object.
984 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
985 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
986 for i
in range(elems
):
987 elt
= addressof(kern
.globals.iv_global_table
[i
])
988 if k
== unsigned(elt
.ivgte_key
):
989 retval
= elt
.ivgte_control
994 def GetVoucherAttributeManagerName(ivam
):
995 """ find the name of the ivam object
996 param: ivam - cvalue object of type ipc_voucher_attr_manager_t
997 returns: str - name of the manager
999 return kern
.Symbolicate(unsigned(ivam
))
1001 def GetVoucherAttributeManagerNameForIndex(idx
):
1002 """ get voucher attribute manager name for index
1003 return: str - name of the attribute manager object
1005 return GetVoucherAttributeManagerName(GetVoucherAttributeManagerForKey(GetVoucherManagerKeyForIndex(idx
)))
1007 def GetVoucherValueHandleFromVoucherForIndex(voucher
, idx
):
1008 """ traverse the voucher attrs and get value_handle in the voucher attr controls table
1010 voucher - cvalue object of type ipc_voucher_t
1011 idx - int index in the entries for which you wish to get actual handle for
1012 returns: cvalue object of type ivac_entry_t
1013 None if no handle found.
1015 manager_key
= GetVoucherManagerKeyForIndex(idx
)
1016 voucher_num_elems
= unsigned(voucher
.iv_table_size
)
1017 if idx
>= voucher_num_elems
:
1018 debuglog("idx %d is out of range max: %d" % (idx
, voucher_num_elems
))
1020 voucher_entry_value
= unsigned(voucher
.iv_inline_table
[idx
])
1021 debuglog("manager_key %d" % manager_key
)
1022 ivac
= GetVoucherAttributeControllerForKey(manager_key
)
1023 if ivac
is None or unsigned(ivac
) == 0:
1024 debuglog("No voucher attribute controller for idx %d" % idx
)
1027 ivac
= kern
.GetValueFromAddress(unsigned(ivac
), 'ipc_voucher_attr_control_t') # ??? No idea why lldb does not addressof directly
1028 ivace_table
= ivac
.ivac_table
1029 if voucher_entry_value
>= unsigned(ivac
.ivac_table_size
):
1030 print "Failed to get ivace for value %d in table of size %d" % (voucher_entry_value
, unsigned(ivac
.ivac_table_size
))
1032 return ivace_table
[voucher_entry_value
]
1036 @lldb_command('showallvouchers')
1037 def ShowAllVouchers(cmd_args
=[], cmd_options
={}):
1038 """ Display a list of all vouchers in the global voucher hash table
1039 Usage: (lldb) showallvouchers
1041 iv_hash_table
= kern
.globals.ivht_bucket
1042 num_buckets
= sizeof(kern
.globals.ivht_bucket
) / sizeof(kern
.globals.ivht_bucket
[0])
1043 print GetIPCVoucherSummary
.header
1044 for i
in range(num_buckets
):
1045 for v
in IterateQueue(iv_hash_table
[i
], 'ipc_voucher_t', 'iv_hash_link'):
1046 print GetIPCVoucherSummary(v
)
1048 @lldb_command('showvoucher', '')
1049 def ShowVoucher(cmd_args
=[], cmd_options
={}):
1050 """ Describe a voucher from <ipc_voucher_t> argument.
1051 Usage: (lldb) showvoucher <ipc_voucher_t>
1054 raise ArgumentError("Please provide valid argument")
1056 voucher
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_t')
1057 print GetIPCVoucherSummary
.header
1058 print GetIPCVoucherSummary(voucher
, show_entries
=True)