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"))
@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
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
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
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:
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
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",
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
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
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
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
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 = ''
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") )
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 =''
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:
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"
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"
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"
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
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:
"""
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
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)