Attempt at implementing ldr:ro with new KProcess
This commit is contained in:
parent
70e42d43d3
commit
1f544bbba4
5 changed files with 193 additions and 61 deletions
|
@ -382,7 +382,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
KPageList CurrentPageList = new KPageList();
|
KPageList CurrentPageList = new KPageList();
|
||||||
|
|
||||||
AddVaRangeToPageList(CurrentPageList, Address, Address + Size);
|
AddVaRangeToPageList(CurrentPageList, Address, PagesCount);
|
||||||
|
|
||||||
if (!CurrentPageList.IsEqual(PageList))
|
if (!CurrentPageList.IsEqual(PageList))
|
||||||
{
|
{
|
||||||
|
@ -585,6 +585,62 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KernelResult MapProcessCodeMemory(ulong Dst, ulong Src, ulong Size)
|
||||||
|
{
|
||||||
|
ulong PagesCount = Size / PageSize;
|
||||||
|
|
||||||
|
lock (Blocks)
|
||||||
|
{
|
||||||
|
bool Success = CheckRange(
|
||||||
|
Src,
|
||||||
|
Size,
|
||||||
|
MemoryState.Mask,
|
||||||
|
MemoryState.Heap,
|
||||||
|
MemoryPermission.Mask,
|
||||||
|
MemoryPermission.ReadAndWrite,
|
||||||
|
MemoryAttribute.Mask,
|
||||||
|
MemoryAttribute.None,
|
||||||
|
MemoryAttribute.IpcAndDeviceMapped,
|
||||||
|
out MemoryState State,
|
||||||
|
out MemoryPermission Permission,
|
||||||
|
out _);
|
||||||
|
|
||||||
|
Success &= IsUnmapped(Dst, Size);
|
||||||
|
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
KPageList PageList = new KPageList();
|
||||||
|
|
||||||
|
AddVaRangeToPageList(PageList, Src, PagesCount);
|
||||||
|
|
||||||
|
KernelResult Result = MmuChangePermission(Src, PagesCount, MemoryPermission.None);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = MapPages(Dst, PageList, MemoryPermission.None);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
MmuChangePermission(Src, PagesCount, Permission);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertBlock(Src, PagesCount, State, MemoryPermission.None, MemoryAttribute.Borrowed);
|
||||||
|
InsertBlock(Dst, PagesCount, MemoryState.ModCodeStatic);
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidMemState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public KernelResult UnmapProcessCodeMemory(ulong Dst, ulong Src, ulong Size)
|
public KernelResult UnmapProcessCodeMemory(ulong Dst, ulong Src, ulong Size)
|
||||||
{
|
{
|
||||||
ulong PagesCount = Size / PageSize;
|
ulong PagesCount = Size / PageSize;
|
||||||
|
@ -844,7 +900,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
KPageList PageList = new KPageList();
|
KPageList PageList = new KPageList();
|
||||||
|
|
||||||
AddVaRangeToPageList(PageList, Src, Src + Size);
|
AddVaRangeToPageList(PageList, Src, PagesCount);
|
||||||
|
|
||||||
KernelResult Result = MmuChangePermission(Src, PagesCount, MemoryPermission.None);
|
KernelResult Result = MmuChangePermission(Src, PagesCount, MemoryPermission.None);
|
||||||
|
|
||||||
|
@ -954,8 +1010,8 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
KPageList SrcPageList = new KPageList();
|
KPageList SrcPageList = new KPageList();
|
||||||
KPageList DstPageList = new KPageList();
|
KPageList DstPageList = new KPageList();
|
||||||
|
|
||||||
AddVaRangeToPageList(SrcPageList, Src, Src + Size);
|
AddVaRangeToPageList(SrcPageList, Src, PagesCount);
|
||||||
AddVaRangeToPageList(DstPageList, Dst, Dst + Size);
|
AddVaRangeToPageList(DstPageList, Dst, PagesCount);
|
||||||
|
|
||||||
if (!DstPageList.IsEqual(SrcPageList))
|
if (!DstPageList.IsEqual(SrcPageList))
|
||||||
{
|
{
|
||||||
|
@ -1220,7 +1276,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
ulong BlockSize = GetSizeInRange(Info, Address, EndAddr);
|
ulong BlockSize = GetSizeInRange(Info, Address, EndAddr);
|
||||||
ulong BlockAddress = GetAddrInRange(Info, Address);
|
ulong BlockAddress = GetAddrInRange(Info, Address);
|
||||||
|
|
||||||
AddVaRangeToPageList(PageList, BlockAddress, BlockAddress + BlockSize);
|
AddVaRangeToPageList(PageList, BlockAddress, BlockSize / PageSize);
|
||||||
|
|
||||||
HeapMappedSize += BlockSize;
|
HeapMappedSize += BlockSize;
|
||||||
}
|
}
|
||||||
|
@ -1380,11 +1436,13 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return Info.Address;
|
return Info.Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddVaRangeToPageList(KPageList PageList, ulong Start, ulong End)
|
private void AddVaRangeToPageList(KPageList PageList, ulong Start, ulong PagesCount)
|
||||||
{
|
{
|
||||||
while (Start < End)
|
ulong Address = Start;
|
||||||
|
|
||||||
|
while (Address < Start + PagesCount * PageSize)
|
||||||
{
|
{
|
||||||
KernelResult Result = ConvertVaToPa(Start, out ulong Pa);
|
KernelResult Result = ConvertVaToPa(Address, out ulong Pa);
|
||||||
|
|
||||||
if (Result != KernelResult.Success)
|
if (Result != KernelResult.Success)
|
||||||
{
|
{
|
||||||
|
@ -1393,22 +1451,10 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
PageList.AddRange(Pa, 1);
|
PageList.AddRange(Pa, 1);
|
||||||
|
|
||||||
Start += PageSize;
|
Address += PageSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HleIsUnmapped(ulong Address, ulong Size)
|
|
||||||
{
|
|
||||||
bool Result = false;
|
|
||||||
|
|
||||||
lock (Blocks)
|
|
||||||
{
|
|
||||||
Result = IsUnmapped(Address, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsUnmapped(ulong Address, ulong Size)
|
private bool IsUnmapped(ulong Address, ulong Size)
|
||||||
{
|
{
|
||||||
return CheckRange(
|
return CheckRange(
|
||||||
|
|
|
@ -95,8 +95,6 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
private KernelResult AllocatePagesImpl(ulong PagesCount, bool Backwards, out KPageList PageList)
|
private KernelResult AllocatePagesImpl(ulong PagesCount, bool Backwards, out KPageList PageList)
|
||||||
{
|
{
|
||||||
Backwards = false;
|
|
||||||
|
|
||||||
PageList = new KPageList();
|
PageList = new KPageList();
|
||||||
|
|
||||||
if (BlockOrdersCount > 0)
|
if (BlockOrdersCount > 0)
|
||||||
|
|
|
@ -264,7 +264,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ulong)(Address + Size) <= (ulong)Address)
|
if (Address + Size <= Address)
|
||||||
{
|
{
|
||||||
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ulong)(Address + Size) <= (ulong)Address)
|
if (Address + Size <= Address)
|
||||||
{
|
{
|
||||||
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ulong)(Address + Size) <= (ulong)Address)
|
if (Address + Size <= Address)
|
||||||
{
|
{
|
||||||
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ulong)(Address + Size) <= (ulong)Address)
|
if (Address + Size <= Address)
|
||||||
{
|
{
|
||||||
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
if (Result != KernelResult.Success)
|
if (Result != KernelResult.Success)
|
||||||
{
|
{
|
||||||
Logger.PrintError(LogClass.Loader, $"Resource limit initialization returned error \"{Result}\".");
|
Logger.PrintError(LogClass.Loader, $"Process initialization failed setting resource limit values.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -128,9 +128,18 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
MemoryHelper.FillWithZeros(Process.CpuMemory, (long)BssStart, (int)(BssEnd - BssStart));
|
MemoryHelper.FillWithZeros(Process.CpuMemory, (long)BssStart, (int)(BssEnd - BssStart));
|
||||||
|
|
||||||
Process.MemoryManager.SetProcessMemoryPermission(TextStart, ROStart - TextStart, MemoryPermission.ReadAndExecute);
|
KMemoryManager MemMgr = Process.MemoryManager;
|
||||||
Process.MemoryManager.SetProcessMemoryPermission(ROStart, DataStart - ROStart, MemoryPermission.Read);
|
|
||||||
Process.MemoryManager.SetProcessMemoryPermission(DataStart, BssEnd - DataStart, MemoryPermission.ReadAndWrite);
|
Result = MemMgr.SetProcessMemoryPermission(TextStart, ROStart - TextStart, MemoryPermission.ReadAndExecute);
|
||||||
|
Result |= MemMgr.SetProcessMemoryPermission(ROStart, DataStart - ROStart, MemoryPermission.Read);
|
||||||
|
Result |= MemMgr.SetProcessMemoryPermission(DataStart, BssEnd - DataStart, MemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
Logger.PrintError(LogClass.Loader, $"Process initialization failed setting memory permissions.");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = Process.Start(MetaData.MainThreadPriority, (ulong)MetaData.MainThreadStackSize);
|
Result = Process.Start(MetaData.MainThreadPriority, (ulong)MetaData.MainThreadStackSize);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
using Ryujinx.HLE.Utilities;
|
using Ryujinx.HLE.Utilities;
|
||||||
|
@ -63,16 +65,31 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
|
|
||||||
class NroInfo
|
class NroInfo
|
||||||
{
|
{
|
||||||
public NxRelocatableObject Executable { get; private set; }
|
public NxRelocatableObject Executable { get; private set; }
|
||||||
|
|
||||||
public byte[] Hash { get; private set; }
|
public byte[] Hash { get; private set; }
|
||||||
public ulong NroAddress { get; private set; }
|
public ulong NroAddress { get; private set; }
|
||||||
|
public ulong NroSize { get; private set; }
|
||||||
|
public ulong BssAddress { get; private set; }
|
||||||
|
public ulong BssSize { get; private set; }
|
||||||
public ulong TotalSize { get; private set; }
|
public ulong TotalSize { get; private set; }
|
||||||
public ulong NroMappedAddress { get; set; }
|
public ulong NroMappedAddress { get; set; }
|
||||||
|
|
||||||
public NroInfo(NxRelocatableObject Executable, byte[] Hash, ulong TotalSize)
|
public NroInfo(
|
||||||
|
NxRelocatableObject Executable,
|
||||||
|
byte[] Hash,
|
||||||
|
ulong NroAddress,
|
||||||
|
ulong NroSize,
|
||||||
|
ulong BssAddress,
|
||||||
|
ulong BssSize,
|
||||||
|
ulong TotalSize)
|
||||||
{
|
{
|
||||||
this.Executable = Executable;
|
this.Executable = Executable;
|
||||||
this.Hash = Hash;
|
this.Hash = Hash;
|
||||||
|
this.NroAddress = NroAddress;
|
||||||
|
this.NroSize = NroSize;
|
||||||
|
this.BssAddress = BssAddress;
|
||||||
|
this.BssSize = BssSize;
|
||||||
this.TotalSize = TotalSize;
|
this.TotalSize = TotalSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +192,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ParseNro(out NroInfo Res, ServiceCtx Context, ulong NroHeapAddress, ulong NroSize, ulong BssHeapAddress, ulong BssSize)
|
public long ParseNro(out NroInfo Res, ServiceCtx Context, ulong NroAddress, ulong NroSize, ulong BssAddress, ulong BssSize)
|
||||||
{
|
{
|
||||||
Res = null;
|
Res = null;
|
||||||
|
|
||||||
|
@ -183,28 +200,28 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.MaxNro);
|
return MakeError(ErrorModule.Loader, LoaderErr.MaxNro);
|
||||||
}
|
}
|
||||||
else if (NroSize == 0 || NroHeapAddress + NroSize <= NroHeapAddress || (NroSize & 0xFFF) != 0)
|
else if (NroSize == 0 || NroAddress + NroSize <= NroAddress || (NroSize & 0xFFF) != 0)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.BadSize);
|
return MakeError(ErrorModule.Loader, LoaderErr.BadSize);
|
||||||
}
|
}
|
||||||
else if (BssSize != 0 && (BssHeapAddress + BssSize) <= BssHeapAddress)
|
else if (BssSize != 0 && (BssAddress + BssSize) <= BssAddress)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.BadSize);
|
return MakeError(ErrorModule.Loader, LoaderErr.BadSize);
|
||||||
}
|
}
|
||||||
else if ((NroHeapAddress & 0xFFF) != 0)
|
else if ((NroAddress & 0xFFF) != 0)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress);
|
return MakeError(ErrorModule.Loader, LoaderErr.UnalignedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Magic = Context.Memory.ReadUInt32((long)NroHeapAddress + 0x10);
|
uint Magic = Context.Memory.ReadUInt32((long)NroAddress + 0x10);
|
||||||
uint NroFileSize = Context.Memory.ReadUInt32((long)NroHeapAddress + 0x18);
|
uint NroFileSize = Context.Memory.ReadUInt32((long)NroAddress + 0x18);
|
||||||
|
|
||||||
if (Magic != NroMagic || NroSize != NroFileSize)
|
if (Magic != NroMagic || NroSize != NroFileSize)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.InvalidNro);
|
return MakeError(ErrorModule.Loader, LoaderErr.InvalidNro);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] NroData = Context.Memory.ReadBytes((long)NroHeapAddress, (long)NroSize);
|
byte[] NroData = Context.Memory.ReadBytes((long)NroAddress, (long)NroSize);
|
||||||
byte[] NroHash = null;
|
byte[] NroHash = null;
|
||||||
|
|
||||||
MemoryStream Stream = new MemoryStream(NroData);
|
MemoryStream Stream = new MemoryStream(NroData);
|
||||||
|
@ -226,7 +243,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
|
|
||||||
Stream.Position = 0;
|
Stream.Position = 0;
|
||||||
|
|
||||||
NxRelocatableObject Executable = new NxRelocatableObject(Stream, NroHeapAddress, BssHeapAddress);
|
NxRelocatableObject Executable = new NxRelocatableObject(Stream, NroAddress, BssAddress);
|
||||||
|
|
||||||
// check if everything is page align.
|
// check if everything is page align.
|
||||||
if ((Executable.Text.Length & 0xFFF) != 0 || (Executable.RO.Length & 0xFFF) != 0 ||
|
if ((Executable.Text.Length & 0xFFF) != 0 || (Executable.RO.Length & 0xFFF) != 0 ||
|
||||||
|
@ -251,7 +268,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
|
|
||||||
int TotalSize = Executable.Text.Length + Executable.RO.Length + Executable.Data.Length + Executable.BssSize;
|
int TotalSize = Executable.Text.Length + Executable.RO.Length + Executable.Data.Length + Executable.BssSize;
|
||||||
|
|
||||||
Res = new NroInfo(Executable, NroHash, (ulong)TotalSize);
|
Res = new NroInfo(
|
||||||
|
Executable,
|
||||||
|
NroHash,
|
||||||
|
NroAddress,
|
||||||
|
NroSize,
|
||||||
|
BssAddress,
|
||||||
|
BssSize,
|
||||||
|
(ulong)TotalSize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -260,36 +284,58 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
{
|
{
|
||||||
NroMappedAddress = 0;
|
NroMappedAddress = 0;
|
||||||
|
|
||||||
ulong TargetAddress = Context.Process.MemoryManager.AddrSpaceStart;
|
KMemoryManager MemMgr = Context.Process.MemoryManager;
|
||||||
|
|
||||||
ulong HeapRegionStart = Context.Process.MemoryManager.HeapRegionStart;
|
ulong TargetAddress = MemMgr.AddrSpaceStart;
|
||||||
ulong HeapRegionEnd = Context.Process.MemoryManager.HeapRegionEnd;
|
|
||||||
|
|
||||||
ulong MapRegionStart = Context.Process.MemoryManager.AliasRegionStart;
|
|
||||||
ulong MapRegionEnd = Context.Process.MemoryManager.AliasRegionEnd;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (TargetAddress + Info.TotalSize >= Context.Process.MemoryManager.AddrSpaceEnd)
|
if (TargetAddress + Info.TotalSize >= MemMgr.AddrSpaceEnd)
|
||||||
{
|
{
|
||||||
return MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState);
|
return MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidAddress = !(HeapRegionStart > 0 && HeapRegionStart <= TargetAddress + Info.TotalSize - 1
|
KMemoryInfo MemInfo = MemMgr.QueryMemory(TargetAddress);
|
||||||
&& TargetAddress <= HeapRegionEnd - 1)
|
|
||||||
&& !(MapRegionStart > 0
|
|
||||||
&& MapRegionStart <= TargetAddress + Info.TotalSize - 1
|
|
||||||
&& TargetAddress <= MapRegionEnd - 1);
|
|
||||||
|
|
||||||
if (IsValidAddress && Context.Process.MemoryManager.HleIsUnmapped(TargetAddress, Info.TotalSize))
|
if (MemInfo.State == MemoryState.Unmapped && MemInfo.Size >= Info.TotalSize)
|
||||||
{
|
{
|
||||||
break;
|
if (!MemMgr.InsideHeapRegion (TargetAddress, Info.TotalSize) &&
|
||||||
|
!MemMgr.InsideAliasRegion(TargetAddress, Info.TotalSize))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetAddress += 0x1000;
|
TargetAddress += MemInfo.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Context.Process.LoadProgram(Info.Executable, TargetAddress);
|
KernelResult Result = MemMgr.MapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
return MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong BssTargetAddress = TargetAddress + Info.NroSize;
|
||||||
|
|
||||||
|
Result = MemMgr.MapProcessCodeMemory(BssTargetAddress, Info.BssAddress, Info.BssSize);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
MemMgr.UnmapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);
|
||||||
|
|
||||||
|
return MakeError(ErrorModule.Loader, LoaderErr.InvalidMemoryState);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = LoadNroIntoMemory(Context.Process, Info.Executable, TargetAddress);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
MemMgr.UnmapProcessCodeMemory(TargetAddress, Info.NroAddress, Info.NroSize);
|
||||||
|
MemMgr.UnmapProcessCodeMemory(BssTargetAddress, Info.BssAddress, Info.BssSize);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Info.NroMappedAddress = TargetAddress;
|
Info.NroMappedAddress = TargetAddress;
|
||||||
NroMappedAddress = TargetAddress;
|
NroMappedAddress = TargetAddress;
|
||||||
|
@ -297,6 +343,41 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KernelResult LoadNroIntoMemory(KProcess Process, IExecutable RelocatableObject, ulong BaseAddress)
|
||||||
|
{
|
||||||
|
ulong TextStart = BaseAddress + (ulong)RelocatableObject.TextOffset;
|
||||||
|
ulong ROStart = BaseAddress + (ulong)RelocatableObject.ROOffset;
|
||||||
|
ulong DataStart = BaseAddress + (ulong)RelocatableObject.DataOffset;
|
||||||
|
|
||||||
|
ulong BssStart = DataStart + (ulong)RelocatableObject.Data.Length;
|
||||||
|
|
||||||
|
ulong BssEnd = BitUtils.AlignUp(BssStart + (ulong)RelocatableObject.BssSize, KMemoryManager.PageSize);
|
||||||
|
|
||||||
|
Process.CpuMemory.WriteBytes((long)TextStart, RelocatableObject.Text);
|
||||||
|
Process.CpuMemory.WriteBytes((long)ROStart, RelocatableObject.RO);
|
||||||
|
Process.CpuMemory.WriteBytes((long)DataStart, RelocatableObject.Data);
|
||||||
|
|
||||||
|
MemoryHelper.FillWithZeros(Process.CpuMemory, (long)BssStart, (int)(BssEnd - BssStart));
|
||||||
|
|
||||||
|
KernelResult Result;
|
||||||
|
|
||||||
|
Result = Process.MemoryManager.SetProcessMemoryPermission(TextStart, ROStart - TextStart, MemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = Process.MemoryManager.SetProcessMemoryPermission(ROStart, DataStart - ROStart, MemoryPermission.Read);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Process.MemoryManager.SetProcessMemoryPermission(DataStart, BssEnd - DataStart, MemoryPermission.ReadAndWrite);
|
||||||
|
}
|
||||||
|
|
||||||
private long RemoveNrrInfo(long NrrAddress)
|
private long RemoveNrrInfo(long NrrAddress)
|
||||||
{
|
{
|
||||||
foreach (NrrInfo Info in NrrInfos)
|
foreach (NrrInfo Info in NrrInfos)
|
||||||
|
@ -320,8 +401,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
|
||||||
{
|
{
|
||||||
NroInfos.Remove(Info);
|
NroInfos.Remove(Info);
|
||||||
|
|
||||||
//Context.Process.RemoveProgram(Info.NroMappedAddress);
|
|
||||||
|
|
||||||
KernelResult Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
KernelResult Result = Context.Process.MemoryManager.UnmapProcessCodeMemory(
|
||||||
Info.NroMappedAddress,
|
Info.NroMappedAddress,
|
||||||
Info.Executable.SourceAddress,
|
Info.Executable.SourceAddress,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue