/* generate all startup events of a given process */ void generate_startup_debug_events( struct process *process, void *entry ) { struct list *ptr; struct thread *thread, *first_thread = get_process_first_thread( process ); /* generate creation events */ LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { if (thread == first_thread) generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT, entry ); else generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT, NULL ); } /* generate dll events (in loading order, i.e. reverse list order) */ ptr = list_tail( &process->dlls ); while (ptr) { struct process_dll *dll = LIST_ENTRY( ptr, struct process_dll, entry ); generate_debug_event( first_thread, LOAD_DLL_DEBUG_EVENT, dll ); ptr = list_prev( &process->dlls, ptr ); } }
/* receive a file descriptor on the process socket */ int receive_fd( struct process *process ) { struct iovec vec; struct send_fd data; struct msghdr msghdr; int fd = -1, ret; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS msghdr.msg_accrightslen = sizeof(int); msghdr.msg_accrights = (void *)&fd; #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; msghdr.msg_control = cmsg_buffer; msghdr.msg_controllen = sizeof(cmsg_buffer); msghdr.msg_flags = 0; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; vec.iov_base = (void *)&data; vec.iov_len = sizeof(data); ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS if (ret > 0) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg )) { if (cmsg->cmsg_level != SOL_SOCKET) continue; if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg); } } #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ if (ret == sizeof(data)) { struct thread *thread; if (data.tid) thread = get_thread_from_id( data.tid ); else thread = (struct thread *)grab_object( get_process_first_thread( process )); if (!thread || thread->process != process || thread->state == TERMINATED) { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d bad thread id\n", data.tid, data.fd, fd ); close( fd ); } else { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d\n", thread->id, data.fd, fd ); thread_add_inflight_fd( thread, data.fd, fd ); } if (thread) release_object( thread ); return 0; } if (!ret) { kill_process( process, 0 ); } else if (ret > 0) { fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n", process->id, ret ); if (fd != -1) close( fd ); kill_process( process, 1 ); } else { if (errno != EWOULDBLOCK && errno != EAGAIN) { fprintf( stderr, "Protocol error: process %04x: ", process->id ); perror( "recvmsg" ); kill_process( process, 1 ); } } return -1; }
/* receive a file descriptor on the process socket */ int receive_fd( struct process *process ) { struct send_fd data; int fd, ret; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS msghdr.msg_accrightslen = sizeof(int); msghdr.msg_accrights = (void *)&fd; #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ msghdr.msg_control = &cmsg; msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); cmsg.fd = -1; #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ myiovec.iov_base = (void *)&data; myiovec.iov_len = sizeof(data); ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS fd = cmsg.fd; #endif if (ret == sizeof(data)) { struct thread *thread; if (data.tid) thread = get_thread_from_id( data.tid ); else thread = (struct thread *)grab_object( get_process_first_thread( process )); if (!thread || thread->process != process || thread->state == TERMINATED) { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d bad thread id\n", data.tid, data.fd, fd ); close( fd ); } else { if (debug_level) fprintf( stderr, "%04x: *fd* %d <- %d\n", thread->id, data.fd, fd ); thread_add_inflight_fd( thread, data.fd, fd ); } if (thread) release_object( thread ); return 0; } if (!ret) { kill_process( process, NULL, 0 ); } else if (ret > 0) { fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n", process->id, ret ); kill_process( process, NULL, 1 ); } else { if (errno != EWOULDBLOCK && errno != EAGAIN) { fprintf( stderr, "Protocol error: process %04x: ", process->id ); perror( "recvmsg" ); kill_process( process, NULL, 1 ); } } return -1; }