From a27dfc269a4d51d05089a4c8776db81bf4fadf39 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Mon, 22 Jul 2019 20:19:03 +0800 Subject: [PATCH] kernel: Add LLE request/reply recording The 'translate' function is a great place to put this in IMO as it is possible to get both untranslated and translated cmdbufs. However a kernel reference has to be passed here, but it is not too hard fortunately. --- src/core/hle/kernel/ipc.cpp | 22 +++++++++++++++++++++- src/core/hle/kernel/ipc.h | 5 ++++- src/core/hle/kernel/svc.cpp | 25 +++++++++++++------------ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index c9616e566..3dacb9831 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -8,6 +8,7 @@ #include "core/hle/ipc.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/ipc.h" +#include "core/hle/kernel/ipc_debugger/recorder.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" @@ -16,7 +17,8 @@ namespace Kernel { -ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr src_thread, +ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory, + std::shared_ptr src_thread, std::shared_ptr dst_thread, VAddr src_address, VAddr dst_address, std::vector& mapped_buffer_context, @@ -37,6 +39,13 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr< std::array cmd_buf; memory.ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32)); + const bool should_record = kernel.GetIPCRecorder().IsEnabled(); + + std::vector untranslated_cmdbuf; + if (should_record) { + untranslated_cmdbuf = std::vector{cmd_buf.begin(), cmd_buf.begin() + command_size}; + } + std::size_t i = untranslated_size; while (i < command_size) { u32 descriptor = cmd_buf[i]; @@ -218,6 +227,17 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr< } } + if (should_record) { + std::vector translated_cmdbuf{cmd_buf.begin(), cmd_buf.begin() + command_size}; + if (reply) { + kernel.GetIPCRecorder().SetReplyInfo(dst_thread, std::move(untranslated_cmdbuf), + std::move(translated_cmdbuf)); + } else { + kernel.GetIPCRecorder().SetRequestInfo(src_thread, std::move(untranslated_cmdbuf), + std::move(translated_cmdbuf), dst_thread); + } + } + memory.WriteBlock(*dst_process, dst_address, cmd_buf.data(), command_size * sizeof(u32)); return RESULT_SUCCESS; diff --git a/src/core/hle/kernel/ipc.h b/src/core/hle/kernel/ipc.h index d84028767..b06079958 100644 --- a/src/core/hle/kernel/ipc.h +++ b/src/core/hle/kernel/ipc.h @@ -16,6 +16,8 @@ class MemorySystem; namespace Kernel { +class KernelSystem; + struct MappedBufferContext { IPC::MappedBufferPermissions permissions; u32 size; @@ -27,7 +29,8 @@ struct MappedBufferContext { }; /// Performs IPC command buffer translation from one process to another. -ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr src_thread, +ResultCode TranslateCommandBuffer(KernelSystem& system, Memory::MemorySystem& memory, + std::shared_ptr src_thread, std::shared_ptr dst_thread, VAddr src_address, VAddr dst_address, std::vector& mapped_buffer_context, diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ef0f35237..b5ebaf936 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -19,6 +19,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/ipc.h" +#include "core/hle/kernel/ipc_debugger/recorder.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/process.h" @@ -599,7 +600,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle } } -static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory, +static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory, std::shared_ptr server_session, std::shared_ptr thread) { if (server_session->parent->client == nullptr) { @@ -609,9 +610,9 @@ static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory, VAddr target_address = thread->GetCommandBufferAddress(); VAddr source_address = server_session->currently_handling->GetCommandBufferAddress(); - ResultCode translation_result = - TranslateCommandBuffer(memory, server_session->currently_handling, thread, source_address, - target_address, server_session->mapped_buffer_context, false); + ResultCode translation_result = TranslateCommandBuffer( + kernel, memory, server_session->currently_handling, thread, source_address, target_address, + server_session->mapped_buffer_context, false); // If a translation error occurred, immediately resume the client thread. if (translation_result.IsError()) { @@ -676,9 +677,9 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co VAddr source_address = thread->GetCommandBufferAddress(); VAddr target_address = request_thread->GetCommandBufferAddress(); - ResultCode translation_result = - TranslateCommandBuffer(memory, SharedFrom(thread), request_thread, source_address, - target_address, session->mapped_buffer_context, true); + ResultCode translation_result = TranslateCommandBuffer( + kernel, memory, SharedFrom(thread), request_thread, source_address, target_address, + session->mapped_buffer_context, true); // Note: The real kernel seems to always panic if the Server->Client buffer translation // fails for whatever reason. @@ -713,7 +714,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co return RESULT_SUCCESS; auto server_session = static_cast(object); - return ReceiveIPCRequest(memory, SharedFrom(server_session), SharedFrom(thread)); + return ReceiveIPCRequest(kernel, memory, SharedFrom(server_session), SharedFrom(thread)); } // No objects were ready to be acquired, prepare to suspend the thread. @@ -729,9 +730,9 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co thread->wait_objects = std::move(objects); - thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason, - std::shared_ptr thread, - std::shared_ptr object) { + thread->wakeup_callback = [& kernel = this->kernel, &memory = this->memory]( + ThreadWakeupReason reason, std::shared_ptr thread, + std::shared_ptr object) { ASSERT(thread->status == ThreadStatus::WaitSynchAny); ASSERT(reason == ThreadWakeupReason::Signal); @@ -739,7 +740,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co if (object->GetHandleType() == HandleType::ServerSession) { auto server_session = DynamicObjectCast(object); - result = ReceiveIPCRequest(memory, server_session, thread); + result = ReceiveIPCRequest(kernel, memory, server_session, thread); } thread->SetWaitSynchronizationResult(result);