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.
13 @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
14 def GetTaskIPCSummary(task
):
15 """ Display a task's ipc summary.
17 task : core.value represeting a Task in kernel
19 str - string of ipc info for the task
22 format_string
= "{0: <#020x} {1: <6d} {2: <6d} {3: <10d} {4: <15s}"
23 pval
= Cast(task
.bsd_info
, 'proc *')
24 table_size
= int(task
.itk_space
.is_table_size
)
25 proc_name
= str(pval
.p_comm
)
26 out_string
+= format_string
.format(task
, pval
.p_pid
, task
.thread_count
, table_size
, proc_name
)
29 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s} {5: <20s} {6: <4s}\n".format(
30 "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
31 def PrintPortSummary(port
, show_kmsg_summary
=True, prefix
=""):
32 """ Display a port's summary
34 port : core.value representing a port in the kernel
36 str : string of ipc info for the given port
39 portp
= Cast(port
, 'struct ipc_port *')
40 destspacep
= kern
.GetValueFromAddress(0, 'struct ipc_space *')
41 spacep
= portp
.data
.receiver
42 format_string
= "{0: #019x} {1: #019x} {2: <8s} {3: #011x} {4: <5s} {5: #05x} {6: #019x} {7: <16s}\n"
43 if portp
.ip_object
.io_bits
& 0x80000000:
44 out_string
+= prefix
+ format_string
.format(
45 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
46 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
47 "APort", portp
.ip_object
.io_references
,
48 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
49 GetPortDestProc(portp
))
51 out_string
+= prefix
+ format_string
.format(
52 unsigned(portp
), addressof(portp
.ip_messages
), ' '*8,
53 unsigned(portp
.ip_messages
.data
.port
.receiver_name
),
54 "DPort", portp
.ip_object
.io_references
, unsigned(portp
),
58 kmsgp
= Cast(portp
.ip_messages
.data
.port
.messages
.ikmq_base
, 'ipc_kmsg_t')
60 print prefix
+ GetKMsgSummary
.header
+ prefix
+ GetKMsgSummary(kmsgp
, prefix
)
62 kmsgp
= kmsgp
.ikm_next
63 while (kmsgp
) != (kmsgheadp
):
64 print prefix
+ GetKMsgSummary(kmsgp
, prefix
)
65 kmsgp
= kmsgp
.ikm_next
68 def GetPortDestProc(portp
):
69 """ Display the name and pid of a given port's receiver
71 portp : core.value representing a pointer to a port in the kernel
72 destspacep : core.value representing a pointer to an ipc_space
74 str : string containing receiver's name and pid
76 spacep
= portp
.data
.receiver
78 for tsk
in kern
.tasks
:
79 if tsk
.itk_space
== spacep
:
81 destprocp
= Cast(tsk
.bsd_info
, 'struct proc *')
82 out_str
= "{0:s}({1: <d})".format(destprocp
.p_comm
, destprocp
.p_pid
)
89 @header("{:<20s} {:<28s} {:<12s} {:<8s} {:<6s} {:<19s} {:<26s} {:<26s}\n".format(
90 "", "kmsg", "msgid", "disp", "size", "reply-port", "source", "destination"))
91 def GetKMsgSummary(kmsgp
, prefix_str
=""):
92 """ Display a summary for type ipc_kmsg_t
94 kmsgp : core.value representing the given ipc_kmsg_t struct
96 str : string of summary info for the given ipc_kmsg_t instance
98 kmsghp
= kmsgp
.ikm_header
99 kmsgh
= dereference(kmsghp
)
101 out_string
+= "{0: <20s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
102 ' ', unsigned(kmsgp
), ' '*8, kmsgh
.msgh_id
)
103 prefix_str
= "{0: <20s} ".format(' ') + prefix_str
105 bits
= kmsgh
.msgh_bits
& 0xff
113 disposition
= "rX" # invalid
115 out_string
+= "{0: <2s}".format(disposition
)
119 bits
= (kmsgh
.msgh_bits
& 0xff00) >> 8
128 disposition
= "lX" # invalid
130 out_string
+= "{0: <2s}".format(disposition
)
134 bits
= (kmsgh
.msgh_bits
& 0xff0000) >> 16
143 out_string
+= "{0: <2s}".format(disposition
)
146 if kmsgh
.msgh_bits
& 0x80000000:
147 out_string
+= "{0: <1s}".format("c")
149 out_string
+= "{0: <1s}".format("s")
152 if kmsgh
.msgh_bits
& 0x20000000:
153 out_string
+= "{0: <1s}".format("I")
155 out_string
+= "{0: <1s}".format("-")
158 if kmsgp
.ikm_header
.msgh_remote_port
:
159 dest_proc_name
= GetDestinationProcessFromPort(kmsgp
.ikm_header
.msgh_remote_port
)
161 out_string
+= "{0: ^6d} {1: <#019x} {2: <26s} {3: <26s}\n".format(
162 unsigned(kmsgh
.msgh_size
), unsigned(kmsgh
.msgh_local_port
),
163 GetKMsgSrc(kmsgp
), dest_proc_name
)
165 if kmsgh
.msgh_bits
& 0x80000000:
166 out_string
+= prefix_str
+ "\t" + GetKMsgBody
.header
+ "\n"
167 out_string
+= prefix_str
+ "\t" + GetKMsgBody(kmsgp
, prefix_str
+ "\t") + "\n"
171 @header("{: <20s} {: <20s} {: <10s}".format("descriptor", "address", "size"))
172 def GetMachMsgOOLDescriptorSummary(desc
):
173 """ Returns description for mach_msg_ool_descriptor_t * object
175 format_string
= "{: <#020x} {: <#020x} {: <#010x}"
176 out_string
= format_string
.format(desc
, desc
.address
, desc
.size
)
179 @header("{: <20s} {: <8s} {: <20s} {: <10s} {: <20s}".format("kmsgheader", "size", "body", "ds_count", "dsc_head"))
180 def GetKMsgBody(kmsgp
, prefix_str
=""):
181 """ Routine that prints a complex kmsg's body
183 kmsghp
= kmsgp
.ikm_header
184 kmsgh
= dereference(kmsghp
)
185 format_string
= "{: <#020x} {: <#08x} {: <#020x} {: <#010x} {: <#020x}"
187 body
= Cast(addressof(kmsghp
[1]), 'mach_msg_body_t *')
188 dsc_count
= body
.msgh_descriptor_count
190 dschead
= Cast(addressof(body
[1]), 'mach_msg_descriptor_t *')
191 out_string
+= format_string
.format(kmsghp
, sizeof(dereference(kmsghp
)), body
, unsigned(dsc_count
), dschead
)
193 for i
in range(dsc_count
):
195 out_string
+= "\n" + prefix_str
+ "Descriptor: " + xnudefines
.mach_msg_type_descriptor_strings
[unsigned(dsc
.type.type)]
196 if unsigned(dsc
.type.type) == 0:
199 out_string
+= " name: {: <#20x}".format(p
)
200 elif unsigned(dsc
.type.type) in (1,3):
201 # its OOL DESCRIPTOR or OOL VOLATILE DESCRIPTOR
202 ool
= dsc
.out_of_line
203 out_string
+= " " + GetMachMsgOOLDescriptorSummary(addressof(ool
))
206 def GetKMsgSrc(kmsgp
):
207 """ Routine that prints a kmsg's source process and pid details
209 kmsgp : core.value representing the given ipc_kmsg_t struct
211 str : string containing the name and pid of the kmsg's source proc
213 kmsgsrchp
= Cast(kmsgp
, 'ipc_kmsg_t').ikm_header
214 kmsgpid
= int(Cast(kern
.GetValueFromAddress(unsigned(kmsgsrchp
) + kmsgsrchp
.msgh_size
, 'uint *')[10], 'pid_t'))
216 return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid
), kmsgpid
)
219 def PrintPortSetMembers(space
, setid
, show_kmsg_summary
):
220 """ Print out the members of a given IPC PSet
222 num_entries
= int(space
.is_table_size
)
223 is_tableval
= space
.is_table
224 setid_str
= GetWaitqSetidString(setid
)
226 prefix_str
= "{0:<21s}".format(' '*21)
229 if config
['verbosity'] > vHUMAN
:
233 while idx
< num_entries
:
234 entryval
= GetObjectAtIndexFromArray(is_tableval
, idx
)
235 ie_bits
= unsigned(entryval
.ie_bits
)
236 if not (ie_bits
& 0x00180000):
237 # It's a port entry that's _not_ dead
238 portval
= Cast(entryval
.ie_object
, 'ipc_port_t')
239 waitq
= addressof(portval
.ip_messages
.data
.port
.waitq
)
240 psets
= GetWaitqSets(addressof(portval
.ip_messages
.data
.port
.waitq
))
245 print "{:s}\n{:s}{:s}".format(GetPortDestProc(portval
), prefix_str
, PrintPortSummary
.header
)
246 PrintPortSummary(portval
, show_kmsg_summary
, prefix_str
)
248 sys
.stderr
.write('{:d}/{:d}... \r'.format(idx
, num_entries
))
253 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
254 "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
255 def PrintPortSetSummary(pset
, space
= 0):
256 """ Display summary for a given struct ipc_pset *
258 pset : core.value representing a pset in the kernel
260 str : string of summary information for the given pset
263 show_kmsg_summary
= False
264 if config
['verbosity'] > vHUMAN
:
265 show_kmsg_summary
= True
268 if pset
.ips_object
.io_bits
& 0x80000000:
269 setid
= pset
.ips_messages
.data
.pset
.setq
.wqset_id
270 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
271 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
272 pset
.ips_messages
.data
.pset
.local_name
, "ASet",
273 pset
.ips_object
.io_references
,
274 pset
.ips_messages
.data
.pset
.local_name
)
277 out_str
+= "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
278 unsigned(pset
), addressof(pset
.ips_messages
), ' '*7,
279 pset
.ips_messages
.data
.pset
.local_name
, "DSet",
280 pset
.ips_object
.io_references
,
281 pset
.ips_messages
.data
.pset
.local_name
)
284 if setid
!= 0 and space
!= 0:
285 PrintPortSetMembers(space
, setid
, show_kmsg_summary
)
291 @lldb_command('showipc')
292 def ShowIPC(cmd_args
=None):
293 """ Routine to print data for the given IPC space
294 Usage: showipc <address of ipc space>
297 print "No arguments passed"
298 print ShowIPC
.__doc
__
300 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
302 print "unknown arguments:", str(cmd_args
)
304 print PrintIPCInformation
.header
305 PrintIPCInformation(ipc
, False, False)
311 @lldb_command('showtaskipc')
312 def ShowTaskIPC(cmd_args
=None):
313 """ Routine to print IPC summary of given task
314 Usage: showtaskipc <address of task>
317 print "No arguments passed"
318 print ShowTaskIPC
.__doc
__
320 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
322 print "unknown arguments:", str(cmd_args
)
324 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
325 pval
= Cast(tval
.bsd_info
, 'proc *')
326 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
327 print GetTaskIPCSummary
.header
328 print GetTaskIPCSummary(tval
)
330 # EndMacro: showtaskipc
334 @lldb_command('showallipc')
335 def ShowAllIPC(cmd_args
=None):
336 """ Routine to print IPC summary of all tasks
340 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
341 pval
= Cast(t
.bsd_info
, 'proc *')
342 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
343 print PrintIPCInformation
.header
344 PrintIPCInformation(t
.itk_space
, False, False) + "\n\n"
346 # EndMacro: showallipc
348 @lldb_command('showipcsummary')
349 def ShowIPCSummary(cmd_args
=None):
350 """ Summarizes the IPC state of all tasks.
351 This is a convenient way to dump some basic clues about IPC messaging. You can use the output to determine
352 tasks that are candidates for further investigation.
354 print GetTaskIPCSummary
.header
356 print GetTaskIPCSummary(t
)
359 def GetKObjectFromPort(portval
):
360 """ Get Kobject description from the port.
361 params: portval - core.value representation of 'ipc_port *' object
362 returns: str - string of kobject information
364 kobject_str
= "{0: <#020x}".format(portval
.kdata
.kobject
)
365 io_bits
= unsigned(portval
.ip_object
.io_bits
)
366 objtype_index
= io_bits
& 0xfff
367 if objtype_index
< len(xnudefines
.kobject_types
) :
368 desc_str
= "kobject({0:s})".format(xnudefines
.kobject_types
[objtype_index
])
369 if xnudefines
.kobject_types
[objtype_index
] in ('TASK_RESUME', 'TASK'):
370 desc_str
+= " " + GetProcNameForTask(Cast(portval
.kdata
.kobject
, 'task *'))
372 desc_str
= "kobject(UNKNOWN) {:d}".format(objtype_index
)
373 return kobject_str
+ " " + desc_str
375 @static_var('destcache', {})
376 def GetDestinationProcessFromPort(port
):
378 params: port - core.value representation of 'ipc_port *' object
379 returns: str - name of process
382 dest_space
= port
.data
.receiver
384 #update destcache if data is not found
385 if hex(dest_space
) not in GetDestinationProcessFromPort
.destcache
:
387 if hex(t
.itk_space
) == hex(dest_space
):
388 pval
= Cast(t
.bsd_info
, 'proc *')
389 GetDestinationProcessFromPort
.destcache
[hex(dest_space
)] = (t
, pval
)
393 else: found_dest
= True
396 (ftask
, fproc
) = GetDestinationProcessFromPort
.destcache
[hex(dest_space
)]
398 out_str
= "{0:s}({1:d})".format(fproc
.p_comm
, fproc
.p_pid
)
400 out_str
= "task {0: <#020x}".format(ftask
)
405 @header("{0: <20s} {1: <20s}".format("destname", "destination") )
406 def GetPortDestinationSummary(port
):
407 """ Get destination information for a port.
408 params: port - core.value representation of 'ipc_port *' object
409 returns: str - string of info about ports destination
412 format_string
= "{0: <20s} {1: <20s}"
415 ipc_space_kernel
= unsigned(kern
.globals.ipc_space_kernel
)
416 target_spaceval
= port
.data
.receiver
417 if unsigned(target_spaceval
) == ipc_space_kernel
:
418 destname_str
= GetKObjectFromPort(port
)
420 if int(port
.ip_object
.io_bits
) & 0x80000000 :
421 destname_str
= "{0: <#020x}".format(port
.ip_messages
.data
.port
.receiver_name
)
422 destination_str
= GetDestinationProcessFromPort(port
)
424 destname_str
= "{0: <#020x}".format(port
)
425 destination_str
= "inactive-port"
427 out_str
+= format_string
.format(destname_str
, destination_str
)
430 @lldb_type_summary(['ipc_entry_t'])
431 @header("{: <20s} {: <20s} {: <8s} {: <8s} {: <8s} {: <8s} {: <20s} {: <20s}".format("object", "name","rite", "urefs", "nsets", "nmsgs", "destname", "destination"))
432 def GetIPCEntrySummary(entry
, ipc_name
='', rights_filter
=0):
433 """ Get summary of a ipc entry.
435 entry - core.value representing ipc_entry_t in the kernel
436 ipc_name - str of format '0x0123' for display in summary.
438 str - string of ipc entry related information
445 'O' : Send-once right
446 types of notifications:
447 's' : Send-Possible notification armed
448 'd' : Send-Possible notification requested
449 'n' : Dead-Name notification requested
451 'x' : No-Senders notification requested
454 entry_ptr
= int(hex(entry
), 16)
455 format_string
= "{: <#020x} {: <12s} {: <8s} {: <8d} {: <8d} {: <8d} {: <20s} {: <20s}"
460 ie_object
= entry
.ie_object
461 ie_bits
= int(entry
.ie_bits
)
462 urefs
= int(ie_bits
& 0xffff)
465 if ie_bits
& 0x00100000 :
467 elif ie_bits
& 0x00080000:
469 psetval
= Cast(ie_object
, 'ipc_pset *')
470 set_str
= GetWaitqSets(addressof(psetval
.ips_messages
.data
.pset
.setq
.wqset_q
))
474 if ie_bits
& 0x00010000 :
475 if ie_bits
& 0x00020000 :
481 elif ie_bits
& 0x00020000:
484 elif ie_bits
& 0x00040000 :
487 portval
= Cast(ie_object
, 'ipc_port_t')
488 if int(entry
.index
.request
) != 0:
489 requestsval
= portval
.ip_requests
490 sorightval
= requestsval
[int(entry
.index
.request
)].notify
.port
491 soright_ptr
= unsigned(sorightval
)
493 # send-possible armed
494 if soright_ptr
& 0x1 : right_str
+='s'
495 # send-possible requested
496 elif soright_ptr
& 0x2 : right_str
+='d'
497 # dead-name notification requested
498 else : right_str
+='n'
499 # XXX: What does this bit mean?
500 if ie_bits
& 0x00800000 : right_str
+='c'
501 # No-senders notification requested
502 if portval
.ip_nsrequest
!= 0: right_str
+='x'
503 # now show the port destination part
504 destname_str
= GetPortDestinationSummary(Cast(ie_object
, 'ipc_port_t'))
505 # Get the number of sets to which this port belongs
506 set_str
= GetWaitqSets(addressof(portval
.ip_messages
.data
.port
.waitq
))
508 nmsgs
= portval
.ip_messages
.data
.port
.msgcount
509 if rights_filter
== 0 or rights_filter
== right_str
:
510 out_str
= format_string
.format(ie_object
, ipc_name
, right_str
, urefs
, nsets
, nmsgs
, destname_str
, destination_str
)
513 @header("{0: >20s}".format("user bt") )
514 def GetPortUserStack(port
, task
):
515 """ Get UserStack information for the given port & task.
516 params: port - core.value representation of 'ipc_port *' object
517 task - value representing 'task *' object
518 returns: str - string information on port's userstack
521 ie_port_callstack
= port
.ip_callstack
522 ie_port_spares
= port
.ip_spares
[0]
523 proc_val
= Cast(task
.bsd_info
, 'proc *')
524 if ie_port_callstack
[0]:
525 out_str
+= "{: <10x}".format(ie_port_callstack
[0])
527 while count
< 16 and ie_port_callstack
[count
]:
528 out_str
+= ": <10x".format(ie_port_callstack
[count
])
530 if ie_port_spares
!= proc_val
.p_pid
:
531 out_str
+= " ({:<10d})".format(ie_port_spares
)
535 @lldb_type_summary(['ipc_space *'])
536 @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'))
537 def PrintIPCInformation(space
, show_entries
=False, show_userstack
=False, rights_filter
=0):
538 """ Provide a summary of the ipc space
541 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#18x} {6: >8d} {7: <8d}"
542 is_tableval
= space
.is_table
543 ports
= int(space
.is_table_size
)
545 is_bits
= int(space
.is_bits
)
546 if (is_bits
& 0x40000000) == 0: flags
+='A'
548 if (is_bits
& 0x20000000) != 0: flags
+='G'
549 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
)
551 #should show the each individual entries if asked.
552 if show_entries
== True:
553 print "\t" + GetIPCEntrySummary
.header
556 while index
< num_entries
:
557 entryval
= GetObjectAtIndexFromArray(is_tableval
, index
)
558 entry_ie_bits
= unsigned(entryval
.ie_bits
)
559 if (int(entry_ie_bits
) & 0x001f0000 ) != 0:
560 entry_name
= "{0: <#020x}".format( (index
<<8 | entry_ie_bits
>> 24) )
561 entry_str
= GetIPCEntrySummary(entryval
, entry_name
, rights_filter
)
562 if len(entry_str
) > 0:
563 print " \r\t" + entry_str
564 if show_userstack
== True:
565 entryport
= Cast(entryval
.ie_object
, 'ipc_port *')
566 if entryval
.ie_object
and (int(entry_ie_bits
) & 0x00070000) and entryport
.ip_callstack
[0]:
567 print GetPortUserStack
.header
+ GetPortUserStack(entryport
, space
.is_task
)
569 # give some progress indication (this is especially
570 # helpful for tasks with large sets of rights)
571 sys
.stderr
.write(' {:d}/{:d}...\r'.format(index
, num_entries
))
573 #done with showing entries
578 @lldb_command('showrights', 'R:')
579 def ShowRights(cmd_args
=None, cmd_options
={}):
580 """ Routine to print rights information for the given IPC space
581 Usage: showrights [-R rights_type] <address of ipc space>
582 -R rights_type : only display rights matching the string 'rights_type'
589 'O' : Send-once right
590 types of notifications (append to rights type string):
591 's' : Send-Possible notification armed
592 'd' : Send-Possible notification requested
593 'n' : Dead-Name notification requested
595 'x' : No-Senders notification requested
598 print "No arguments passed"
599 print ShowRights
.__doc
__
601 ipc
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_space *')
603 print "unknown arguments:", str(cmd_args
)
606 if "-R" in cmd_options
:
607 rights_type
= cmd_options
["-R"]
608 print PrintIPCInformation
.header
609 PrintIPCInformation(ipc
, True, False, rights_type
)
611 # EndMacro: showrights
613 @lldb_command('showtaskrights','R:')
614 def ShowTaskRights(cmd_args
=None, cmd_options
={}):
615 """ Routine to ipc rights information for a task
616 Usage: showtaskrights [-R rights_type] <task address>
617 -R rights_type : only display rights matching the string 'rights_type'
624 'O' : Send-once right
625 types of notifications (append to rights type string):
626 's' : Send-Possible notification armed
627 'd' : Send-Possible notification requested
628 'n' : Dead-Name notification requested
630 'x' : No-Senders notification requested
633 print "No arguments passed"
634 print ShowTaskStacksCmdHelper
.__doc
__
636 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
638 print "unknown arguments:", str(cmd_args
)
641 if "-R" in cmd_options
:
642 rights_type
= cmd_options
["-R"]
643 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
644 pval
= Cast(tval
.bsd_info
, 'proc *')
645 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
646 print PrintIPCInformation
.header
647 PrintIPCInformation(tval
.itk_space
, True, False, rights_type
)
649 # Macro: showataskrightsbt
651 @lldb_command('showtaskrightsbt', 'R:')
652 def ShowTaskRightsBt(cmd_args
=None, cmd_options
={}):
653 """ Routine to ipc rights information with userstacks for a task
654 Usage: showtaskrightsbt [-R rights_type] <task address>
655 -R rights_type : only display rights matching the string 'rights_type'
662 'O' : Send-once right
663 types of notifications (append to rights type string):
664 's' : Send-Possible notification armed
665 'd' : Send-Possible notification requested
666 'n' : Dead-Name notification requested
668 'x' : No-Senders notification requested
671 print "No arguments passed"
672 print ShowTaskRightsBt
.__doc
__
674 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
676 print "unknown arguments:", str(cmd_args
)
679 if "-R" in cmd_options
:
680 rights_type
= cmd_options
["-R"]
681 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
682 pval
= Cast(tval
.bsd_info
, 'proc *')
683 print GetTaskSummary(tval
) + " " + GetProcSummary(pval
)
684 print PrintIPCInformation
.header
685 PrintIPCInformation(tval
.itk_space
, True, True, rights_type
)
687 # EndMacro: showtaskrightsbt
689 # Macro: showallrights
691 @lldb_command('showallrights', 'R:')
692 def ShowAllRights(cmd_args
=None, cmd_options
={}):
693 """ Routine to print rights information for IPC space of all tasks
694 Usage: showallrights [-R rights_type]
695 -R rights_type : only display rights matching the string 'rights_type'
702 'O' : Send-once right
703 types of notifications (append to rights type string):
704 's' : Send-Possible notification armed
705 'd' : Send-Possible notification requested
706 'n' : Dead-Name notification requested
708 'x' : No-Senders notification requested
711 if "-R" in cmd_options
:
712 rights_type
= cmd_options
["-R"]
714 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
715 pval
= Cast(t
.bsd_info
, 'proc *')
716 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
718 print PrintIPCInformation
.header
719 PrintIPCInformation(t
.itk_space
, True, False, rights_type
) + "\n\n"
720 except (KeyboardInterrupt, SystemExit):
723 print "Failed to get IPC information. Do individual showtaskrights <task> to find the error. \n\n"
725 # EndMacro: showallrights
727 # Macro: showpipestats
728 @lldb_command('showpipestats')
729 def ShowPipeStats(cmd_args
=None):
730 """ Display pipes usage information in the kernel
732 print "Number of pipes: {: d}".format(kern
.globals.amountpipes
)
733 print "Memory used by pipes: {:s}".format(sizeof_fmt(int(kern
.globals.amountpipekva
)))
734 print "Max memory allowed for pipes: {:s}".format(sizeof_fmt(int(kern
.globals.maxpipekva
)))
735 # EndMacro: showpipestats
737 # Macro: showtaskbusyports
738 @lldb_command('showtaskbusyports')
739 def ShowTaskBusyPorts(cmd_args
=None):
740 """ Routine to print information about receive rights belonging to this task that
741 have enqueued messages. This is oten a sign of a blocked or hung process
742 Usage: showtaskbusyports <task address>
745 print "No arguments passed. Please pass in the address of a task"
746 print ShowTaskBusyPorts
.__doc
__
748 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
749 PrintTaskBusyPorts(task
)
752 def PrintTaskBusyPorts(task
):
753 """ Prints all busy ports for a given task. ie. all receive rights belonging
754 to this task that have enqueued messages.
756 task : core.value representing a task in kernel
758 str : String containing information about the given task's busy ports
762 while i
< isp
.is_table_size
:
763 iep
= addressof(isp
.is_table
[i
])
764 if iep
.ie_bits
& 0x00020000:
765 port
= Cast(iep
.ie_object
, 'ipc_port_t')
766 if port
.ip_messages
.data
.port
.msgcount
> 0:
767 print PrintPortSummary
.header
768 PrintPortSummary(port
)
771 # EndMacro: showtaskbusyports
773 # Macro: showallbusyports
774 @lldb_command('showallbusyports')
775 def ShowAllBusyPorts(cmd_args
=None):
776 """ Routine to print information about all receive rights on the system that
777 have enqueued messages.
779 task_queue_head
= kern
.globals.tasks
781 for tsk
in kern
.tasks
:
782 PrintTaskBusyPorts(tsk
)
784 # EndMacro: showallbusyports
787 @lldb_command('showport','K')
788 def ShowPort(cmd_args
=None, cmd_options
={}):
789 """ Routine that lists details about a given IPC port
790 Syntax: (lldb) showport 0xaddr
793 if "-K" in cmd_options
:
796 print "Please specify the address of the port whose details you want to print"
797 print ShowPort
.__doc
__
799 port
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_port *')
800 print PrintPortSummary
.header
801 PrintPortSummary(port
, show_kmsgs
)
805 @lldb_command('showmqueue', "S:")
806 def ShowMQueue(cmd_args
=None, cmd_options
={}):
807 """ Routine that lists details about a given mqueue
808 Syntax: (lldb) showmqueue 0xaddr [-S ipc_space]
811 print "Please specify the address of the ipc_mqueue whose details you want to print"
812 print ShowMQueue
.__doc
__
815 if "-S" in cmd_options
:
816 space
= kern
.GetValueFromAddress(cmd_options
["-S"], 'struct ipc_space *')
817 mqueue
= kern
.GetValueFromAddress(cmd_args
[0], 'struct ipc_mqueue *')
818 wq_type
= mqueue
.data
.pset
.setq
.wqset_q
.waitq_type
819 if int(wq_type
) == 3:
820 psetoff
= getfieldoffset('struct ipc_pset', 'ips_messages')
821 pset
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(psetoff
)
822 print PrintPortSetSummary
.header
823 PrintPortSetSummary(kern
.GetValueFromAddress(pset
, 'struct ipc_pset *'), space
)
824 elif int(wq_type
) == 2:
825 portoff
= getfieldoffset('struct ipc_port', 'ip_messages')
826 port
= unsigned(ArgumentStringToInt(cmd_args
[0])) - unsigned(portoff
)
827 print PrintPortSummary
.header
828 PrintPortSummary(kern
.GetValueFromAddress(port
, 'struct ipc_port *'))
830 print "Invalid mqueue? (waitq type {:d} is invalid)".format(int(wq_type
))
831 # EndMacro: showmqueue
834 @lldb_command('showkmsg')
835 def ShowKMSG(cmd_args
=[]):
836 """ Show detail information about a <ipc_kmsg_t> structure
837 Usage: (lldb) showkmsg <ipc_kmsg_t>
840 raise ArgumentError('Invalid arguments')
841 kmsg
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_kmsg_t')
842 print GetKMsgSummary
.header
843 print GetKMsgSummary(kmsg
)
848 @lldb_command('showpset', "S:")
849 def ShowPSet(cmd_args
=None, cmd_options
={}):
850 """ Routine that prints details for a given ipc_pset *
851 Syntax: (lldb) showpset 0xaddr [-S ipc_space]
854 print "Please specify the address of the pset whose details you want to print"
855 print ShowPSet
.__doc
__
858 if "-S" in cmd_options
:
859 space
= kern
.GetValueFromAddress(cmd_options
["-S"], 'struct ipc_space *')
861 print PrintPortSetSummary
.header
862 PrintPortSetSummary(kern
.GetValueFromAddress(cmd_args
[0], 'ipc_pset *'), space
)
865 # IPC importance inheritance related macros.
867 @lldb_command('showalliits')
868 def ShowAllIITs(cmd_args
=[], cmd_options
={}):
869 """ Development only macro. Show list of all iits allocated in the system. """
871 iit_queue
= kern
.globals.global_iit_alloc_queue
873 print "This debug macro is only available in development or debug kernels"
876 print GetIPCImportantTaskSummary
.header
877 for iit
in IterateQueue(iit_queue
, 'struct ipc_importance_task *', 'iit_allocation'):
878 print GetIPCImportantTaskSummary(iit
)
881 @header("{: <18s} {: <3s} {: <18s} {: <20s} {: <18s} {: <8s}".format("ipc_imp_inherit", "don", "to_task", "proc_name", "from_elem", "depth"))
882 @lldb_type_summary(['ipc_importance_inherit *', 'ipc_importance_inherit_t'])
883 def GetIPCImportanceInheritSummary(iii
):
884 """ describes iii object of type ipc_importance_inherit_t * """
886 fmt
= "{o: <#018x} {don: <3s} {o.iii_to_task.iit_task: <#018x} {task_name: <20s} {o.iii_from_elem: <#018x} {o.iii_depth: <#08x}"
888 if unsigned(iii
.iii_donating
):
890 taskname
= GetProcNameForTask(iii
.iii_to_task
.iit_task
)
891 if hasattr(iii
.iii_to_task
, 'iit_bsd_pid'):
892 taskname
= "({:d}) {:s}".format(iii
.iii_to_task
.iit_bsd_pid
, iii
.iii_to_task
.iit_procname
)
893 out_str
+= fmt
.format(o
=iii
, task_name
= taskname
, don
=donating_str
)
896 @static_var('recursion_count', 0)
897 @header("{: <18s} {: <4s} {: <8s} {: <8s} {: <18s} {: <18s}".format("iie", "type", "refs", "made", "#kmsgs", "#inherits"))
898 @lldb_type_summary(['ipc_importance_elem *'])
899 def GetIPCImportanceElemSummary(iie
):
900 """ describes an ipc_importance_elem * object """
902 if GetIPCImportanceElemSummary
.recursion_count
> 500:
903 GetIPCImportanceElemSummary
.recursion_count
= 0
904 return "Recursion of 500 reached"
907 fmt
= "{: <#018x} {: <4s} {: <8d} {: <8d} {: <#018x} {: <#018x}"
909 if unsigned(iie
.iie_bits
) & 0x80000000:
911 refs
= unsigned(iie
.iie_bits
) & 0x7fffffff
912 made_refs
= unsigned(iie
.iie_made
)
913 kmsg_count
= sum(1 for i
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'))
914 inherit_count
= sum(1 for i
in IterateQueue(iie
.iie_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'))
915 out_str
+= fmt
.format(iie
, type_str
, refs
, made_refs
, kmsg_count
, inherit_count
)
916 if config
['verbosity'] > vHUMAN
:
918 out_str
+= "\n\t"+ GetKMsgSummary
.header
919 for k
in IterateQueue(iie
.iie_kmsgs
, 'struct ipc_kmsg *', 'ikm_inheritance'):
920 out_str
+= "\t" + "{: <#018x}".format(k
.ikm_header
.msgh_remote_port
) + ' ' + GetKMsgSummary(k
, "\t").lstrip()
922 if inherit_count
> 0:
923 out_str
+= "\n\t" + GetIPCImportanceInheritSummary
.header
+ "\n"
924 for i
in IterateQueue(iie
.iie_inherits
, 'struct ipc_importance_inherit *', 'iii_inheritance'):
925 out_str
+= "\t" + GetIPCImportanceInheritSummary(i
) + "\n"
927 if type_str
== "INH":
928 iii
= Cast(iie
, 'struct ipc_importance_inherit *')
929 out_str
+= "Inherit from: " + GetIPCImportanceElemSummary(iii
.iii_from_elem
)
933 @header("{: <18s} {: <18s} {: <20s}".format("iit", "task", "name"))
934 @lldb_type_summary(['ipc_importance_task *'])
935 def GetIPCImportantTaskSummary(iit
):
936 """ iit is a ipc_importance_task value object.
938 fmt
= "{: <#018x} {: <#018x} {: <20s}"
940 pname
= GetProcNameForTask(iit
.iit_task
)
941 if hasattr(iit
, 'iit_bsd_pid'):
942 pname
= "({:d}) {:s}".format(iit
.iit_bsd_pid
, iit
.iit_procname
)
943 out_str
+= fmt
.format(iit
, iit
.iit_task
, pname
)
946 @lldb_command('showallimportancetasks')
947 def ShowIPCImportanceTasks(cmd_args
=[], cmd_options
={}):
948 """ display a list of all tasks with ipc importance information.
949 Usage: (lldb) showallimportancetasks
950 Tip: add "-v" to see detailed information on each kmsg or inherit elems
952 print ' ' + GetIPCImportantTaskSummary
.header
+ ' ' + GetIPCImportanceElemSummary
.header
955 if unsigned(t
.task_imp_base
):
956 s
+= ' ' + GetIPCImportantTaskSummary(t
.task_imp_base
)
957 s
+= ' ' + GetIPCImportanceElemSummary(addressof(t
.task_imp_base
.iit_elem
))
960 @lldb_command('showipcimportance', '')
961 def ShowIPCImportance(cmd_args
=[], cmd_options
={}):
962 """ Describe an importance from <ipc_importance_elem_t> argument.
963 Usage: (lldb) showimportance <ipc_importance_elem_t>
966 raise ArgumentError("Please provide valid argument")
968 elem
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_importance_elem_t')
969 print GetIPCImportanceElemSummary
.header
970 print GetIPCImportanceElemSummary(elem
)
972 @header("{: <18s} {: <10s} {: <18s} {: <18s} {: <8s} {: <5s} {: <5s} {: <5s}".format("ivac", "refs", "port", "tbl", "tblsize", "index", "Grow", "freelist"))
973 @lldb_type_summary(['ipc_voucher_attr_control *', 'ipc_voucher_attr_control_t'])
974 def GetIPCVoucherAttrControlSummary(ivac
):
975 """ describes a voucher attribute control settings """
977 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}"
980 if unsigned(ivac
) == 0:
981 return "{: <#018x}".format(ivac
)
983 if unsigned(ivac
.ivac_is_growing
):
985 out_str
+= fmt
.format(c
=ivac
, growing
= growing_str
)
988 @lldb_command('showivac','')
989 def ShowIPCVoucherAttributeControl(cmd_args
=[], cmd_options
={}):
990 """ Show summary of voucher attribute contols.
991 Usage: (lldb) showivac <ipc_voucher_attr_control_t>
994 raise ArgumentError("Please provide correct arguments.")
995 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
996 print GetIPCVoucherAttrControlSummary
.header
997 print GetIPCVoucherAttrControlSummary(ivac
)
998 if config
['verbosity'] > vHUMAN
:
1000 last_entry_index
= unsigned(ivac
.ivac_table_size
)
1001 print "index " + GetIPCVoucherAttributeEntrySummary
.header
1002 while cur_entry_index
< last_entry_index
:
1003 print "{: <5d} ".format(cur_entry_index
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[cur_entry_index
]))
1004 cur_entry_index
+= 1
1009 @header("{: <18s} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}".format("ivam", "get_value_fn", "extract_fn", "release_value_fn", "command_fn", "release_fn"))
1010 @lldb_type_summary(['ipc_voucher_attr_manager *', 'ipc_voucher_attr_manager_t'])
1011 def GetIPCVoucherAttrManagerSummary(ivam
):
1012 """ describes a voucher attribute manager settings """
1014 fmt
= "{: <#018x} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}"
1016 if unsigned(ivam
) == 0 :
1017 return "{: <#018x}".format(ivam
)
1019 get_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_get_value
))
1020 extract_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_extract_content
))
1021 release_value_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release_value
))
1022 command_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_command
))
1023 release_fn
= kern
.Symbolicate(unsigned(ivam
.ivam_release
))
1024 out_str
+= fmt
.format(ivam
, get_value_fn
, extract_fn
, release_value_fn
, command_fn
, release_fn
)
1029 @header("{: <18s} {: <10s} {:s} {:s}".format("ivgte", "key", GetIPCVoucherAttrControlSummary
.header
.strip(), GetIPCVoucherAttrManagerSummary
.header
.strip()))
1030 @lldb_type_summary(['ipc_voucher_global_table_element *', 'ipc_voucher_global_table_element_t'])
1031 def GetIPCVoucherGlobalTableElementSummary(ivgte
):
1032 """ describes a ipc_voucher_global_table_element object """
1034 fmt
= "{g: <#018x} {g.ivgte_key: <10d} {ctrl_s:s} {mgr_s:s}"
1035 out_str
+= fmt
.format(g
=ivgte
, ctrl_s
=GetIPCVoucherAttrControlSummary(ivgte
.ivgte_control
), mgr_s
=GetIPCVoucherAttrManagerSummary(ivgte
.ivgte_manager
))
1038 @lldb_command('showglobalvouchertable', '')
1039 def ShowGlobalVoucherTable(cmd_args
=[], cmd_options
={}):
1040 """ show detailed information of all voucher attribute managers registered with vouchers system
1041 Usage: (lldb) showglobalvouchertable
1043 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1044 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1045 print GetIPCVoucherGlobalTableElementSummary
.header
1046 for i
in range(elems
):
1047 elt
= addressof(kern
.globals.iv_global_table
[i
])
1048 print GetIPCVoucherGlobalTableElementSummary(elt
)
1050 # Type summaries for Bag of Bits.
1052 @lldb_type_summary(['user_data_value_element', 'user_data_element_t'])
1053 @header("{0: <20s} {1: <16s} {2: <20s} {3: <20s} {4: <16s} {5: <20s}".format("user_data_ve", "maderefs", "checksum", "hash value", "size", "data"))
1054 def GetBagofBitsElementSummary(data_element
):
1055 """ Summarizes the Bag of Bits element
1056 params: data_element = value of the object of type user_data_value_element_t
1057 returns: String with summary of the type.
1059 format_str
= "{0: <#020x} {1: <16d} {2: <#020x} {3: <#020x} {4: <16d}"
1060 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
))
1063 for i
in range(0, (unsigned(data_element
.e_size
) - 1)):
1064 out_string
+= "{:02x}".format(int(data_element
.e_data
[i
]))
1067 def GetIPCHandleSummary(handle_ptr
):
1068 """ converts a handle value inside a voucher attribute table to ipc element and returns appropriate summary.
1069 params: handle_ptr - uint64 number stored in handle of voucher.
1070 returns: str - string summary of the element held in internal structure
1072 elem
= kern
.GetValueFromAddress(handle_ptr
, 'ipc_importance_elem_t')
1073 if elem
.iie_bits
& 0x80000000 :
1074 iie
= Cast(elem
, 'struct ipc_importance_inherit *')
1075 return GetIPCImportanceInheritSummary(iie
)
1077 iit
= Cast(elem
, 'struct ipc_importance_task *')
1078 return GetIPCImportantTaskSummary(iit
)
1080 def GetATMHandleSummary(handle_ptr
):
1081 """ Convert a handle value to atm value and returns corresponding summary of its fields.
1082 params: handle_ptr - uint64 number stored in handle of voucher
1083 returns: str - summary of atm value
1085 elem
= kern
.GetValueFromAddress(handle_ptr
, 'atm_value *')
1086 return GetATMValueSummary(elem
)
1088 def GetBankHandleSummary(handle_ptr
):
1089 """ converts a handle value inside a voucher attribute table to bank element and returns appropriate summary.
1090 params: handle_ptr - uint64 number stored in handle of voucher.
1091 returns: str - summary of bank element
1093 if handle_ptr
== 1 :
1094 return "Bank task of Current task"
1095 elem
= kern
.GetValueFromAddress(handle_ptr
, 'bank_element_t')
1096 if elem
.be_type
& 1 :
1097 ba
= Cast(elem
, 'struct bank_account *')
1098 return GetBankAccountSummary(ba
)
1100 bt
= Cast(elem
, 'struct bank_task *')
1101 return GetBankTaskSummary(bt
)
1103 def GetBagofBitsHandleSummary(handle_ptr
):
1104 """ Convert a handle value to bag of bits value and returns corresponding summary of its fields.
1105 params: handle_ptr - uint64 number stored in handle of voucher
1106 returns: str - summary of bag of bits element
1108 elem
= kern
.GetValueFromAddress(handle_ptr
, 'user_data_element_t')
1109 return GetBagofBitsElementSummary(elem
)
1111 @static_var('attr_managers',{1: GetATMHandleSummary, 2: GetIPCHandleSummary, 3: GetBankHandleSummary, 7: GetBagofBitsHandleSummary}
)
1112 def GetHandleSummaryForKey(handle_ptr
, key_num
):
1113 """ Get a summary of handle pointer from the voucher attribute manager.
1114 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.
1115 key 2 -> ipc and it puts either ipc_importance_inherit_t or ipc_important_task_t.
1116 key 3 -> Bank and it puts either bank_task_t or bank_account_t.
1117 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.
1119 key_num
= int(key_num
)
1120 if key_num
not in GetHandleSummaryForKey
.attr_managers
:
1121 return "Unknown key %d" % key_num
1122 return GetHandleSummaryForKey
.attr_managers
[key_num
](handle_ptr
)
1125 @header("{: <18s} {: <18s} {: <10s} {: <4s} {: <18s} {: <18s}".format("ivace", "value_handle", "#refs", "rel?", "maderefs", "next_layer"))
1126 @lldb_type_summary(['ivac_entry *', 'ivac_entry_t'])
1127 def GetIPCVoucherAttributeEntrySummary(ivace
, manager_key_num
= 0):
1128 """ Get summary for voucher attribute entry.
1131 fmt
= "{e: <#018x} {e.ivace_value: <#018x} {e.ivace_refs: <10d} {release: <4s} {made_refs: <18s} {next_layer: <18s}"
1137 if unsigned(ivace
.ivace_releasing
):
1139 if unsigned(ivace
.ivace_free
):
1141 if unsigned(ivace
.ivace_layered
):
1142 next_layer
= "{: <#018x}".format(ivace
.ivace_u
.ivaceu_layer
)
1144 made_refs
= "{: <18d}".format(ivace
.ivace_u
.ivaceu_made
)
1146 out_str
+= fmt
.format(e
=ivace
, release
=release_str
, made_refs
=made_refs
, next_layer
=next_layer
)
1147 if config
['verbosity'] > vHUMAN
and manager_key_num
> 0:
1148 out_str
+= " " + GetHandleSummaryForKey(unsigned(ivace
.ivace_value
), manager_key_num
)
1149 if config
['verbosity'] > vHUMAN
:
1150 out_str
+= ' {: <2s} {: <4d} {: <4d}'.format(free_str
, ivace
.ivace_next
, ivace
.ivace_index
)
1153 @lldb_command('showivacfreelist','')
1154 def ShowIVACFreeList(cmd_args
=[], cmd_options
={}):
1155 """ Walk the free list and print every entry in the list.
1156 usage: (lldb) showivacfreelist <ipc_voucher_attr_control_t>
1159 raise ArgumentError('Please provide <ipc_voucher_attr_control_t>')
1160 ivac
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_attr_control_t')
1161 print GetIPCVoucherAttrControlSummary
.header
1162 print GetIPCVoucherAttrControlSummary(ivac
)
1163 if unsigned(ivac
.ivac_freelist
) == 0:
1164 print "ivac table is full"
1166 print "index " + GetIPCVoucherAttributeEntrySummary
.header
1167 next_free
= unsigned(ivac
.ivac_freelist
)
1168 while next_free
!= 0:
1169 print "{: <5d} ".format(next_free
) + GetIPCVoucherAttributeEntrySummary(addressof(ivac
.ivac_table
[next_free
]))
1170 next_free
= unsigned(ivac
.ivac_table
[next_free
].ivace_next
)
1174 @header('{: <18s} {: <8s} {: <18s} {: <18s} {: <18s} {: <18s} {: <18s}'.format("ipc_voucher", "refs", "checksum", "hash", "tbl_size", "table", "voucher_port"))
1175 @lldb_type_summary(['ipc_voucher *', 'ipc_voucher_t'])
1176 def GetIPCVoucherSummary(voucher
, show_entries
=False):
1177 """ describe a voucher from its ipc_voucher * object """
1179 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}"
1180 out_str
+= fmt
.format(v
= voucher
)
1182 if show_entries
or config
['verbosity'] > vHUMAN
:
1183 elems
= unsigned(voucher
.iv_table_size
)
1184 entries_header_str
= "\n\t" + "{: <5s} {: <3s} {: <16s} {: <30s}".format("index", "key", "value_index", "manager") + " " + GetIPCVoucherAttributeEntrySummary
.header
1185 fmt
= "{: <5d} {: <3d} {: <16d} {: <30s}"
1186 for i
in range(elems
):
1187 voucher_entry_index
= unsigned(voucher
.iv_inline_table
[i
])
1188 if voucher_entry_index
:
1189 s
= fmt
.format(i
, GetVoucherManagerKeyForIndex(i
), voucher_entry_index
, GetVoucherAttributeManagerNameForIndex(i
))
1190 e
= GetVoucherValueHandleFromVoucherForIndex(voucher
, i
)
1192 s
+= " " + GetIPCVoucherAttributeEntrySummary(addressof(e
), GetVoucherManagerKeyForIndex(i
) )
1193 if entries_header_str
:
1194 entries_str
= entries_header_str
1195 entries_header_str
= ''
1196 entries_str
+= "\n\t" + s
1197 if not entries_header_str
:
1198 entries_str
+= "\n\t"
1199 out_str
+= entries_str
1202 def GetVoucherManagerKeyForIndex(idx
):
1203 """ Returns key number for index based on global table. Will raise index error if value is incorrect
1205 return unsigned(kern
.globals.iv_global_table
[idx
].ivgte_key
)
1207 def GetVoucherAttributeManagerForKey(k
):
1208 """ Walks through the iv_global_table and finds the attribute manager name
1209 params: k - int key number of the manager
1210 return: cvalue - the attribute manager object.
1214 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1215 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1216 for i
in range(elems
):
1217 elt
= addressof(kern
.globals.iv_global_table
[i
])
1218 if k
== unsigned(elt
.ivgte_key
):
1219 retval
= elt
.ivgte_manager
1223 def GetVoucherAttributeControllerForKey(k
):
1224 """ Walks through the iv_global_table and finds the attribute controller
1225 params: k - int key number of the manager
1226 return: cvalue - the attribute controller object.
1230 entry_size
= sizeof(kern
.globals.iv_global_table
[0])
1231 elems
= sizeof(kern
.globals.iv_global_table
) / entry_size
1232 for i
in range(elems
):
1233 elt
= addressof(kern
.globals.iv_global_table
[i
])
1234 if k
== unsigned(elt
.ivgte_key
):
1235 retval
= elt
.ivgte_control
1240 def GetVoucherAttributeManagerName(ivam
):
1241 """ find the name of the ivam object
1242 param: ivam - cvalue object of type ipc_voucher_attr_manager_t
1243 returns: str - name of the manager
1245 return kern
.Symbolicate(unsigned(ivam
))
1247 def GetVoucherAttributeManagerNameForIndex(idx
):
1248 """ get voucher attribute manager name for index
1249 return: str - name of the attribute manager object
1251 return GetVoucherAttributeManagerName(GetVoucherAttributeManagerForKey(GetVoucherManagerKeyForIndex(idx
)))
1253 def GetVoucherValueHandleFromVoucherForIndex(voucher
, idx
):
1254 """ traverse the voucher attrs and get value_handle in the voucher attr controls table
1256 voucher - cvalue object of type ipc_voucher_t
1257 idx - int index in the entries for which you wish to get actual handle for
1258 returns: cvalue object of type ivac_entry_t
1259 None if no handle found.
1261 manager_key
= GetVoucherManagerKeyForIndex(idx
)
1262 voucher_num_elems
= unsigned(voucher
.iv_table_size
)
1263 if idx
>= voucher_num_elems
:
1264 debuglog("idx %d is out of range max: %d" % (idx
, voucher_num_elems
))
1266 voucher_entry_value
= unsigned(voucher
.iv_inline_table
[idx
])
1267 debuglog("manager_key %d" % manager_key
)
1268 ivac
= GetVoucherAttributeControllerForKey(manager_key
)
1269 if ivac
is None or unsigned(ivac
) == 0:
1270 debuglog("No voucher attribute controller for idx %d" % idx
)
1273 ivac
= kern
.GetValueFromAddress(unsigned(ivac
), 'ipc_voucher_attr_control_t') # ??? No idea why lldb does not addressof directly
1274 ivace_table
= ivac
.ivac_table
1275 if voucher_entry_value
>= unsigned(ivac
.ivac_table_size
):
1276 print "Failed to get ivace for value %d in table of size %d" % (voucher_entry_value
, unsigned(ivac
.ivac_table_size
))
1278 return ivace_table
[voucher_entry_value
]
1282 @lldb_command('showallvouchers')
1283 def ShowAllVouchers(cmd_args
=[], cmd_options
={}):
1284 """ Display a list of all vouchers in the global voucher hash table
1285 Usage: (lldb) showallvouchers
1287 iv_hash_table
= kern
.globals.ivht_bucket
1288 num_buckets
= sizeof(kern
.globals.ivht_bucket
) / sizeof(kern
.globals.ivht_bucket
[0])
1289 print GetIPCVoucherSummary
.header
1290 for i
in range(num_buckets
):
1291 for v
in IterateQueue(iv_hash_table
[i
], 'ipc_voucher_t', 'iv_hash_link'):
1292 print GetIPCVoucherSummary(v
)
1294 @lldb_command('showvoucher', '')
1295 def ShowVoucher(cmd_args
=[], cmd_options
={}):
1296 """ Describe a voucher from <ipc_voucher_t> argument.
1297 Usage: (lldb) showvoucher <ipc_voucher_t>
1300 raise ArgumentError("Please provide valid argument")
1302 voucher
= kern
.GetValueFromAddress(cmd_args
[0], 'ipc_voucher_t')
1303 print GetIPCVoucherSummary
.header
1304 print GetIPCVoucherSummary(voucher
, show_entries
=True)