X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..ecc0ceb4089d506a0b8d16686a95817b331af9cb:/tools/lldbmacros/ipc.py diff --git a/tools/lldbmacros/ipc.py b/tools/lldbmacros/ipc.py index db09a4b46..f06087393 100644 --- a/tools/lldbmacros/ipc.py +++ b/tools/lldbmacros/ipc.py @@ -5,6 +5,9 @@ from xnu import * import sys, shlex from utils import * from process import * +from atm import * +from bank import * +from waitq import * import xnudefines @header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command")) @@ -25,7 +28,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 +53,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 +81,14 @@ def GetPortDestProc(portp): destprocp = Cast(tsk.bsd_info, 'struct proc *') out_str = "{0:s}({1: > 8 + + 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("-") + + 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" - out_string += "{0: >5d} {1: #019x} {2: <16s}\n".format( - unsigned(kmsgh.msgh_size), kmsgh.msgh_local_port, - GetKMsgSrc(kmsgp)) 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 +215,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 +260,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 +279,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 +301,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 +340,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 @@ -247,6 +366,8 @@ def GetKObjectFromPort(portval): objtype_index = io_bits & 0xfff if objtype_index < len(xnudefines.kobject_types) : desc_str = "kobject({0:s})".format(xnudefines.kobject_types[objtype_index]) + 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 +428,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 +460,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 +533,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 +546,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 +558,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
+ Usage: showrights [-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 """ if not cmd_args: print "No arguments passed" @@ -429,15 +602,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 + Usage: showtaskrights [-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 """ if cmd_args == None: print "No arguments passed" @@ -447,18 +637,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 + Usage: showtaskrightsbt [-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 """ if cmd_args == None: print "No arguments passed" @@ -468,27 +675,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 to find the error. \n\n" # EndMacro: showallrights @@ -514,10 +746,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 +759,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 +777,530 @@ 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 structure + Usage: (lldb) showkmsg + """ + 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}" + type_str = 'TASK' + if unsigned(iie.iie_bits) & 0x80000000: + type_str = "INH" + 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')) + inherit_count = sum(1 for i in IterateQueue(iie.iie_inherits, 'struct ipc_importance_inherit *', 'iii_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(iie.iie_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 argument. + Usage: (lldb) showimportance + """ + 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 + """ + 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 + """ + if not cmd_args: + raise ArgumentError('Please provide ') + 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 argument. + Usage: (lldb) showvoucher + """ + 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) + +