kern_return_t lsPorts(task_t TargetTask) { kern_return_t kr; mach_port_name_array_t portNames = NULL; mach_msg_type_number_t portNamesCount; mach_port_type_array_t portRightTypes = NULL; mach_msg_type_number_t portRightTypesCount; mach_port_type_t mac_port_type; kr = mach_port_names(TargetTask, &portNames, &portNamesCount, &portRightTypes, &portRightTypesCount); if (kr != KERN_SUCCESS) { fprintf(stderr, "Unable to obtain MACH port names. %d\n", kr); return kr; } for (unsigned int p = 0; p < portNamesCount; p++) { printf("Hex Code: "); printf("0x%x 0x%x\n", portNames[p], portRightTypes[p]); switch(portRightTypes[p]) { case MACH_PORT_TYPE_NONE: printf("This port has send right\n"); break; case MACH_PORT_TYPE_RECEIVE: printf("This port has receive right\n"); break; case MACH_PORT_TYPE_SEND_ONCE: printf("This port has a send-once right\n"); break; case MACH_PORT_TYPE_PORT_SET: printf("This port has a port set\n"); break; case MACH_PORT_TYPE_DEAD_NAME: printf("The name is a dead name\n"); break; case MACH_PORT_TYPE_DNREQUEST: printf("A dead-name request has been registered for the right.\n"); break; case MACH_PORT_TYPE_PORT_RIGHTS: case MACH_PORT_TYPE_SEND_RECEIVE: printf("Port has both send and receive right\n"); break; case MACH_PORT_TYPE_SEND_RIGHTS: printf("Port had send right\n"); break; case MACH_PORT_TYPE_PORT_OR_DEAD: printf("Port has send receive rights or is dead\n"); break; case MACH_PORT_TYPE_ALL_RIGHTS: printf("Port has all rights\n"); break; default: printf("Unknown PORT right 0x%x\n", portRightTypes[p]); } } return kr; }
/* Return a new port name translator translating names between FROM_TASK and TO_TASK, in XLATOR, or an error. */ error_t port_name_xlator_create (mach_port_t from_task, mach_port_t to_task, struct port_name_xlator **xlator) { error_t err; struct port_name_xlator *x = malloc (sizeof (struct port_name_xlator)); if (! x) return ENOMEM; x->from_task = from_task; x->to_task = to_task; x->to_names = 0; x->to_types = 0; x->to_names_len = 0; x->to_types_len = 0; /* Cache a list of names in TO_TASK. */ err = mach_port_names (to_task, &x->to_names, &x->to_names_len, &x->to_types, &x->to_types_len); if (! err) /* Make an array to hold ports from TO_TASK which have been translated into our namespace. */ { x->ports = malloc (sizeof (mach_port_t) * x->to_names_len); if (x->ports) { int i; for (i = 0; i < x->to_names_len; i++) x->ports[i] = MACH_PORT_NULL; } else { munmap ((caddr_t) x->to_names, x->to_names_len * sizeof (mach_port_t)); munmap ((caddr_t) x->to_types, x->to_types_len * sizeof (mach_port_type_t)); err = ENOMEM; } } if (err) free (x); else *xlator = x; return err; }
static int get_mach_ports(task_t task, task_record_t *tinfo) { kern_return_t kr; mach_msg_type_number_t ncnt, tcnt; mach_port_name_array_t names; mach_port_type_array_t types; kr = mach_port_names(task, &names, &ncnt, &types, &tcnt); if (kr != KERN_SUCCESS) return 0; tinfo->ports = ncnt; kr = vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)names, ncnt * sizeof(*names)); kr = vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)types, tcnt * sizeof(*types)); return kr; }
/* * fileport_walk * * Description: Invoke the action function on every fileport in the task. * * This could be more efficient if we refactored mach_port_names() * so that (a) it didn't compute the type information unless asked * and (b) it could be asked to -not- unwire/copyout the memory * and (c) if we could ask for port names by kobject type. Not * clear that it's worth all that complexity, though. * * Parameters: task The target task * action The function to invoke on each fileport * arg Anonymous pointer to caller state. */ kern_return_t fileport_walk(task_t task, int (*action)(mach_port_name_t, struct fileglob *, void *arg), void *arg) { mach_port_name_t *names; mach_msg_type_number_t ncnt, tcnt; vm_map_copy_t map_copy_names, map_copy_types; vm_map_address_t map_names; kern_return_t kr; uint_t i; int rval; /* * mach_port_names returns the 'name' and 'types' in copied-in * form. Discard 'types' immediately, then copyout 'names' * back into the kernel before walking the array. */ kr = mach_port_names(task->itk_space, (mach_port_name_t **)&map_copy_names, &ncnt, (mach_port_type_t **)&map_copy_types, &tcnt); if (kr != KERN_SUCCESS) return (kr); vm_map_copy_discard(map_copy_types); kr = vm_map_copyout(ipc_kernel_map, &map_names, map_copy_names); if (kr != KERN_SUCCESS) { vm_map_copy_discard(map_copy_names); return (kr); } names = (mach_port_name_t *)(uintptr_t)map_names; for (rval = 0, i = 0; i < ncnt; i++) if (fileport_invoke(task, names[i], action, arg, &rval) == KERN_SUCCESS && -1 == rval) break; /* early termination clause */ vm_deallocate(ipc_kernel_map, (vm_address_t)names, ncnt * sizeof (*names)); return (KERN_SUCCESS); }
bool inferior_namespace_mach_port_num (task_t task, thread_t examine_threads_port, thread_t *inferior_port) { kern_return_t retval; mach_port_name_array_t names; mach_msg_type_number_t nameslen; mach_port_type_array_t types; mach_msg_type_number_t typeslen; if (inferior_port == NULL) return false; retval = mach_port_names (task, &names, &nameslen, &types, &typeslen); if (retval != KERN_SUCCESS) { printf ("Error - unable to get mach port names for inferior.\n"); return false; } int i = 0; for (i = 0; i < nameslen; i++) { mach_port_t local_name; mach_msg_type_name_t local_type; retval = mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &local_name, &local_type); if (retval == KERN_SUCCESS) { mach_port_deallocate (mach_task_self(), local_name); if (local_name == examine_threads_port) { *inferior_port = names[i]; vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); return true; } } } vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); return false; }
/* Prints info about every port common to both tasks in X, but only if the port in X->from_task has a type in ONLY, to STREAM. */ error_t print_xlated_task_ports_info (struct port_name_xlator *x, mach_port_type_t only, unsigned show, FILE *stream) { mach_port_t *names = 0; mach_port_type_t *types = 0; mach_msg_type_number_t names_len = 0, types_len = 0, i; error_t err = mach_port_names (x->from_task, &names, &names_len, &types, &types_len); if (err) return err; for (i = 0; i < names_len; i++) if (types[i] & only) print_xlated_port_info (names[i], types[i], x, show, stream); munmap ((caddr_t) names, names_len * sizeof *names); munmap ((caddr_t) types, types_len * sizeof *types); return 0; }
static kern_return_t PrintProcessPortSpace(pid_t pid, bool verbose) // Prints port rights owned by the specified process. { kern_return_t err; kern_return_t junk; mach_port_t taskSendRight; mach_port_name_array_t rightNames; mach_msg_type_number_t rightNamesCount; mach_port_type_array_t rightTypes; mach_msg_type_number_t rightTypesCount; unsigned int i; taskSendRight = MACH_PORT_NULL; rightNames = NULL; rightTypes = NULL; // Get the task control port for the process. err = task_for_pid(mach_task_self(), pid, &taskSendRight); if (err != KERN_SUCCESS) { fprintf(stderr, "%s: Could not attach to process %lld (%#08x).\n", gProgramName, (long long) pid, err); } // Get a snapshot of the port name space for the task. if (err == KERN_SUCCESS) { err = mach_port_names(taskSendRight, &rightNames, &rightNamesCount, &rightTypes, &rightTypesCount); } if (err == KERN_SUCCESS) { if ( rightNamesCount != rightTypesCount ) { fprintf(stderr, "%s: Count mismatch (%u/%u)\n", gProgramName, rightNamesCount, rightTypesCount); err = KERN_FAILURE; } } // Print that snapshot. if (err == KERN_SUCCESS) { fprintf(stdout, " Name Send Receive SendOnce PortSet DeadName DNR"); if (verbose) { fprintf(stdout, " flg seqno mscount qlimit msgcount sorights pset"); } fprintf(stdout, "\n"); fprintf(stdout, " ---- ---- ------- -------- ------- -------- ---"); if (verbose) { fprintf(stdout, " --- ----- ------- ------ -------- -------- ----"); } fprintf(stdout, "\n"); // For each name, print a reference count of each type of right. If running // verbose, print other information as well. for (i = 0; i < rightNamesCount; i++) { mach_port_right_t right; // We print the right name in hex because it makes it easier to // see the index and generation fields. See <mach/port.h> for // information about this. fprintf(stdout, "%#8x ", rightNames[i]); for (right = MACH_PORT_RIGHT_SEND; right <= MACH_PORT_RIGHT_DEAD_NAME; right++) { mach_port_urefs_t refCount; // If the rightTypes for this name has the bit associated // with this type of right set (that is, if the name // references this type of right), get the name's reference // for this right and print it. Otherwise just print an // empty string to keep the columns lined up. if (rightTypes[i] & MACH_PORT_TYPE(right)) { err = mach_port_get_refs(taskSendRight, rightNames[i], right, &refCount); if (err == KERN_SUCCESS) { fprintf(stdout, "%8d ", refCount); } else { fprintf(stdout, "%8s ", "???"); } } else { fprintf(stdout, "%8s ", ""); } } if ( rightTypes[i] & MACH_PORT_TYPE_DNREQUEST ) { fprintf(stdout, "yes "); } else { fprintf(stdout, " "); } if (verbose) { if (rightTypes[i] & MACH_PORT_TYPE_PORT_SET) { PrintPortSetMembers(taskSendRight, rightNames[i]); } else if (rightTypes[i] & MACH_PORT_TYPE_RECEIVE) { PrintPortReceiveStatus(taskSendRight, rightNames[i]); } } fprintf(stdout, "\n"); } } // Clean up. if (rightNames != NULL) { junk = vm_deallocate(mach_task_self(), (vm_address_t) rightNames, rightNamesCount * sizeof(*rightNames)); assert(junk == KERN_SUCCESS); } if (rightTypes != NULL) { junk = vm_deallocate(mach_task_self(), (vm_address_t) rightTypes, rightTypesCount * sizeof(*rightTypes)); assert(junk == KERN_SUCCESS); } if (taskSendRight != MACH_PORT_NULL) { junk = mach_port_deallocate(mach_task_self(), taskSendRight); assert(junk == KERN_SUCCESS); } return err; }
static void info_mach_ports_command (char *args, int from_tty) { port_name_array_t names; port_type_array_t types; unsigned int name_count, type_count; kern_return_t result; int index; task_t task; task = get_task_from_args (args); if (task == TASK_NULL) return; result = mach_port_names (task, &names, &name_count, &types, &type_count); MACH_CHECK_ERROR (result); gdb_assert (name_count == type_count); printf_unfiltered (_("Ports for task 0x%x:\n"), task); printf_unfiltered (_("port type\n")); for (index = 0; index < name_count; ++index) { mach_port_t port = names[index]; unsigned int j; struct type_descr { mach_port_type_t type; const char *name; mach_port_right_t right; }; static struct type_descr descrs[] = { {MACH_PORT_TYPE_SEND, "send", MACH_PORT_RIGHT_SEND}, {MACH_PORT_TYPE_SEND_ONCE, "send-once", MACH_PORT_RIGHT_SEND_ONCE}, {MACH_PORT_TYPE_RECEIVE, "receive", MACH_PORT_RIGHT_RECEIVE}, {MACH_PORT_TYPE_PORT_SET, "port-set", MACH_PORT_RIGHT_PORT_SET}, {MACH_PORT_TYPE_DEAD_NAME, "dead", MACH_PORT_RIGHT_DEAD_NAME} }; printf_unfiltered (_("%04x: %08x "), port, types[index]); for (j = 0; j < sizeof(descrs) / sizeof(*descrs); j++) if (types[index] & descrs[j].type) { mach_port_urefs_t ref; kern_return_t ret; printf_unfiltered (_(" %s("), descrs[j].name); ret = mach_port_get_refs (task, port, descrs[j].right, &ref); if (ret != KERN_SUCCESS) printf_unfiltered (_("??")); else printf_unfiltered (_("%u"), ref); printf_unfiltered (_(" refs)")); } if (task == task_self ()) { if (port == task_self()) printf_unfiltered (_(" gdb-task")); else if (port == darwin_host_self) printf_unfiltered (_(" host-self")); else if (port == darwin_ex_port) printf_unfiltered (_(" gdb-exception")); else if (port == darwin_port_set) printf_unfiltered (_(" gdb-port_set")); else if (!ptid_equal (inferior_ptid, null_ptid)) { struct inferior *inf = current_inferior (); if (port == inf->priv->task) printf_unfiltered (_(" inferior-task")); else if (port == inf->priv->notify_port) printf_unfiltered (_(" inferior-notify")); else { int k; darwin_thread_t *t; for (k = 0; k < inf->priv->exception_info.count; k++) if (port == inf->priv->exception_info.ports[k]) { printf_unfiltered (_(" inferior-excp-port")); break; } if (inf->priv->threads) { for (k = 0; VEC_iterate(darwin_thread_t, inf->priv->threads, k, t); k++) if (port == t->gdb_port) { printf_unfiltered (_(" inferior-thread for 0x%x"), inf->priv->task); break; } } } } } printf_unfiltered (_("\n")); } vm_deallocate (task_self (), (vm_address_t) names, (name_count * sizeof (mach_port_t))); vm_deallocate (task_self (), (vm_address_t) types, (type_count * sizeof (mach_port_type_t))); }