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)
|
lock (Blocks)
|
||||||
{
|
{
|
||||||
bool Success = CheckRange(
|
bool Success = CheckRange(
|
||||||
Dst,
|
Src,
|
||||||
Size,
|
Size,
|
||||||
MemoryState.Mask,
|
MemoryState.Mask,
|
||||||
MemoryState.CodeStatic,
|
MemoryState.Heap,
|
||||||
MemoryPermission.None,
|
MemoryPermission.None,
|
||||||
MemoryPermission.None,
|
MemoryPermission.None,
|
||||||
MemoryAttribute.Mask,
|
MemoryAttribute.Mask,
|
||||||
MemoryAttribute.None,
|
MemoryAttribute.Borrowed,
|
||||||
MemoryAttribute.IpcAndDeviceMapped,
|
MemoryAttribute.IpcAndDeviceMapped,
|
||||||
out _,
|
out _,
|
||||||
out _,
|
out _,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
Success &= CheckRange(
|
Success &= CheckRange(
|
||||||
Src,
|
Dst,
|
||||||
Size,
|
PageSize,
|
||||||
MemoryState.Mask,
|
MemoryState.UnmapProcessCodeMemoryAllowed,
|
||||||
MemoryState.Heap,
|
MemoryState.UnmapProcessCodeMemoryAllowed,
|
||||||
MemoryPermission.Mask,
|
MemoryPermission.None,
|
||||||
MemoryPermission.None,
|
MemoryPermission.None,
|
||||||
MemoryAttribute.Mask,
|
MemoryAttribute.Mask,
|
||||||
MemoryAttribute.None,
|
MemoryAttribute.None,
|
||||||
MemoryAttribute.IpcAndDeviceMapped,
|
MemoryAttribute.IpcAndDeviceMapped,
|
||||||
out _,
|
out MemoryState State,
|
||||||
out _,
|
out _,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
|
Success &= CheckRange(
|
||||||
|
Dst,
|
||||||
|
Size,
|
||||||
|
MemoryState.Mask,
|
||||||
|
State,
|
||||||
|
MemoryPermission.None,
|
||||||
|
MemoryPermission.None,
|
||||||
|
MemoryAttribute.Mask,
|
||||||
|
MemoryAttribute.None);
|
||||||
|
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
KernelResult Result = MmuUnmap(Dst, PagesCount);
|
KernelResult Result = MmuUnmap(Dst, PagesCount);
|
||||||
|
@ -1688,6 +1698,45 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return false;
|
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(
|
private void InsertBlock(
|
||||||
ulong BaseAddress,
|
ulong BaseAddress,
|
||||||
ulong PagesCount,
|
ulong PagesCount,
|
||||||
|
|
|
@ -286,7 +286,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
|
|
||||||
KMemoryManager MemMgr = Context.Process.MemoryManager;
|
KMemoryManager MemMgr = Context.Process.MemoryManager;
|
||||||
|
|
||||||
ulong TargetAddress = MemMgr.AddrSpaceStart;
|
ulong TargetAddress = MemMgr.GetAddrSpaceBaseAddr();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -400,25 +400,43 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.BadNrrAddress);
|
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)
|
foreach (NroInfo Info in NroInfos)
|
||||||
{
|
{
|
||||||
if (Info.NroMappedAddress == NroMappedAddress && Info.Executable.SourceAddress == NroHeapAddress)
|
if (Info.NroMappedAddress == NroMappedAddress)
|
||||||
{
|
{
|
||||||
NroInfos.Remove(Info);
|
NroInfos.Remove(Info);
|
||||||
|
|
||||||
KernelResult Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
ulong TextSize = (ulong)Info.Executable.Text.Length;
|
||||||
Info.NroMappedAddress,
|
ulong ROSize = (ulong)Info.Executable.RO.Length;
|
||||||
Info.Executable.SourceAddress,
|
ulong DataSize = (ulong)Info.Executable.Data.Length;
|
||||||
Info.TotalSize - (ulong)Info.Executable.BssSize);
|
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(
|
Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||||
Info.NroMappedAddress + Info.TotalSize - (ulong)Info.Executable.BssSize,
|
Info.NroMappedAddress + TextSize + ROSize + DataSize,
|
||||||
Info.Executable.BssAddress,
|
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;
|
return (long)Result;
|
||||||
|
@ -470,17 +488,19 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
{
|
{
|
||||||
long Result = MakeError(ErrorModule.Loader, LoaderErr.BadInitialization);
|
long Result = MakeError(ErrorModule.Loader, LoaderErr.BadInitialization);
|
||||||
|
|
||||||
|
// Zero
|
||||||
|
Context.RequestData.ReadUInt64();
|
||||||
|
|
||||||
ulong NroMappedAddress = Context.RequestData.ReadUInt64();
|
ulong NroMappedAddress = Context.RequestData.ReadUInt64();
|
||||||
ulong NroHeapAddress = Context.RequestData.ReadUInt64();
|
|
||||||
|
|
||||||
if (IsInitialized)
|
if (IsInitialized)
|
||||||
{
|
{
|
||||||
if ((NroMappedAddress & 0xFFF) != 0 || (NroHeapAddress & 0xFFF) != 0)
|
if ((NroMappedAddress & 0xFFF) != 0)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress);
|
return MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = RemoveNroInfo(Context, NroMappedAddress, NroHeapAddress);
|
Result = RemoveNroInfo(Context, NroMappedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue