Between io_connect_method and is_io_connect_method

Questions and Answers about all things *OS (macOS, iOS, tvOS, watchOS)

Between io_connect_method and is_io_connect_method

Postby chengyang » Tue Feb 14, 2017 8:56 am

There is a question always puzzles me during my research.
When we call IOConnectCallMethod from user space, it will finnaly call io_connect_method in the IOKitUser.framework;

In the kernel source code we can find a is_io_connect_method, seems to be the kernel implementation.

So the question is, what happened between this two function? How does the pointers and datas transfer from user space into kernel space? :?: :?: :?:
chengyang
 
Posts: 14
Joined: Wed Aug 03, 2016 7:44 am

Re: Between io_connect_method and is_io_connect_method

Postby Siguza » Tue Feb 14, 2017 11:17 am

MIG.

IOKit is implemented as a MIG subsystem, which means that effectively all its functions are implemented solely around the "mach_message" trap, with the help of template files and a whole lot of boilerplate code.
The "missing link" you're looking for is most likely osfmk/device/device.defs in the XNU source, which can be turned into client-side and server-side C files with the command:
Code: Select all
mig -DIOKIT /path/to/xnu/osfmk/device/device.defs
That will give you three files: iokit.h, iokitServer.c and iokitUser.c.
In iokitUser.c, you can find this monstrosity:
Code: Select all
/* Routine io_connect_method */
mig_external kern_return_t io_connect_method
(
   mach_port_t connection,
   uint32_t selector,
   io_scalar_inband64_t scalar_input,
   mach_msg_type_number_t scalar_inputCnt,
   io_struct_inband_t inband_input,
   mach_msg_type_number_t inband_inputCnt,
   mach_vm_address_t ool_input,
   mach_vm_size_t ool_input_size,
   io_struct_inband_t inband_output,
   mach_msg_type_number_t *inband_outputCnt,
   io_scalar_inband64_t scalar_output,
   mach_msg_type_number_t *scalar_outputCnt,
   mach_vm_address_t ool_output,
   mach_vm_size_t *ool_output_size
)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
   typedef struct {
      mach_msg_header_t Head;
      NDR_record_t NDR;
      uint32_t selector;
      mach_msg_type_number_t scalar_inputCnt;
      uint64_t scalar_input[16];
      mach_msg_type_number_t inband_inputCnt;
      char inband_input[4096];
      mach_vm_address_t ool_input;
      mach_vm_size_t ool_input_size;
      mach_msg_type_number_t inband_outputCnt;
      mach_msg_type_number_t scalar_outputCnt;
      mach_vm_address_t ool_output;
      mach_vm_size_t ool_output_size;
   } Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
   typedef struct {
      mach_msg_header_t Head;
      NDR_record_t NDR;
      kern_return_t RetCode;
      mach_msg_type_number_t inband_outputCnt;
      char inband_output[4096];
      mach_msg_type_number_t scalar_outputCnt;
      uint64_t scalar_output[16];
      mach_vm_size_t ool_output_size;
      mach_msg_trailer_t trailer;
   } Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
   typedef struct {
      mach_msg_header_t Head;
      NDR_record_t NDR;
      kern_return_t RetCode;
      mach_msg_type_number_t inband_outputCnt;
      char inband_output[4096];
      mach_msg_type_number_t scalar_outputCnt;
      uint64_t scalar_output[16];
      mach_vm_size_t ool_output_size;
   } __Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif
   /*
    * typedef struct {
    *    mach_msg_header_t Head;
    *    NDR_record_t NDR;
    *    kern_return_t RetCode;
    * } mig_reply_error_t;
    */

   union {
      Request In;
      Reply Out;
   } Mess;

   Request *InP = &Mess.In;
   Reply *Out0P = &Mess.Out;
   Reply *Out1P = NULL;
   Reply *Out2P = NULL;

   mach_msg_return_t msg_result;
   unsigned int msgh_size;
   unsigned int msgh_size_delta;


#ifdef   __MIG_check__Reply__io_connect_method_t__defined
   kern_return_t check_result;
#endif   /* __MIG_check__Reply__io_connect_method_t__defined */

   __DeclareSendRpc(2865, "io_connect_method")

   InP->NDR = NDR_record;

   InP->selector = selector;

   if (scalar_inputCnt > 16) {
      { return MIG_ARRAY_TOO_LARGE; }
   }
   (void)memcpy((char *) InP->scalar_input, (const char *) scalar_input, 8 * scalar_inputCnt);

   InP->scalar_inputCnt = scalar_inputCnt;

   msgh_size_delta = (8 * scalar_inputCnt);
   msgh_size = (mach_msg_size_t)(sizeof(Request) - 4224) + msgh_size_delta;
   InP = (Request *) ((pointer_t) InP + msgh_size_delta - 128);

   if (inband_inputCnt > 4096) {
      { return MIG_ARRAY_TOO_LARGE; }
   }
   (void)memcpy((char *) InP->inband_input, (const char *) inband_input, inband_inputCnt);

   InP->inband_inputCnt = inband_inputCnt;

   msgh_size_delta = _WALIGN_(inband_inputCnt);
   msgh_size += msgh_size_delta;
   InP = (Request *) ((pointer_t) InP + msgh_size_delta - 4096);

   InP->ool_input = ool_input;

   InP->ool_input_size = ool_input_size;

   if (*inband_outputCnt < 4096)
      InP->inband_outputCnt = *inband_outputCnt;
   else
      InP->inband_outputCnt = 4096;

   if (*scalar_outputCnt < 16)
      InP->scalar_outputCnt = *scalar_outputCnt;
   else
      InP->scalar_outputCnt = 16;

   InP->ool_output = ool_output;

   InP->ool_output_size = *ool_output_size;

   InP = &Mess.In;
   InP->Head.msgh_bits =
      MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
   /* msgh_size passed as argument */
   InP->Head.msgh_request_port = connection;
   InP->Head.msgh_reply_port = mig_get_reply_port();
   InP->Head.msgh_id = 2865;
   InP->Head.msgh_reserved = 0;
   
/* BEGIN VOUCHER CODE */

#ifdef USING_VOUCHERS
   if (voucher_mach_msg_set != NULL) {
      voucher_mach_msg_set(&InP->Head);
   }
#endif // USING_VOUCHERS
   
/* END VOUCHER CODE */

   __BeforeSendRpc(2865, "io_connect_method")
   msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
   __AfterSendRpc(2865, "io_connect_method")
   if (msg_result != MACH_MSG_SUCCESS) {
      __MachMsgErrorWithoutTimeout(msg_result);
      { return msg_result; }
   }


#if   defined(__MIG_check__Reply__io_connect_method_t__defined)
   check_result = __MIG_check__Reply__io_connect_method_t((__Reply__io_connect_method_t *)Out0P, (__Reply__io_connect_method_t **)&Out1P, (__Reply__io_connect_method_t **)&Out2P);
   if (check_result != MACH_MSG_SUCCESS)
      { return check_result; }
#endif   /* defined(__MIG_check__Reply__io_connect_method_t__defined) */

   if (Out0P->inband_outputCnt > *inband_outputCnt) {
      (void)memcpy((char *) inband_output, (const char *) Out0P->inband_output,  *inband_outputCnt);
      *inband_outputCnt = Out0P->inband_outputCnt;
      { return MIG_ARRAY_TOO_LARGE; }
   }
   (void)memcpy((char *) inband_output, (const char *) Out0P->inband_output, Out0P->inband_outputCnt);

   *inband_outputCnt = Out0P->inband_outputCnt;

   if (Out1P->scalar_outputCnt > *scalar_outputCnt) {
      (void)memcpy((char *) scalar_output, (const char *) Out1P->scalar_output, 8 *  *scalar_outputCnt);
      *scalar_outputCnt = Out1P->scalar_outputCnt;
      { return MIG_ARRAY_TOO_LARGE; }
   }
   (void)memcpy((char *) scalar_output, (const char *) Out1P->scalar_output, 8 * Out1P->scalar_outputCnt);

   *scalar_outputCnt = Out1P->scalar_outputCnt;

   *ool_output_size = Out2P->ool_output_size;

   return KERN_SUCCESS;
}
In all of that, this line is where control is transferred to the kernel:
Code: Select all
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
On the kernel side, this is picked up by mach_msg_trap(), which passes it on to ipc_kmsg_send(). SInce the target port (your IOConnect handle) is in the kernel space, it is passed further on to ipc_kobject_server(), where the appropriate MIG subsystem is chosen from a variable named "mig_buckets", which has been initialized by mig_init() from the global array "mig_e", which is defined as follows:
Code: Select all
const struct mig_subsystem *mig_e[] = {
        (const struct mig_subsystem *)&mach_vm_subsystem,
        (const struct mig_subsystem *)&mach_port_subsystem,
        (const struct mig_subsystem *)&mach_host_subsystem,
        (const struct mig_subsystem *)&host_priv_subsystem,
        (const struct mig_subsystem *)&host_security_subsystem,
        (const struct mig_subsystem *)&clock_subsystem,
        (const struct mig_subsystem *)&clock_priv_subsystem,
        (const struct mig_subsystem *)&processor_subsystem,
        (const struct mig_subsystem *)&processor_set_subsystem,
        (const struct mig_subsystem *)&is_iokit_subsystem,
   (const struct mig_subsystem *)&lock_set_subsystem,
   (const struct mig_subsystem *)&task_subsystem,
   (const struct mig_subsystem *)&thread_act_subsystem,
#ifdef VM32_SUPPORT
   (const struct mig_subsystem *)&vm32_map_subsystem,
#endif
   (const struct mig_subsystem *)&UNDReply_subsystem,
   (const struct mig_subsystem *)&mach_voucher_subsystem,
   (const struct mig_subsystem *)&mach_voucher_attr_control_subsystem,

#if     XK_PROXY
        (const struct mig_subsystem *)&do_uproxy_xk_uproxy_subsystem,
#endif /* XK_PROXY */
#if     MACH_MACHINE_ROUTINES
        (const struct mig_subsystem *)&MACHINE_SUBSYSTEM,
#endif  /* MACH_MACHINE_ROUTINES */
#if     MCMSG && iPSC860
   (const struct mig_subsystem *)&mcmsg_info_subsystem,
#endif  /* MCMSG && iPSC860 */
};
One of these, "is_iokit_subsystem", is part of our generated iokitServer.c, and another monstrosity:
Code: Select all
/* Description of this subsystem, for use in direct RPC */
const struct is_iokit_subsystem {
   mig_server_routine_t    server;   /* Server routine */
   mach_msg_id_t   start;   /* Min routine number */
   mach_msg_id_t   end;   /* Max routine number + 1 */
   unsigned int   maxsize;   /* Max msg size */
   vm_address_t   reserved;   /* Reserved */
   struct routine_descriptor   /*Array of routine descriptors */
      routine[87];
} is_iokit_subsystem = {
   iokit_server_routine,
   2800,
   2887,
   (mach_msg_size_t)sizeof(union __ReplyUnion__is_iokit_subsystem),
   (vm_address_t)0,
   {
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_object_get_class, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_object_get_class_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_object_conforms_to, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_object_conforms_to_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_iterator_next, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_iterator_next_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_iterator_reset, 1, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_iterator_reset_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_services, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_services_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_property, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_property_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_create_iterator, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_create_iterator_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_iterator_enter_entry, 1, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_iterator_enter_entry_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_iterator_exit_entry, 1, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_iterator_exit_entry_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_from_path, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_from_path_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_name, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_name_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_properties, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_properties_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_property_bytes, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_property_bytes_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_child_iterator, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_child_iterator_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_parent_iterator, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_parent_iterator_t)},
      {0, 0, 0, 0, 0, 0},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_close, 1, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_close_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_get_service, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_get_service_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_set_notification_port, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_set_notification_port_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_map_memory, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_map_memory_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_add_client, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_add_client_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_set_properties, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_set_properties_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method_scalarI_scalarO, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_scalarI_scalarO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method_scalarI_structureO, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_scalarI_structureO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method_scalarI_structureI, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_scalarI_structureI_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method_structureI_structureO, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_structureI_structureO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_path, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_path_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_get_root_entry, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_get_root_entry_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_set_properties, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_set_properties_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_in_plane, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_in_plane_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_object_get_retain_count, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_object_get_retain_count_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_busy_state, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_busy_state_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_wait_quiet, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_wait_quiet_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_create_iterator, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_create_iterator_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_iterator_is_valid, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_iterator_is_valid_t)},
      {0, 0, 0, 0, 0, 0},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_send_data, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_send_data_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_terminate, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_terminate_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_get_data, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_get_data_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_get_gen_count, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_get_gen_count_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_module_loaded, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_module_loaded_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_catalog_reset, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_catalog_reset_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_request_probe, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_request_probe_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_name_in_plane, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_name_in_plane_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_match_property_table, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_match_property_table_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_async_method_scalarI_scalarO, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_async_method_scalarI_scalarO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_async_method_scalarI_structureO, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_async_method_scalarI_structureO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_async_method_scalarI_structureI, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_async_method_scalarI_structureI_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_async_method_structureI_structureO, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_async_method_structureI_structureO_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_add_notification, 7, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_add_notification_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_add_interest_notification, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_add_interest_notification_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_acknowledge_notification, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_acknowledge_notification_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_get_notification_semaphore, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_get_notification_semaphore_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_unmap_memory, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_unmap_memory_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_location_in_plane, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_location_in_plane_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_property_recursively, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_property_recursively_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_state, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_state_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_services_ool, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_services_ool_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_match_property_table_ool, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_match_property_table_ool_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_add_notification_ool, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_add_notification_ool_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_object_get_superclass, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_object_get_superclass_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_object_get_bundle_identifier, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_object_get_bundle_identifier_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_open_extended, 8, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_open_extended_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_map_memory_into_task, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_map_memory_into_task_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_unmap_memory_from_task, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_unmap_memory_from_task_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method, 17, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_async_method, 20, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_async_method_t)},
      {0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_registry_entry_id, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_registry_entry_id_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_connect_method_var_output, 16, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_connect_method_var_output_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_service, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_service_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_service_ool, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_service_ool_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_authorization_id, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_authorization_id_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_set_authorization_id, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_set_authorization_id_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_server_version, 2, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_server_version_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_properties_bin, 3, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_properties_bin_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_property_bin, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_property_bin_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_service_bin, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_service_bin_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_get_matching_services_bin, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_get_matching_services_bin_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_match_property_table_bin, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_match_property_table_bin_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_service_add_notification_bin, 8, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_service_add_notification_bin_t)},
      {0, 0, 0, 0, 0, 0},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_get_path_ool, 5, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_get_path_ool_t)},
          { (mig_impl_routine_t) 0,
          (mig_stub_routine_t) _Xio_registry_entry_from_path_ool, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__io_registry_entry_from_path_ool_t)},
   }
};
As you might have guessed (after a lot of reading), _Xio_connect_method() is where you'll end up, which is defined in the same file as yet another monstrously looking thing:
Code: Select all
/* Routine io_connect_method */
mig_internal novalue _Xio_connect_method
   (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
   typedef struct {
      mach_msg_header_t Head;
      NDR_record_t NDR;
      uint32_t selector;
      mach_msg_type_number_t scalar_inputCnt;
      uint64_t scalar_input[16];
      mach_msg_type_number_t inband_inputCnt;
      char inband_input[4096];
      mach_vm_address_t ool_input;
      mach_vm_size_t ool_input_size;
      mach_msg_type_number_t inband_outputCnt;
      mach_msg_type_number_t scalar_outputCnt;
      mach_vm_address_t ool_output;
      mach_vm_size_t ool_output_size;
      mach_msg_trailer_t trailer;
   } Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif
   typedef __Request__io_connect_method_t __Request;
   typedef __Reply__io_connect_method_t Reply __attribute__((unused));

   /*
    * typedef struct {
    *    mach_msg_header_t Head;
    *    NDR_record_t NDR;
    *    kern_return_t RetCode;
    * } mig_reply_error_t;
    */

   Request *In0P = (Request *) InHeadP;
   Request *In1P;
   Request *In2P;
   Reply *OutP = (Reply *) OutHeadP;
   unsigned int msgh_size;
   unsigned int msgh_size_delta;

#ifdef   __MIG_check__Request__io_connect_method_t__defined
   kern_return_t check_result;
#endif   /* __MIG_check__Request__io_connect_method_t__defined */

   uint64_t scalar_output[16];
   mach_msg_type_number_t scalar_outputCnt;

   __DeclareRcvRpc(2865, "io_connect_method")
   __BeforeRcvRpc(2865, "io_connect_method")

#if   defined(__MIG_check__Request__io_connect_method_t__defined)
   check_result = __MIG_check__Request__io_connect_method_t((__Request *)In0P, (__Request **)&In1P, (__Request **)&In2P);
   if (check_result != MACH_MSG_SUCCESS)
      { MIG_RETURN_ERROR(OutP, check_result); }
#endif   /* defined(__MIG_check__Request__io_connect_method_t__defined) */

   OutP->inband_outputCnt = 4096;
   if (In2P->inband_outputCnt < OutP->inband_outputCnt)
      OutP->inband_outputCnt = In2P->inband_outputCnt;

   scalar_outputCnt = 16;
   if (In2P->scalar_outputCnt < scalar_outputCnt)
      scalar_outputCnt = In2P->scalar_outputCnt;

   OutP->RetCode = is_io_connect_method(In0P->Head.msgh_request_port, In0P->selector, In0P->scalar_input, In0P->scalar_inputCnt, In1P->inband_input, In1P->inband_inputCnt, In2P->ool_input, In2P->ool_input_size, OutP->inband_output, &OutP->inband_outputCnt, scalar_output, &scalar_outputCnt, In2P->ool_output, &In2P->ool_output_size);
   if (OutP->RetCode != KERN_SUCCESS) {
      MIG_RETURN_ERROR(OutP, OutP->RetCode);
   }

   OutP->NDR = NDR_record;

   msgh_size_delta = _WALIGN_((OutP->inband_outputCnt + 3) & ~3);
   msgh_size = (mach_msg_size_t)(sizeof(Reply) - 4224) + msgh_size_delta;
   OutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - 4096);
   (void)memcpy((char *) OutP->scalar_output, (const char *) scalar_output, 8 * scalar_outputCnt);
   OutP->scalar_outputCnt = scalar_outputCnt;
   msgh_size_delta = ((8 * scalar_outputCnt));
   msgh_size += msgh_size_delta;
   OutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - 128);

   OutP->ool_output_size = In2P->ool_output_size;

   OutP = (Reply *) OutHeadP;
   OutP->Head.msgh_size = msgh_size;
   __AfterRcvRpc(2865, "io_connect_method")
}
And in the middle of all of that is the call to is_io_connect_method() you've been looking for:
Code: Select all
OutP->RetCode = is_io_connect_method(In0P->Head.msgh_request_port, In0P->selector, In0P->scalar_input, In0P->scalar_inputCnt, In1P->inband_input, In1P->inband_inputCnt, In2P->ool_input, In2P->ool_input_size, OutP->inband_output, &OutP->inband_outputCnt, scalar_output, &scalar_outputCnt, In2P->ool_output, &In2P->ool_output_size);
User avatar
Siguza
Unicorn
 
Posts: 159
Joined: Thu Jan 28, 2016 10:38 am

Re: Between io_connect_method and is_io_connect_method

Postby chengyang » Wed Feb 15, 2017 9:15 am

Great explanation!
Thanks for ur reply very much.
chengyang
 
Posts: 14
Joined: Wed Aug 03, 2016 7:44 am


Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 6 guests