diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Socket.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Socket.cpp index 4ffa25e87..0421a1352 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Socket.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Socket.cpp @@ -40,16 +40,6 @@ namespace FEX::HLE { SYSCALL_ERRNO(); }); - REGISTER_SYSCALL_IMPL(sendmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, const struct msghdr *msg, int flags) -> uint64_t { - uint64_t Result = ::sendmsg(sockfd, msg, flags); - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL(recvmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, struct msghdr *msg, int flags) -> uint64_t { - uint64_t Result = ::recvmsg(sockfd, msg, flags); - SYSCALL_ERRNO(); - }); - REGISTER_SYSCALL_IMPL(shutdown, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, int how) -> uint64_t { uint64_t Result = ::shutdown(sockfd, how); SYSCALL_ERRNO(); diff --git a/Source/Tests/LinuxSyscalls/x32/Socket.cpp b/Source/Tests/LinuxSyscalls/x32/Socket.cpp index 245b7489a..cc3346fbf 100644 --- a/Source/Tests/LinuxSyscalls/x32/Socket.cpp +++ b/Source/Tests/LinuxSyscalls/x32/Socket.cpp @@ -40,6 +40,123 @@ namespace FEX::HLE::x32 { OP_SENDMMSG = 20, }; + static uint64_t SendMsg(int sockfd, const struct msghdr32 *msg, int flags) { + struct msghdr HostHeader{}; + std::vector Host_iovec(msg->msg_iovlen); + for (int i = 0; i < msg->msg_iovlen; ++i) { + Host_iovec[i] = msg->msg_iov[i]; + } + + HostHeader.msg_name = msg->msg_name; + HostHeader.msg_namelen = msg->msg_namelen; + + HostHeader.msg_iov = &Host_iovec.at(0); + HostHeader.msg_iovlen = msg->msg_iovlen; + + HostHeader.msg_control = alloca(msg->msg_controllen * 2); + HostHeader.msg_controllen = msg->msg_controllen; + + HostHeader.msg_flags = msg->msg_flags; + if (HostHeader.msg_controllen) { + void *CurrentGuestPtr = msg->msg_control; + struct cmsghdr *CurrentHost = reinterpret_cast(HostHeader.msg_control); + + for (cmsghdr32 *msghdr_guest = reinterpret_cast(CurrentGuestPtr); + CurrentGuestPtr != 0; + msghdr_guest = reinterpret_cast(CurrentGuestPtr)) { + + CurrentHost->cmsg_level = msghdr_guest->cmsg_level; + CurrentHost->cmsg_type = msghdr_guest->cmsg_type; + + if (msghdr_guest->cmsg_len) { + size_t SizeIncrease = (CMSG_LEN(0) - sizeof(cmsghdr32)); + CurrentHost->cmsg_len = msghdr_guest->cmsg_len + SizeIncrease; + HostHeader.msg_controllen += SizeIncrease; + memcpy(CMSG_DATA(CurrentHost), msghdr_guest->cmsg_data, msghdr_guest->cmsg_len - sizeof(cmsghdr32)); + } + + // Go to next host + CurrentHost = CMSG_NXTHDR(&HostHeader, CurrentHost); + + // Go to next msg + if (msghdr_guest->cmsg_len < sizeof(cmsghdr32)) { + CurrentGuestPtr = nullptr; + } + else { + CurrentGuestPtr = reinterpret_cast(reinterpret_cast(CurrentGuestPtr) + msghdr_guest->cmsg_len); + CurrentGuestPtr = reinterpret_cast((reinterpret_cast(CurrentGuestPtr) + 3) & ~3ULL); + if (CurrentGuestPtr >= reinterpret_cast(reinterpret_cast(static_cast(msg->msg_control)) + msg->msg_controllen)) { + CurrentGuestPtr = nullptr; + } + } + } + } + + uint64_t Result = ::sendmsg(sockfd, &HostHeader, flags); + SYSCALL_ERRNO(); + } + + static uint64_t RecvMsg(int sockfd, struct msghdr32 *msg, int flags) { + struct msghdr HostHeader{}; + std::vector Host_iovec(msg->msg_iovlen); + for (int i = 0; i < msg->msg_iovlen; ++i) { + Host_iovec[i] = msg->msg_iov[i]; + } + + HostHeader.msg_name = msg->msg_name; + HostHeader.msg_namelen = msg->msg_namelen; + + HostHeader.msg_iov = &Host_iovec.at(0); + HostHeader.msg_iovlen = msg->msg_iovlen; + + HostHeader.msg_control = alloca(msg->msg_controllen*2); + HostHeader.msg_controllen = msg->msg_controllen*2; + + HostHeader.msg_flags = msg->msg_flags; + + uint64_t Result = ::recvmsg(sockfd, &HostHeader, flags); + if (Result != -1) { + for (int i = 0; i < msg->msg_iovlen; ++i) { + msg->msg_iov[i] = Host_iovec[i]; + } + + msg->msg_namelen = HostHeader.msg_namelen; + msg->msg_controllen = HostHeader.msg_controllen; + msg->msg_flags = HostHeader.msg_flags; + if (HostHeader.msg_controllen) { + // Host and guest cmsg data structures aren't compatible. + // Copy them over now + void *CurrentGuestPtr = msg->msg_control; + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&HostHeader); + cmsg != nullptr; + cmsg = CMSG_NXTHDR(&HostHeader, cmsg)) { + cmsghdr32 *CurrentGuest = reinterpret_cast(CurrentGuestPtr); + + // Copy over the header first + // cmsg_len needs to be adjusted by the size of the header between host and guest + // Host is 16 bytes, guest is 12 bytes + CurrentGuest->cmsg_level = cmsg->cmsg_level; + CurrentGuest->cmsg_type = cmsg->cmsg_type; + + // Now copy over the data + if (cmsg->cmsg_len) { + size_t SizeIncrease = (CMSG_LEN(0) - sizeof(cmsghdr32)); + CurrentGuest->cmsg_len = cmsg->cmsg_len - SizeIncrease; + + // Controllen size also changes + msg->msg_controllen -= SizeIncrease; + + memcpy(CurrentGuest->cmsg_data, CMSG_DATA(cmsg), cmsg->cmsg_len - sizeof(struct cmsghdr)); + CurrentGuestPtr = reinterpret_cast(reinterpret_cast(CurrentGuestPtr) + CurrentGuest->cmsg_len); + CurrentGuestPtr = reinterpret_cast((reinterpret_cast(CurrentGuestPtr) + 3) & ~3ULL); + + } + } + } + } + SYSCALL_ERRNO(); + } + void RegisterSocket() { REGISTER_SYSCALL_IMPL_X32(socketcall, [](FEXCore::Core::CpuStateFrame *Frame, uint32_t call, uint32_t *Arguments) -> uint64_t { uint64_t Result{}; @@ -130,122 +247,11 @@ namespace FEX::HLE::x32 { break; } case OP_SENDMSG: { - const struct msghdr32 *guest_msg = reinterpret_cast(Arguments[1]); - - struct msghdr HostHeader{}; - std::vector Host_iovec(guest_msg->msg_iovlen); - for (int i = 0; i < guest_msg->msg_iovlen; ++i) { - Host_iovec[i] = guest_msg->msg_iov[i]; - } - - HostHeader.msg_name = guest_msg->msg_name; - HostHeader.msg_namelen = guest_msg->msg_namelen; - - HostHeader.msg_iov = &Host_iovec.at(0); - HostHeader.msg_iovlen = guest_msg->msg_iovlen; - - HostHeader.msg_control = alloca(guest_msg->msg_controllen * 2); - HostHeader.msg_controllen = guest_msg->msg_controllen; - - HostHeader.msg_flags = guest_msg->msg_flags; - if (HostHeader.msg_controllen) { - void *CurrentGuestPtr = guest_msg->msg_control; - struct cmsghdr *CurrentHost = reinterpret_cast(HostHeader.msg_control); - - for (cmsghdr32 *msghdr_guest = reinterpret_cast(CurrentGuestPtr); - CurrentGuestPtr != 0; - msghdr_guest = reinterpret_cast(CurrentGuestPtr)) { - - CurrentHost->cmsg_level = msghdr_guest->cmsg_level; - CurrentHost->cmsg_type = msghdr_guest->cmsg_type; - - if (msghdr_guest->cmsg_len) { - size_t SizeIncrease = (CMSG_LEN(0) - sizeof(cmsghdr32)); - CurrentHost->cmsg_len = msghdr_guest->cmsg_len + SizeIncrease; - HostHeader.msg_controllen += SizeIncrease; - memcpy(CMSG_DATA(CurrentHost), msghdr_guest->cmsg_data, msghdr_guest->cmsg_len - sizeof(cmsghdr32)); - } - - // Go to next host - CurrentHost = CMSG_NXTHDR(&HostHeader, CurrentHost); - - // Go to next msg - if (msghdr_guest->cmsg_len < sizeof(cmsghdr32)) { - CurrentGuestPtr = nullptr; - } - else { - CurrentGuestPtr = reinterpret_cast(reinterpret_cast(CurrentGuestPtr) + msghdr_guest->cmsg_len); - CurrentGuestPtr = reinterpret_cast((reinterpret_cast(CurrentGuestPtr) + 3) & ~3ULL); - if (CurrentGuestPtr >= reinterpret_cast(reinterpret_cast(static_cast(guest_msg->msg_control)) + guest_msg->msg_controllen)) { - CurrentGuestPtr = nullptr; - } - } - } - } - - Result = ::sendmsg(Arguments[0], &HostHeader, Arguments[2]); + return SendMsg(Arguments[0], reinterpret_cast(Arguments[1]), Arguments[2]); break; } case OP_RECVMSG: { - struct msghdr32 *guest_msg = reinterpret_cast(Arguments[1]); - - struct msghdr HostHeader{}; - std::vector Host_iovec(guest_msg->msg_iovlen); - for (int i = 0; i < guest_msg->msg_iovlen; ++i) { - Host_iovec[i] = guest_msg->msg_iov[i]; - } - - HostHeader.msg_name = guest_msg->msg_name; - HostHeader.msg_namelen = guest_msg->msg_namelen; - - HostHeader.msg_iov = &Host_iovec.at(0); - HostHeader.msg_iovlen = guest_msg->msg_iovlen; - - HostHeader.msg_control = alloca(guest_msg->msg_controllen*2); - HostHeader.msg_controllen = guest_msg->msg_controllen*2; - - HostHeader.msg_flags = guest_msg->msg_flags; - - Result = ::recvmsg(Arguments[0], &HostHeader, Arguments[2]); - if (Result != -1) { - for (int i = 0; i < guest_msg->msg_iovlen; ++i) { - guest_msg->msg_iov[i] = Host_iovec[i]; - } - - guest_msg->msg_namelen = HostHeader.msg_namelen; - guest_msg->msg_controllen = HostHeader.msg_controllen; - guest_msg->msg_flags = HostHeader.msg_flags; - if (HostHeader.msg_controllen) { - // Host and guest cmsg data structures aren't compatible. - // Copy them over now - void *CurrentGuestPtr = guest_msg->msg_control; - for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&HostHeader); - cmsg != nullptr; - cmsg = CMSG_NXTHDR(&HostHeader, cmsg)) { - cmsghdr32 *CurrentGuest = reinterpret_cast(CurrentGuestPtr); - - // Copy over the header first - // cmsg_len needs to be adjusted by the size of the header between host and guest - // Host is 16 bytes, guest is 12 bytes - CurrentGuest->cmsg_level = cmsg->cmsg_level; - CurrentGuest->cmsg_type = cmsg->cmsg_type; - - // Now copy over the data - if (cmsg->cmsg_len) { - size_t SizeIncrease = (CMSG_LEN(0) - sizeof(cmsghdr32)); - CurrentGuest->cmsg_len = cmsg->cmsg_len - SizeIncrease; - - // Controllen size also changes - guest_msg->msg_controllen -= SizeIncrease; - - memcpy(CurrentGuest->cmsg_data, CMSG_DATA(cmsg), cmsg->cmsg_len - sizeof(struct cmsghdr)); - CurrentGuestPtr = reinterpret_cast(reinterpret_cast(CurrentGuestPtr) + CurrentGuest->cmsg_len); - CurrentGuestPtr = reinterpret_cast((reinterpret_cast(CurrentGuestPtr) + 3) & ~3ULL); - - } - } - } - } + return RecvMsg(Arguments[0], reinterpret_cast(Arguments[1]), Arguments[2]); break; } default: @@ -255,6 +261,10 @@ namespace FEX::HLE::x32 { SYSCALL_ERRNO(); }); + REGISTER_SYSCALL_IMPL_X32(sendmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, const struct msghdr32 *msg, int flags) -> uint64_t { + return SendMsg(sockfd, msg, flags); + }); + REGISTER_SYSCALL_IMPL_X32(sendmmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, compat_ptr msgvec, uint32_t vlen, int flags) -> uint64_t { std::vector Host_iovec; std::vector Controllen; @@ -343,5 +353,9 @@ namespace FEX::HLE::x32 { } SYSCALL_ERRNO(); }); + + REGISTER_SYSCALL_IMPL_X32(recvmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, struct msghdr32 *msg, int flags) -> uint64_t { + return RecvMsg(sockfd, msg, flags); + }); } } diff --git a/Source/Tests/LinuxSyscalls/x64/Socket.cpp b/Source/Tests/LinuxSyscalls/x64/Socket.cpp index aa1c8b705..88a8abef9 100644 --- a/Source/Tests/LinuxSyscalls/x64/Socket.cpp +++ b/Source/Tests/LinuxSyscalls/x64/Socket.cpp @@ -24,5 +24,15 @@ namespace FEX::HLE::x64 { uint64_t Result = ::sendmmsg(sockfd, msgvec, vlen, flags); SYSCALL_ERRNO(); }); + + REGISTER_SYSCALL_IMPL_X64(sendmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, const struct msghdr *msg, int flags) -> uint64_t { + uint64_t Result = ::sendmsg(sockfd, msg, flags); + SYSCALL_ERRNO(); + }); + + REGISTER_SYSCALL_IMPL_X64(recvmsg, [](FEXCore::Core::CpuStateFrame *Frame, int sockfd, struct msghdr *msg, int flags) -> uint64_t { + uint64_t Result = ::recvmsg(sockfd, msg, flags); + SYSCALL_ERRNO(); + }); } }