Merge pull request #4480 from wwylele/memory-global-2
Memory: eliminate global state
This commit is contained in:
commit
edbdbf0ba1
57 changed files with 670 additions and 491 deletions
|
@ -65,7 +65,7 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
|
|||
return thread;
|
||||
}
|
||||
|
||||
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel) {}
|
||||
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
||||
AddressArbiter::~AddressArbiter() {}
|
||||
|
||||
SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
|
||||
|
@ -103,31 +103,31 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, Arbitratio
|
|||
|
||||
// Wait current thread (acquire the arbiter)...
|
||||
case ArbitrationType::WaitIfLessThan:
|
||||
if ((s32)Memory::Read32(address) < value) {
|
||||
if ((s32)kernel.memory.Read32(address) < value) {
|
||||
WaitThread(std::move(thread), address);
|
||||
}
|
||||
break;
|
||||
case ArbitrationType::WaitIfLessThanWithTimeout:
|
||||
if ((s32)Memory::Read32(address) < value) {
|
||||
if ((s32)kernel.memory.Read32(address) < value) {
|
||||
thread->wakeup_callback = timeout_callback;
|
||||
thread->WakeAfterDelay(nanoseconds);
|
||||
WaitThread(std::move(thread), address);
|
||||
}
|
||||
break;
|
||||
case ArbitrationType::DecrementAndWaitIfLessThan: {
|
||||
s32 memory_value = Memory::Read32(address);
|
||||
s32 memory_value = kernel.memory.Read32(address);
|
||||
if (memory_value < value) {
|
||||
// Only change the memory value if the thread should wait
|
||||
Memory::Write32(address, (s32)memory_value - 1);
|
||||
kernel.memory.Write32(address, (s32)memory_value - 1);
|
||||
WaitThread(std::move(thread), address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
|
||||
s32 memory_value = Memory::Read32(address);
|
||||
s32 memory_value = kernel.memory.Read32(address);
|
||||
if (memory_value < value) {
|
||||
// Only change the memory value if the thread should wait
|
||||
Memory::Write32(address, (s32)memory_value - 1);
|
||||
kernel.memory.Write32(address, (s32)memory_value - 1);
|
||||
thread->wakeup_callback = timeout_callback;
|
||||
thread->WakeAfterDelay(nanoseconds);
|
||||
WaitThread(std::move(thread), address);
|
||||
|
|
|
@ -52,6 +52,8 @@ private:
|
|||
explicit AddressArbiter(KernelSystem& kernel);
|
||||
~AddressArbiter() override;
|
||||
|
||||
KernelSystem& kernel;
|
||||
|
||||
/// Puts the thread to wait on the specified arbitration address under this address arbiter.
|
||||
void WaitThread(SharedPtr<Thread> thread, VAddr wait_address);
|
||||
|
||||
|
|
|
@ -48,12 +48,13 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
|||
// the translation might need to read from it in order to retrieve the StaticBuffer
|
||||
// target addresses.
|
||||
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
|
||||
Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
Memory::MemorySystem& memory = Core::System::GetInstance().Memory();
|
||||
memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
|
||||
// Copy the translated command buffer back into the thread's command buffer area.
|
||||
Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
memory.WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
};
|
||||
|
||||
auto event = Core::System::GetInstance().Kernel().CreateEvent(Kernel::ResetType::OneShot,
|
||||
|
@ -142,7 +143,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
|||
|
||||
// Copy the input buffer into our own vector and store it.
|
||||
std::vector<u8> data(buffer_info.size);
|
||||
Memory::ReadBlock(src_process, source_address, data.data(), data.size());
|
||||
Core::System::GetInstance().Memory().ReadBlock(src_process, source_address, data.data(),
|
||||
data.size());
|
||||
|
||||
AddStaticBuffer(buffer_info.buffer_id, std::move(data));
|
||||
cmd_buf[i++] = source_address;
|
||||
|
@ -209,7 +211,8 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
|
|||
|
||||
ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big");
|
||||
|
||||
Memory::WriteBlock(dst_process, target_address, data.data(), data.size());
|
||||
Core::System::GetInstance().Memory().WriteBlock(dst_process, target_address,
|
||||
data.data(), data.size());
|
||||
|
||||
dst_cmdbuf[i++] = target_address;
|
||||
break;
|
||||
|
@ -242,13 +245,15 @@ MappedBuffer::MappedBuffer(const Process& process, u32 descriptor, VAddr address
|
|||
void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) {
|
||||
ASSERT(perms & IPC::R);
|
||||
ASSERT(offset + size <= this->size);
|
||||
Memory::ReadBlock(*process, address + static_cast<VAddr>(offset), dest_buffer, size);
|
||||
Core::System::GetInstance().Memory().ReadBlock(*process, address + static_cast<VAddr>(offset),
|
||||
dest_buffer, size);
|
||||
}
|
||||
|
||||
void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) {
|
||||
ASSERT(perms & IPC::W);
|
||||
ASSERT(offset + size <= this->size);
|
||||
Memory::WriteBlock(*process, address + static_cast<VAddr>(offset), src_buffer, size);
|
||||
Core::System::GetInstance().Memory().WriteBlock(*process, address + static_cast<VAddr>(offset),
|
||||
src_buffer, size);
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include "common/alignment.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/ipc.h"
|
||||
|
@ -19,13 +20,13 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
VAddr src_address, VAddr dst_address,
|
||||
std::vector<MappedBufferContext>& mapped_buffer_context,
|
||||
bool reply) {
|
||||
|
||||
Memory::MemorySystem& memory = Core::System::GetInstance().Memory();
|
||||
auto& src_process = src_thread->owner_process;
|
||||
auto& dst_process = dst_thread->owner_process;
|
||||
|
||||
IPC::Header header;
|
||||
// TODO(Subv): Replace by Memory::Read32 when possible.
|
||||
Memory::ReadBlock(*src_process, src_address, &header.raw, sizeof(header.raw));
|
||||
memory.ReadBlock(*src_process, src_address, &header.raw, sizeof(header.raw));
|
||||
|
||||
std::size_t untranslated_size = 1u + header.normal_params_size;
|
||||
std::size_t command_size = untranslated_size + header.translate_params_size;
|
||||
|
@ -34,7 +35,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH);
|
||||
|
||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||
Memory::ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||
memory.ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||
|
||||
std::size_t i = untranslated_size;
|
||||
while (i < command_size) {
|
||||
|
@ -90,7 +91,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
VAddr static_buffer_src_address = cmd_buf[i];
|
||||
|
||||
std::vector<u8> data(bufferInfo.size);
|
||||
Memory::ReadBlock(*src_process, static_buffer_src_address, data.data(), data.size());
|
||||
memory.ReadBlock(*src_process, static_buffer_src_address, data.data(), data.size());
|
||||
|
||||
// Grab the address that the target thread set up to receive the response static buffer
|
||||
// and write our data there. The static buffers area is located right after the command
|
||||
|
@ -106,15 +107,15 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
|
||||
u32 static_buffer_offset = IPC::COMMAND_BUFFER_LENGTH * sizeof(u32) +
|
||||
sizeof(StaticBuffer) * bufferInfo.buffer_id;
|
||||
Memory::ReadBlock(*dst_process, dst_address + static_buffer_offset, &target_buffer,
|
||||
sizeof(target_buffer));
|
||||
memory.ReadBlock(*dst_process, dst_address + static_buffer_offset, &target_buffer,
|
||||
sizeof(target_buffer));
|
||||
|
||||
// Note: The real kernel doesn't seem to have any error recovery mechanisms for this
|
||||
// case.
|
||||
ASSERT_MSG(target_buffer.descriptor.size >= data.size(),
|
||||
"Static buffer data is too big");
|
||||
|
||||
Memory::WriteBlock(*dst_process, target_buffer.address, data.data(), data.size());
|
||||
memory.WriteBlock(*dst_process, target_buffer.address, data.data(), data.size());
|
||||
|
||||
cmd_buf[i++] = target_buffer.address;
|
||||
break;
|
||||
|
@ -153,8 +154,8 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
|
||||
if (permissions != IPC::MappedBufferPermissions::R) {
|
||||
// Copy the modified buffer back into the target process
|
||||
Memory::CopyBlock(*src_process, *dst_process, found->target_address,
|
||||
found->source_address, size);
|
||||
memory.CopyBlock(*src_process, *dst_process, found->target_address,
|
||||
found->source_address, size);
|
||||
}
|
||||
|
||||
VAddr prev_reserve = page_start - Memory::PAGE_SIZE;
|
||||
|
@ -187,7 +188,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||
|
||||
auto buffer = std::make_unique<u8[]>(num_pages * Memory::PAGE_SIZE);
|
||||
Memory::ReadBlock(*src_process, source_address, buffer.get() + page_offset, size);
|
||||
memory.ReadBlock(*src_process, source_address, buffer.get() + page_offset, size);
|
||||
|
||||
// Map the page(s) into the target process' address space.
|
||||
target_address =
|
||||
|
@ -215,7 +216,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
|
|||
}
|
||||
}
|
||||
|
||||
Memory::WriteBlock(*dst_process, dst_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||
memory.WriteBlock(*dst_process, dst_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
namespace Kernel {
|
||||
|
||||
/// Initialize the kernel
|
||||
KernelSystem::KernelSystem(u32 system_mode) {
|
||||
KernelSystem::KernelSystem(Memory::MemorySystem& memory, u32 system_mode) : memory(memory) {
|
||||
MemoryInit(system_mode);
|
||||
|
||||
resource_limits = std::make_unique<ResourceLimitList>(*this);
|
||||
thread_manager = std::make_unique<ThreadManager>();
|
||||
thread_manager = std::make_unique<ThreadManager>(*this);
|
||||
timer_manager = std::make_unique<TimerManager>();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace SharedPage {
|
|||
class Handler;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class AddressArbiter;
|
||||
|
@ -42,6 +46,7 @@ class SharedMemory;
|
|||
class ThreadManager;
|
||||
class TimerManager;
|
||||
class VMManager;
|
||||
struct AddressMapping;
|
||||
|
||||
enum class ResetType {
|
||||
OneShot,
|
||||
|
@ -73,7 +78,7 @@ using SharedPtr = boost::intrusive_ptr<T>;
|
|||
|
||||
class KernelSystem {
|
||||
public:
|
||||
explicit KernelSystem(u32 system_mode);
|
||||
explicit KernelSystem(Memory::MemorySystem& memory, u32 system_mode);
|
||||
~KernelSystem();
|
||||
|
||||
/**
|
||||
|
@ -212,6 +217,8 @@ public:
|
|||
|
||||
MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
|
||||
|
||||
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
|
||||
|
||||
std::array<MemoryRegionInfo, 3> memory_regions;
|
||||
|
||||
/// Adds a port to the named port table
|
||||
|
@ -220,6 +227,8 @@ public:
|
|||
/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
|
||||
std::unordered_map<std::string, SharedPtr<ClientPort>> named_ports;
|
||||
|
||||
Memory::MemorySystem& memory;
|
||||
|
||||
private:
|
||||
void MemoryInit(u32 mem_type);
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ MemoryRegionInfo* KernelSystem::GetMemoryRegion(MemoryRegion region) {
|
|||
}
|
||||
}
|
||||
|
||||
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {
|
||||
void KernelSystem::HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {
|
||||
using namespace Memory;
|
||||
|
||||
struct MemoryArea {
|
||||
|
@ -128,7 +128,7 @@ void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mappin
|
|||
return;
|
||||
}
|
||||
|
||||
u8* target_pointer = Memory::GetPhysicalPointer(area->paddr_base + offset_into_region);
|
||||
u8* target_pointer = memory.GetPhysicalPointer(area->paddr_base + offset_into_region);
|
||||
|
||||
// TODO(yuriks): This flag seems to have some other effect, but it's unknown what
|
||||
MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO;
|
||||
|
|
|
@ -62,6 +62,4 @@ struct MemoryRegionInfo {
|
|||
void Free(u32 offset, u32 size);
|
||||
};
|
||||
|
||||
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -120,8 +120,8 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
|
|||
auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
|
||||
MemoryState memory_state) {
|
||||
HeapAllocate(segment.addr, segment.size, permissions, memory_state, true);
|
||||
Memory::WriteBlock(*this, segment.addr, codeset->memory->data() + segment.offset,
|
||||
segment.size);
|
||||
kernel.memory.WriteBlock(*this, segment.addr, codeset->memory->data() + segment.offset,
|
||||
segment.size);
|
||||
};
|
||||
|
||||
// Map CodeSet segments
|
||||
|
@ -136,7 +136,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
|
|||
// Map special address mappings
|
||||
kernel.MapSharedPages(vm_manager);
|
||||
for (const auto& mapping : address_mappings) {
|
||||
HandleSpecialMapping(vm_manager, mapping);
|
||||
kernel.HandleSpecialMapping(vm_manager, mapping);
|
||||
}
|
||||
|
||||
status = ProcessStatus::Running;
|
||||
|
@ -188,10 +188,11 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
|
|||
u32 interval_size = interval.upper() - interval.lower();
|
||||
LOG_DEBUG(Kernel, "Allocated FCRAM region lower={:08X}, upper={:08X}", interval.lower(),
|
||||
interval.upper());
|
||||
std::fill(Memory::fcram.begin() + interval.lower(),
|
||||
Memory::fcram.begin() + interval.upper(), 0);
|
||||
auto vma = vm_manager.MapBackingMemory(
|
||||
interval_target, Memory::fcram.data() + interval.lower(), interval_size, memory_state);
|
||||
std::fill(kernel.memory.GetFCRAMPointer(interval.lower()),
|
||||
kernel.memory.GetFCRAMPointer(interval.upper()), 0);
|
||||
auto vma = vm_manager.MapBackingMemory(interval_target,
|
||||
kernel.memory.GetFCRAMPointer(interval.lower()),
|
||||
interval_size, memory_state);
|
||||
ASSERT(vma.Succeeded());
|
||||
vm_manager.Reprotect(vma.Unwrap(), perms);
|
||||
interval_target += interval_size;
|
||||
|
@ -218,7 +219,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
|
|||
// Free heaps block by block
|
||||
CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size));
|
||||
for (const auto [backing_memory, block_size] : backing_blocks) {
|
||||
memory_region->Free(Memory::GetFCRAMOffset(backing_memory), block_size);
|
||||
memory_region->Free(kernel.memory.GetFCRAMOffset(backing_memory), block_size);
|
||||
}
|
||||
|
||||
ResultCode result = vm_manager.UnmapRange(target, size);
|
||||
|
@ -262,7 +263,7 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
|
|||
}
|
||||
}
|
||||
|
||||
u8* backing_memory = Memory::fcram.data() + physical_offset;
|
||||
u8* backing_memory = kernel.memory.GetFCRAMPointer(physical_offset);
|
||||
|
||||
std::fill(backing_memory, backing_memory + size, 0);
|
||||
auto vma = vm_manager.MapBackingMemory(target, backing_memory, size, MemoryState::Continuous);
|
||||
|
|
|
@ -43,8 +43,8 @@ ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory(
|
|||
|
||||
ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!");
|
||||
|
||||
std::fill(Memory::fcram.data() + *offset, Memory::fcram.data() + *offset + size, 0);
|
||||
shared_memory->backing_blocks = {{Memory::fcram.data() + *offset, size}};
|
||||
std::fill(memory.GetFCRAMPointer(*offset), memory.GetFCRAMPointer(*offset + size), 0);
|
||||
shared_memory->backing_blocks = {{memory.GetFCRAMPointer(*offset), size}};
|
||||
shared_memory->holding_memory += MemoryRegionInfo::Interval(*offset, *offset + size);
|
||||
shared_memory->linear_heap_phys_offset = *offset;
|
||||
|
||||
|
@ -86,9 +86,9 @@ SharedPtr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
|
|||
shared_memory->other_permissions = other_permissions;
|
||||
for (const auto& interval : backing_blocks) {
|
||||
shared_memory->backing_blocks.push_back(
|
||||
{Memory::fcram.data() + interval.lower(), interval.upper() - interval.lower()});
|
||||
std::fill(Memory::fcram.data() + interval.lower(), Memory::fcram.data() + interval.upper(),
|
||||
0);
|
||||
{memory.GetFCRAMPointer(interval.lower()), interval.upper() - interval.lower()});
|
||||
std::fill(memory.GetFCRAMPointer(interval.lower()),
|
||||
memory.GetFCRAMPointer(interval.upper()), 0);
|
||||
}
|
||||
shared_memory->base_address = Memory::HEAP_VADDR + offset;
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
private:
|
||||
Core::System& system;
|
||||
Kernel::KernelSystem& kernel;
|
||||
Memory::MemorySystem& memory;
|
||||
|
||||
friend class SVCWrapper<SVC>;
|
||||
|
||||
|
@ -351,7 +352,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
|
|||
|
||||
static constexpr std::size_t PortNameMaxLength = 11;
|
||||
// Read 1 char beyond the max allowed port name to detect names that are too long.
|
||||
std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
|
||||
std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
|
||||
if (port_name.size() > PortNameMaxLength)
|
||||
return ERR_PORT_NAME_TOO_LONG;
|
||||
|
||||
|
@ -466,7 +467,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
|||
std::vector<ObjectPtr> objects(handle_count);
|
||||
|
||||
for (int i = 0; i < handle_count; ++i) {
|
||||
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
||||
Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
|
||||
auto object = kernel.GetCurrentProcess()->handle_table.Get<WaitObject>(handle);
|
||||
if (object == nullptr)
|
||||
return ERR_INVALID_HANDLE;
|
||||
|
@ -635,7 +636,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
|||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
||||
|
||||
for (int i = 0; i < handle_count; ++i) {
|
||||
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
||||
Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
|
||||
auto object = current_process->handle_table.Get<WaitObject>(handle);
|
||||
if (object == nullptr)
|
||||
return ERR_INVALID_HANDLE;
|
||||
|
@ -645,7 +646,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
|||
// We are also sending a command reply.
|
||||
// Do not send a reply if the command id in the command buffer is 0xFFFF.
|
||||
Thread* thread = kernel.GetThreadManager().GetCurrentThread();
|
||||
u32 cmd_buff_header = Memory::Read32(thread->GetCommandBufferAddress());
|
||||
u32 cmd_buff_header = memory.Read32(thread->GetCommandBufferAddress());
|
||||
IPC::Header header{cmd_buff_header};
|
||||
if (reply_target != 0 && header.command_id != 0xFFFF) {
|
||||
auto session = current_process->handle_table.Get<ServerSession>(reply_target);
|
||||
|
@ -801,7 +802,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) {
|
|||
}
|
||||
|
||||
std::string string(len, ' ');
|
||||
Memory::ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len);
|
||||
memory.ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len);
|
||||
LOG_DEBUG(Debug_Emulated, "{}", string);
|
||||
}
|
||||
|
||||
|
@ -831,9 +832,9 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi
|
|||
return ERR_INVALID_HANDLE;
|
||||
|
||||
for (unsigned int i = 0; i < name_count; ++i) {
|
||||
u32 name = Memory::Read32(names + i * sizeof(u32));
|
||||
u32 name = memory.Read32(names + i * sizeof(u32));
|
||||
s64 value = resource_limit->GetCurrentResourceValue(name);
|
||||
Memory::Write64(values + i * sizeof(u64), value);
|
||||
memory.Write64(values + i * sizeof(u64), value);
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
|
@ -851,9 +852,9 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
|
|||
return ERR_INVALID_HANDLE;
|
||||
|
||||
for (unsigned int i = 0; i < name_count; ++i) {
|
||||
u32 name = Memory::Read32(names + i * sizeof(u32));
|
||||
u32 name = memory.Read32(names + i * sizeof(u32));
|
||||
s64 value = resource_limit->GetMaxResourceValue(name);
|
||||
Memory::Write64(values + i * sizeof(u64), value);
|
||||
memory.Write64(values + i * sizeof(u64), value);
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
|
@ -1584,7 +1585,7 @@ void SVC::CallSVC(u32 immediate) {
|
|||
}
|
||||
}
|
||||
|
||||
SVC::SVC(Core::System& system) : system(system), kernel(system.Kernel()) {}
|
||||
SVC::SVC(Core::System& system) : system(system), kernel(system.Kernel()), memory(system.Memory()) {}
|
||||
|
||||
u32 SVC::GetReg(std::size_t n) {
|
||||
return system.CPU().GetReg(static_cast<int>(n));
|
||||
|
|
|
@ -104,7 +104,7 @@ void ThreadManager::SwitchContext(Thread* new_thread) {
|
|||
// Cancel any outstanding wakeup events for this thread
|
||||
timing.UnscheduleEvent(ThreadWakeupEventType, new_thread->thread_id);
|
||||
|
||||
auto previous_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
|
||||
auto previous_process = kernel.GetCurrentProcess();
|
||||
|
||||
current_thread = new_thread;
|
||||
|
||||
|
@ -112,8 +112,9 @@ void ThreadManager::SwitchContext(Thread* new_thread) {
|
|||
new_thread->status = ThreadStatus::Running;
|
||||
|
||||
if (previous_process != current_thread->owner_process) {
|
||||
Core::System::GetInstance().Kernel().SetCurrentProcess(current_thread->owner_process);
|
||||
SetCurrentPageTable(¤t_thread->owner_process->vm_manager.page_table);
|
||||
kernel.SetCurrentProcess(current_thread->owner_process);
|
||||
kernel.memory.SetCurrentPageTable(
|
||||
¤t_thread->owner_process->vm_manager.page_table);
|
||||
}
|
||||
|
||||
Core::CPU().LoadContext(new_thread->context);
|
||||
|
@ -354,7 +355,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
|
|||
|
||||
// Map the page to the current process' address space.
|
||||
vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
|
||||
Memory::fcram.data() + *offset, Memory::PAGE_SIZE,
|
||||
memory.GetFCRAMPointer(*offset), Memory::PAGE_SIZE,
|
||||
MemoryState::Locked);
|
||||
}
|
||||
|
||||
|
@ -363,7 +364,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
|
|||
thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
|
||||
available_slot * Memory::TLS_ENTRY_SIZE;
|
||||
|
||||
Memory::ZeroBlock(owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||
memory.ZeroBlock(owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||
|
||||
// TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
|
||||
// to initialize the context
|
||||
|
@ -460,7 +461,7 @@ VAddr Thread::GetCommandBufferAddress() const {
|
|||
return GetTLSAddress() + CommandHeaderOffset;
|
||||
}
|
||||
|
||||
ThreadManager::ThreadManager() {
|
||||
ThreadManager::ThreadManager(Kernel::KernelSystem& kernel) : kernel(kernel) {
|
||||
ThreadWakeupEventType = Core::System::GetInstance().CoreTiming().RegisterEvent(
|
||||
"ThreadWakeupCallback",
|
||||
[this](u64 thread_id, s64 cycle_late) { ThreadWakeupCallback(thread_id, cycle_late); });
|
||||
|
|
|
@ -57,7 +57,7 @@ enum class ThreadWakeupReason {
|
|||
|
||||
class ThreadManager {
|
||||
public:
|
||||
ThreadManager();
|
||||
explicit ThreadManager(Kernel::KernelSystem& kernel);
|
||||
~ThreadManager();
|
||||
|
||||
/**
|
||||
|
@ -121,6 +121,8 @@ private:
|
|||
*/
|
||||
void ThreadWakeupCallback(u64 thread_id, s64 cycles_late);
|
||||
|
||||
Kernel::KernelSystem& kernel;
|
||||
|
||||
u32 next_thread_id = 1;
|
||||
SharedPtr<Thread> current_thread;
|
||||
Common::ThreadQueueList<Thread*, ThreadPrioLowest + 1> ready_queue;
|
||||
|
|
|
@ -113,7 +113,7 @@ void Module::CompletionEventCallBack(u64 port_id, s64) {
|
|||
if (copy_length <= 0) {
|
||||
break;
|
||||
}
|
||||
Memory::WriteBlock(*port.dest_process, dest_ptr, src_ptr, copy_length);
|
||||
system.Memory().WriteBlock(*port.dest_process, dest_ptr, src_ptr, copy_length);
|
||||
dest_ptr += copy_length;
|
||||
dest_size_left -= copy_length;
|
||||
src_ptr += original_width;
|
||||
|
@ -125,8 +125,8 @@ void Module::CompletionEventCallBack(u64 port_id, s64) {
|
|||
LOG_ERROR(Service_CAM, "The destination size ({}) doesn't match the source ({})!",
|
||||
port.dest_size, buffer_size);
|
||||
}
|
||||
Memory::WriteBlock(*port.dest_process, port.dest, buffer.data(),
|
||||
std::min<std::size_t>(port.dest_size, buffer_size));
|
||||
system.Memory().WriteBlock(*port.dest_process, port.dest, buffer.data(),
|
||||
std::min<std::size_t>(port.dest_size, buffer_size));
|
||||
}
|
||||
|
||||
port.is_receiving = false;
|
||||
|
|
|
@ -491,6 +491,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
|
|||
// GX request DMA - typically used for copying memory from GSP heap to VRAM
|
||||
case CommandId::REQUEST_DMA: {
|
||||
MICROPROFILE_SCOPE(GPU_GSP_DMA);
|
||||
Memory::MemorySystem& memory = Core::System::GetInstance().Memory();
|
||||
|
||||
// TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
|
||||
// possible/likely
|
||||
|
@ -502,9 +503,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
|
|||
|
||||
// TODO(Subv): These memory accesses should not go through the application's memory mapping.
|
||||
// They should go through the GSP module's memory mapping.
|
||||
Memory::CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
command.dma_request.dest_address, command.dma_request.source_address,
|
||||
command.dma_request.size);
|
||||
memory.CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
command.dma_request.dest_address, command.dma_request.source_address,
|
||||
command.dma_request.size);
|
||||
SignalInterrupt(InterruptId::DMA);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
|
|||
return 0;
|
||||
|
||||
SegmentEntry entry;
|
||||
GetEntry(segment_tag.segment_index, entry);
|
||||
GetEntry(memory, segment_tag.segment_index, entry);
|
||||
|
||||
if (segment_tag.offset_into_segment >= entry.size)
|
||||
return 0;
|
||||
|
@ -71,11 +71,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc
|
|||
break;
|
||||
case RelocationType::AbsoluteAddress:
|
||||
case RelocationType::AbsoluteAddress2:
|
||||
Memory::Write32(target_address, symbol_address + addend);
|
||||
memory.Write32(target_address, symbol_address + addend);
|
||||
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
|
||||
break;
|
||||
case RelocationType::RelativeAddress:
|
||||
Memory::Write32(target_address, symbol_address + addend - target_future_address);
|
||||
memory.Write32(target_address, symbol_address + addend - target_future_address);
|
||||
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
|
||||
break;
|
||||
case RelocationType::ThumbBranch:
|
||||
|
@ -98,7 +98,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc
|
|||
case RelocationType::AbsoluteAddress:
|
||||
case RelocationType::AbsoluteAddress2:
|
||||
case RelocationType::RelativeAddress:
|
||||
Memory::Write32(target_address, 0);
|
||||
memory.Write32(target_address, 0);
|
||||
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
|
||||
break;
|
||||
case RelocationType::ThumbBranch:
|
||||
|
@ -121,7 +121,7 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
|
|||
VAddr relocation_address = batch;
|
||||
while (true) {
|
||||
RelocationEntry relocation;
|
||||
Memory::ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry));
|
||||
memory.ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry));
|
||||
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
if (relocation_target == 0) {
|
||||
|
@ -142,9 +142,9 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
|
|||
}
|
||||
|
||||
RelocationEntry relocation;
|
||||
Memory::ReadBlock(process, batch, &relocation, sizeof(RelocationEntry));
|
||||
memory.ReadBlock(process, batch, &relocation, sizeof(RelocationEntry));
|
||||
relocation.is_batch_resolved = reset ? 0 : 1;
|
||||
Memory::WriteBlock(process, batch, &relocation, sizeof(RelocationEntry));
|
||||
memory.WriteBlock(process, batch, &relocation, sizeof(RelocationEntry));
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -154,13 +154,13 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
|
|||
|
||||
std::size_t len = name.size();
|
||||
ExportTreeEntry entry;
|
||||
GetEntry(0, entry);
|
||||
GetEntry(memory, 0, entry);
|
||||
ExportTreeEntry::Child next;
|
||||
next.raw = entry.left.raw;
|
||||
u32 found_id;
|
||||
|
||||
while (true) {
|
||||
GetEntry(next.next_index, entry);
|
||||
GetEntry(memory, next.next_index, entry);
|
||||
|
||||
if (next.is_end) {
|
||||
found_id = entry.export_table_index;
|
||||
|
@ -186,9 +186,9 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
|
|||
|
||||
u32 export_strings_size = GetField(ExportStringsSize);
|
||||
ExportNamedSymbolEntry symbol_entry;
|
||||
GetEntry(found_id, symbol_entry);
|
||||
GetEntry(memory, found_id, symbol_entry);
|
||||
|
||||
if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name)
|
||||
if (memory.ReadCString(symbol_entry.name_offset, export_strings_size) != name)
|
||||
return 0;
|
||||
|
||||
return SegmentTagToAddress(symbol_entry.symbol_position);
|
||||
|
@ -279,7 +279,7 @@ ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_
|
|||
u32 segment_num = GetField(SegmentNum);
|
||||
for (u32 i = 0; i < segment_num; ++i) {
|
||||
SegmentEntry segment;
|
||||
GetEntry(i, segment);
|
||||
GetEntry(memory, i, segment);
|
||||
if (segment.type == SegmentType::Data) {
|
||||
if (segment.size != 0) {
|
||||
if (segment.size > data_segment_size)
|
||||
|
@ -298,7 +298,7 @@ ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_
|
|||
if (segment.offset > module_address + cro_size)
|
||||
return CROFormatError(0x19);
|
||||
}
|
||||
SetEntry(i, segment);
|
||||
SetEntry(memory, i, segment);
|
||||
}
|
||||
return MakeResult<u32>(prev_data_segment + module_address);
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
|
|||
u32 export_named_symbol_num = GetField(ExportNamedSymbolNum);
|
||||
for (u32 i = 0; i < export_named_symbol_num; ++i) {
|
||||
ExportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset += module_address;
|
||||
|
@ -320,7 +320,7 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
|
|||
}
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ ResultCode CROHelper::VerifyExportTreeTable() const {
|
|||
u32 tree_num = GetField(ExportTreeNum);
|
||||
for (u32 i = 0; i < tree_num; ++i) {
|
||||
ExportTreeEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.left.next_index >= tree_num || entry.right.next_index >= tree_num) {
|
||||
return CROFormatError(0x11);
|
||||
|
@ -353,7 +353,7 @@ ResultCode CROHelper::RebaseImportModuleTable() {
|
|||
u32 module_num = GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset += module_address;
|
||||
|
@ -379,7 +379,7 @@ ResultCode CROHelper::RebaseImportModuleTable() {
|
|||
}
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
|
|||
u32 num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset += module_address;
|
||||
|
@ -413,7 +413,7 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
|
|||
}
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
|
|||
u32 num = GetField(ImportIndexedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset += module_address;
|
||||
|
@ -437,7 +437,7 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
|
|||
}
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
|
|||
u32 num = GetField(ImportAnonymousSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset += module_address;
|
||||
|
@ -461,7 +461,7 @@ ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
|
|||
}
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -476,14 +476,14 @@ ResultCode CROHelper::ResetExternalRelocations() {
|
|||
ExternalRelocationEntry relocation;
|
||||
|
||||
// Verifies that the last relocation is the end of a batch
|
||||
GetEntry(external_relocation_num - 1, relocation);
|
||||
GetEntry(memory, external_relocation_num - 1, relocation);
|
||||
if (!relocation.is_batch_end) {
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
bool batch_begin = true;
|
||||
for (u32 i = 0; i < external_relocation_num; ++i) {
|
||||
GetEntry(i, relocation);
|
||||
GetEntry(memory, i, relocation);
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
|
||||
if (relocation_target == 0) {
|
||||
|
@ -500,7 +500,7 @@ ResultCode CROHelper::ResetExternalRelocations() {
|
|||
if (batch_begin) {
|
||||
// resets to unresolved state
|
||||
relocation.is_batch_resolved = 0;
|
||||
SetEntry(i, relocation);
|
||||
SetEntry(memory, i, relocation);
|
||||
}
|
||||
|
||||
// if current is an end, then the next is a beginning
|
||||
|
@ -516,7 +516,7 @@ ResultCode CROHelper::ClearExternalRelocations() {
|
|||
|
||||
bool batch_begin = true;
|
||||
for (u32 i = 0; i < external_relocation_num; ++i) {
|
||||
GetEntry(i, relocation);
|
||||
GetEntry(memory, i, relocation);
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
|
||||
if (relocation_target == 0) {
|
||||
|
@ -532,7 +532,7 @@ ResultCode CROHelper::ClearExternalRelocations() {
|
|||
if (batch_begin) {
|
||||
// resets to unresolved state
|
||||
relocation.is_batch_resolved = 0;
|
||||
SetEntry(i, relocation);
|
||||
SetEntry(memory, i, relocation);
|
||||
}
|
||||
|
||||
// if current is an end, then the next is a beginning
|
||||
|
@ -548,13 +548,13 @@ ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) {
|
|||
static_relocation_table_offset +
|
||||
GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry);
|
||||
|
||||
CROHelper crs(crs_address, process);
|
||||
CROHelper crs(crs_address, process, memory);
|
||||
u32 offset_export_num = GetField(StaticAnonymousSymbolNum);
|
||||
LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(),
|
||||
offset_export_num);
|
||||
for (u32 i = 0; i < offset_export_num; ++i) {
|
||||
StaticAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
u32 batch_address = entry.relocation_batch_offset + module_address;
|
||||
|
||||
if (batch_address < static_relocation_table_offset ||
|
||||
|
@ -579,7 +579,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
|
|||
u32 internal_relocation_num = GetField(InternalRelocationNum);
|
||||
for (u32 i = 0; i < internal_relocation_num; ++i) {
|
||||
InternalRelocationEntry relocation;
|
||||
GetEntry(i, relocation);
|
||||
GetEntry(memory, i, relocation);
|
||||
VAddr target_addressB = SegmentTagToAddress(relocation.target_position);
|
||||
if (target_addressB == 0) {
|
||||
return CROFormatError(0x15);
|
||||
|
@ -587,7 +587,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
|
|||
|
||||
VAddr target_address;
|
||||
SegmentEntry target_segment;
|
||||
GetEntry(relocation.target_position.segment_index, target_segment);
|
||||
GetEntry(memory, relocation.target_position.segment_index, target_segment);
|
||||
|
||||
if (target_segment.type == SegmentType::Data) {
|
||||
// If the relocation is to the .data segment, we need to relocate it in the old buffer
|
||||
|
@ -602,7 +602,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
|
|||
}
|
||||
|
||||
SegmentEntry symbol_segment;
|
||||
GetEntry(relocation.symbol_segment, symbol_segment);
|
||||
GetEntry(memory, relocation.symbol_segment, symbol_segment);
|
||||
LOG_TRACE(Service_LDR, "Internally relocates 0x{:08X} with 0x{:08X}", target_address,
|
||||
symbol_segment.offset);
|
||||
ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend,
|
||||
|
@ -619,7 +619,7 @@ ResultCode CROHelper::ClearInternalRelocations() {
|
|||
u32 internal_relocation_num = GetField(InternalRelocationNum);
|
||||
for (u32 i = 0; i < internal_relocation_num; ++i) {
|
||||
InternalRelocationEntry relocation;
|
||||
GetEntry(i, relocation);
|
||||
GetEntry(memory, i, relocation);
|
||||
VAddr target_address = SegmentTagToAddress(relocation.target_position);
|
||||
|
||||
if (target_address == 0) {
|
||||
|
@ -639,13 +639,13 @@ void CROHelper::UnrebaseImportAnonymousSymbolTable() {
|
|||
u32 num = GetField(ImportAnonymousSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,13 +653,13 @@ void CROHelper::UnrebaseImportIndexedSymbolTable() {
|
|||
u32 num = GetField(ImportIndexedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ void CROHelper::UnrebaseImportNamedSymbolTable() {
|
|||
u32 num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset -= module_address;
|
||||
|
@ -677,7 +677,7 @@ void CROHelper::UnrebaseImportNamedSymbolTable() {
|
|||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,7 +685,7 @@ void CROHelper::UnrebaseImportModuleTable() {
|
|||
u32 module_num = GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset -= module_address;
|
||||
|
@ -699,7 +699,7 @@ void CROHelper::UnrebaseImportModuleTable() {
|
|||
entry.import_anonymous_symbol_table_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,13 +707,13 @@ void CROHelper::UnrebaseExportNamedSymbolTable() {
|
|||
u32 export_named_symbol_num = GetField(ExportNamedSymbolNum);
|
||||
for (u32 i = 0; i < export_named_symbol_num; ++i) {
|
||||
ExportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
SetEntry(memory, i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,7 +721,7 @@ void CROHelper::UnrebaseSegmentTable() {
|
|||
u32 segment_num = GetField(SegmentNum);
|
||||
for (u32 i = 0; i < segment_num; ++i) {
|
||||
SegmentEntry segment;
|
||||
GetEntry(i, segment);
|
||||
GetEntry(memory, i, segment);
|
||||
|
||||
if (segment.type == SegmentType::BSS) {
|
||||
segment.offset = 0;
|
||||
|
@ -729,7 +729,7 @@ void CROHelper::UnrebaseSegmentTable() {
|
|||
segment.offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, segment);
|
||||
SetEntry(memory, i, segment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,17 +751,17 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
|
|||
u32 symbol_import_num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (!relocation_entry.is_batch_resolved) {
|
||||
ResultCode result =
|
||||
ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
ResultCode result = ForEachAutoLinkCRO(
|
||||
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
std::string symbol_name =
|
||||
Memory::ReadCString(entry.name_offset, import_strings_size);
|
||||
memory.ReadCString(entry.name_offset, import_strings_size);
|
||||
u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
|
||||
|
||||
if (symbol_address != 0) {
|
||||
|
@ -794,11 +794,11 @@ ResultCode CROHelper::ResetImportNamedSymbol() {
|
|||
u32 symbol_import_num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
|
@ -815,11 +815,11 @@ ResultCode CROHelper::ResetImportIndexedSymbol() {
|
|||
u32 import_num = GetField(ImportIndexedSymbolNum);
|
||||
for (u32 i = 0; i < import_num; ++i) {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
|
@ -836,11 +836,11 @@ ResultCode CROHelper::ResetImportAnonymousSymbol() {
|
|||
u32 import_num = GetField(ImportAnonymousSymbolNum);
|
||||
for (u32 i = 0; i < import_num; ++i) {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
|
@ -857,19 +857,19 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
|
|||
u32 import_module_num = GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < import_module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
GetEntry(i, entry);
|
||||
std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size);
|
||||
GetEntry(memory, i, entry);
|
||||
std::string want_cro_name = memory.ReadCString(entry.name_offset, import_strings_size);
|
||||
|
||||
ResultCode result =
|
||||
ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
ResultCode result = ForEachAutoLinkCRO(
|
||||
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
if (want_cro_name == source.ModuleName()) {
|
||||
LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"",
|
||||
ModuleName(), entry.import_indexed_symbol_num, source.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
|
||||
ImportIndexedSymbolEntry im;
|
||||
entry.GetImportIndexedSymbolEntry(process, j, im);
|
||||
entry.GetImportIndexedSymbolEntry(process, memory, j, im);
|
||||
ExportIndexedSymbolEntry ex;
|
||||
source.GetEntry(im.index, ex);
|
||||
source.GetEntry(memory, im.index, ex);
|
||||
u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " Imports 0x{:08X}", symbol_address);
|
||||
ResultCode result =
|
||||
|
@ -884,7 +884,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
|
|||
ModuleName(), entry.import_anonymous_symbol_num, source.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
|
||||
ImportAnonymousSymbolEntry im;
|
||||
entry.GetImportAnonymousSymbolEntry(process, j, im);
|
||||
entry.GetImportAnonymousSymbolEntry(process, memory, j, im);
|
||||
u32 symbol_address = source.SegmentTagToAddress(im.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " Imports 0x{:08X}", symbol_address);
|
||||
ResultCode result =
|
||||
|
@ -913,15 +913,15 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
|
|||
u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < target_symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
target.GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (!relocation_entry.is_batch_resolved) {
|
||||
std::string symbol_name =
|
||||
Memory::ReadCString(entry.name_offset, target_import_strings_size);
|
||||
memory.ReadCString(entry.name_offset, target_import_strings_size);
|
||||
u32 symbol_address = FindExportNamedSymbol(symbol_name);
|
||||
if (symbol_address != 0) {
|
||||
LOG_TRACE(Service_LDR, " exports symbol \"{}\"", symbol_name);
|
||||
|
@ -944,15 +944,15 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
|
|||
u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < target_symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
target.GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (relocation_entry.is_batch_resolved) {
|
||||
std::string symbol_name =
|
||||
Memory::ReadCString(entry.name_offset, target_import_strings_size);
|
||||
memory.ReadCString(entry.name_offset, target_import_strings_size);
|
||||
u32 symbol_address = FindExportNamedSymbol(symbol_name);
|
||||
if (symbol_address != 0) {
|
||||
LOG_TRACE(Service_LDR, " unexports symbol \"{}\"", symbol_name);
|
||||
|
@ -974,18 +974,18 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
|
|||
u32 target_import_module_num = target.GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < target_import_module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
target.GetEntry(memory, i, entry);
|
||||
|
||||
if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
|
||||
if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
|
||||
continue;
|
||||
|
||||
LOG_INFO(Service_LDR, "CRO \"{}\" exports {} indexed symbols to \"{}\"", module_name,
|
||||
entry.import_indexed_symbol_num, target.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
|
||||
ImportIndexedSymbolEntry im;
|
||||
entry.GetImportIndexedSymbolEntry(process, j, im);
|
||||
entry.GetImportIndexedSymbolEntry(process, memory, j, im);
|
||||
ExportIndexedSymbolEntry ex;
|
||||
GetEntry(im.index, ex);
|
||||
GetEntry(memory, im.index, ex);
|
||||
u32 symbol_address = SegmentTagToAddress(ex.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " exports symbol 0x{:08X}", symbol_address);
|
||||
ResultCode result =
|
||||
|
@ -1000,7 +1000,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
|
|||
entry.import_anonymous_symbol_num, target.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
|
||||
ImportAnonymousSymbolEntry im;
|
||||
entry.GetImportAnonymousSymbolEntry(process, j, im);
|
||||
entry.GetImportAnonymousSymbolEntry(process, memory, j, im);
|
||||
u32 symbol_address = SegmentTagToAddress(im.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " exports symbol 0x{:08X}", symbol_address);
|
||||
ResultCode result =
|
||||
|
@ -1023,16 +1023,16 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
|
|||
u32 target_import_module_num = target.GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < target_import_module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
target.GetEntry(memory, i, entry);
|
||||
|
||||
if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
|
||||
if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
|
||||
continue;
|
||||
|
||||
LOG_DEBUG(Service_LDR, "CRO \"{}\" unexports indexed symbols to \"{}\"", module_name,
|
||||
target.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
|
||||
ImportIndexedSymbolEntry im;
|
||||
entry.GetImportIndexedSymbolEntry(process, j, im);
|
||||
entry.GetImportIndexedSymbolEntry(process, memory, j, im);
|
||||
ResultCode result =
|
||||
target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
|
@ -1045,7 +1045,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
|
|||
target.ModuleName());
|
||||
for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
|
||||
ImportAnonymousSymbolEntry im;
|
||||
entry.GetImportAnonymousSymbolEntry(process, j, im);
|
||||
entry.GetImportAnonymousSymbolEntry(process, memory, j, im);
|
||||
ResultCode result =
|
||||
target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
|
@ -1063,15 +1063,15 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
|
|||
u32 symbol_import_num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
memory.ReadBlock(process, relocation_addr, &relocation_entry,
|
||||
sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
|
||||
ResultCode result =
|
||||
ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
if (memory.ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
|
||||
ResultCode result = ForEachAutoLinkCRO(
|
||||
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
|
||||
u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
|
||||
|
||||
if (symbol_address != 0) {
|
||||
|
@ -1108,9 +1108,9 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
|
|||
* @param size the size of the string (table), including the terminating 0
|
||||
* @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code.
|
||||
*/
|
||||
static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
|
||||
static ResultCode VerifyStringTableLength(Memory::MemorySystem& memory, VAddr address, u32 size) {
|
||||
if (size != 0) {
|
||||
if (Memory::Read8(address + size - 1) != 0)
|
||||
if (memory.Read8(address + size - 1) != 0)
|
||||
return CROFormatError(0x0B);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
|
@ -1126,7 +1126,7 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
|
|||
return result;
|
||||
}
|
||||
|
||||
result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize));
|
||||
result = VerifyStringTableLength(memory, GetField(ModuleNameOffset), GetField(ModuleNameSize));
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error verifying module name {:08X}", result.raw);
|
||||
return result;
|
||||
|
@ -1155,7 +1155,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
|
|||
return result;
|
||||
}
|
||||
|
||||
result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize));
|
||||
result =
|
||||
VerifyStringTableLength(memory, GetField(ExportStringsOffset), GetField(ExportStringsSize));
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error verifying export strings {:08X}", result.raw);
|
||||
return result;
|
||||
|
@ -1191,7 +1192,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
|
|||
return result;
|
||||
}
|
||||
|
||||
result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize));
|
||||
result =
|
||||
VerifyStringTableLength(memory, GetField(ImportStringsOffset), GetField(ImportStringsSize));
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error verifying import strings {:08X}", result.raw);
|
||||
return result;
|
||||
|
@ -1264,11 +1266,11 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) {
|
|||
// so we do the same
|
||||
if (GetField(SegmentNum) >= 2) { // means we have .data segment
|
||||
SegmentEntry entry;
|
||||
GetEntry(2, entry);
|
||||
GetEntry(memory, 2, entry);
|
||||
ASSERT(entry.type == SegmentType::Data);
|
||||
data_segment_address = entry.offset;
|
||||
entry.offset = GetField(DataOffset);
|
||||
SetEntry(2, entry);
|
||||
SetEntry(memory, 2, entry);
|
||||
}
|
||||
}
|
||||
SCOPE_EXIT({
|
||||
|
@ -1276,9 +1278,9 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) {
|
|||
if (link_on_load_bug_fix) {
|
||||
if (GetField(SegmentNum) >= 2) {
|
||||
SegmentEntry entry;
|
||||
GetEntry(2, entry);
|
||||
GetEntry(memory, 2, entry);
|
||||
entry.offset = data_segment_address;
|
||||
SetEntry(2, entry);
|
||||
SetEntry(memory, 2, entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1299,17 +1301,18 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) {
|
|||
}
|
||||
|
||||
// Exports symbols to other modules
|
||||
result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal<bool> {
|
||||
ResultCode result = ApplyExportNamedSymbol(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
result = ForEachAutoLinkCRO(process, memory, crs_address,
|
||||
[this](CROHelper target) -> ResultVal<bool> {
|
||||
ResultCode result = ApplyExportNamedSymbol(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
result = ApplyModuleExport(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
result = ApplyModuleExport(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying export {:08X}", result.raw);
|
||||
return result;
|
||||
|
@ -1343,17 +1346,18 @@ ResultCode CROHelper::Unlink(VAddr crs_address) {
|
|||
|
||||
// Resets all symbols in other modules imported from this module
|
||||
// Note: the RO service seems only searching in auto-link modules
|
||||
result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal<bool> {
|
||||
ResultCode result = ResetExportNamedSymbol(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
result = ForEachAutoLinkCRO(process, memory, crs_address,
|
||||
[this](CROHelper target) -> ResultVal<bool> {
|
||||
ResultCode result = ResetExportNamedSymbol(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
result = ResetModuleExport(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
result = ResetModuleExport(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting export {:08X}", result.raw);
|
||||
return result;
|
||||
|
@ -1383,13 +1387,13 @@ void CROHelper::InitCRS() {
|
|||
}
|
||||
|
||||
void CROHelper::Register(VAddr crs_address, bool auto_link) {
|
||||
CROHelper crs(crs_address, process);
|
||||
CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process);
|
||||
CROHelper crs(crs_address, process, memory);
|
||||
CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process, memory);
|
||||
|
||||
if (head.module_address) {
|
||||
// there are already CROs registered
|
||||
// register as the new tail
|
||||
CROHelper tail(head.PreviousModule(), process);
|
||||
CROHelper tail(head.PreviousModule(), process, memory);
|
||||
|
||||
// link with the old tail
|
||||
ASSERT(tail.NextModule() == 0);
|
||||
|
@ -1415,9 +1419,11 @@ void CROHelper::Register(VAddr crs_address, bool auto_link) {
|
|||
}
|
||||
|
||||
void CROHelper::Unregister(VAddr crs_address) {
|
||||
CROHelper crs(crs_address, process);
|
||||
CROHelper next_head(crs.NextModule(), process), previous_head(crs.PreviousModule(), process);
|
||||
CROHelper next(NextModule(), process), previous(PreviousModule(), process);
|
||||
CROHelper crs(crs_address, process, memory);
|
||||
CROHelper next_head(crs.NextModule(), process, memory);
|
||||
CROHelper previous_head(crs.PreviousModule(), process, memory);
|
||||
CROHelper next(NextModule(), process, memory);
|
||||
CROHelper previous(PreviousModule(), process, memory);
|
||||
|
||||
if (module_address == next_head.module_address ||
|
||||
module_address == previous_head.module_address) {
|
||||
|
@ -1511,7 +1517,7 @@ std::tuple<VAddr, u32> CROHelper::GetExecutablePages() const {
|
|||
u32 segment_num = GetField(SegmentNum);
|
||||
for (u32 i = 0; i < segment_num; ++i) {
|
||||
SegmentEntry entry;
|
||||
GetEntry(i, entry);
|
||||
GetEntry(memory, i, entry);
|
||||
if (entry.type == SegmentType::Code && entry.size != 0) {
|
||||
VAddr begin = Common::AlignDown(entry.offset, Memory::PAGE_SIZE);
|
||||
VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::PAGE_SIZE);
|
||||
|
|
|
@ -40,11 +40,11 @@ static constexpr u32 CRO_HASH_SIZE = 0x80;
|
|||
class CROHelper final {
|
||||
public:
|
||||
// TODO (wwylele): pass in the process handle for memory access
|
||||
explicit CROHelper(VAddr cro_address, Kernel::Process& process)
|
||||
: module_address(cro_address), process(process) {}
|
||||
explicit CROHelper(VAddr cro_address, Kernel::Process& process, Memory::MemorySystem& memory)
|
||||
: module_address(cro_address), process(process), memory(memory) {}
|
||||
|
||||
std::string ModuleName() const {
|
||||
return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
|
||||
return memory.ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
|
||||
}
|
||||
|
||||
u32 GetFileSize() const {
|
||||
|
@ -150,6 +150,7 @@ public:
|
|||
private:
|
||||
const VAddr module_address; ///< the virtual address of this module
|
||||
Kernel::Process& process; ///< the owner process of this module
|
||||
Memory::MemorySystem& memory;
|
||||
|
||||
/**
|
||||
* Each item in this enum represents a u32 field in the header begin from address+0x80,
|
||||
|
@ -317,20 +318,20 @@ private:
|
|||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;
|
||||
|
||||
void GetImportIndexedSymbolEntry(Kernel::Process& process, u32 index,
|
||||
ImportIndexedSymbolEntry& entry) {
|
||||
Memory::ReadBlock(process,
|
||||
import_indexed_symbol_table_offset +
|
||||
index * sizeof(ImportIndexedSymbolEntry),
|
||||
&entry, sizeof(ImportIndexedSymbolEntry));
|
||||
void GetImportIndexedSymbolEntry(Kernel::Process& process, Memory::MemorySystem& memory,
|
||||
u32 index, ImportIndexedSymbolEntry& entry) {
|
||||
memory.ReadBlock(process,
|
||||
import_indexed_symbol_table_offset +
|
||||
index * sizeof(ImportIndexedSymbolEntry),
|
||||
&entry, sizeof(ImportIndexedSymbolEntry));
|
||||
}
|
||||
|
||||
void GetImportAnonymousSymbolEntry(Kernel::Process& process, u32 index,
|
||||
ImportAnonymousSymbolEntry& entry) {
|
||||
Memory::ReadBlock(process,
|
||||
import_anonymous_symbol_table_offset +
|
||||
index * sizeof(ImportAnonymousSymbolEntry),
|
||||
&entry, sizeof(ImportAnonymousSymbolEntry));
|
||||
void GetImportAnonymousSymbolEntry(Kernel::Process& process, Memory::MemorySystem& memory,
|
||||
u32 index, ImportAnonymousSymbolEntry& entry) {
|
||||
memory.ReadBlock(process,
|
||||
import_anonymous_symbol_table_offset +
|
||||
index * sizeof(ImportAnonymousSymbolEntry),
|
||||
&entry, sizeof(ImportAnonymousSymbolEntry));
|
||||
}
|
||||
};
|
||||
ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
|
||||
|
@ -407,11 +408,11 @@ private:
|
|||
}
|
||||
|
||||
u32 GetField(HeaderField field) const {
|
||||
return Memory::Read32(Field(field));
|
||||
return memory.Read32(Field(field));
|
||||
}
|
||||
|
||||
void SetField(HeaderField field, u32 value) {
|
||||
Memory::Write32(Field(field), value);
|
||||
memory.Write32(Field(field), value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -422,10 +423,10 @@ private:
|
|||
* indicating which table the entry is in.
|
||||
*/
|
||||
template <typename T>
|
||||
void GetEntry(std::size_t index, T& data) const {
|
||||
Memory::ReadBlock(process,
|
||||
GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)),
|
||||
&data, sizeof(T));
|
||||
void GetEntry(Memory::MemorySystem& memory, std::size_t index, T& data) const {
|
||||
memory.ReadBlock(process,
|
||||
GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)),
|
||||
&data, sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -436,10 +437,10 @@ private:
|
|||
* indicating which table the entry is in.
|
||||
*/
|
||||
template <typename T>
|
||||
void SetEntry(std::size_t index, const T& data) {
|
||||
Memory::WriteBlock(process,
|
||||
GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)),
|
||||
&data, sizeof(T));
|
||||
void SetEntry(Memory::MemorySystem& memory, std::size_t index, const T& data) {
|
||||
memory.WriteBlock(process,
|
||||
GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)),
|
||||
&data, sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -478,11 +479,11 @@ private:
|
|||
* otherwise error code of the last iteration.
|
||||
*/
|
||||
template <typename FunctionObject>
|
||||
static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, VAddr crs_address,
|
||||
FunctionObject func) {
|
||||
static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, Memory::MemorySystem& memory,
|
||||
VAddr crs_address, FunctionObject func) {
|
||||
VAddr current = crs_address;
|
||||
while (current != 0) {
|
||||
CROHelper cro(current, process);
|
||||
CROHelper cro(current, process, memory);
|
||||
CASCADE_RESULT(bool next, func(cro));
|
||||
if (!next)
|
||||
break;
|
||||
|
|
|
@ -115,7 +115,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
CROHelper crs(crs_address, *process);
|
||||
CROHelper crs(crs_address, *process, system.Memory());
|
||||
crs.InitCRS();
|
||||
|
||||
result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true);
|
||||
|
@ -249,7 +249,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
|
|||
return;
|
||||
}
|
||||
|
||||
CROHelper cro(cro_address, *process);
|
||||
CROHelper cro(cro_address, *process, system.Memory());
|
||||
|
||||
result = cro.VerifyHash(cro_size, crr_address);
|
||||
if (result.IsError()) {
|
||||
|
@ -331,7 +331,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
|
|||
LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}, zero={}, cro_buffer_ptr=0x{:08X}",
|
||||
cro_address, zero, cro_buffer_ptr);
|
||||
|
||||
CROHelper cro(cro_address, *process);
|
||||
CROHelper cro(cro_address, *process, system.Memory());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
|
||||
|
@ -398,7 +398,7 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address);
|
||||
|
||||
CROHelper cro(cro_address, *process);
|
||||
CROHelper cro(cro_address, *process, system.Memory());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
|
||||
|
@ -438,7 +438,7 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address);
|
||||
|
||||
CROHelper cro(cro_address, *process);
|
||||
CROHelper cro(cro_address, *process, system.Memory());
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
|
||||
|
@ -487,7 +487,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
CROHelper crs(slot->loaded_crs, *process);
|
||||
CROHelper crs(slot->loaded_crs, *process, system.Memory());
|
||||
crs.Unrebase(true);
|
||||
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
|
@ -502,7 +502,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) {
|
|||
rb.Push(result);
|
||||
}
|
||||
|
||||
RO::RO() : ServiceFramework("ldr:ro", 2) {
|
||||
RO::RO(Core::System& system) : ServiceFramework("ldr:ro", 2), system(system) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0x000100C2, &RO::Initialize, "Initialize"},
|
||||
{0x00020082, &RO::LoadCRR, "LoadCRR"},
|
||||
|
@ -519,7 +519,7 @@ RO::RO() : ServiceFramework("ldr:ro", 2) {
|
|||
|
||||
void InstallInterfaces(Core::System& system) {
|
||||
auto& service_manager = system.ServiceManager();
|
||||
std::make_shared<RO>()->InstallAsService(service_manager);
|
||||
std::make_shared<RO>(system)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::LDR
|
||||
|
|
|
@ -18,7 +18,7 @@ struct ClientSlot : public Kernel::SessionRequestHandler::SessionDataBase {
|
|||
|
||||
class RO final : public ServiceFramework<RO, ClientSlot> {
|
||||
public:
|
||||
RO();
|
||||
explicit RO(Core::System& system);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -149,6 +149,8 @@ private:
|
|||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void Shutdown(Kernel::HLERequestContext& self);
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
|
|
@ -180,7 +180,8 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
|
|||
Kernel::KernelSystem& kernel = Core::System::GetInstance().Kernel();
|
||||
auto thread = kernel.GetThreadManager().GetCurrentThread();
|
||||
// TODO(wwylele): avoid GetPointer
|
||||
u32* cmd_buf = reinterpret_cast<u32*>(Memory::GetPointer(thread->GetCommandBufferAddress()));
|
||||
u32* cmd_buf = reinterpret_cast<u32*>(
|
||||
Core::System::GetInstance().Memory().GetPointer(thread->GetCommandBufferAddress()));
|
||||
|
||||
u32 header_code = cmd_buf[0];
|
||||
auto itr = handlers.find(header_code);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue