]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/lldbmacros/ipc.py
xnu-3789.51.2.tar.gz
[apple/xnu.git] / tools / lldbmacros / ipc.py
index db09a4b460d03b0b698016c82972e880fd2cb7d0..6a71e6e3a17979bc8bc329573d9f7c742560aea1 100644 (file)
@@ -5,6 +5,10 @@ from xnu import *
 import sys, shlex
 from utils import *
 from process import *
+from atm import *
+from bank import *
+from waitq import *
+from ioreg import *
 import xnudefines
 
 @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
@@ -25,7 +29,7 @@ def GetTaskIPCSummary(task):
 
 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s}  {5: <20s} {6: <4s}\n".format(
             "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
-def GetPortSummary(port, show_kmsg_summary=True, prefix=""):
+def PrintPortSummary(port, show_kmsg_summary=True, prefix=""):
     """ Display a port's summary
         params:
             port : core.value representing a port in the kernel
@@ -50,17 +54,17 @@ def GetPortSummary(port, show_kmsg_summary=True, prefix=""):
                                 unsigned(portp.ip_messages.data.port.receiver_name),
                                 "DPort", portp.ip_object.io_references, unsigned(portp),
                                 "inactive-port")
-    
+    print out_string
     if show_kmsg_summary:
         kmsgp = Cast(portp.ip_messages.data.port.messages.ikmq_base, 'ipc_kmsg_t')
-        out_string += prefix + GetKMsgSummary.header + prefix + GetKMsgSummary(kmsgp)
-        
-        kmsgheadp = kmsgp
-        kmsgp = kmsgp.ikm_next
-        while (kmsgp) != (kmsgheadp):
-            out_string += prefix + GetKMsgSummary(kmsgp)
+        if unsigned(kmsgp):
+            print prefix + GetKMsgSummary.header + prefix + GetKMsgSummary(kmsgp, prefix)
+            kmsgheadp = kmsgp
             kmsgp = kmsgp.ikm_next
-    return out_string
+            while (kmsgp) != (kmsgheadp):
+                print prefix + GetKMsgSummary(kmsgp, prefix)
+                kmsgp = kmsgp.ikm_next
+    return
 
 def GetPortDestProc(portp):
     """ Display the name and pid of a given port's receiver
@@ -78,14 +82,14 @@ def GetPortDestProc(portp):
                 destprocp = Cast(tsk.bsd_info, 'struct proc *')
                 out_str = "{0:s}({1: <d})".format(destprocp.p_comm, destprocp.p_pid)
             else:
-                out_str = "task {0: #019x}".format(desttaskp)
+                out_str = "unknown"
             break
     
     return out_str
 
-@header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <19s} {6: <6s}\n".format(
-            "dest-port", "kmsg", "msgid", "disp", "size", "reply-port", "source"))
-def GetKMsgSummary(kmsgp):
+@header("{:<20s} {:<28s} {:<12s} {:<8s} {:<6s} {:<19s} {:<26s} {:<26s}\n".format(
+            "", "kmsg", "msgid", "disp", "size", "reply-port", "source", "destination"))
+def GetKMsgSummary(kmsgp, prefix_str=""):
     """ Display a summary for type ipc_kmsg_t
         params:
             kmsgp : core.value representing the given ipc_kmsg_t struct
@@ -95,28 +99,111 @@ def GetKMsgSummary(kmsgp):
     kmsghp = kmsgp.ikm_header
     kmsgh = dereference(kmsghp)
     out_string = ""
-    out_string += "{0: <19s} {1: #019x} {2: <8s} {3: #011x}   ".format(
-                    ' '*19, unsigned(kmsgp), ' '*8, kmsgh.msgh_id)
+    out_string += "{0: <20s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
+                    ' ', unsigned(kmsgp), ' '*8, kmsgh.msgh_id)
+    prefix_str = "{0: <20s} ".format(' ') + prefix_str
+    disposition = ""
+    bits = kmsgh.msgh_bits & 0xff
+    
+    # remote port
+    if bits == 17:
+        disposition = "rS"
+    elif bits == 18:
+        disposition = "rO"
+    else :
+        disposition = "rX" # invalid
+    
+    out_string += "{0: <2s}".format(disposition)
+    
+    # local port
+    disposition = ""
+    bits = (kmsgh.msgh_bits & 0xff00) >> 8
     
-    if (kmsgh.msgh_bits & 0xff) == 19:
-        out_string += "{0: <2s}".format("rC")
+    if bits == 17:
+        disposition = "lS"
+    elif bits == 18:
+        disposition = "lO"
+    elif bits == 0:
+        disposition = "l-"
     else:
-        out_string += "{0: <2s}".format("rM")
+        disposition = "lX"  # invalid
+        
+    out_string += "{0: <2s}".format(disposition)
+    
+    # voucher
+    disposition = ""
+    bits = (kmsgh.msgh_bits & 0xff0000) >> 16
     
-    if (kmsgh.msgh_bits & 0xff00) == (19 << 8):
-        out_string += "{0: <2s}".format("lC")
+    if bits == 17:
+        disposition = "vS"
+    elif bits == 0:
+        disposition = "v-"
+    else:
+        disposition = "vX"
+
+    out_string += "{0: <2s}".format(disposition) 
+        
+    # complex message
+    if kmsgh.msgh_bits & 0x80000000:
+        out_string += "{0: <1s}".format("c")
     else:
-        out_string += "{0: <2s}".format("lM")
-    if kmsgh.msgh_bits & 0xf0000000:
-        out_string += "{0: <2s}".format("c")
+        out_string += "{0: <1s}".format("s")
+    
+    # importance boost
+    if kmsgh.msgh_bits & 0x20000000:
+        out_string += "{0: <1s}".format("I")
     else:
-        out_string += "{0: <2s}".format("s")
+        out_string += "{0: <1s}".format("-")
     
-    out_string += "{0: >5d}  {1: #019x}  {2: <16s}\n".format(
-                    unsigned(kmsgh.msgh_size), kmsgh.msgh_local_port,
-                    GetKMsgSrc(kmsgp))
+    dest_proc_name = ""
+    if kmsgp.ikm_header.msgh_remote_port:
+        dest_proc_name = GetDestinationProcessFromPort(kmsgp.ikm_header.msgh_remote_port)
+
+    out_string += "{0: ^6d}   {1: <#019x} {2: <26s} {3: <26s}\n".format(
+                    unsigned(kmsgh.msgh_size), unsigned(kmsgh.msgh_local_port),
+                    GetKMsgSrc(kmsgp), dest_proc_name)
+    
+    if kmsgh.msgh_bits & 0x80000000:
+        out_string += prefix_str + "\t" + GetKMsgBody.header + "\n"
+        out_string += prefix_str + "\t" + GetKMsgBody(kmsgp, prefix_str + "\t") + "\n"
+    
+    return out_string
+
+@header("{: <20s} {: <20s} {: <10s}".format("descriptor", "address", "size"))
+def GetMachMsgOOLDescriptorSummary(desc):
+    """ Returns description for mach_msg_ool_descriptor_t * object
+    """
+    format_string = "{: <#020x} {: <#020x} {: <#010x}"
+    out_string = format_string.format(desc, desc.address, desc.size)
     return out_string
 
+@header("{: <20s} {: <8s} {: <20s} {: <10s} {: <20s}".format("kmsgheader", "size", "body", "ds_count", "dsc_head"))
+def GetKMsgBody(kmsgp, prefix_str=""):
+    """ Routine that prints a complex kmsg's body
+    """
+    kmsghp = kmsgp.ikm_header
+    kmsgh = dereference(kmsghp)
+    format_string = "{: <#020x} {: <#08x} {: <#020x} {: <#010x} {: <#020x}"
+    out_string = ""
+    body = Cast(addressof(kmsghp[1]), 'mach_msg_body_t *')
+    dsc_count = body.msgh_descriptor_count
+
+    dschead = Cast(addressof(body[1]), 'mach_msg_descriptor_t *')
+    out_string += format_string.format(kmsghp, sizeof(dereference(kmsghp)), body, unsigned(dsc_count), dschead)
+    
+    for i in range(dsc_count):
+        dsc = dschead[i]        
+        out_string += "\n" + prefix_str + "Descriptor: " + xnudefines.mach_msg_type_descriptor_strings[unsigned(dsc.type.type)]
+        if unsigned(dsc.type.type) == 0:
+            # its a port.
+            p = dsc.port.name
+            out_string += " name: {: <#20x}".format(p)
+        elif unsigned(dsc.type.type) in (1,3):
+            # its OOL DESCRIPTOR or OOL VOLATILE DESCRIPTOR
+            ool = dsc.out_of_line
+            out_string += " " + GetMachMsgOOLDescriptorSummary(addressof(ool))
+    return out_string 
+
 def GetKMsgSrc(kmsgp):
     """ Routine that prints a kmsg's source process and pid details
         params:
@@ -129,9 +216,44 @@ def GetKMsgSrc(kmsgp):
     
     return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid), kmsgpid)
 
+
+def PrintPortSetMembers(space, setid, show_kmsg_summary):
+    """ Print out the members of a given IPC PSet
+    """
+    num_entries = int(space.is_table_size)
+    is_tableval = space.is_table
+    setid_str = GetWaitqSetidString(setid)
+
+    prefix_str = "{0:<21s}".format(' '*21)
+    once = True
+    verbose = False
+    if config['verbosity'] > vHUMAN:
+        verbose = True
+
+    idx = 0
+    while idx < num_entries:
+        entryval = GetObjectAtIndexFromArray(is_tableval, idx)
+        ie_bits = unsigned(entryval.ie_bits)
+        if not (ie_bits & 0x00180000):
+            # It's a port entry that's _not_ dead
+            portval = Cast(entryval.ie_object, 'ipc_port_t')
+            waitq = addressof(portval.ip_messages.data.port.waitq)
+            psets = GetWaitqSets(addressof(portval.ip_messages.data.port.waitq))
+            for ps in psets:
+                if ps == setid_str:
+                    if once:
+                        once = False
+                        print "{:s}\n{:s}{:s}".format(GetPortDestProc(portval), prefix_str, PrintPortSummary.header)
+                    PrintPortSummary(portval, show_kmsg_summary, prefix_str)
+            if verbose:
+                sys.stderr.write('{:d}/{:d}...          \r'.format(idx, num_entries))
+        idx += 1
+    return
+
+
 @header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
             "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
-def GetPortSetSummary(pset):
+def PrintPortSetSummary(pset, space = 0):
     """ Display summary for a given struct ipc_pset *
         params:
             pset : core.value representing a pset in the kernel
@@ -139,7 +261,13 @@ def GetPortSetSummary(pset):
             str  : string of summary information for the given pset
     """
     out_str = ""
+    show_kmsg_summary = False
+    if config['verbosity'] > vHUMAN :
+        show_kmsg_summary = True
+
+    setid = 0
     if pset.ips_object.io_bits & 0x80000000:
+        setid = pset.ips_messages.data.pset.setq.wqset_id
         out_str += "{0: #019x}  {1: #019x} {2: <7s} {3: #011x}   {4: <4s} {5: >6d}  {6: #019x}   ".format(
                     unsigned(pset), addressof(pset.ips_messages), ' '*7,
                     pset.ips_messages.data.pset.local_name, "ASet",
@@ -152,20 +280,12 @@ def GetPortSetSummary(pset):
                     pset.ips_messages.data.pset.local_name, "DSet",
                     pset.ips_object.io_references,
                     pset.ips_messages.data.pset.local_name)
-    
-    once = True
-    setlinksp = addressof(pset.ips_messages.data.pset.set_queue.wqs_setlinks)
-    wql = Cast(pset.ips_messages.data.pset.set_queue.wqs_setlinks.next, 'WaitQueueLink *')
-    portoff = getfieldoffset('struct ipc_port', 'ip_messages')
-    prefix_str = "{0:<21s}".format(' '*21)
-    while unsigned(wql) != unsigned(Cast(setlinksp, 'void *')):
-        portp = kern.GetValueFromAddress(unsigned(wql.wql_element.wqe_queue) - portoff, 'ipc_port *')
-        if once:
-            once = False
-            out_str += "{0:s}\n{1:s}{2:s}".format(GetPortDestProc(portp), prefix_str, GetPortSummary.header)
-        out_str += GetPortSummary(portp, False, prefix_str)
-        wql = Cast(wql.wql_setlinks.next, 'WaitQueueLink *')
-    return out_str
+    print out_str
+
+    if setid != 0 and space != 0:
+        PrintPortSetMembers(space, setid, show_kmsg_summary)
+
+    return
 
 # Macro: showipc
 
@@ -182,8 +302,8 @@ def ShowIPC(cmd_args=None):
     if not ipc:
         print "unknown arguments:", str(cmd_args)
         return False
-    print GetIPCInformation.header
-    print GetIPCInformation(ipc, False, False)
+    print PrintIPCInformation.header
+    PrintIPCInformation(ipc, False, False)
 
 # EndMacro: showipc
 
@@ -221,8 +341,8 @@ def ShowAllIPC(cmd_args=None):
         print GetTaskSummary.header + " " + GetProcSummary.header
         pval = Cast(t.bsd_info, 'proc *')
         print GetTaskSummary(t) + " " + GetProcSummary(pval)
-        print GetIPCInformation.header
-        print GetIPCInformation(t.itk_space, False, False) + "\n\n"
+        print PrintIPCInformation.header
+        PrintIPCInformation(t.itk_space, False, False) + "\n\n"
 
 # EndMacro: showallipc
 
@@ -246,7 +366,18 @@ def GetKObjectFromPort(portval):
     io_bits = unsigned(portval.ip_object.io_bits)
     objtype_index = io_bits & 0xfff
     if objtype_index < len(xnudefines.kobject_types) :
-        desc_str = "kobject({0:s})".format(xnudefines.kobject_types[objtype_index])
+        objtype_str = xnudefines.kobject_types[objtype_index]
+        if objtype_str == 'IOKIT_OBJ':
+            iokit_classnm = GetObjectTypeStr(portval.kdata.kobject)
+            if not iokit_classnm:
+                iokit_classnm = "<unknown class>"
+            else:
+                iokit_classnm = re.sub(r'vtable for ', r'', iokit_classnm)
+            desc_str = "kobject({:s}:{:s})".format(objtype_str, iokit_classnm)
+        else:
+            desc_str = "kobject({0:s})".format(objtype_str)
+            if xnudefines.kobject_types[objtype_index] in ('TASK_RESUME', 'TASK'):
+                desc_str += " " + GetProcNameForTask(Cast(portval.kdata.kobject, 'task *'))
     else:
         desc_str = "kobject(UNKNOWN) {:d}".format(objtype_index)
     return kobject_str + " " + desc_str
@@ -307,18 +438,31 @@ def GetPortDestinationSummary(port):
     return out_str
     
 @lldb_type_summary(['ipc_entry_t'])
-@header("{0: <20s} {1: <20s} {2: <8s} {3: <8s} {4: <20s} {5: <20s}".format("object", "name","rite", "urefs", "destname", "destination"))
-def GetIPCEntrySummary(entry, ipc_name=''):
+@header("{: <20s} {: <20s} {: <8s} {: <8s} {: <8s} {: <8s} {: <20s} {: <20s}".format("object", "name","rite", "urefs", "nsets", "nmsgs", "destname", "destination"))
+def GetIPCEntrySummary(entry, ipc_name='', rights_filter=0):
     """ Get summary of a ipc entry.
         params:
             entry - core.value representing ipc_entry_t in the kernel
             ipc_name - str of format '0x0123' for display in summary.  
         returns:
             str - string of ipc entry related information
+
+        types of rights:
+            'Dead'  : Dead name
+            'Set'   : Port set
+            'S'     : Send right
+            'R'     : Receive right
+            'O'     : Send-once right
+        types of notifications:
+            's'     : Send-Possible notification armed
+            'd'     : Send-Possible notification requested
+            'n'     : Dead-Name notification requested
+            'c'     : ???
+            'x'     : No-Senders notification requested
     """
     out_str = ''    
     entry_ptr = int(hex(entry), 16)
-    format_string = "{0: <#020x} {1: <12s} {2: <8s} {3: <8d} {4: <20s} {5: <20s}"
+    format_string = "{: <#020x} {: <12s} {: <8s} {: <8d} {: <8d} {: <8d} {: <20s} {: <20s}"
     right_str = ''
     destname_str = ''
     destination_str = ''
@@ -326,34 +470,54 @@ def GetIPCEntrySummary(entry, ipc_name=''):
     ie_object = entry.ie_object
     ie_bits = int(entry.ie_bits)
     urefs = int(ie_bits & 0xffff)
+    nsets = 0
+    nmsgs = 0
     if ie_bits & 0x00100000 :
         right_str = 'Dead'
     elif ie_bits & 0x00080000:
         right_str = 'Set'
+        psetval = Cast(ie_object, 'ipc_pset *')
+        set_str = GetWaitqSets(addressof(psetval.ips_messages.data.pset.setq.wqset_q))
+        nsets = len(set_str)
+        nmsgs = 0
     else:
         if ie_bits & 0x00010000 :
             if ie_bits & 0x00020000 :
+                # SEND + RECV
                 right_str = 'SR'
             else:
+                # SEND only
                 right_str = 'S'
         elif ie_bits & 0x00020000:
+            # RECV only
             right_str = 'R'
         elif ie_bits & 0x00040000 :
+            # SEND_ONCE
             right_str = 'O'
+        portval = Cast(ie_object, 'ipc_port_t')
         if int(entry.index.request) != 0:
-            portval = Cast(ie_object, 'ipc_port_t')
             requestsval = portval.ip_requests
             sorightval = requestsval[int(entry.index.request)].notify.port
             soright_ptr = unsigned(sorightval)
             if soright_ptr != 0:
+                 # send-possible armed
                  if soright_ptr & 0x1 : right_str +='s'
+                 # send-possible requested
                  elif soright_ptr & 0x2 : right_str +='d'
+                 # dead-name notification requested
                  else : right_str +='n'
+        # XXX: What does this bit mean?
         if ie_bits & 0x00800000 : right_str +='c'
+        # No-senders notification requested
+        if portval.ip_nsrequest != 0: right_str +='x'
         # now show the port destination part
         destname_str = GetPortDestinationSummary(Cast(ie_object, 'ipc_port_t'))
-        
-    out_str = format_string.format(ie_object, ipc_name, right_str, urefs, destname_str, destination_str)
+        # Get the number of sets to which this port belongs
+        set_str = GetWaitqSets(addressof(portval.ip_messages.data.port.waitq))
+        nsets = len(set_str)
+        nmsgs = portval.ip_messages.data.port.msgcount
+    if rights_filter == 0 or rights_filter == right_str:
+        out_str = format_string.format(ie_object, ipc_name, right_str, urefs, nsets, nmsgs, destname_str, destination_str)
     return out_str
 
 @header("{0: >20s}".format("user bt") )
@@ -379,12 +543,12 @@ def GetPortUserStack(port, task):
     return out_str
 
 @lldb_type_summary(['ipc_space *'])
-@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'))
-def GetIPCInformation(space, show_entries=False, show_userstack=False):
+@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'))
+def PrintIPCInformation(space, show_entries=False, show_userstack=False, rights_filter=0):
     """ Provide a summary of the ipc space
     """
     out_str = ''
-    format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#01x} {6: >10d} {7: >10d}"
+    format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#18x} {6: >8d} {7: <8d}"
     is_tableval = space.is_table
     ports = int(space.is_table_size)
     flags =''
@@ -392,11 +556,11 @@ def GetIPCInformation(space, show_entries=False, show_userstack=False):
     if (is_bits & 0x40000000) == 0: flags +='A'
     else: flags += ' '
     if (is_bits & 0x20000000) != 0: flags +='G'
-    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)
+    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)
     
     #should show the each individual entries if asked.
     if show_entries == True:
-        out_str += "\n\t" + GetIPCEntrySummary.header + "\n"
+        print "\t" + GetIPCEntrySummary.header
         num_entries = ports
         index = 0
         while index < num_entries:
@@ -404,22 +568,41 @@ def GetIPCInformation(space, show_entries=False, show_userstack=False):
             entry_ie_bits = unsigned(entryval.ie_bits)
             if (int(entry_ie_bits) & 0x001f0000 ) != 0:
                 entry_name = "{0: <#020x}".format( (index <<8 | entry_ie_bits >> 24) )
-                out_str += "\t" + GetIPCEntrySummary(entryval, entry_name) + "\n"
-                if show_userstack == True:
-                    entryport = Cast(entryval.ie_object, 'ipc_port *')
-                    if entryval.ie_object and (int(entry_ie_bits) & 0x00070000) and entryport.ip_callstack[0]:
-                        out_str += GetPortUserStack.header
-                        out_str += GetPortUserStack(entryport, space.is_task)
-            index +=1    
+                entry_str = GetIPCEntrySummary(entryval, entry_name, rights_filter)
+                if len(entry_str) > 0:
+                    print "                  \r\t" + entry_str
+                    if show_userstack == True:
+                        entryport = Cast(entryval.ie_object, 'ipc_port *')
+                        if entryval.ie_object and (int(entry_ie_bits) & 0x00070000) and entryport.ip_callstack[0]:
+                            print GetPortUserStack.header + GetPortUserStack(entryport, space.is_task)
+                else:
+                    # give some progress indication (this is especially
+                    # helpful for tasks with large sets of rights)
+                    sys.stderr.write(' {:d}/{:d}...\r'.format(index, num_entries))
+            index += 1
     #done with showing entries
     return out_str
 
 # Macro: showrights
 
-@lldb_command('showrights'
-def ShowRights(cmd_args=None):
+@lldb_command('showrights', 'R:')
+def ShowRights(cmd_args=None, cmd_options={}):
     """  Routine to print rights information for the given IPC space 
-         Usage: showrights <address of ipc space>
+         Usage: showrights [-R rights_type] <address of ipc space>
+                -R rights_type  : only display rights matching the string 'rights_type'
+
+                types of rights:
+                    'Dead'  : Dead name
+                    'Set'   : Port set
+                    'S'     : Send right
+                    'R'     : Receive right
+                    'O'     : Send-once right
+                types of notifications (append to rights type string):
+                    's'     : Send-Possible notification armed
+                    'd'     : Send-Possible notification requested
+                    'n'     : Dead-Name notification requested
+                    'c'     : ???
+                    'x'     : No-Senders notification requested
     """
     if not cmd_args:
         print "No arguments passed"
@@ -429,15 +612,32 @@ def ShowRights(cmd_args=None):
     if not ipc:
         print "unknown arguments:", str(cmd_args)
         return False
-    print GetIPCInformation.header
-    print GetIPCInformation(ipc, True, False)
+    rights_type = 0
+    if "-R" in cmd_options:
+        rights_type = cmd_options["-R"]
+    print PrintIPCInformation.header
+    PrintIPCInformation(ipc, True, False, rights_type)
 
 # EndMacro: showrights
 
-@lldb_command('showtaskrights')
-def ShowTaskRights(cmd_args=None):
+@lldb_command('showtaskrights','R:')
+def ShowTaskRights(cmd_args=None, cmd_options={}):
     """ Routine to ipc rights information for a task
-        Usage: showtaskrights <task address>
+        Usage: showtaskrights [-R rights_type] <task address>
+               -R rights_type  : only display rights matching the string 'rights_type'
+
+               types of rights:
+                   'Dead'  : Dead name
+                   'Set'   : Port set
+                   'S'     : Send right
+                   'R'     : Receive right
+                   'O'     : Send-once right
+               types of notifications (append to rights type string):
+                   's'     : Send-Possible notification armed
+                   'd'     : Send-Possible notification requested
+                   'n'     : Dead-Name notification requested
+                   'c'     : ???
+                   'x'     : No-Senders notification requested
     """
     if cmd_args == None:
         print "No arguments passed"
@@ -447,18 +647,35 @@ def ShowTaskRights(cmd_args=None):
     if not tval:
         print "unknown arguments:", str(cmd_args)
         return False
+    rights_type = 0
+    if "-R" in cmd_options:
+        rights_type = cmd_options["-R"]
     print GetTaskSummary.header + " " + GetProcSummary.header
     pval = Cast(tval.bsd_info, 'proc *')
     print GetTaskSummary(tval) + " " + GetProcSummary(pval)
-    print GetIPCInformation.header
-    print GetIPCInformation(tval.itk_space, True, False)
+    print PrintIPCInformation.header
+    PrintIPCInformation(tval.itk_space, True, False, rights_type)
 
 # Macro: showataskrightsbt
 
-@lldb_command('showtaskrightsbt')
-def ShowTaskRightsBt(cmd_args=None):
+@lldb_command('showtaskrightsbt', 'R:')
+def ShowTaskRightsBt(cmd_args=None, cmd_options={}):
     """ Routine to ipc rights information with userstacks for a task
-        Usage: showtaskrightsbt <task address>
+        Usage: showtaskrightsbt [-R rights_type] <task address>
+               -R rights_type  : only display rights matching the string 'rights_type'
+
+               types of rights:
+                   'Dead'  : Dead name
+                   'Set'   : Port set
+                   'S'     : Send right
+                   'R'     : Receive right
+                   'O'     : Send-once right
+               types of notifications (append to rights type string):
+                   's'     : Send-Possible notification armed
+                   'd'     : Send-Possible notification requested
+                   'n'     : Dead-Name notification requested
+                   'c'     : ???
+                   'x'     : No-Senders notification requested
     """
     if cmd_args == None:
         print "No arguments passed"
@@ -468,27 +685,52 @@ def ShowTaskRightsBt(cmd_args=None):
     if not tval:
         print "unknown arguments:", str(cmd_args)
         return False
+    rights_type = 0
+    if "-R" in cmd_options:
+        rights_type = cmd_options["-R"]
     print GetTaskSummary.header + " " + GetProcSummary.header
     pval = Cast(tval.bsd_info, 'proc *')
     print GetTaskSummary(tval) + " " + GetProcSummary(pval)
-    print GetIPCInformation.header
-    print GetIPCInformation(tval.itk_space, True, True)
+    print PrintIPCInformation.header
+    PrintIPCInformation(tval.itk_space, True, True, rights_type)
 
 # EndMacro: showtaskrightsbt
 
 # Macro: showallrights
 
-@lldb_command('showallrights'
-def ShowAllRights(cmd_args=None):
+@lldb_command('showallrights', 'R:')
+def ShowAllRights(cmd_args=None, cmd_options={}):
     """  Routine to print rights information for IPC space of all tasks
-         Usage: showallrights
+         Usage: showallrights [-R rights_type]
+                -R rights_type  : only display rights matching the string 'rights_type'
+
+                types of rights:
+                    'Dead'  : Dead name
+                    'Set'   : Port set
+                    'S'     : Send right
+                    'R'     : Receive right
+                    'O'     : Send-once right
+                types of notifications (append to rights type string):
+                    's'     : Send-Possible notification armed
+                    'd'     : Send-Possible notification requested
+                    'n'     : Dead-Name notification requested
+                    'c'     : ???
+                    'x'     : No-Senders notification requested
     """
+    rights_type = 0
+    if "-R" in cmd_options:
+        rights_type = cmd_options["-R"]
     for t in kern.tasks:
         print GetTaskSummary.header + " " + GetProcSummary.header
         pval = Cast(t.bsd_info, 'proc *')
         print GetTaskSummary(t) + " " + GetProcSummary(pval)
-        print GetIPCInformation.header
-        print GetIPCInformation(t.itk_space, True, False) + "\n\n"
+        try:
+            print PrintIPCInformation.header
+            PrintIPCInformation(t.itk_space, True, False, rights_type) + "\n\n"
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            print "Failed to get IPC information. Do individual showtaskrights <task> to find the error. \n\n"
 
 # EndMacro: showallrights
 
@@ -514,10 +756,10 @@ def ShowTaskBusyPorts(cmd_args=None):
         print ShowTaskBusyPorts.__doc__
         return
     task = kern.GetValueFromAddress(cmd_args[0], 'task_t')
-    print GetTaskBusyPorts(task)
+    PrintTaskBusyPorts(task)
     return
 
-def GetTaskBusyPorts(task):
+def PrintTaskBusyPorts(task):
     """ Prints all busy ports for a given task. ie. all receive rights belonging
         to this task that have enqueued messages.
         params:
@@ -527,15 +769,15 @@ def GetTaskBusyPorts(task):
     """
     isp = task.itk_space
     i = 0
-    out_string = ""
     while i < isp.is_table_size:
         iep = addressof(isp.is_table[i])
         if iep.ie_bits & 0x00020000:
             port = Cast(iep.ie_object, 'ipc_port_t')
             if port.ip_messages.data.port.msgcount > 0:
-                out_string += GetPortSummary.header + GetPortSummary(port)
+                print PrintPortSummary.header
+                PrintPortSummary(port)
         i = i + 1
-    return out_string
+    return
 # EndMacro: showtaskbusyports
 
 # Macro: showallbusyports
@@ -545,45 +787,605 @@ def ShowAllBusyPorts(cmd_args=None):
         have enqueued messages.
     """
     task_queue_head = kern.globals.tasks
-    
+
     for tsk in kern.tasks:
-        print GetTaskBusyPorts(tsk)
+        PrintTaskBusyPorts(tsk)
     return
 # EndMacro: showallbusyports
 
+# Macro: showport:
+@lldb_command('showport','K')
+def ShowPort(cmd_args=None, cmd_options={}):
+    """ Routine that lists details about a given IPC port 
+        Syntax: (lldb) showport 0xaddr
+    """
+    show_kmsgs = True
+    if "-K" in cmd_options:
+        show_kmsgs = False
+    if not cmd_args:
+        print "Please specify the address of the port whose details you want to print"
+        print ShowPort.__doc__
+        return
+    port = kern.GetValueFromAddress(cmd_args[0], 'struct ipc_port *')
+    print PrintPortSummary.header
+    PrintPortSummary(port, show_kmsgs)
+# EndMacro: showport
+
 # Macro: showmqueue:
-@lldb_command('showmqueue')
-def ShowMQueue(cmd_args=None):
+@lldb_command('showmqueue', "S:")
+def ShowMQueue(cmd_args=None, cmd_options={}):
     """ Routine that lists details about a given mqueue
-        Syntax: (lldb) showmqueue 0xaddr
+        Syntax: (lldb) showmqueue 0xaddr [-S ipc_space]
     """
     if not cmd_args:
         print "Please specify the address of the ipc_mqueue whose details you want to print"
         print ShowMQueue.__doc__
         return
+    space = 0
+    if "-S" in cmd_options:
+        space = kern.GetValueFromAddress(cmd_options["-S"], 'struct ipc_space *')
     mqueue = kern.GetValueFromAddress(cmd_args[0], 'struct ipc_mqueue *')
-    wq_type = mqueue.data.pset.set_queue.wqs_wait_queue.wq_type
+    wq_type = mqueue.data.pset.setq.wqset_q.waitq_type
     if int(wq_type) == 3:
-        psetoff = getfieldoffset('struct ipc_pset *', 'ips_messages')
+        psetoff = getfieldoffset('struct ipc_pset', 'ips_messages')
         pset = unsigned(ArgumentStringToInt(cmd_args[0])) - unsigned(psetoff)
-        print GetPortSetSummary.header + GetPortSetSummary(kern.GetValueFromAddress(pset, 'struct ipc_pset *'))
-    if int(wq_type) == 2:
+        print PrintPortSetSummary.header
+        PrintPortSetSummary(kern.GetValueFromAddress(pset, 'struct ipc_pset *'), space)
+    elif int(wq_type) == 2:
         portoff = getfieldoffset('struct ipc_port', 'ip_messages')
         port = unsigned(ArgumentStringToInt(cmd_args[0])) - unsigned(portoff)
-        print GetPortSummary.header + GetPortSummary(kern.GetValueFromAddress(port, 'struct ipc_port *'))
+        print PrintPortSummary.header
+        PrintPortSummary(kern.GetValueFromAddress(port, 'struct ipc_port *'))
+    else:
+        print "Invalid mqueue? (waitq type {:d} is invalid)".format(int(wq_type))
 # EndMacro: showmqueue
 
+# Macro: showkmsg:
+@lldb_command('showkmsg')
+def ShowKMSG(cmd_args=[]):
+    """ Show detail information about a <ipc_kmsg_t> structure
+        Usage: (lldb) showkmsg <ipc_kmsg_t>
+    """
+    if not cmd_args:
+        raise ArgumentError('Invalid arguments')
+    kmsg = kern.GetValueFromAddress(cmd_args[0], 'ipc_kmsg_t')
+    print GetKMsgSummary.header
+    print GetKMsgSummary(kmsg)
+
+# EndMacro: showkmsg
+
 # Macro: showpset
-@lldb_command('showpset')
-def ShowPSet(cmd_args=None):
+@lldb_command('showpset', "S:")
+def ShowPSet(cmd_args=None, cmd_options={}):
     """ Routine that prints details for a given ipc_pset *
-        Syntax: (lldb) showpset 0xaddr
+        Syntax: (lldb) showpset 0xaddr [-S ipc_space]
     """
     if not cmd_args:
         print "Please specify the address of the pset whose details you want to print"
         print ShowPSet.__doc__
         return
-    
-    print GetPortSetSummary.header + GetPortSetSummary(kern.GetValueFromAddress(cmd_args[0], 'ipc_pset *'))
+    space = 0
+    if "-S" in cmd_options:
+        space = kern.GetValueFromAddress(cmd_options["-S"], 'struct ipc_space *')
+
+    print PrintPortSetSummary.header
+    PrintPortSetSummary(kern.GetValueFromAddress(cmd_args[0], 'ipc_pset *'), space)
 # EndMacro: showpset
 
+# IPC importance inheritance related macros.
+
+@lldb_command('showalliits')
+def ShowAllIITs(cmd_args=[], cmd_options={}):
+    """ Development only macro. Show list of all iits allocated in the system. """
+    try:
+        iit_queue = kern.globals.global_iit_alloc_queue 
+    except ValueError:
+        print "This debug macro is only available in development or debug kernels"
+        return
+    
+    print GetIPCImportantTaskSummary.header
+    for iit in IterateQueue(iit_queue, 'struct ipc_importance_task *', 'iit_allocation'):
+        print GetIPCImportantTaskSummary(iit)
+    return
+
+@header("{: <18s} {: <3s} {: <18s} {: <20s} {: <18s} {: <8s}".format("ipc_imp_inherit", "don", "to_task", "proc_name", "from_elem", "depth"))
+@lldb_type_summary(['ipc_importance_inherit *', 'ipc_importance_inherit_t'])
+def GetIPCImportanceInheritSummary(iii):
+    """ describes iii object of type ipc_importance_inherit_t * """
+    out_str = ""
+    fmt = "{o: <#018x} {don: <3s} {o.iii_to_task.iit_task: <#018x} {task_name: <20s} {o.iii_from_elem: <#018x} {o.iii_depth: <#08x}"
+    donating_str = ""
+    if unsigned(iii.iii_donating):
+        donating_str = "DON"
+    taskname = GetProcNameForTask(iii.iii_to_task.iit_task)
+    if hasattr(iii.iii_to_task, 'iit_bsd_pid'):
+        taskname =  "({:d}) {:s}".format(iii.iii_to_task.iit_bsd_pid, iii.iii_to_task.iit_procname)
+    out_str += fmt.format(o=iii, task_name = taskname, don=donating_str)
+    return out_str
+
+@static_var('recursion_count', 0)
+@header("{: <18s} {: <4s} {: <8s} {: <8s} {: <18s} {: <18s}".format("iie", "type", "refs", "made", "#kmsgs", "#inherits"))
+@lldb_type_summary(['ipc_importance_elem *'])
+def GetIPCImportanceElemSummary(iie):
+    """ describes an ipc_importance_elem * object """
+
+    if GetIPCImportanceElemSummary.recursion_count > 500:
+        GetIPCImportanceElemSummary.recursion_count = 0
+        return "Recursion of 500 reached"
+
+    out_str = ''
+    fmt = "{: <#018x} {: <4s} {: <8d} {: <8d} {: <#018x} {: <#018x}"
+    if unsigned(iie.iie_bits) & 0x80000000:
+        type_str = "INH"
+        inherit_count = 0
+    else:
+        type_str = 'TASK'
+        iit = Cast(iie, 'struct ipc_importance_task *')
+        inherit_count = sum(1 for i in IterateQueue(iit.iit_inherits, 'struct ipc_importance_inherit *',  'iii_inheritance'))
+
+    refs = unsigned(iie.iie_bits) & 0x7fffffff
+    made_refs = unsigned(iie.iie_made)
+    kmsg_count = sum(1 for i in IterateQueue(iie.iie_kmsgs, 'struct ipc_kmsg *',  'ikm_inheritance'))
+    out_str += fmt.format(iie, type_str, refs, made_refs, kmsg_count, inherit_count)
+    if config['verbosity'] > vHUMAN:
+        if kmsg_count > 0:
+            out_str += "\n\t"+ GetKMsgSummary.header 
+            for k in IterateQueue(iie.iie_kmsgs, 'struct ipc_kmsg *',  'ikm_inheritance'):
+                out_str += "\t" + "{: <#018x}".format(k.ikm_header.msgh_remote_port) + '   ' + GetKMsgSummary(k, "\t").lstrip() 
+            out_str += "\n"
+        if inherit_count > 0:
+            out_str += "\n\t" + GetIPCImportanceInheritSummary.header + "\n"
+            for i in IterateQueue(iit.iit_inherits, 'struct ipc_importance_inherit *',  'iii_inheritance'):
+                out_str += "\t" + GetIPCImportanceInheritSummary(i) + "\n"
+            out_str += "\n"
+        if type_str == "INH":
+            iii = Cast(iie, 'struct ipc_importance_inherit *')
+            out_str += "Inherit from: " + GetIPCImportanceElemSummary(iii.iii_from_elem)
+
+    return out_str
+
+@header("{: <18s} {: <18s} {: <20s}".format("iit", "task", "name"))
+@lldb_type_summary(['ipc_importance_task *'])
+def GetIPCImportantTaskSummary(iit):
+    """ iit is a ipc_importance_task value object.
+    """
+    fmt = "{: <#018x} {: <#018x} {: <20s}"
+    out_str=''
+    pname = GetProcNameForTask(iit.iit_task)
+    if hasattr(iit, 'iit_bsd_pid'):
+        pname = "({:d}) {:s}".format(iit.iit_bsd_pid, iit.iit_procname)
+    out_str += fmt.format(iit, iit.iit_task, pname)
+    return out_str
+
+@lldb_command('showallimportancetasks')
+def ShowIPCImportanceTasks(cmd_args=[], cmd_options={}):
+    """ display a list of all tasks with ipc importance information. 
+        Usage: (lldb) showallimportancetasks
+        Tip: add "-v" to see detailed information on each kmsg or inherit elems 
+    """
+    print ' ' + GetIPCImportantTaskSummary.header + ' ' + GetIPCImportanceElemSummary.header
+    for t in kern.tasks:
+        s = ""
+        if unsigned(t.task_imp_base):
+            s += ' ' + GetIPCImportantTaskSummary(t.task_imp_base)
+            s += ' ' + GetIPCImportanceElemSummary(addressof(t.task_imp_base.iit_elem))
+            print s
+
+@lldb_command('showipcimportance', '')
+def ShowIPCImportance(cmd_args=[], cmd_options={}):
+    """ Describe an importance from <ipc_importance_elem_t> argument.
+        Usage: (lldb) showimportance <ipc_importance_elem_t>
+    """
+    if not cmd_args:
+        raise ArgumentError("Please provide valid argument")
+
+    elem = kern.GetValueFromAddress(cmd_args[0], 'ipc_importance_elem_t')
+    print GetIPCImportanceElemSummary.header
+    print GetIPCImportanceElemSummary(elem)
+
+@header("{: <18s} {: <10s} {: <18s} {: <18s} {: <8s} {: <5s} {: <5s} {: <5s}".format("ivac", "refs", "port", "tbl", "tblsize", "index", "Grow", "freelist"))
+@lldb_type_summary(['ipc_voucher_attr_control *', 'ipc_voucher_attr_control_t'])
+def GetIPCVoucherAttrControlSummary(ivac):
+    """ describes a voucher attribute control settings """
+    out_str = ""
+    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}"
+    growing_str = ""
+    
+    if unsigned(ivac) == 0:
+        return "{: <#018x}".format(ivac)
+
+    if unsigned(ivac.ivac_is_growing):
+        growing_str = "Y"
+    out_str += fmt.format(c=ivac, growing = growing_str)
+    return out_str
+
+@lldb_command('showivac','')
+def ShowIPCVoucherAttributeControl(cmd_args=[], cmd_options={}):
+    """ Show summary of voucher attribute contols.
+        Usage: (lldb) showivac <ipc_voucher_attr_control_t>
+    """
+    if not cmd_args:
+        raise ArgumentError("Please provide correct arguments.")
+    ivac = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_attr_control_t')
+    print GetIPCVoucherAttrControlSummary.header
+    print GetIPCVoucherAttrControlSummary(ivac)
+    if config['verbosity'] > vHUMAN:
+        cur_entry_index = 0
+        last_entry_index = unsigned(ivac.ivac_table_size)
+        print "index " + GetIPCVoucherAttributeEntrySummary.header
+        while cur_entry_index < last_entry_index:
+            print "{: <5d} ".format(cur_entry_index) + GetIPCVoucherAttributeEntrySummary(addressof(ivac.ivac_table[cur_entry_index]))
+            cur_entry_index += 1
+
+    
+
+
+@header("{: <18s} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}".format("ivam", "get_value_fn", "extract_fn", "release_value_fn", "command_fn", "release_fn"))
+@lldb_type_summary(['ipc_voucher_attr_manager *', 'ipc_voucher_attr_manager_t'])
+def GetIPCVoucherAttrManagerSummary(ivam):
+    """ describes a voucher attribute manager settings """
+    out_str = ""
+    fmt = "{: <#018x} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}"
+    
+    if unsigned(ivam) == 0 :
+        return "{: <#018x}".format(ivam)
+
+    get_value_fn = kern.Symbolicate(unsigned(ivam.ivam_get_value))
+    extract_fn = kern.Symbolicate(unsigned(ivam.ivam_extract_content))
+    release_value_fn = kern.Symbolicate(unsigned(ivam.ivam_release_value))
+    command_fn = kern.Symbolicate(unsigned(ivam.ivam_command))
+    release_fn = kern.Symbolicate(unsigned(ivam.ivam_release))
+    out_str += fmt.format(ivam, get_value_fn, extract_fn, release_value_fn, command_fn, release_fn)
+    return out_str
+
+
+
+@header("{: <18s} {: <10s} {:s} {:s}".format("ivgte", "key", GetIPCVoucherAttrControlSummary.header.strip(), GetIPCVoucherAttrManagerSummary.header.strip()))
+@lldb_type_summary(['ipc_voucher_global_table_element *', 'ipc_voucher_global_table_element_t'])
+def GetIPCVoucherGlobalTableElementSummary(ivgte):
+    """ describes a ipc_voucher_global_table_element object """
+    out_str = ""
+    fmt = "{g: <#018x} {g.ivgte_key: <10d} {ctrl_s:s} {mgr_s:s}"
+    out_str += fmt.format(g=ivgte, ctrl_s=GetIPCVoucherAttrControlSummary(ivgte.ivgte_control), mgr_s=GetIPCVoucherAttrManagerSummary(ivgte.ivgte_manager))
+    return out_str
+
+@lldb_command('showglobalvouchertable', '')
+def ShowGlobalVoucherTable(cmd_args=[], cmd_options={}):
+    """ show detailed information of all voucher attribute managers registered with vouchers system
+        Usage: (lldb) showglobalvouchertable
+    """
+    entry_size = sizeof(kern.globals.iv_global_table[0])
+    elems = sizeof(kern.globals.iv_global_table) / entry_size
+    print GetIPCVoucherGlobalTableElementSummary.header
+    for i in range(elems):
+        elt = addressof(kern.globals.iv_global_table[i])
+        print GetIPCVoucherGlobalTableElementSummary(elt)
+
+# Type summaries for Bag of Bits.
+
+@lldb_type_summary(['user_data_value_element', 'user_data_element_t'])
+@header("{0: <20s} {1: <16s} {2: <20s} {3: <20s} {4: <16s} {5: <20s}".format("user_data_ve", "maderefs", "checksum", "hash value", "size", "data"))
+def GetBagofBitsElementSummary(data_element):
+    """ Summarizes the Bag of Bits element
+        params: data_element = value of the object of type user_data_value_element_t
+        returns: String with summary of the type.
+    """
+    format_str = "{0: <#020x} {1: <16d} {2: <#020x} {3: <#020x} {4: <16d}"
+    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))
+    out_string += " 0x"
+
+    for i in range(0, (unsigned(data_element.e_size) - 1)):
+      out_string += "{:02x}".format(int(data_element.e_data[i]))
+    return out_string
+
+def GetIPCHandleSummary(handle_ptr):
+    """ converts a handle value inside a voucher attribute table to ipc element and returns appropriate summary.
+        params: handle_ptr - uint64 number stored in handle of voucher.
+        returns: str - string summary of the element held in internal structure
+    """
+    elem = kern.GetValueFromAddress(handle_ptr, 'ipc_importance_elem_t')
+    if elem.iie_bits & 0x80000000 :
+        iie = Cast(elem, 'struct ipc_importance_inherit *')
+        return GetIPCImportanceInheritSummary(iie)
+    else:
+        iit = Cast(elem, 'struct ipc_importance_task *')
+        return GetIPCImportantTaskSummary(iit)
+
+def GetATMHandleSummary(handle_ptr):
+    """ Convert a handle value to atm value and returns corresponding summary of its fields.
+        params: handle_ptr - uint64 number stored in handle of voucher
+        returns: str - summary of atm value
+    """
+    elem = kern.GetValueFromAddress(handle_ptr, 'atm_value *')
+    return GetATMValueSummary(elem)
+
+def GetBankHandleSummary(handle_ptr):
+    """ converts a handle value inside a voucher attribute table to bank element and returns appropriate summary.
+        params: handle_ptr - uint64 number stored in handle of voucher.
+        returns: str - summary of bank element
+    """
+    if handle_ptr == 1 :
+        return "Bank task of Current task"
+    elem = kern.GetValueFromAddress(handle_ptr, 'bank_element_t')
+    if elem.be_type & 1 :
+        ba = Cast(elem, 'struct bank_account *')
+        return GetBankAccountSummary(ba)
+    else:
+        bt = Cast(elem, 'struct bank_task *')
+        return GetBankTaskSummary(bt)
+
+def GetBagofBitsHandleSummary(handle_ptr):
+    """ Convert a handle value to bag of bits value and returns corresponding summary of its fields.
+        params: handle_ptr - uint64 number stored in handle of voucher
+        returns: str - summary of bag of bits element
+    """
+    elem = kern.GetValueFromAddress(handle_ptr, 'user_data_element_t')
+    return GetBagofBitsElementSummary(elem)
+
+@static_var('attr_managers',{1: GetATMHandleSummary, 2: GetIPCHandleSummary, 3: GetBankHandleSummary, 7: GetBagofBitsHandleSummary})
+def GetHandleSummaryForKey(handle_ptr, key_num):
+    """ Get a summary of handle pointer from the voucher attribute manager. 
+        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.
+                    key 2 -> ipc and it puts either ipc_importance_inherit_t or ipc_important_task_t.
+                    key 3 -> Bank and it puts either bank_task_t or bank_account_t.
+                    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.
+    """
+    key_num = int(key_num)
+    if key_num not in GetHandleSummaryForKey.attr_managers:
+        return "Unknown key %d" % key_num
+    return GetHandleSummaryForKey.attr_managers[key_num](handle_ptr)
+
+
+@header("{: <18s} {: <18s} {: <10s} {: <4s} {: <18s} {: <18s}".format("ivace", "value_handle", "#refs", "rel?", "maderefs", "next_layer"))
+@lldb_type_summary(['ivac_entry *', 'ivac_entry_t'])
+def GetIPCVoucherAttributeEntrySummary(ivace, manager_key_num = 0):
+    """ Get summary for voucher attribute entry.
+    """
+    out_str = ""
+    fmt = "{e: <#018x} {e.ivace_value: <#018x} {e.ivace_refs: <10d} {release: <4s} {made_refs: <18s} {next_layer: <18s}"
+    release_str = ""
+    free_str = ""
+    made_refs = ""
+    next_layer = ""
+
+    if unsigned(ivace.ivace_releasing):
+        release_str = "Y"
+    if unsigned(ivace.ivace_free):
+        free_str = 'F'
+    if unsigned(ivace.ivace_layered):
+        next_layer = "{: <#018x}".format(ivace.ivace_u.ivaceu_layer)
+    else:
+        made_refs = "{: <18d}".format(ivace.ivace_u.ivaceu_made)
+
+    out_str += fmt.format(e=ivace, release=release_str, made_refs=made_refs, next_layer=next_layer)
+    if config['verbosity'] > vHUMAN and manager_key_num > 0:
+        out_str += " " + GetHandleSummaryForKey(unsigned(ivace.ivace_value), manager_key_num)
+    if config['verbosity'] > vHUMAN :
+        out_str += ' {: <2s} {: <4d} {: <4d}'.format(free_str, ivace.ivace_next, ivace.ivace_index)
+    return out_str
+
+@lldb_command('showivacfreelist','')
+def ShowIVACFreeList(cmd_args=[], cmd_options={}):
+    """ Walk the free list and print every entry in the list.
+        usage: (lldb) showivacfreelist <ipc_voucher_attr_control_t>
+    """
+    if not cmd_args:
+        raise ArgumentError('Please provide <ipc_voucher_attr_control_t>')
+    ivac = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_attr_control_t')
+    print GetIPCVoucherAttrControlSummary.header
+    print GetIPCVoucherAttrControlSummary(ivac)
+    if unsigned(ivac.ivac_freelist) == 0:
+        print "ivac table is full"
+        return
+    print "index " + GetIPCVoucherAttributeEntrySummary.header
+    next_free = unsigned(ivac.ivac_freelist)
+    while next_free != 0:
+        print "{: <5d} ".format(next_free) + GetIPCVoucherAttributeEntrySummary(addressof(ivac.ivac_table[next_free]))
+        next_free = unsigned(ivac.ivac_table[next_free].ivace_next)
+
+
+
+@header('{: <18s} {: <8s} {: <18s} {: <18s} {: <18s} {: <18s} {: <18s}'.format("ipc_voucher", "refs", "checksum", "hash", "tbl_size", "table", "voucher_port"))
+@lldb_type_summary(['ipc_voucher *', 'ipc_voucher_t'])
+def GetIPCVoucherSummary(voucher, show_entries=False):
+    """ describe a voucher from its ipc_voucher * object """
+    out_str = ""
+    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}"
+    out_str += fmt.format(v = voucher)
+    entries_str = ''
+    if show_entries or config['verbosity'] > vHUMAN:
+        elems = unsigned(voucher.iv_table_size)
+        entries_header_str = "\n\t" + "{: <5s} {: <3s} {: <16s} {: <30s}".format("index", "key", "value_index", "manager") + " " + GetIPCVoucherAttributeEntrySummary.header
+        fmt =  "{: <5d} {: <3d} {: <16d} {: <30s}"
+        for i in range(elems):
+            voucher_entry_index = unsigned(voucher.iv_inline_table[i])
+            if voucher_entry_index:
+                s = fmt.format(i, GetVoucherManagerKeyForIndex(i), voucher_entry_index, GetVoucherAttributeManagerNameForIndex(i))
+                e = GetVoucherValueHandleFromVoucherForIndex(voucher, i)
+                if e is not None:
+                    s += " " + GetIPCVoucherAttributeEntrySummary(addressof(e), GetVoucherManagerKeyForIndex(i) )
+                if entries_header_str :
+                    entries_str = entries_header_str
+                    entries_header_str = ''
+                entries_str += "\n\t" + s 
+        if not entries_header_str:
+            entries_str += "\n\t"
+    out_str += entries_str
+    return out_str
+
+def GetVoucherManagerKeyForIndex(idx):
+    """ Returns key number for index based on global table. Will raise index error if value is incorrect
+    """
+    return unsigned(kern.globals.iv_global_table[idx].ivgte_key)
+
+def GetVoucherAttributeManagerForKey(k):
+    """ Walks through the iv_global_table and finds the attribute manager name
+        params: k - int key number of the manager
+        return: cvalue - the attribute manager object. 
+                None - if not found
+    """
+    retval = None
+    entry_size = sizeof(kern.globals.iv_global_table[0])
+    elems = sizeof(kern.globals.iv_global_table) / entry_size
+    for i in range(elems):
+        elt = addressof(kern.globals.iv_global_table[i])
+        if k == unsigned(elt.ivgte_key):
+            retval = elt.ivgte_manager
+            break
+    return retval
+
+def GetVoucherAttributeControllerForKey(k):
+    """ Walks through the iv_global_table and finds the attribute controller
+        params: k - int key number of the manager
+        return: cvalue - the attribute controller object. 
+                None - if not found
+    """
+    retval = None
+    entry_size = sizeof(kern.globals.iv_global_table[0])
+    elems = sizeof(kern.globals.iv_global_table) / entry_size
+    for i in range(elems):
+        elt = addressof(kern.globals.iv_global_table[i])
+        if k == unsigned(elt.ivgte_key):
+            retval = elt.ivgte_control
+            break
+    return retval
+
+
+def GetVoucherAttributeManagerName(ivam):
+    """ find the name of the ivam object
+        param: ivam - cvalue object of type ipc_voucher_attr_manager_t
+        returns: str - name of the manager
+    """
+    return kern.Symbolicate(unsigned(ivam))
+
+def GetVoucherAttributeManagerNameForIndex(idx):
+    """ get voucher attribute manager name for index 
+        return: str - name of the attribute manager object
+    """
+    return GetVoucherAttributeManagerName(GetVoucherAttributeManagerForKey(GetVoucherManagerKeyForIndex(idx)))
+
+def GetVoucherValueHandleFromVoucherForIndex(voucher, idx):
+    """ traverse the voucher attrs and get value_handle in the voucher attr controls table
+        params:
+            voucher - cvalue object of type ipc_voucher_t
+            idx - int index in the entries for which you wish to get actual handle for
+        returns: cvalue object of type ivac_entry_t
+                 None if no handle found.
+    """
+    manager_key = GetVoucherManagerKeyForIndex(idx)
+    voucher_num_elems = unsigned(voucher.iv_table_size)
+    if idx >= voucher_num_elems:
+        debuglog("idx %d is out of range max: %d" % (idx, voucher_num_elems))
+        return None
+    voucher_entry_value = unsigned(voucher.iv_inline_table[idx])
+    debuglog("manager_key %d" % manager_key)
+    ivac = GetVoucherAttributeControllerForKey(manager_key)
+    if ivac is None or unsigned(ivac) == 0:
+        debuglog("No voucher attribute controller for idx %d" % idx)
+        return None
+
+    ivac = kern.GetValueFromAddress(unsigned(ivac), 'ipc_voucher_attr_control_t')  # ??? No idea why lldb does not addressof directly
+    ivace_table = ivac.ivac_table
+    if voucher_entry_value >= unsigned(ivac.ivac_table_size):
+        print "Failed to get ivace for value %d in table of size %d" % (voucher_entry_value, unsigned(ivac.ivac_table_size))
+        return None
+    return ivace_table[voucher_entry_value]
+
+
+
+@lldb_command('showallvouchers')
+def ShowAllVouchers(cmd_args=[], cmd_options={}):
+    """ Display a list of all vouchers in the global voucher hash table
+        Usage: (lldb) showallvouchers 
+    """
+    iv_hash_table = kern.globals.ivht_bucket
+    num_buckets =  sizeof(kern.globals.ivht_bucket) / sizeof(kern.globals.ivht_bucket[0])
+    print GetIPCVoucherSummary.header
+    for i in range(num_buckets):
+        for v in IterateQueue(iv_hash_table[i], 'ipc_voucher_t', 'iv_hash_link'):
+            print GetIPCVoucherSummary(v)
+
+@lldb_command('showvoucher', '')
+def ShowVoucher(cmd_args=[], cmd_options={}):
+    """ Describe a voucher from <ipc_voucher_t> argument.
+        Usage: (lldb) showvoucher <ipc_voucher_t>
+    """
+    if not cmd_args:
+        raise ArgumentError("Please provide valid argument")
+
+    voucher = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_t')
+    print GetIPCVoucherSummary.header
+    print GetIPCVoucherSummary(voucher, show_entries=True)
+
+def GetSpaceSendRightEntries(space, port):
+    """ Get entry summaries for all send rights to port address in an IPC space.
+        params:
+            space - the IPC space to search for send rights
+            port_addr - the port address to match, or 0 to get all send rights
+        returns: an array of IPC entries
+    """
+    entry_table = space.is_table
+    ports = int(space.is_table_size)
+    i = 0
+    entries = []
+
+    while i < ports:
+        entry = GetObjectAtIndexFromArray(entry_table, i)
+
+        entry_ie_bits = unsigned(entry.ie_bits)
+        if (entry_ie_bits & 0x00010000) != 0 and (not port or entry.ie_object == port):
+            entries.append(entry)
+        i += 1
+
+    return entries
+
+@lldb_command('showportsendrights')
+def ShowPortSendRights(cmd_args=[], cmd_options={}):
+    """ Display a list of send rights across all tasks for a given port.
+        Usage: (lldb) showportsendrights <ipc_port_t>
+    """
+    if not cmd_args:
+        raise ArgumentError("no port address provided")
+    port = kern.GetValueFromAddress(cmd_args[0], 'struct ipc_port *')
+    i = 1
+
+    for t in kern.tasks:
+        # Write a progress line.  Using stderr avoids automatic newline when
+        # writing to stdout from lldb.  Blank spaces at the end clear out long
+        # lines.
+        sys.stderr.write("checking {:s} ({}/{})...{:30s}\r".format(Cast(t.bsd_info, 'proc_t').p_name, i, len(kern.tasks), ''))
+        i += 1
+        entries = GetSpaceSendRightEntries(t.itk_space, port)
+
+        if entries:
+            print GetTaskIPCSummary.header
+            print GetTaskIPCSummary(t)
+            print '\t' + GetIPCEntrySummary.header
+
+        for entry in entries:
+            print "\t" + GetIPCEntrySummary(entry)
+
+@lldb_command('showtasksuspenders')
+def ShowTaskSuspenders(cmd_args=[], cmd_options={}):
+    """ Display the tasks and send rights that are holding a target task suspended.
+        Usage: (lldb) showtasksuspenders <task_t>
+    """
+    if not cmd_args:
+        raise ArgumentError("no task address provided")
+    task = kern.GetValueFromAddress(cmd_args[0], 'task_t')
+
+    if task.suspend_count == 0:
+        print "task {:#x} ({:s}) is not suspended".format(unsigned(task), Cast(task.bsd_info, 'proc_t').p_name)
+        return
+
+    # If the task has been suspended by the kernel (potentially by
+    # kperf, using task_suspend_internal) or a client of task_suspend2
+    # that does not convert its task suspension token to a port using
+    # convert_task_suspension_token_to_port, then it's impossible to determine
+    # which task did the suspension.
+    port = task.itk_resume
+    if not port:
+        print "task {:#x} ({:s}) is suspended but no resume port exists".format(unsigned(task), Cast(task.bsd_info, 'proc_t').p_name)
+        return
+
+    return ShowPortSendRights(cmd_args=[unsigned(port)], cmd_options=cmd_options)