static void protMustSend(mach_msg_header_t *head) { kern_return_t kr; kr = mach_msg(head, MACH_SEND_MSG, head->msgh_size, /* recv_size */ 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); AVER(kr == KERN_SUCCESS); if (kr != KERN_SUCCESS) mach_error("ERROR: MPS mach_msg send", kr); /* .trans.must */ }
mach_port_t recover_shared_port_child() { kern_return_t err; // grab the shared port which our parent stashed somewhere in the special ports mach_port_t shared_port_child = MACH_PORT_NULL; err = task_get_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, &shared_port_child); MACH_ERR("child getting stashed port", err); LOG("child got stashed port"); // say hello to our parent and send a reply port so it can send us back the special port to restore // allocate a reply port mach_port_t reply_port; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &reply_port); MACH_ERR("child allocating reply port", err); // send the reply port in a hello message simple_msg_send_t msg = {0}; msg.header.msgh_size = sizeof(msg); msg.header.msgh_local_port = reply_port; msg.header.msgh_remote_port = shared_port_child; msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); err = mach_msg_send(&msg.header); MACH_ERR("child sending task port message", err); LOG("child sent hello message to parent over shared port"); // wait for a message on the reply port containing the stolen port to restore port_msg_rcv_t stolen_port_msg = {0}; err = mach_msg(&stolen_port_msg.header, MACH_RCV_MSG, 0, sizeof(stolen_port_msg), reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); MACH_ERR("child receiving stolen port\n", err); // extract the port right from the message mach_port_t stolen_port_to_restore = stolen_port_msg.port.name; if (stolen_port_to_restore == MACH_PORT_NULL) { FAIL("child received invalid stolen port to restore"); } // restore the special port for the child err = task_set_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, stolen_port_to_restore); MACH_ERR("child restoring special port", err); LOG("child restored stolen port"); return shared_port_child; }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ void server_handle_request(CFMachPortRef port, void *msg, CFIndex size, void *info) { mach_msg_return_t r; mach_msg_header_t * request = (mach_msg_header_t *)msg; mach_msg_header_t * reply; char reply_s[128] __attribute__ ((aligned (4))); // Wcast-align fix - force alignment if (process_notification(request) == FALSE) { if (_pppcontroller_subsystem.maxsize > sizeof(reply_s)) { syslog(LOG_ERR, "PPPController: %d > %ld", _pppcontroller_subsystem.maxsize, sizeof(reply_s)); reply = (mach_msg_header_t *) malloc(_pppcontroller_subsystem.maxsize); } else { reply = ALIGNED_CAST(mach_msg_header_t *)reply_s; } if (pppcontroller_server(request, reply) == FALSE) { syslog(LOG_INFO, "unknown message ID (%d) received", request->msgh_id); mach_msg_destroy(request); } else { int options; options = MACH_SEND_MSG; if (MACH_MSGH_BITS_REMOTE(reply->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND) { options |= MACH_SEND_TIMEOUT; } r = mach_msg(reply, options, reply->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (r != MACH_MSG_SUCCESS) { syslog(LOG_INFO, "PPPController: mach_msg(send): %s", mach_error_string(r)); mach_msg_destroy(reply); } } if (reply != ALIGNED_CAST(mach_msg_header_t *)reply_s) { free(reply); } } return; }
/* SimpleRoutine consume_send_once_right */ mig_external kern_return_t _dispatch_send_consume_send_once_right ( mach_port_t _port ) { #ifdef __MigPackStructs #pragma pack(4) #endif typedef struct { mach_msg_header_t Head; } Request; #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; } Mess; Request *InP = &Mess.In; mach_msg_return_t msg_result; #ifdef __MIG_check__Reply__consume_send_once_right_t__defined kern_return_t check_result; #endif /* __MIG_check__Reply__consume_send_once_right_t__defined */ __DeclareSendSimple(79, "consume_send_once_right") InP->Head.msgh_bits = MACH_MSGH_BITS(18, 0); /* msgh_size passed as argument */ InP->Head.msgh_request_port = _port; InP->Head.msgh_reply_port = MACH_PORT_NULL; InP->Head.msgh_id = 79; __BeforeSendSimple(79, "consume_send_once_right") msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); __AfterSendSimple(79, "consume_send_once_right") return msg_result; }
void SignalHandler(int signum) { SignalMessage msg; msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0); msg.header.msgh_size = sizeof(msg) - sizeof(mach_msg_trailer_t); msg.header.msgh_remote_port = gSignalPort; msg.header.msgh_local_port = MACH_PORT_NULL; msg.header.msgh_id = kSignalMessage; msg.body.msgh_descriptor_count = 0; msg.signum = signum; mach_msg(&msg.header,(MACH_SEND_MSG | MACH_SEND_TIMEOUT), msg.header.msgh_size,0,MACH_PORT_NULL,0,MACH_PORT_NULL); }
/* * Exception thread handler. */ static void * mach_exception_thread (void *arg) { for (;;) { mach_exception_msg_t request; mach_exception_msg_t reply; mach_msg_return_t result; /* receive from "mach_exception_port" */ result = mach_msg (&request.msg.header, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (request), mach_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); g_assert (result == MACH_MSG_SUCCESS); /* dispatch to catch_exception_raise () */ exc_server (&request.msg.header, &reply.msg.header); /* send back to sender */ result = mach_msg (&reply.msg.header, MACH_SEND_MSG, reply.msg.header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); g_assert (result == MACH_MSG_SUCCESS); } return NULL; }
/* this is the thread which forwards of exceptions read from the exception server off to our exception catchers and then back out to the other thread */ void exception_thread(void *shared_thread_state) { mach_msg_header_t *message; mach_msg_header_t *reply; kern_return_t retval; #ifdef USE_THREAD_LOCAL pthread_setspecific(scheme_thread_local_key, shared_thread_state); #endif /* allocate the space for the message and reply */ message = (mach_msg_header_t*)malloc(sizeof(mach_exc_msg_t)); reply = (mach_msg_header_t*)malloc(sizeof(mach_reply_msg_t)); /* do this loop forever */ while(1) { /* block until we get an exception message */ retval = mach_msg(message, MACH_RCV_MSG, 0, sizeof(mach_exc_msg_t), exc_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if(retval != KERN_SUCCESS) { GCPRINT(GCOUTF, "Message receive failed: %s\n", mach_error_string(retval)); abort(); } /* forward off the handling of this message */ if(!exc_server(message, reply)) { GCPRINT(GCOUTF, "INTERNAL ERROR: exc_server() didn't like something\n"); abort(); } /* send the message back out to the thread */ retval = mach_msg(reply, MACH_SEND_MSG, sizeof(mach_reply_msg_t), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if(retval != KERN_SUCCESS) { GCPRINT(GCOUTF, "Message send failed: %s\n", mach_error_string(retval)); abort(); } } }
/* this is the thread which forwards of exceptions read from the exception server off to our exception catchers and then back out to the other thread */ void exception_thread(void) { mach_msg_header_t *message; mach_msg_header_t *reply; kern_return_t retval; /* allocate the space for the message and reply */ message = (mach_msg_header_t*)malloc(sizeof(mach_exc_msg_t)); reply = (mach_msg_header_t*)malloc(sizeof(mach_reply_msg_t)); /* do this loop forever */ while(1) { /* block until we get an exception message */ retval = mach_msg(message, MACH_RCV_MSG, 0, sizeof(mach_exc_msg_t), exc_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); /* forward off the handling of this message */ if(!exc_server(message, reply)) { GCPRINT(GCOUTF, "INTERNAL ERROR: exc_server() didn't like something\n"); abort(); } /* send the message back out to the thread */ retval = mach_msg(reply, MACH_SEND_MSG, sizeof(mach_reply_msg_t), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); } }
static void *mach_exception_thread(void *data) { while (true) { struct { mach_msg_header_t head; mach_msg_body_t msgh_body; char data[1024]; } msg; struct { mach_msg_header_t head; char data[1024]; } reply; // wait for a message on the exception port mach_msg_return_t ret = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(msg), s_listen_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (ret != MACH_MSG_SUCCESS) { LOG_INFO("mach_msg receive failed with %d %s", ret, mach_error_string(ret)); break; } // call exc_server, which will call back into catch_exception_raise exc_server(&msg.head, &reply.head); // send the reply ret = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (ret != MACH_MSG_SUCCESS) { LOG_INFO("mach_msg send failed with %d %s", ret, mach_error_string(ret)); break; } } return NULL; }
void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord) { MSG_SET_THREAD MsgSet; kern_return_t MachRet; EXCEPTION_POINTERS pointers; pointers.ExceptionRecord = pExRecord; pointers.ContextRecord = pContext; // Raise the exception SEHRaiseException(&pointers, 0); // We need to send a message to the worker thread so that it can set our thread context // Setup the heaer MsgSet.m_MsgHdr.msgh_size = sizeof(MsgSet); MsgSet.m_MsgHdr.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND|MACH_MSG_TYPE_MOVE_RECEIVE); // Simple Message MsgSet.m_MsgHdr.msgh_remote_port = s_ExceptionPort; // Send, dest port MsgSet.m_MsgHdr.msgh_local_port = MACH_PORT_NULL; // We're not expecting a msg back MsgSet.m_MsgHdr.msgh_id = SET_THREAD_MESSAGE_ID; // Message ID MsgSet.m_MsgHdr.msgh_reserved = 0; // Not used // Setup the thread and thread context MsgSet.m_ThreadPort = mach_thread_self(); MsgSet.m_ThreadContext = *pContext; // Send the message to the exception port MachRet = mach_msg(&MsgSet.m_MsgHdr, MACH_SEND_MSG, MsgSet.m_MsgHdr.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (MachRet != KERN_SUCCESS) { UTIL_SetLastErrorFromMach(MachRet); ExitProcess(GetLastError()); } // Make sure we don't do anything while(1) { sched_yield(); } }
void Connection::receiveSourceEventHandler() { char buffer[inlineMessageMaxSize]; mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(&buffer); kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, sizeof(buffer), m_receivePort, 0, MACH_PORT_NULL); if (kr == MACH_RCV_TIMED_OUT) return; if (kr != MACH_MSG_SUCCESS) { ASSERT_NOT_REACHED(); // FIXME: Handle MACH_RCV_MSG_TOO_LARGE. return; } MessageID messageID = MessageID::fromInt(header->msgh_id); std::auto_ptr<ArgumentDecoder> arguments = createArgumentDecoder(header); ASSERT(arguments.get()); if (messageID == MessageID(CoreIPCMessage::InitializeConnection)) { ASSERT(m_isServer); ASSERT(!m_isConnected); ASSERT(!m_sendPort); MachPort port; if (!arguments->decode(port)) { // FIXME: Disconnect. return; } m_sendPort = port.port(); // Set the dead name source if needed. if (m_sendPort) initializeDeadNameSource(); m_isConnected = true; // Send any pending outgoing messages. sendOutgoingMessages(); return; } processIncomingMessage(messageID, arguments); }
IOReturn IODataQueueWaitForAvailableData(IODataQueueMemory *dataQueue, mach_port_t notifyPort) { IOReturn kr; struct { mach_msg_header_t msgHdr; // OSNotificationHeader notifyHeader; mach_msg_trailer_t trailer; } msg; if (dataQueue && (notifyPort != MACH_PORT_NULL)) { kr = mach_msg(&msg.msgHdr, MACH_RCV_MSG, 0, sizeof(msg), notifyPort, 0, MACH_PORT_NULL); } else { kr = kIOReturnBadArgument; } return kr; }
static void TerminateMachExceptionHandlerThread() { // Send a simple quit message to the exception handler thread. mach_msg_header_t msg; msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); msg.msgh_size = static_cast<mach_msg_size_t>(sizeof(msg)); msg.msgh_remote_port = sMachExceptionState.current.port; msg.msgh_local_port = MACH_PORT_NULL; msg.msgh_reserved = 0; msg.msgh_id = sIDQuit; kern_return_t ret = mach_msg(&msg, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (ret == MACH_MSG_SUCCESS) sMachExceptionState.handlerThread.join(); else MOZ_CRASH("MachExceptionHandler: Handler thread failed to terminate!"); }
static int recv_port (mach_port_t recv_port, mach_port_t *port) { kern_return_t err; struct { mach_msg_header_t header; mach_msg_body_t body; mach_msg_port_descriptor_t task_port; mach_msg_trailer_t trailer; } msg; err = mach_msg (&msg.header, MACH_RCV_MSG, 0, sizeof msg, recv_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); CHECK_MACH_ERROR (err, "mach_msg failed:"); *port = msg.task_port.name; return 0; }
error_t send (mach_msg_id_t msgid) { error_t err; Message.Request = RequestTemplate; Message.Request.Head.msgh_id = msgid; err = mach_msg (&Message.Request.Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, sizeof Message.Request, sizeof Message.Reply, Message.Request.Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (err) return err; /* XXX typecheck */ return Message.Reply.RetCode; }
STATIC void server_handle_request(CFMachPortRef port, void * msg, CFIndex size, void * info) { mach_msg_return_t r; mach_msg_header_t * request = (mach_msg_header_t *)msg; mach_msg_header_t * reply; char reply_s[eapolcfg_auth_subsystem.maxsize]; if (process_notification(request) == FALSE) { reply = (mach_msg_header_t *)reply_s; if (eapolcfg_auth_server(request, reply) == FALSE) { syslog(LOG_NOTICE, "eapolcfg_auth: unknown message ID (%d)", request->msgh_id); mach_msg_destroy(request); } else { int options; S_handled_request = TRUE; options = MACH_SEND_MSG; if (MACH_MSGH_BITS_REMOTE(reply->msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) { options |= MACH_SEND_TIMEOUT; } r = mach_msg(reply, options, reply->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (r != MACH_MSG_SUCCESS) { syslog(LOG_NOTICE, "eapolcfg_auth: mach_msg(send): %s", mach_error_string(r)); mach_msg_destroy(reply); } } } return; }
mach_port_t do_parent(mach_port_t shared_port) { kern_return_t err; // wait for our child to send us its task port port_msg_rcv_t msg = {0}; err = mach_msg(&msg.header, MACH_RCV_MSG, 0, sizeof(msg), shared_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); MACH_ERR("parent receiving child task port message", err); mach_port_t child_task_port = msg.port.name; if (child_task_port == MACH_PORT_NULL) { FAIL("invalid child task port"); } return child_task_port; }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ void mach_client_notify (mach_port_t port, CFStringRef serviceID, u_long event, u_long error) { mach_msg_empty_send_t msg; kern_return_t status; /* Post notification as mach message */ msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); msg.header.msgh_size = sizeof(msg); msg.header.msgh_remote_port = port; msg.header.msgh_local_port = MACH_PORT_NULL; msg.header.msgh_id = 0; status = mach_msg(&msg.header, /* msg */ MACH_SEND_MSG|MACH_SEND_TIMEOUT, /* options */ msg.header.msgh_size, /* send_size */ 0, /* rcv_size */ MACH_PORT_NULL, /* rcv_name */ 0, /* timeout */ MACH_PORT_NULL); /* notify */ if (status == MACH_SEND_TIMEOUT) mach_msg_destroy(&msg.header); }
void receive_integer( mach_port_t source, int *ip ) { kern_return_t err; struct integer_message message; err = mach_msg( &(message.head), MACH_RCV_MSG, 0,message.head.msgh_size, source,MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL ); if( err == MACH_MSG_SUCCESS ) { printf( "success: the message was received\n" ); } else { perror( "error: Some unexpected error ocurred\n" ); } *ip = message.inline_integer; return; }
void bad_xpc(mach_port_t p) { kern_return_t err; struct xpc_bad_ool msg = {0}; msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX); msg.hdr.msgh_size = sizeof(msg); msg.hdr.msgh_remote_port = p; msg.hdr.msgh_id = 0x10000000; msg.body.msgh_descriptor_count = 0; msg.ool0.address = 0x414141414141; msg.ool0.size = 0x4000; msg.ool0.type = MACH_MSG_OOL_DESCRIPTOR; msg.port1.name = 0x41414141; // port name to mach_port_deallocate in target msg.port1.disposition = 0x11; msg.port1.type = MACH_MSG_PORT_DESCRIPTOR; msg.ool2.address = 0x414141414141; msg.ool2.size = 0x4000; msg.ool2.type = MACH_MSG_OOL_DESCRIPTOR; err = mach_msg(&msg.hdr, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, msg.hdr.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (err != KERN_SUCCESS) { printf("xpc message send failed: %s\n", mach_error_string(err)); exit(EXIT_FAILURE); } else { printf("sent xpc message\n"); } }
void do_free(mach_port_t host_service, mach_port_t target_port) { kern_return_t err; int port_count = 0x10000; mach_port_t* ports = malloc(port_count * sizeof(mach_port_t)); for (int i = 0; i < port_count; i++) { ports[i] = target_port; } // build the message to free the target port name struct launchd_ool_msg* free_msg = malloc(sizeof(struct launchd_ool_msg)); memset(free_msg, 0, sizeof(struct launchd_ool_msg)); free_msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); free_msg->hdr.msgh_size = sizeof(struct launchd_ool_msg); free_msg->hdr.msgh_remote_port = host_service; free_msg->hdr.msgh_local_port = MACH_PORT_NULL; free_msg->hdr.msgh_id = msgh_id_to_get_destroyed; free_msg->body.msgh_descriptor_count = 1; free_msg->ool_ports.address = ports; free_msg->ool_ports.count = port_count; free_msg->ool_ports.deallocate = 0; free_msg->ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND; free_msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR; free_msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY; // send the free message err = mach_msg(&free_msg->hdr, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(struct launchd_ool_msg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); printf("free message: %s\n", mach_error_string(err)); }
mach_port_t recover_shared_port_parent() { kern_return_t err; // restore the special port for ourselves err = task_set_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, saved_special_port); MACH_ERR("parent restoring special port", err); // wait for a message from the child on the shared port simple_msg_rcv_t msg = {0}; err = mach_msg(&msg.header, MACH_RCV_MSG, 0, sizeof(msg), shared_port_parent, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); MACH_ERR("parent receiving child hello message", err); LOG("parent received hello message from child"); // send the special port to our child over the hello message's reply port port_msg_send_t special_port_msg = {0}; special_port_msg.header.msgh_size = sizeof(special_port_msg); special_port_msg.header.msgh_local_port = MACH_PORT_NULL; special_port_msg.header.msgh_remote_port = msg.header.msgh_remote_port; special_port_msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(msg.header.msgh_bits), 0) | MACH_MSGH_BITS_COMPLEX; special_port_msg.body.msgh_descriptor_count = 1; special_port_msg.port.name = saved_special_port; special_port_msg.port.disposition = MACH_MSG_TYPE_COPY_SEND; special_port_msg.port.type = MACH_MSG_PORT_DESCRIPTOR; err = mach_msg_send(&special_port_msg.header); MACH_ERR("parent sending special port back to child", err); return shared_port_parent; }
void spoof(mach_port_t port, uint32_t name) { kern_return_t err; struct notification_msg not = {0}; not.not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); not.not_header.msgh_size = sizeof(struct notification_msg); not.not_header.msgh_remote_port = port; not.not_header.msgh_local_port = MACH_PORT_NULL; not.not_header.msgh_id = 0110; // MACH_NOTIFY_DEAD_NAME not.NDR = NDR_record; not.not_port = name; // send the fake notification message err = mach_msg(¬.not_header, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(struct notification_msg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); }
static void __DACommandSignal( int sig ) { /* * Process a SIGCHLD signal. mach_msg() is safe from a signal handler. */ mach_msg_header_t message; kern_return_t status; message.msgh_bits = MACH_MSGH_BITS( MACH_MSG_TYPE_COPY_SEND, 0 ); message.msgh_id = 0; message.msgh_local_port = MACH_PORT_NULL; message.msgh_remote_port = CFMachPortGetPort( __gDACommandRunLoopSourcePort ); message.msgh_reserved = 0; message.msgh_size = sizeof( message ); status = mach_msg( &message, MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL ); if ( status == MACH_SEND_TIMED_OUT ) { mach_msg_destroy( &message ); } }
kern_return_t CACFMachPort::ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut) { // snag the port mach_port_t thePort = CFMachPortGetPort(mMachPort); // fill out the message header outMessage->msgh_bits = 0; outMessage->msgh_size = 0; outMessage->msgh_remote_port = MACH_PORT_NULL; outMessage->msgh_local_port = thePort; outMessage->msgh_reserved = 0; outMessage->msgh_id = 0; // figure the options mach_msg_options_t theOptions = MACH_RCV_MSG; if(inTimeOut > 0) { theOptions |= MACH_RCV_TIMEOUT; } // receive the messsage return mach_msg(outMessage, theOptions, 0, inMaxMessageSize, thePort, inTimeOut, MACH_PORT_NULL); }
kern_return_t oxpc_object_send_as_mach_message( oxpc_object_t obj, mach_port_t destination_port, mach_port_t reply_port) { size_t msg_size = 0; mach_msg_header_t* msg = oxpc_object_serialize_to_mach_message(obj, destination_port, reply_port, &msg_size); if (!msg) { ERROR("unable to serialize oxpc object to mach message"); } kern_return_t err; err = mach_msg(msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)msg_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); return err; }
void *ExceptionHandlerThread(void *thread_arg) { mach_port_t handler_port = (mach_port_t) (uintptr_t) thread_arg; while (1) { struct { mach_msg_header_t header; uint8_t data[256]; } receive; mach_msg_header_t reply; kern_return_t rc; receive.header.msgh_local_port = handler_port; receive.header.msgh_size = sizeof(receive); rc = mach_msg(&receive.header, MACH_RCV_MSG | MACH_RCV_LARGE, 0, receive.header.msgh_size, handler_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); CHECK(rc == KERN_SUCCESS); CHECK(exc_server(&receive.header, &reply)); exit(1); } return NULL; }
void CEeExecutor::HandlerThreadProc() { #pragma pack(push, 4) struct INPUT_MESSAGE { mach_msg_header_t head; NDR_record_t ndr; exception_type_t exception; mach_msg_type_number_t codeCount; intptr_t code[2]; int flavor; mach_msg_type_number_t stateCount; natural_t state[STATE_FLAVOR_COUNT]; mach_msg_trailer_t trailer; }; struct OUTPUT_MESSAGE { mach_msg_header_t head; NDR_record_t ndr; kern_return_t result; int flavor; mach_msg_type_number_t stateCount; natural_t state[STATE_FLAVOR_COUNT]; }; #pragma pack(pop) while(1) { kern_return_t result = KERN_SUCCESS; INPUT_MESSAGE inMsg; result = mach_msg(&inMsg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(inMsg), m_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); assert(result == KERN_SUCCESS); assert(inMsg.head.msgh_id == 2406); //MACH_EXCEPTION_RAISE_RPC bool success = HandleAccessFault(inMsg.code[1]); OUTPUT_MESSAGE outMsg; outMsg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inMsg.head.msgh_bits), 0); outMsg.head.msgh_remote_port = inMsg.head.msgh_remote_port; outMsg.head.msgh_local_port = MACH_PORT_NULL; outMsg.head.msgh_id = inMsg.head.msgh_id + 100; outMsg.head.msgh_size = sizeof(outMsg); outMsg.ndr = inMsg.ndr; if(success) { outMsg.result = KERN_SUCCESS; outMsg.flavor = STATE_FLAVOR; outMsg.stateCount = STATE_FLAVOR_COUNT; memcpy(outMsg.state, inMsg.state, STATE_FLAVOR_COUNT * sizeof(natural_t)); } else { outMsg.result = KERN_FAILURE; outMsg.flavor = 0; outMsg.stateCount = 0; } result = mach_msg(&outMsg.head, MACH_SEND_MSG | MACH_RCV_LARGE, sizeof(outMsg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); assert(result == KERN_SUCCESS); } }
void *mach_profile_listener(void *arg) { (void)arg; int max_size = 512; mach_profiler_thread = mach_thread_self(); mig_reply_error_t *bufRequest = (mig_reply_error_t *) malloc(max_size); while (1) { kern_return_t ret = mach_msg(&bufRequest->Head, MACH_RCV_MSG, 0, max_size, profile_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); HANDLE_MACH_ERROR("mach_msg",ret); if (bt_size_cur < bt_size_max) { kern_return_t ret; // Suspend the thread so we may safely sample it ret = thread_suspend(main_thread); HANDLE_MACH_ERROR("thread_suspend",ret); // Do the actual sampling unsigned int count = MACHINE_THREAD_STATE_COUNT; x86_thread_state64_t state; // Get the state of the suspended thread ret = thread_get_state(main_thread,x86_THREAD_STATE64,(thread_state_t)&state,&count); HANDLE_MACH_ERROR("thread_get_state",ret); // Initialize the unwind context with the suspend thread's state unw_context_t uc; memset(&uc,0,sizeof(unw_context_t)); memcpy(&uc,&state,sizeof(x86_thread_state64_t)); /* * Unfortunately compact unwind info is incorrectly generated for quite a number of * libraries by quite a large number of compilers. We can fall back to DWARF unwind info * in some cases, but in quite a number of cases (especially libraries not compiled in debug * mode, only the compact unwind info may be available). Even more unfortunately, there is no * way to detect such bogus compact unwind info (other than noticing the resulting segfault). * What we do here is ugly, but necessary until the compact unwind info situation improves. * We try to use the compact unwind info and if that results in a segfault, we retry with DWARF info. * Note that in a small number of cases this may result in bogus stack traces, but at least the topmost * entry will always be correct, and the number of cases in which this is an issue is rather small. * Other than that, this implementation is not incorrect as the other thread is paused while we are profiling * and during stack unwinding we only ever read memory, but never write it. */ forceDwarf = 0; unw_getcontext(&profiler_uc); if (forceDwarf == 0) { // Save the backtrace bt_size_cur += rec_backtrace_ctx((ptrint_t*)bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1, &uc); } else if (forceDwarf == 1) { bt_size_cur += rec_backtrace_ctx_dwarf((ptrint_t*)bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1, &uc); } else if (forceDwarf == -1) { JL_PRINTF(JL_STDERR, "Warning: Profiler attempt to access an invalid memory location\n"); } forceDwarf = -2; // Mark the end of this block with 0 bt_data_prof[bt_size_cur] = 0; bt_size_cur++; // We're done! Resume the thread. ret = thread_resume(main_thread); HANDLE_MACH_ERROR("thread_resume",ret) if (running) { // Reset the alarm ret = clock_alarm(clk, TIME_RELATIVE, timerprof, profile_port); HANDLE_MACH_ERROR("clock_alarm",ret) } } }
/* * This message server catches user task exceptions. Most user exceptions * will be received on the thread exception port. This server servers * only exceptions from unknown threads or from external debuggers. * It runs in a dedicated thread. */ void * task_exception_catcher( void *arg) { struct server_thread_priv_data priv_data; kern_return_t kr; #define MSG_BUFFER_SIZE 8192 union request_msg { mach_msg_header_t hdr; mig_reply_error_t death_pill; char space[MSG_BUFFER_SIZE]; } *msg_buffer_1, *msg_buffer_2; mach_msg_header_t *request; mig_reply_error_t *reply; mach_msg_header_t *tmp; cthread_set_name(cthread_self(), "task exc catcher"); server_thread_set_priv_data(cthread_self(), &priv_data); uniproc_enter(); kr = vm_allocate(mach_task_self(), (vm_address_t *) &msg_buffer_1, 2 * sizeof *msg_buffer_1, TRUE); if (kr != KERN_SUCCESS) { MACH3_DEBUG(0, kr, ("task_exception_catcher: vm_allocate")); panic("task_exception_catcher"); } msg_buffer_2 = msg_buffer_1 + 1; request = &msg_buffer_1->hdr; reply = &msg_buffer_2->death_pill; do { uniproc_exit(); kr = mach_msg(request, MACH_RCV_MSG, 0, sizeof *msg_buffer_1, user_trap_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (kr != MACH_MSG_SUCCESS) { MACH3_DEBUG(1, kr, ("task_exception_catcher: mach_msg")); panic("task_exception_catcher: receive"); } uniproc_enter(); if (exc_server(request, &reply->Head)) {} else { printk("trap_exception_catcher: invalid message" "(id = %d = 0x%x)\n", request->msgh_id, request->msgh_id); } if (reply->Head.msgh_remote_port == MACH_PORT_NULL) { /* no reply port, just get another request */ continue; } if (!(reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && reply->RetCode == MIG_NO_REPLY) { /* deallocate reply port right */ (void) mach_port_deallocate(mach_task_self(), reply->Head.msgh_remote_port); continue; } /* Send reply to request and receive another */ uniproc_exit(); kr = mach_msg(&reply->Head, MACH_SEND_MSG, reply->Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); uniproc_enter(); if (kr != MACH_MSG_SUCCESS) { if (kr == MACH_SEND_INVALID_DEST) { /* deallocate reply port right */ /* XXX should destroy reply msg */ (void) mach_port_deallocate(mach_task_self(), reply->Head.msgh_remote_port); } else { MACH3_DEBUG(0, kr, ("mach_msg")); panic("task_exception_catcher: send"); } } tmp = request; request = (mach_msg_header_t *) reply; reply = (mig_reply_error_t *) tmp; } while (1); cthread_detach(cthread_self()); cthread_exit((void *) 0); /*NOTREACHED*/ return (void *) 0; }