-
-void dyld_process_info_notify_base::setMachSourceOnQueue()
-{
- NotifyExit exitHandler = _notifyExit;
- _machSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, _receivePortInMonitor, 0, _queue);
- dispatch_source_set_event_handler(_machSource, ^{
- uint8_t messageBuffer[DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE];
- mach_msg_header_t* h = (mach_msg_header_t*)messageBuffer;
-
- kern_return_t r = mach_msg(h, MACH_RCV_MSG, 0, sizeof(messageBuffer), _receivePortInMonitor, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if ( r == KERN_SUCCESS ) {
- //fprintf(stderr, "received message id=0x%X, size=%d\n", h->msgh_id, h->msgh_size);
- if ( h->msgh_id == DYLD_PROCESS_INFO_NOTIFY_LOAD_ID || h->msgh_id == DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID ) {
- // run notifier block for each [un]load image
- const dyld_process_info_notify_header* header = (dyld_process_info_notify_header*)messageBuffer;
- const dyld_process_info_image_entry* entries = (dyld_process_info_image_entry*)&messageBuffer[header->imagesOffset];
- const char* const stringPool = (char*)&messageBuffer[header->stringsOffset];
- for (unsigned i=0; i < header->imageCount; ++i) {
- bool isUnload = (h->msgh_id == DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID);
- _notify(isUnload, header->timestamp, entries[i].loadAddress, entries[i].uuid, stringPool + entries[i].pathStringOffset);
- }
- // reply to dyld, so it can continue
- mach_msg_header_t replyHeader;
- replyHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND);
- replyHeader.msgh_id = 0;
- replyHeader.msgh_local_port = MACH_PORT_NULL;
- replyHeader.msgh_remote_port = h->msgh_remote_port;
- replyHeader.msgh_reserved = 0;
- replyHeader.msgh_size = sizeof(replyHeader);
- mach_msg(&replyHeader, MACH_SEND_MSG | MACH_SEND_TIMEOUT, replyHeader.msgh_size, 0, MACH_PORT_NULL, 100, MACH_PORT_NULL);
- }
- else if ( h->msgh_id == DYLD_PROCESS_INFO_NOTIFY_MAIN_ID ) {
- if ( _notifyMain != NULL ) {
- _notifyMain();
- }
- // reply to dyld, so it can continue
- mach_msg_header_t replyHeader;
- replyHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND);
- replyHeader.msgh_id = 0;
- replyHeader.msgh_local_port = MACH_PORT_NULL;
- replyHeader.msgh_remote_port = h->msgh_remote_port;
- replyHeader.msgh_reserved = 0;
- replyHeader.msgh_size = sizeof(replyHeader);
- mach_msg(&replyHeader, MACH_SEND_MSG | MACH_SEND_TIMEOUT, replyHeader.msgh_size, 0, MACH_PORT_NULL, 100, MACH_PORT_NULL);
- }
- else if ( h->msgh_id == MACH_NOTIFY_PORT_DELETED ) {
- mach_port_t deadPort = ((mach_port_deleted_notification_t *)h)->not_port;
- //fprintf(stderr, "received message id=MACH_NOTIFY_PORT_DELETED, size=%d, deadPort=%d\n", h->msgh_size, deadPort);
- if ( deadPort == _sendPortInTarget ) {
- // target process died. Clean up ports
- _sendPortInTarget = 0;
- mach_port_deallocate(mach_task_self(), _receivePortInMonitor);
- _receivePortInMonitor = 0;
- _portAddressInTarget = 0;
- // notify that target is gone
- exitHandler();
- }
- }
- else {
- fprintf(stderr, "received unknown message id=0x%X, size=%d\n", h->msgh_id, h->msgh_size);
- }
+void dyld_process_info_notify_base::teardown() {
+ if (!_disabled) {
+ _disabled = true;
+ // The connection to the target is dead. Clean up ports
+ if ( _remoteAllImageInfoBuffer.getLocalAddress() != 0 && _notifySlot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT) {
+ mach_port_t extractedPort = MACH_PORT_NULL;
+ mach_msg_type_name_t extractedPortType;
+ kern_return_t kr = mach_port_extract_right(_targetTask, _sendPortInTarget, MACH_MSG_TYPE_COPY_SEND, &extractedPort, &extractedPortType);
+ if (kr == KERN_SUCCESS) {
+ if (extractedPort == _receivePortInMonitor) {
+ if (OSAtomicCompareAndSwap32(_sendPortInTarget, 0, (volatile int32_t*)&_notifyMachPorts[_notifySlot])) {
+ (void)mach_port_deallocate(_targetTask, _sendPortInTarget);
+ }
+ }
+ (void)mach_port_deallocate(mach_task_self(), extractedPort);
+ }