kern_return_t catch_mach_exception_raise_state ( mach_port_t exc_port, exception_type_t exc_type, const mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count, int * flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t * new_stateCnt ) { if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { DNBLogThreaded("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data = " MACH_EXCEPTION_DATA_FMT_HEX ", exc_data_count = %d)", __FUNCTION__, exc_port, exc_type, MachException::Name(exc_type), exc_data, exc_data_count); } return KERN_FAILURE; }
void MachThread::Dump(uint32_t index) { const char * thread_run_state = NULL; switch (m_basicInfo.run_state) { case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a default: thread_run_state = "???"; break; } DNBLogThreaded("[%3u] #%3u tid: 0x%4.4x, pc: 0x%16.16llx, sp: 0x%16.16llx, breakID: %3d, user: %d.%06.6d, system: %d.%06.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", index, m_seq_id, m_tid, GetPC(INVALID_NUB_ADDRESS), GetSP(INVALID_NUB_ADDRESS), m_breakID, m_basicInfo.user_time.seconds, m_basicInfo.user_time.microseconds, m_basicInfo.system_time.seconds, m_basicInfo.system_time.microseconds, m_basicInfo.cpu_usage, m_basicInfo.policy, m_basicInfo.run_state, thread_run_state, m_basicInfo.flags, m_basicInfo.suspend_count, m_suspendCount, m_basicInfo.sleep_time); //DumpRegisterState(0); }
kern_return_t catch_mach_exception_raise ( mach_port_t exc_port, mach_port_t thread_port, mach_port_t task_port, exception_type_t exc_type, mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count) { if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { " MACH_EXCEPTION_DATA_FMT_HEX ", " MACH_EXCEPTION_DATA_FMT_HEX " })", __FUNCTION__, exc_port, thread_port, task_port, exc_type, MachException::Name(exc_type), exc_data_count, exc_data_count > 0 ? exc_data[0] : 0xBADDBADD, exc_data_count > 1 ? exc_data[1] : 0xBADDBADD); } g_message->task_port = task_port; g_message->thread_port = thread_port; g_message->exc_type = exc_type; g_message->exc_data.resize(exc_data_count); ::memcpy (&g_message->exc_data[0], exc_data, g_message->exc_data.size() * sizeof (mach_exception_data_type_t)); return KERN_SUCCESS; }
bool MachException::Message::CatchExceptionRaise() { bool success = false; // locker will keep a mutex locked until it goes out of scope // PThreadMutex::Locker locker(&g_message_mutex); // DNBLogThreaded("calling mach_exc_server"); g_message = &state; // The exc_server function is the MIG generated server handling function // to handle messages from the kernel relating to the occurrence of an // exception in a thread. Such messages are delivered to the exception port // set via thread_set_exception_ports or task_set_exception_ports. When an // exception occurs in a thread, the thread sends an exception message to // its exception port, blocking in the kernel waiting for the receipt of a // reply. The exc_server function performs all necessary argument handling // for this kernel message and calls catch_exception_raise, // catch_exception_raise_state or catch_exception_raise_state_identity, // which should handle the exception. If the called routine returns // KERN_SUCCESS, a reply message will be sent, allowing the thread to // continue from the point of the exception; otherwise, no reply message // is sent and the called routine must have dealt with the exception // thread directly. if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr)) { success = true; } else if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { DNBLogThreaded("mach_exc_server returned zero..."); } g_message = NULL; return success; }
kern_return_t catch_mach_exception_raise_state_identity ( mach_port_t exc_port, mach_port_t thread_port, mach_port_t task_port, exception_type_t exc_type, mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count, int * flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt ) { kern_return_t kret; if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { " MACH_EXCEPTION_DATA_FMT_HEX ", " MACH_EXCEPTION_DATA_FMT_HEX " })", __FUNCTION__, exc_port, thread_port, task_port, exc_type, MachException::Name(exc_type), exc_data_count, exc_data_count > 0 ? exc_data[0] : 0xBADDBADD, exc_data_count > 1 ? exc_data[1] : 0xBADDBADD); } kret = mach_port_deallocate (mach_task_self (), task_port); kret = mach_port_deallocate (mach_task_self (), thread_port); return KERN_FAILURE; }
rnb_err_t RNBSocket::Connect (const char *host, uint16_t port) { Disconnect (false); // Create the socket m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_fd == -1) return rnb_err; // Enable local address reuse SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (port); if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) { DNBLogThreaded("error: failed to resolve host '%s'", host); Disconnect (false); return rnb_err; } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { Disconnect (false); return rnb_err; } // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); return rnb_success; }
//---------------------------------------------------------------------- // MachTask::BasicInfo //---------------------------------------------------------------------- kern_return_t MachTask::BasicInfo(task_t task, struct task_basic_info *info) { if (info == NULL) return KERN_INVALID_ARGUMENT; DNBError err; mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; err = ::task_info (task, TASK_BASIC_INFO, (task_info_t)info, &count); const bool log_process = DNBLogCheckLogBit(LOG_TASK); if (log_process || err.Fail()) err.LogThreaded("::task_info ( target_task = 0x%4.4x, flavor = TASK_BASIC_INFO, task_info_out => %p, task_info_outCnt => %u )", task, info, count); if (DNBLogCheckLogBit(LOG_TASK) && DNBLogCheckLogBit(LOG_VERBOSE) && err.Success()) { float user = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; float system = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; DNBLogThreaded ("task_basic_info = { suspend_count = %i, virtual_size = 0x%8.8llx, resident_size = 0x%8.8llx, user_time = %f, system_time = %f }", info->suspend_count, (uint64_t)info->virtual_size, (uint64_t)info->resident_size, user, system); } return err.Error(); }
kern_return_t MachException::Message::Receive(mach_port_t port, mach_msg_option_t options, mach_msg_timeout_t timeout, mach_port_t notify_port) { DNBError err; const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS); mach_msg_timeout_t mach_msg_timeout = options & MACH_RCV_TIMEOUT ? timeout : 0; if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0)) { // Dump this log message if we have no timeout in case it never returns DNBLogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)", exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, sizeof (exc_msg.data), port, mach_msg_timeout, notify_port); } err = ::mach_msg (&exc_msg.hdr, options, // options 0, // Send size sizeof (exc_msg.data), // Receive size port, // exception port to watch for exception on mach_msg_timeout, // timeout in msec (obeyed only if MACH_RCV_TIMEOUT is ORed into the options parameter) notify_port); // Dump any errors we get if (log_exceptions) { err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)", exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, sizeof (exc_msg.data), port, mach_msg_timeout, notify_port); } return err.Error(); }
rnb_err_t RNBSocket::Listen (const char *listen_host, uint16_t port, PortBoundCallback callback, const void *callback_baton) { //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); // Disconnect without saving errno Disconnect (false); // Now figure out the hostname that will be attaching and palce it into struct sockaddr_in listen_addr; ::memset (&listen_addr, 0, sizeof listen_addr); listen_addr.sin_len = sizeof listen_addr; listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons (port); listen_addr.sin_addr.s_addr = INADDR_ANY; if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) { DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); return rnb_err; } DNBError err; int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); if (err.Fail()) return rnb_err; // enable local address reuse SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof sa); sa.sin_len = sizeof sa; sa.sin_family = AF_INET; sa.sin_port = htons (port); sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } error = ::listen (listen_fd, 5); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } if (callback) { // We were asked to listen on port zero which means we // must now read the actual port that was given to us // as port zero is a special code for "find an open port // for me". if (port == 0) { socklen_t sa_len = sizeof (sa); if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) { port = ntohs (sa.sin_port); callback (callback_baton, port); } } else { callback (callback_baton, port); } } struct sockaddr_in accept_addr; ::memset (&accept_addr, 0, sizeof accept_addr); accept_addr.sin_len = sizeof accept_addr; bool accept_connection = false; // Loop until we are happy with our connection while (!accept_connection) { socklen_t accept_addr_len = sizeof accept_addr; m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); if (m_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); if (err.Fail()) break; if (listen_addr.sin_addr.s_addr == INADDR_ANY) accept_connection = true; else { if (accept_addr_len == listen_addr.sin_len && accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) { accept_connection = true; } else { ::close (m_fd); m_fd = -1; const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); } } } ClosePort (listen_fd, false); if (err.Fail()) { return rnb_err; } else { // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); } return rnb_success; }