Fix some issues with UnloadNro on ldr:ro
This commit is contained in:
parent
f20a3648de
commit
3d737dcd09
2 changed files with 91 additions and 22 deletions
|
@ -691,33 +691,43 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
lock (Blocks)
|
||||
{
|
||||
bool Success = CheckRange(
|
||||
Dst,
|
||||
Src,
|
||||
Size,
|
||||
MemoryState.Mask,
|
||||
MemoryState.CodeStatic,
|
||||
MemoryState.Heap,
|
||||
MemoryPermission.None,
|
||||
MemoryPermission.None,
|
||||
MemoryAttribute.Mask,
|
||||
MemoryAttribute.None,
|
||||
MemoryAttribute.Borrowed,
|
||||
MemoryAttribute.IpcAndDeviceMapped,
|
||||
out _,
|
||||
out _,
|
||||
out _);
|
||||
|
||||
Success &= CheckRange(
|
||||
Src,
|
||||
Size,
|
||||
MemoryState.Mask,
|
||||
MemoryState.Heap,
|
||||
MemoryPermission.Mask,
|
||||
Dst,
|
||||
PageSize,
|
||||
MemoryState.UnmapProcessCodeMemoryAllowed,
|
||||
MemoryState.UnmapProcessCodeMemoryAllowed,
|
||||
MemoryPermission.None,
|
||||
MemoryPermission.None,
|
||||
MemoryAttribute.Mask,
|
||||
MemoryAttribute.None,
|
||||
MemoryAttribute.IpcAndDeviceMapped,
|
||||
out _,
|
||||
out MemoryState State,
|
||||
out _,
|
||||
out _);
|
||||
|
||||
Success &= CheckRange(
|
||||
Dst,
|
||||
Size,
|
||||
MemoryState.Mask,
|
||||
State,
|
||||
MemoryPermission.None,
|
||||
MemoryPermission.None,
|
||||
MemoryAttribute.Mask,
|
||||
MemoryAttribute.None);
|
||||
|
||||
if (Success)
|
||||
{
|
||||
KernelResult Result = MmuUnmap(Dst, PagesCount);
|
||||
|
@ -1688,6 +1698,45 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
return false;
|
||||
}
|
||||
|
||||
private bool CheckRange(
|
||||
ulong Address,
|
||||
ulong Size,
|
||||
MemoryState StateMask,
|
||||
MemoryState StateExpected,
|
||||
MemoryPermission PermissionMask,
|
||||
MemoryPermission PermissionExpected,
|
||||
MemoryAttribute AttributeMask,
|
||||
MemoryAttribute AttributeExpected)
|
||||
{
|
||||
ulong EndAddr = Address + Size - 1;
|
||||
|
||||
LinkedListNode<KMemoryBlock> Node = FindBlockNode(Address);
|
||||
|
||||
do
|
||||
{
|
||||
KMemoryInfo Info = Node.Value.GetInfo();
|
||||
|
||||
//Check if the block state matches what we expect.
|
||||
if ((Info.State & StateMask) != StateExpected ||
|
||||
(Info.Permission & PermissionMask) != PermissionExpected ||
|
||||
(Info.Attribute & AttributeMask) != AttributeExpected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//Check if this is the last block on the range, if so return success.
|
||||
if (EndAddr <= Info.Address + Info.Size - 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Node = Node.Next;
|
||||
}
|
||||
while (Node != null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void InsertBlock(
|
||||
ulong BaseAddress,
|
||||
ulong PagesCount,
|
||||
|
|
|
@ -286,7 +286,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
|||
|
||||
KMemoryManager MemMgr = Context.Process.MemoryManager;
|
||||
|
||||
ulong TargetAddress = MemMgr.AddrSpaceStart;
|
||||
ulong TargetAddress = MemMgr.GetAddrSpaceBaseAddr();
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -400,25 +400,43 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
|||
return MakeError(ErrorModule.Loader, LoaderErr.BadNrrAddress);
|
||||
}
|
||||
|
||||
private long RemoveNroInfo(ServiceCtx Context, ulong NroMappedAddress, ulong NroHeapAddress)
|
||||
private long RemoveNroInfo(ServiceCtx Context, ulong NroMappedAddress)
|
||||
{
|
||||
foreach (NroInfo Info in NroInfos)
|
||||
{
|
||||
if (Info.NroMappedAddress == NroMappedAddress && Info.Executable.SourceAddress == NroHeapAddress)
|
||||
if (Info.NroMappedAddress == NroMappedAddress)
|
||||
{
|
||||
NroInfos.Remove(Info);
|
||||
|
||||
KernelResult Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||
Info.NroMappedAddress,
|
||||
Info.Executable.SourceAddress,
|
||||
Info.TotalSize - (ulong)Info.Executable.BssSize);
|
||||
ulong TextSize = (ulong)Info.Executable.Text.Length;
|
||||
ulong ROSize = (ulong)Info.Executable.RO.Length;
|
||||
ulong DataSize = (ulong)Info.Executable.Data.Length;
|
||||
ulong BssSize = (ulong)Info.Executable.BssSize;
|
||||
|
||||
if (Result == KernelResult.Success && Info.Executable.BssSize != 0)
|
||||
KernelResult Result = KernelResult.Success;
|
||||
|
||||
if (Info.Executable.BssSize != 0)
|
||||
{
|
||||
Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||
Info.NroMappedAddress + Info.TotalSize - (ulong)Info.Executable.BssSize,
|
||||
Info.NroMappedAddress + TextSize + ROSize + DataSize,
|
||||
Info.Executable.BssAddress,
|
||||
(ulong)Info.Executable.BssSize);
|
||||
BssSize);
|
||||
}
|
||||
|
||||
if (Result == KernelResult.Success)
|
||||
{
|
||||
Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||
Info.NroMappedAddress + TextSize + ROSize,
|
||||
Info.Executable.SourceAddress + TextSize + ROSize,
|
||||
DataSize);
|
||||
|
||||
if (Result == KernelResult.Success)
|
||||
{
|
||||
Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||
Info.NroMappedAddress,
|
||||
Info.Executable.SourceAddress,
|
||||
TextSize + ROSize);
|
||||
}
|
||||
}
|
||||
|
||||
return (long)Result;
|
||||
|
@ -470,17 +488,19 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
|||
{
|
||||
long Result = MakeError(ErrorModule.Loader, LoaderErr.BadInitialization);
|
||||
|
||||
// Zero
|
||||
Context.RequestData.ReadUInt64();
|
||||
|
||||
ulong NroMappedAddress = Context.RequestData.ReadUInt64();
|
||||
ulong NroHeapAddress = Context.RequestData.ReadUInt64();
|
||||
|
||||
if (IsInitialized)
|
||||
{
|
||||
if ((NroMappedAddress & 0xFFF) != 0 || (NroHeapAddress & 0xFFF) != 0)
|
||||
if ((NroMappedAddress & 0xFFF) != 0)
|
||||
{
|
||||
return MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress);
|
||||
}
|
||||
|
||||
Result = RemoveNroInfo(Context, NroMappedAddress, NroHeapAddress);
|
||||
Result = RemoveNroInfo(Context, NroMappedAddress);
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
|
Loading…
Add table
Reference in a new issue