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