Beispiel #1
0
void Port::dump(const char *descr)
{
    if (mPort == MACH_PORT_NULL) {
        Debug::dump("[%s==NULL]\n", descr ? descr : "port");
    } else {
        Debug::dump("[%s(%d)", descr ? descr : "port", mPort);
        mach_port_type_t type;
        if (kern_return_t err = mach_port_type(self(), mPort, &type)) {
            Debug::dump(" !%s", mach_error_string(err));
        } else {
            if (type & MACH_PORT_TYPE_SEND)
                Debug::dump(" send(%d)", getRefs(MACH_PORT_RIGHT_SEND));
            if (type & MACH_PORT_TYPE_RECEIVE)
                Debug::dump(" rcv");
            if (type & MACH_PORT_TYPE_SEND_ONCE)
                Debug::dump(" once(%d)", getRefs(MACH_PORT_RIGHT_SEND));
            if (type & MACH_PORT_TYPE_PORT_SET)
                Debug::dump(" set");
            if (type & MACH_PORT_TYPE_DEAD_NAME)
                Debug::dump(" dead(%d)", getRefs(MACH_PORT_RIGHT_SEND));        
            if (type & MACH_PORT_TYPE_DNREQUEST)
                Debug::dump(" dnreq");
            // handle unknown/unexpected type flags
            if (type & ~(MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_SEND_ONCE|
                    MACH_PORT_TYPE_PORT_SET|MACH_PORT_TYPE_DEAD_NAME|MACH_PORT_TYPE_DNREQUEST))
                Debug::dump(" type(0x%x)", type);
        }
        Debug::dump("]\n");
    }
}
void
test_mach_debug_port(mach_port_t name, const char *str, unsigned int line)
{
	mach_port_type_t type;
	mach_msg_bits_t ns = 0, nr = 0, nso = 0, nd = 0;
	unsigned int dnreqs = 0, dnrsiz;
	kern_return_t kr = mach_port_type(mach_task_self(), name, &type);
	if (kr) {
		fprintf(stderr, "machport[0x%08x] = { error(0x%x) \"%s\" }: %s %u\n",
				name, kr, mach_error_string(kr), str, line);
		return;
	}
	if (type & MACH_PORT_TYPE_SEND) {
		test_mach_assume_zero(mach_port_get_refs(mach_task_self(), name,
				MACH_PORT_RIGHT_SEND, &ns));
	}
	if (type & MACH_PORT_TYPE_SEND_ONCE) {
		test_mach_assume_zero(mach_port_get_refs(mach_task_self(), name,
				MACH_PORT_RIGHT_SEND_ONCE, &nso));
	}
	if (type & MACH_PORT_TYPE_DEAD_NAME) {
		test_mach_assume_zero(mach_port_get_refs(mach_task_self(), name,
				MACH_PORT_RIGHT_DEAD_NAME, &nd));
	}
	if (type & (MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_SEND)) {
		test_mach_assume_zero(mach_port_dnrequest_info(mach_task_self(), name,
				&dnrsiz, &dnreqs));
		}
	if (type & MACH_PORT_TYPE_RECEIVE) {
		mach_port_status_t status = { .mps_pset = 0, };
		mach_msg_type_number_t cnt = MACH_PORT_RECEIVE_STATUS_COUNT;
		test_mach_assume_zero(mach_port_get_refs(mach_task_self(), name,
				MACH_PORT_RIGHT_RECEIVE, &nr));
		test_mach_assume_zero(mach_port_get_attributes(mach_task_self(), name,
				MACH_PORT_RECEIVE_STATUS, (void*)&status, &cnt));
		fprintf(stderr, "machport[0x%08x] = { R(%03u) S(%03u) SO(%03u) D(%03u) "
				"dnreqs(%03u) spreq(%s) nsreq(%s) pdreq(%s) srights(%s) "
				"sorights(%03u) qlim(%03u) msgcount(%03u) mkscount(%03u) "
				"seqno(%03u) }: %s %u\n", name, nr, ns, nso, nd, dnreqs,
				type & MACH_PORT_TYPE_SPREQUEST ? "Y":"N",
				status.mps_nsrequest ? "Y":"N", status.mps_pdrequest ? "Y":"N",
				status.mps_srights ? "Y":"N", status.mps_sorights,
				status.mps_qlimit, status.mps_msgcount, status.mps_mscount,
				status.mps_seqno, str, line);
	} else if (type & (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_SEND_ONCE|
/* Translate the port FROM between the tasks in X, returning the translated
   name in TO, and the types of TO in TO_TYPE, or an error.  If TYPE is
   non-zero, it should be what mach_port_type returns for FROM.  */
error_t
port_name_xlator_xlate (struct port_name_xlator *x,
			mach_port_t from, mach_port_type_t from_type,
			mach_port_t *to, mach_port_type_t *to_type)
{
  error_t err;
  mach_port_t port;
  mach_msg_type_number_t i;
  mach_msg_type_name_t aquired_type;
  mach_msg_type_name_t valid_to_types;

  if (from_type == 0)
    {
      error_t err = mach_port_type (x->from_task, from, &from_type);
      if (err)
	return err;
    }

  if (from_type & MACH_PORT_TYPE_RECEIVE)
    valid_to_types = MACH_PORT_TYPE_SEND;
  else if (from_type & MACH_PORT_TYPE_SEND)
    valid_to_types = MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_RECEIVE;
  else
    return EKERN_INVALID_RIGHT;

  /* Translate the name FROM, in FROM_TASK's namespace into our namespace. */
  err =
    mach_port_extract_right (x->from_task, from,
			     ((from_type & MACH_PORT_TYPE_RECEIVE)
			      ? MACH_MSG_TYPE_MAKE_SEND
			      : MACH_MSG_TYPE_COPY_SEND),
			     &port,
			     &aquired_type);

  if (err)
    return err;

  /* Look for likely candidates in TO_TASK's namespace to test against PORT. */
  for (i = 0; i < x->to_names_len; i++)
    {
      if (x->ports[i] == MACH_PORT_NULL && (x->to_types[i] & valid_to_types))
	/* Port I shows possibilities... */
	{
	  err =
	    mach_port_extract_right (x->to_task,
				     x->to_names[i],
				     ((x->to_types[i] & MACH_PORT_TYPE_RECEIVE)
				      ? MACH_MSG_TYPE_MAKE_SEND
				      : MACH_MSG_TYPE_COPY_SEND),
				     &x->ports[i],
				     &aquired_type);
	  if (err)
	    x->to_types[i] = 0;	/* Don't try to fetch this port again.  */
	}

      if (x->ports[i] == port)
	/* We win!  Port I in TO_TASK is the same as PORT.  */
	break;
  }

  mach_port_deallocate (mach_task_self (), port);

  if (i < x->to_names_len)
    /* Port I is the right translation; return its name in TO_TASK.  */
    {
      *to = x->to_names[i];
      *to_type = x->to_types[i];
      return 0;
    }
  else
    return EKERN_INVALID_NAME;
}