Correct type of executable sizes (#1802)
This commit is contained in:
parent
ef157bbe26
commit
19d18662ea
9 changed files with 95 additions and 77 deletions
|
@ -4,6 +4,11 @@ namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
public static uint AlignUp(uint value, int size)
|
||||||
|
{
|
||||||
|
return (uint)AlignUp((int)value, size);
|
||||||
|
}
|
||||||
|
|
||||||
public static int AlignUp(int value, int size)
|
public static int AlignUp(int value, int size)
|
||||||
{
|
{
|
||||||
return (value + (size - 1)) & -size;
|
return (value + (size - 1)) & -size;
|
||||||
|
@ -19,6 +24,11 @@ namespace Ryujinx.Common
|
||||||
return (value + (size - 1)) & -(long)size;
|
return (value + (size - 1)) & -(long)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static uint AlignDown(uint value, int size)
|
||||||
|
{
|
||||||
|
return (uint)AlignDown((int)value, size);
|
||||||
|
}
|
||||||
|
|
||||||
public static int AlignDown(int value, int size)
|
public static int AlignDown(int value, int size)
|
||||||
{
|
{
|
||||||
return value & -size;
|
return value & -size;
|
||||||
|
|
|
@ -1072,7 +1072,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
private bool InvalidAccessHandler(ulong va)
|
private bool InvalidAccessHandler(ulong va)
|
||||||
{
|
{
|
||||||
KernelStatic.GetCurrentThread().PrintGuestStackTrace();
|
KernelStatic.GetCurrentThread()?.PrintGuestStackTrace();
|
||||||
|
|
||||||
Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}.");
|
Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}.");
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,16 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public static bool LoadKip(KernelContext context, KipExecutable kip)
|
public static bool LoadKip(KernelContext context, KipExecutable kip)
|
||||||
{
|
{
|
||||||
int endOffset = kip.DataOffset + kip.Data.Length;
|
uint endOffset = kip.DataOffset + (uint)kip.Data.Length;
|
||||||
|
|
||||||
if (kip.BssSize != 0)
|
if (kip.BssSize != 0)
|
||||||
{
|
{
|
||||||
endOffset = kip.BssOffset + kip.BssSize;
|
endOffset = kip.BssOffset + kip.BssSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KMemoryManager.PageSize);
|
uint codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KMemoryManager.PageSize);
|
||||||
|
|
||||||
int codePagesCount = codeSize / KMemoryManager.PageSize;
|
int codePagesCount = (int)(codeSize / KMemoryManager.PageSize);
|
||||||
|
|
||||||
ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL;
|
ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL;
|
||||||
|
|
||||||
|
@ -124,35 +124,31 @@ namespace Ryujinx.HLE.HOS
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool LoadNsos(
|
public static bool LoadNsos(KernelContext context, Npdm metaData, byte[] arguments = null, params IExecutable[] executables)
|
||||||
KernelContext context,
|
|
||||||
Npdm metaData,
|
|
||||||
byte[] arguments = null,
|
|
||||||
params IExecutable[] executables)
|
|
||||||
{
|
{
|
||||||
ulong argsStart = 0;
|
ulong argsStart = 0;
|
||||||
int argsSize = 0;
|
uint argsSize = 0;
|
||||||
ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
|
ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
|
||||||
int codeSize = 0;
|
uint codeSize = 0;
|
||||||
|
|
||||||
ulong[] nsoBase = new ulong[executables.Length];
|
ulong[] nsoBase = new ulong[executables.Length];
|
||||||
|
|
||||||
for (int index = 0; index < executables.Length; index++)
|
for (int index = 0; index < executables.Length; index++)
|
||||||
{
|
{
|
||||||
IExecutable staticObject = executables[index];
|
IExecutable nso = executables[index];
|
||||||
|
|
||||||
int textEnd = staticObject.TextOffset + staticObject.Text.Length;
|
uint textEnd = nso.TextOffset + (uint)nso.Text.Length;
|
||||||
int roEnd = staticObject.RoOffset + staticObject.Ro.Length;
|
uint roEnd = nso.RoOffset + (uint)nso.Ro.Length;
|
||||||
int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize;
|
uint dataEnd = nso.DataOffset + (uint)nso.Data.Length + nso.BssSize;
|
||||||
|
|
||||||
int nsoSize = textEnd;
|
uint nsoSize = textEnd;
|
||||||
|
|
||||||
if ((uint)nsoSize < (uint)roEnd)
|
if (nsoSize < roEnd)
|
||||||
{
|
{
|
||||||
nsoSize = roEnd;
|
nsoSize = roEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uint)nsoSize < (uint)dataEnd)
|
if (nsoSize < dataEnd)
|
||||||
{
|
{
|
||||||
nsoSize = dataEnd;
|
nsoSize = dataEnd;
|
||||||
}
|
}
|
||||||
|
@ -167,16 +163,16 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
argsStart = (ulong)codeSize;
|
argsStart = (ulong)codeSize;
|
||||||
|
|
||||||
argsSize = BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize);
|
argsSize = (uint)BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize);
|
||||||
|
|
||||||
codeSize += argsSize;
|
codeSize += argsSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PtcProfiler.StaticCodeStart = codeStart;
|
PtcProfiler.StaticCodeStart = codeStart;
|
||||||
PtcProfiler.StaticCodeSize = codeSize;
|
PtcProfiler.StaticCodeSize = (int)codeSize;
|
||||||
|
|
||||||
int codePagesCount = codeSize / KMemoryManager.PageSize;
|
int codePagesCount = (int)(codeSize / KMemoryManager.PageSize);
|
||||||
|
|
||||||
int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize;
|
int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize;
|
||||||
|
|
||||||
|
@ -284,7 +280,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
process.CpuMemory.Write(roStart, image.Ro);
|
process.CpuMemory.Write(roStart, image.Ro);
|
||||||
process.CpuMemory.Write(dataStart, image.Data);
|
process.CpuMemory.Write(dataStart, image.Data);
|
||||||
|
|
||||||
MemoryHelper.FillWithZeros(process.CpuMemory, (long)bssStart, image.BssSize);
|
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
||||||
|
|
||||||
KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,7 +187,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.InvalidNro;
|
return ResultCode.InvalidNro;
|
||||||
}
|
}
|
||||||
|
|
||||||
int totalSize = nro.Text.Length + nro.Ro.Length + nro.Data.Length + nro.BssSize;
|
uint totalSize = (uint)nro.Text.Length + (uint)nro.Ro.Length + (uint)nro.Data.Length + nro.BssSize;
|
||||||
|
|
||||||
// Apply patches
|
// Apply patches
|
||||||
context.Device.FileSystem.ModLoader.ApplyNroPatches(nro);
|
context.Device.FileSystem.ModLoader.ApplyNroPatches(nro);
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
Span<byte> Ro { get; }
|
Span<byte> Ro { get; }
|
||||||
Span<byte> Data { get; }
|
Span<byte> Data { get; }
|
||||||
|
|
||||||
int TextOffset { get; }
|
uint TextOffset { get; }
|
||||||
int RoOffset { get; }
|
uint RoOffset { get; }
|
||||||
int DataOffset { get; }
|
uint DataOffset { get; }
|
||||||
int BssOffset { get; }
|
uint BssOffset { get; }
|
||||||
int BssSize { get; }
|
uint BssSize { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,19 +7,19 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
class KipExecutable : IExecutable
|
class KipExecutable : IExecutable
|
||||||
{
|
{
|
||||||
public byte[] Program { get; }
|
public byte[] Program { get; }
|
||||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, TextSize);
|
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize);
|
||||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, RoSize);
|
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize);
|
||||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, DataSize);
|
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize);
|
||||||
|
|
||||||
public int TextOffset { get; }
|
public uint TextOffset { get; }
|
||||||
public int RoOffset { get; }
|
public uint RoOffset { get; }
|
||||||
public int DataOffset { get; }
|
public uint DataOffset { get; }
|
||||||
public int BssOffset { get; }
|
public uint BssOffset { get; }
|
||||||
|
|
||||||
public int TextSize { get; }
|
public uint TextSize { get; }
|
||||||
public int RoSize { get; }
|
public uint RoSize { get; }
|
||||||
public int DataSize { get; }
|
public uint DataSize { get; }
|
||||||
public int BssSize { get; }
|
public uint BssSize { get; }
|
||||||
|
|
||||||
public int[] Capabilities { get; }
|
public int[] Capabilities { get; }
|
||||||
public bool UsesSecureMemory { get; }
|
public bool UsesSecureMemory { get; }
|
||||||
|
@ -38,11 +38,11 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
|
|
||||||
reader.Initialize(inStorage).ThrowIfFailure();
|
reader.Initialize(inStorage).ThrowIfFailure();
|
||||||
|
|
||||||
TextOffset = reader.Segments[0].MemoryOffset;
|
TextOffset = (uint)reader.Segments[0].MemoryOffset;
|
||||||
RoOffset = reader.Segments[1].MemoryOffset;
|
RoOffset = (uint)reader.Segments[1].MemoryOffset;
|
||||||
DataOffset = reader.Segments[2].MemoryOffset;
|
DataOffset = (uint)reader.Segments[2].MemoryOffset;
|
||||||
BssOffset = reader.Segments[3].MemoryOffset;
|
BssOffset = (uint)reader.Segments[3].MemoryOffset;
|
||||||
BssSize = reader.Segments[3].Size;
|
BssSize = (uint)reader.Segments[3].Size;
|
||||||
|
|
||||||
StackSize = reader.StackSize;
|
StackSize = reader.StackSize;
|
||||||
|
|
||||||
|
@ -71,15 +71,15 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
DataSize = DecompressSection(reader, KipReader.SegmentType.Data, DataOffset, Program);
|
DataSize = DecompressSection(reader, KipReader.SegmentType.Data, DataOffset, Program);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int DecompressSection(KipReader reader, KipReader.SegmentType segmentType, int offset, byte[] program)
|
private static uint DecompressSection(KipReader reader, KipReader.SegmentType segmentType, uint offset, byte[] program)
|
||||||
{
|
{
|
||||||
reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure();
|
reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure();
|
||||||
|
|
||||||
var span = program.AsSpan().Slice(offset, uncompressedSize);
|
var span = program.AsSpan().Slice((int)offset, uncompressedSize);
|
||||||
|
|
||||||
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
||||||
|
|
||||||
return uncompressedSize;
|
return (uint)uncompressedSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,18 +7,18 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
class NroExecutable : Nro, IExecutable
|
class NroExecutable : Nro, IExecutable
|
||||||
{
|
{
|
||||||
public byte[] Program { get; }
|
public byte[] Program { get; }
|
||||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, (int)Header.NroSegments[0].Size);
|
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)Header.NroSegments[0].Size);
|
||||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, (int)Header.NroSegments[1].Size);
|
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)Header.NroSegments[1].Size);
|
||||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, (int)Header.NroSegments[2].Size);
|
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)Header.NroSegments[2].Size);
|
||||||
|
|
||||||
public int TextOffset => (int)Header.NroSegments[0].FileOffset;
|
public uint TextOffset => Header.NroSegments[0].FileOffset;
|
||||||
public int RoOffset => (int)Header.NroSegments[1].FileOffset;
|
public uint RoOffset => Header.NroSegments[1].FileOffset;
|
||||||
public int DataOffset => (int)Header.NroSegments[2].FileOffset;
|
public uint DataOffset => Header.NroSegments[2].FileOffset;
|
||||||
public int BssOffset => DataOffset + Data.Length;
|
public uint BssOffset => DataOffset + (uint)Data.Length;
|
||||||
public int BssSize => (int)Header.BssSize;
|
public uint BssSize => Header.BssSize;
|
||||||
|
|
||||||
public int Mod0Offset => Start.Mod0Offset;
|
public uint Mod0Offset => (uint)Start.Mod0Offset;
|
||||||
public int FileSize => (int)Header.Size;
|
public uint FileSize => Header.Size;
|
||||||
|
|
||||||
public ulong SourceAddress { get; private set; }
|
public ulong SourceAddress { get; private set; }
|
||||||
public ulong BssAddress { get; private set; }
|
public ulong BssAddress { get; private set; }
|
||||||
|
|
|
@ -13,19 +13,19 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
class NsoExecutable : IExecutable
|
class NsoExecutable : IExecutable
|
||||||
{
|
{
|
||||||
public byte[] Program { get; }
|
public byte[] Program { get; }
|
||||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, TextSize);
|
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize);
|
||||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, RoSize);
|
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize);
|
||||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, DataSize);
|
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize);
|
||||||
|
|
||||||
public int TextOffset { get; }
|
public uint TextOffset { get; }
|
||||||
public int RoOffset { get; }
|
public uint RoOffset { get; }
|
||||||
public int DataOffset { get; }
|
public uint DataOffset { get; }
|
||||||
public int BssOffset => DataOffset + Data.Length;
|
public uint BssOffset => DataOffset + (uint)Data.Length;
|
||||||
|
|
||||||
public int TextSize { get; }
|
public uint TextSize { get; }
|
||||||
public int RoSize { get; }
|
public uint RoSize { get; }
|
||||||
public int DataSize { get; }
|
public uint DataSize { get; }
|
||||||
public int BssSize { get; }
|
public uint BssSize { get; }
|
||||||
|
|
||||||
public string Name;
|
public string Name;
|
||||||
public Buffer32 BuildId;
|
public Buffer32 BuildId;
|
||||||
|
@ -36,10 +36,10 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
|
|
||||||
reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure();
|
reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure();
|
||||||
|
|
||||||
TextOffset = (int)reader.Header.Segments[0].MemoryOffset;
|
TextOffset = reader.Header.Segments[0].MemoryOffset;
|
||||||
RoOffset = (int)reader.Header.Segments[1].MemoryOffset;
|
RoOffset = reader.Header.Segments[1].MemoryOffset;
|
||||||
DataOffset = (int)reader.Header.Segments[2].MemoryOffset;
|
DataOffset = reader.Header.Segments[2].MemoryOffset;
|
||||||
BssSize = (int)reader.Header.BssSize;
|
BssSize = reader.Header.BssSize;
|
||||||
|
|
||||||
reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure();
|
reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure();
|
||||||
|
|
||||||
|
@ -55,21 +55,21 @@ namespace Ryujinx.HLE.Loaders.Executables
|
||||||
PrintRoSectionInfo();
|
PrintRoSectionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, int offset)
|
private uint DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, uint offset)
|
||||||
{
|
{
|
||||||
reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure();
|
reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure();
|
||||||
|
|
||||||
var span = Program.AsSpan().Slice(offset, (int)uncompressedSize);
|
var span = Program.AsSpan().Slice((int)offset, (int)uncompressedSize);
|
||||||
|
|
||||||
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
||||||
|
|
||||||
return (int)uncompressedSize;
|
return uncompressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrintRoSectionInfo()
|
private void PrintRoSectionInfo()
|
||||||
{
|
{
|
||||||
byte[] roBuffer = Ro.ToArray();
|
byte[] roBuffer = Ro.ToArray();
|
||||||
string rawTextBuffer = Encoding.ASCII.GetString(roBuffer, 0, RoSize);
|
string rawTextBuffer = Encoding.ASCII.GetString(roBuffer, 0, (int)RoSize);
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
int zero = BitConverter.ToInt32(roBuffer, 0);
|
int zero = BitConverter.ToInt32(roBuffer, 0);
|
||||||
|
|
|
@ -13,6 +13,18 @@ namespace Ryujinx.Memory
|
||||||
void Write<T>(ulong va, T value) where T : unmanaged;
|
void Write<T>(ulong va, T value) where T : unmanaged;
|
||||||
void Write(ulong va, ReadOnlySpan<byte> data);
|
void Write(ulong va, ReadOnlySpan<byte> data);
|
||||||
|
|
||||||
|
void Fill(ulong va, ulong size, byte value)
|
||||||
|
{
|
||||||
|
const int MaxChunkSize = 1 << 30;
|
||||||
|
|
||||||
|
for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize)
|
||||||
|
{
|
||||||
|
int copySize = (int)Math.Min(MaxChunkSize, size - subOffset);
|
||||||
|
|
||||||
|
GetWritableRegion(va + subOffset, copySize).Memory.Span.Fill(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false);
|
ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false);
|
||||||
WritableRegion GetWritableRegion(ulong va, int size);
|
WritableRegion GetWritableRegion(ulong va, int size);
|
||||||
ref T GetRef<T>(ulong va) where T : unmanaged;
|
ref T GetRef<T>(ulong va) where T : unmanaged;
|
||||||
|
|
Reference in a new issue