def IterateAllPorts()

in tools/lldbmacros/ipc.py [0:0]


def IterateAllPorts(tasklist, func, ctx, include_psets, follow_busyports, should_log):
    """ Iterate over all ports in the system, calling 'func'
        for each entry in 
    """
    global port_iteration_do_print_taskname
    global intransit_idx, taskports_idx, thports_idx, registeredport_idx, excports_idx

    ## XXX: also host special ports

    entry_port_type_mask = 0x00070000
    if include_psets:
        entry_port_type_mask = 0x000f0000

    if tasklist is None:
        tasklist = kern.tasks
        tasklist += kern.terminated_tasks

    tidx = 1

    for t in tasklist:
        # Write a progress line.  Using stderr avoids automatic newline when
        # writing to stdout from lldb.  Blank spaces at the end clear out long
        # lines.
        if should_log:
            procname = ""
            if not t.active:
                procname = 'terminated: '
            if t.halting:
                procname += 'halting: '
            t_p = Cast(t.bsd_info, 'proc *')
            if unsigned(t_p) != 0:
                procname += GetProcName(t_p)
            elif unsigned(t.task_imp_base) != 0 and hasattr(t.task_imp_base, 'iit_procname'):
                procname += str(t.task_imp_base.iit_procname)
            sys.stderr.write("  checking {:s} ({}/{})...{:50s}\r".format(procname, tidx, len(tasklist), ''))
        tidx += 1

        port_iteration_do_print_taskname = True
        space = t.itk_space
        num_entries = int(space.is_table_size)
        is_tableval = space.is_table
        idx = 0
        while idx < num_entries:
            entry_val = GetObjectAtIndexFromArray(is_tableval, idx)
            entry_bits= unsigned(entry_val.ie_bits)
            entry_obj = 0
            entry_str = ''
            entry_name = "{:x}".format( (idx << 8 | entry_bits >> 24) )

            entry_disp = GetDispositionFromEntryType(entry_bits)

            ## If the entry in the table represents a port of some sort,
            ## then make the callback provided
            if int(entry_bits) & entry_port_type_mask:
                eport = Cast(entry_val.ie_object, 'ipc_port_t')
                ## Make the callback
                func(t, space, ctx, idx, entry_val, eport, entry_disp)

                ## if the port has pending messages, look through
                ## each message for ports (and recurse)
                if follow_busyports and unsigned(eport) > 0 and eport.ip_messages.data.port.msgcount > 0:
                    ## collect all port references from all messages
                    kmsgp = Cast(eport.ip_messages.data.port.messages.ikmq_base, 'ipc_kmsg_t')
                    kmsgheadp = kmsgp
                    while unsigned(kmsgp) > 0:
                        p_refs = set()
                        CollectKmsgPortRefs(t, eport, kmsgp, p_refs)
                        for (port, pdisp, ptype) in p_refs:
                            func(t, space, ctx, intransit_idx, None, port, pdisp)
                        kmsgp = kmsgp.ikm_next
                        if kmsgp == kmsgheadp:
                            break

            idx = idx + 1
        ## while (idx < num_entries)

        ## Task ports (send rights)
        if unsigned(t.itk_settable_self) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_settable_self, 17)
        if unsigned(t.itk_host) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_host, 17)
        if unsigned(t.itk_bootstrap) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_bootstrap, 17)
        if unsigned(t.itk_seatbelt) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_seatbelt, 17)
        if unsigned(t.itk_gssd) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_gssd, 17)
        if unsigned(t.itk_debug_control) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_debug_control, 17)
        if unsigned(t.itk_task_access) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_task_access, 17)
        if unsigned(t.itk_task_ports[1]) > 0: ## task read port
            func(t, space, ctx, taskports_idx, 0, t.itk_task_ports[1], 17)
        if unsigned(t.itk_task_ports[2]) > 0: ## task inspect port
            func(t, space, ctx, taskports_idx, 0, t.itk_task_ports[2], 17)

        ## Task name port (not a send right, just a naked ref); TASK_FLAVOR_NAME = 3
        if unsigned(t.itk_task_ports[3]) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_task_ports[3], 0)

        ## task resume port is a receive right to resume the task
        if unsigned(t.itk_resume) > 0:
            func(t, space, ctx, taskports_idx, 0, t.itk_resume, 16)

        ## registered task ports (all send rights)
        tr_idx = 0
        tr_max = sizeof(t.itk_registered) / sizeof(t.itk_registered[0])
        while tr_idx < tr_max:
            tport = t.itk_registered[tr_idx]
            if unsigned(tport) > 0:
                try:
                    func(t, space, ctx, registeredport_idx, 0, tport, 17)
                except Exception, e:
                    print("\texception looking through registered port {:d}/{:d} in {:s}".format(tr_idx,tr_max,t))
                    pass
            tr_idx += 1

        ## Task exception ports
        exidx = 0
        exmax = sizeof(t.exc_actions) / sizeof(t.exc_actions[0])
        while exidx < exmax: ## see: osfmk/mach/[arm|i386]/exception.h
            export = t.exc_actions[exidx].port ## send right
            if unsigned(export) > 0:
                try:
                    func(t, space, ctx, excports_idx, 0, export, 17)
                except Exception, e:
                    print("\texception looking through exception port {:d}/{:d} in {:s}".format(exidx,exmax,t))
                    pass
            exidx += 1

        ## XXX: any  ports still valid after clearing IPC space?!

        for thval in IterateQueue(t.threads, 'thread *', 'task_threads'):
            ## XXX: look at block reason to see if it's in mach_msg_receive - then look at saved state / message

            ## Thread port (send right)
            if unsigned(thval.ith_settable_self) > 0:
                thport = thval.ith_settable_self
                func(t, space, ctx, thports_idx, 0, thport, 17) ## see: osfmk/mach/message.h
            ## Thread special reply port (send-once right)
            if unsigned(thval.ith_special_reply_port) > 0:
                thport = thval.ith_special_reply_port
                func(t, space, ctx, thports_idx, 0, thport, 18) ## see: osfmk/mach/message.h
            ## Thread voucher port
            if unsigned(thval.ith_voucher) > 0:
                vport = thval.ith_voucher.iv_port
                if unsigned(vport) > 0:
                    vdisp = GetDispositionFromVoucherPort(vport)
                    func(t, space, ctx, thports_idx, 0, vport, vdisp)
            ## Thread exception ports
            if unsigned(thval.exc_actions) > 0:
                exidx = 0
                while exidx < exmax: ## see: osfmk/mach/[arm|i386]/exception.h
                    export = thval.exc_actions[exidx].port ## send right
                    if unsigned(export) > 0:
                        try:
                            func(t, space, ctx, excports_idx, 0, export, 17)
                        except Exception, e:
                            print("\texception looking through exception port {:d}/{:d} in {:s}".format(exidx,exmax,t))
                            pass
                    exidx += 1