ldr_ro: use ServiceFramework's session slot for client slot

This commit is contained in:
wwylele 2017-12-17 01:43:12 +02:00
parent 6e2a4ba665
commit eeec04fcaa
2 changed files with 41 additions and 50 deletions

View file

@ -63,15 +63,13 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
auto insert_result = slots.insert({process->process_id, {}}); ClientSlot* slot = GetSessionData(ctx.Session());
if (!insert_result.second) { if (slot->loaded_crs != 0) {
LOG_ERROR(Service_LDR, "Already initialized"); LOG_ERROR(Service_LDR, "Already initialized");
rb.Push(ERROR_ALREADY_INITIALIZED); rb.Push(ERROR_ALREADY_INITIALIZED);
return; return;
} }
auto& slot = insert_result.first->second;
if (crs_size < CRO_HEADER_SIZE) { if (crs_size < CRO_HEADER_SIZE) {
LOG_ERROR(Service_LDR, "CRS is too small"); LOG_ERROR(Service_LDR, "CRS is too small");
rb.Push(ERROR_BUFFER_TOO_SMALL); rb.Push(ERROR_BUFFER_TOO_SMALL);
@ -132,7 +130,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) {
return; return;
} }
slot.memory_synchronizer.AddMemoryBlock(crs_address, crs_buffer_ptr, crs_size); slot->memory_synchronizer.AddMemoryBlock(crs_address, crs_buffer_ptr, crs_size);
} else { } else {
// Do nothing if buffer_ptr == address // Do nothing if buffer_ptr == address
// TODO(wwylele): verify this behaviour. This is only seen in the web browser app, // TODO(wwylele): verify this behaviour. This is only seen in the web browser app,
@ -151,9 +149,9 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) {
return; return;
} }
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
slot.loaded_crs = crs_address; slot->loaded_crs = crs_address;
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -207,14 +205,13 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
auto find_result = slots.find(process->process_id); ClientSlot* slot = GetSessionData(ctx.Session());
if (find_result == slots.end()) { if (slot->loaded_crs == 0) {
LOG_ERROR(Service_LDR, "Not initialized"); LOG_ERROR(Service_LDR, "Not initialized");
rb.Push(ERROR_NOT_INITIALIZED); rb.Push(ERROR_NOT_INITIALIZED);
rb.Push<u32>(0); rb.Push<u32>(0);
return; return;
} }
auto& slot = find_result->second;
if (cro_size < CRO_HEADER_SIZE) { if (cro_size < CRO_HEADER_SIZE) {
LOG_ERROR(Service_LDR, "CRO too small"); LOG_ERROR(Service_LDR, "CRO too small");
@ -293,7 +290,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
return; return;
} }
slot.memory_synchronizer.AddMemoryBlock(cro_address, cro_buffer_ptr, cro_size); slot->memory_synchronizer.AddMemoryBlock(cro_address, cro_buffer_ptr, cro_size);
} else { } else {
// Do nothing if buffer_ptr == address // Do nothing if buffer_ptr == address
// TODO(wwylele): verify this behaviour. // TODO(wwylele): verify this behaviour.
@ -314,7 +311,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
return; return;
} }
result = cro.Rebase(slot.loaded_crs, cro_size, data_segment_address, data_segment_size, result = cro.Rebase(slot->loaded_crs, cro_size, data_segment_address, data_segment_size,
bss_segment_address, bss_segment_size, false); bss_segment_address, bss_segment_size, false);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw);
@ -324,7 +321,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
return; return;
} }
result = cro.Link(slot.loaded_crs, link_on_load_bug_fix); result = cro.Link(slot->loaded_crs, link_on_load_bug_fix);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw);
process->vm_manager.UnmapRange(cro_address, cro_size); process->vm_manager.UnmapRange(cro_address, cro_size);
@ -333,11 +330,11 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
return; return;
} }
cro.Register(slot.loaded_crs, auto_link); cro.Register(slot->loaded_crs, auto_link);
u32 fix_size = cro.Fix(fix_level); u32 fix_size = cro.Fix(fix_level);
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
// TODO(wwylele): verify the behaviour when buffer_ptr == address // TODO(wwylele): verify the behaviour when buffer_ptr == address
if (cro_buffer_ptr != cro_address) { if (cro_buffer_ptr != cro_address) {
@ -353,7 +350,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
} }
// Changes the block size // Changes the block size
slot.memory_synchronizer.ResizeMemoryBlock(cro_address, cro_buffer_ptr, fix_size); slot->memory_synchronizer.ResizeMemoryBlock(cro_address, cro_buffer_ptr, fix_size);
} }
VAddr exe_begin; VAddr exe_begin;
@ -393,13 +390,12 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
auto find_result = slots.find(process->process_id); ClientSlot* slot = GetSessionData(ctx.Session());
if (find_result == slots.end()) { if (slot->loaded_crs == 0) {
LOG_ERROR(Service_LDR, "Not initialized"); LOG_ERROR(Service_LDR, "Not initialized");
rb.Push(ERROR_NOT_INITIALIZED); rb.Push(ERROR_NOT_INITIALIZED);
return; return;
} }
auto& slot = find_result->second;
if (cro_address & Memory::PAGE_MASK) { if (cro_address & Memory::PAGE_MASK) {
LOG_ERROR(Service_LDR, "CRO address is not aligned"); LOG_ERROR(Service_LDR, "CRO address is not aligned");
@ -417,9 +413,9 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
u32 fixed_size = cro.GetFixedSize(); u32 fixed_size = cro.GetFixedSize();
cro.Unregister(slot.loaded_crs); cro.Unregister(slot->loaded_crs);
ResultCode result = cro.Unlink(slot.loaded_crs); ResultCode result = cro.Unlink(slot->loaded_crs);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw);
rb.Push(result); rb.Push(result);
@ -439,7 +435,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
cro.Unrebase(false); cro.Unrebase(false);
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
// TODO(wwylele): verify the behaviour when buffer_ptr == address // TODO(wwylele): verify the behaviour when buffer_ptr == address
if (cro_address != cro_buffer_ptr) { if (cro_address != cro_buffer_ptr) {
@ -447,7 +443,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error unmapping CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error unmapping CRO %08X", result.raw);
} }
slot.memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr); slot->memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr);
} }
Core::CPU().InvalidateCacheRange(cro_address, fixed_size); Core::CPU().InvalidateCacheRange(cro_address, fixed_size);
@ -466,13 +462,12 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
auto find_result = slots.find(process->process_id); ClientSlot* slot = GetSessionData(ctx.Session());
if (find_result == slots.end()) { if (slot->loaded_crs == 0) {
LOG_ERROR(Service_LDR, "Not initialized"); LOG_ERROR(Service_LDR, "Not initialized");
rb.Push(ERROR_NOT_INITIALIZED); rb.Push(ERROR_NOT_INITIALIZED);
return; return;
} }
auto& slot = find_result->second;
if (cro_address & Memory::PAGE_MASK) { if (cro_address & Memory::PAGE_MASK) {
LOG_ERROR(Service_LDR, "CRO address is not aligned"); LOG_ERROR(Service_LDR, "CRO address is not aligned");
@ -488,12 +483,12 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_LDR, "Linking CRO \"%s\"", cro.ModuleName().data()); LOG_INFO(Service_LDR, "Linking CRO \"%s\"", cro.ModuleName().data());
ResultCode result = cro.Link(slot.loaded_crs, false); ResultCode result = cro.Link(slot->loaded_crs, false);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw);
} }
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
rb.Push(result); rb.Push(result);
} }
@ -509,13 +504,12 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
auto find_result = slots.find(process->process_id); ClientSlot* slot = GetSessionData(ctx.Session());
if (find_result == slots.end()) { if (slot->loaded_crs == 0) {
LOG_ERROR(Service_LDR, "Not initialized"); LOG_ERROR(Service_LDR, "Not initialized");
rb.Push(ERROR_NOT_INITIALIZED); rb.Push(ERROR_NOT_INITIALIZED);
return; return;
} }
auto& slot = find_result->second;
if (cro_address & Memory::PAGE_MASK) { if (cro_address & Memory::PAGE_MASK) {
LOG_ERROR(Service_LDR, "CRO address is not aligned"); LOG_ERROR(Service_LDR, "CRO address is not aligned");
@ -531,12 +525,12 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_LDR, "Unlinking CRO \"%s\"", cro.ModuleName().data()); LOG_INFO(Service_LDR, "Unlinking CRO \"%s\"", cro.ModuleName().data());
ResultCode result = cro.Unlink(slot.loaded_crs); ResultCode result = cro.Unlink(slot->loaded_crs);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw); LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw);
} }
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
rb.Push(result); rb.Push(result);
} }
@ -550,31 +544,30 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
auto find_result = slots.find(process->process_id); ClientSlot* slot = GetSessionData(ctx.Session());
if (find_result == slots.end()) { if (slot->loaded_crs == 0) {
LOG_ERROR(Service_LDR, "Not initialized"); LOG_ERROR(Service_LDR, "Not initialized");
rb.Push(ERROR_NOT_INITIALIZED); rb.Push(ERROR_NOT_INITIALIZED);
return; return;
} }
auto& slot = find_result->second;
CROHelper crs(slot.loaded_crs); CROHelper crs(slot->loaded_crs);
crs.Unrebase(true); crs.Unrebase(true);
slot.memory_synchronizer.SynchronizeOriginalMemory(*process); slot->memory_synchronizer.SynchronizeOriginalMemory(*process);
ResultCode result = RESULT_SUCCESS; ResultCode result = RESULT_SUCCESS;
// TODO(wwylele): verify the behaviour when buffer_ptr == address // TODO(wwylele): verify the behaviour when buffer_ptr == address
if (slot.loaded_crs != crs_buffer_ptr) { if (slot->loaded_crs != crs_buffer_ptr) {
result = process->vm_manager.UnmapRange(slot.loaded_crs, crs.GetFileSize()); result = process->vm_manager.UnmapRange(slot->loaded_crs, crs.GetFileSize());
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error unmapping CRS %08X", result.raw); LOG_ERROR(Service_LDR, "Error unmapping CRS %08X", result.raw);
} }
slot.memory_synchronizer.RemoveMemoryBlock(slot.loaded_crs, crs_buffer_ptr); slot->memory_synchronizer.RemoveMemoryBlock(slot->loaded_crs, crs_buffer_ptr);
} }
slots.erase(find_result); slot->loaded_crs = 0;
rb.Push(result); rb.Push(result);
} }

View file

@ -4,14 +4,18 @@
#pragma once #pragma once
#include <unordered_map>
#include "core/hle/service/ldr_ro/memory_synchronizer.h" #include "core/hle/service/ldr_ro/memory_synchronizer.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Service { namespace Service {
namespace LDR { namespace LDR {
class RO final : public ServiceFramework<RO> { struct ClientSlot : public Kernel::SessionRequestHandler::SessionDataBase {
MemorySynchronizer memory_synchronizer;
VAddr loaded_crs = 0; ///< the virtual address of the static module
};
class RO final : public ServiceFramework<RO, ClientSlot> {
public: public:
RO(); RO();
@ -144,12 +148,6 @@ private:
* 1 : Result of function, 0 on success, otherwise error code * 1 : Result of function, 0 on success, otherwise error code
*/ */
void Shutdown(Kernel::HLERequestContext& self); void Shutdown(Kernel::HLERequestContext& self);
struct ClientSlot {
MemorySynchronizer memory_synchronizer;
VAddr loaded_crs = 0; ///< the virtual address of the static module
};
std::unordered_map<u32, ClientSlot> slots;
}; };
void InstallInterfaces(SM::ServiceManager& service_manager); void InstallInterfaces(SM::ServiceManager& service_manager);