Fix some issues with UnloadNro on ldr:ro

This commit is contained in:
gdkchan 2018-11-28 18:38:38 -03:00
parent f20a3648de
commit 3d737dcd09
2 changed files with 91 additions and 22 deletions

View file

@ -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,

View file

@ -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;