forked from Mirror/Ryujinx
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 };
|
||||
|
||||
public static uint AlignUp(uint value, int size)
|
||||
{
|
||||
return (uint)AlignUp((int)value, size);
|
||||
}
|
||||
|
||||
public static int AlignUp(int value, int size)
|
||||
{
|
||||
return (value + (size - 1)) & -size;
|
||||
|
@ -19,6 +24,11 @@ namespace Ryujinx.Common
|
|||
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)
|
||||
{
|
||||
return value & -size;
|
||||
|
|
|
@ -1072,7 +1072,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
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}.");
|
||||
|
||||
|
|
|
@ -21,16 +21,16 @@ namespace Ryujinx.HLE.HOS
|
|||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -124,35 +124,31 @@ namespace Ryujinx.HLE.HOS
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool LoadNsos(
|
||||
KernelContext context,
|
||||
Npdm metaData,
|
||||
byte[] arguments = null,
|
||||
params IExecutable[] executables)
|
||||
public static bool LoadNsos(KernelContext context, Npdm metaData, byte[] arguments = null, params IExecutable[] executables)
|
||||
{
|
||||
ulong argsStart = 0;
|
||||
int argsSize = 0;
|
||||
uint argsSize = 0;
|
||||
ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL;
|
||||
int codeSize = 0;
|
||||
uint codeSize = 0;
|
||||
|
||||
ulong[] nsoBase = new ulong[executables.Length];
|
||||
|
||||
for (int index = 0; index < executables.Length; index++)
|
||||
{
|
||||
IExecutable staticObject = executables[index];
|
||||
IExecutable nso = executables[index];
|
||||
|
||||
int textEnd = staticObject.TextOffset + staticObject.Text.Length;
|
||||
int roEnd = staticObject.RoOffset + staticObject.Ro.Length;
|
||||
int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize;
|
||||
uint textEnd = nso.TextOffset + (uint)nso.Text.Length;
|
||||
uint roEnd = nso.RoOffset + (uint)nso.Ro.Length;
|
||||
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;
|
||||
}
|
||||
|
||||
if ((uint)nsoSize < (uint)dataEnd)
|
||||
if (nsoSize < dataEnd)
|
||||
{
|
||||
nsoSize = dataEnd;
|
||||
}
|
||||
|
@ -167,16 +163,16 @@ namespace Ryujinx.HLE.HOS
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -284,7 +280,7 @@ namespace Ryujinx.HLE.HOS
|
|||
process.CpuMemory.Write(roStart, image.Ro);
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
|||
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
|
||||
context.Device.FileSystem.ModLoader.ApplyNroPatches(nro);
|
||||
|
|
|
@ -4,15 +4,15 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
{
|
||||
interface IExecutable
|
||||
{
|
||||
byte[] Program { get; }
|
||||
byte[] Program { get; }
|
||||
Span<byte> Text { get; }
|
||||
Span<byte> Ro { get; }
|
||||
Span<byte> Data { get; }
|
||||
|
||||
int TextOffset { get; }
|
||||
int RoOffset { get; }
|
||||
int DataOffset { get; }
|
||||
int BssOffset { get; }
|
||||
int BssSize { get; }
|
||||
uint TextOffset { get; }
|
||||
uint RoOffset { get; }
|
||||
uint DataOffset { get; }
|
||||
uint BssOffset { get; }
|
||||
uint BssSize { get; }
|
||||
}
|
||||
}
|
|
@ -7,19 +7,19 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
class KipExecutable : IExecutable
|
||||
{
|
||||
public byte[] Program { get; }
|
||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, TextSize);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, RoSize);
|
||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, DataSize);
|
||||
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize);
|
||||
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize);
|
||||
|
||||
public int TextOffset { get; }
|
||||
public int RoOffset { get; }
|
||||
public int DataOffset { get; }
|
||||
public int BssOffset { get; }
|
||||
public uint TextOffset { get; }
|
||||
public uint RoOffset { get; }
|
||||
public uint DataOffset { get; }
|
||||
public uint BssOffset { get; }
|
||||
|
||||
public int TextSize { get; }
|
||||
public int RoSize { get; }
|
||||
public int DataSize { get; }
|
||||
public int BssSize { get; }
|
||||
public uint TextSize { get; }
|
||||
public uint RoSize { get; }
|
||||
public uint DataSize { get; }
|
||||
public uint BssSize { get; }
|
||||
|
||||
public int[] Capabilities { get; }
|
||||
public bool UsesSecureMemory { get; }
|
||||
|
@ -38,11 +38,11 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
|
||||
reader.Initialize(inStorage).ThrowIfFailure();
|
||||
|
||||
TextOffset = reader.Segments[0].MemoryOffset;
|
||||
RoOffset = reader.Segments[1].MemoryOffset;
|
||||
DataOffset = reader.Segments[2].MemoryOffset;
|
||||
BssOffset = reader.Segments[3].MemoryOffset;
|
||||
BssSize = reader.Segments[3].Size;
|
||||
TextOffset = (uint)reader.Segments[0].MemoryOffset;
|
||||
RoOffset = (uint)reader.Segments[1].MemoryOffset;
|
||||
DataOffset = (uint)reader.Segments[2].MemoryOffset;
|
||||
BssOffset = (uint)reader.Segments[3].MemoryOffset;
|
||||
BssSize = (uint)reader.Segments[3].Size;
|
||||
|
||||
StackSize = reader.StackSize;
|
||||
|
||||
|
@ -71,15 +71,15 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
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();
|
||||
|
||||
var span = program.AsSpan().Slice(offset, uncompressedSize);
|
||||
var span = program.AsSpan().Slice((int)offset, uncompressedSize);
|
||||
|
||||
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
||||
|
||||
return uncompressedSize;
|
||||
return (uint)uncompressedSize;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,18 +7,18 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
class NroExecutable : Nro, IExecutable
|
||||
{
|
||||
public byte[] Program { get; }
|
||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, (int)Header.NroSegments[0].Size);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, (int)Header.NroSegments[1].Size);
|
||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, (int)Header.NroSegments[2].Size);
|
||||
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)Header.NroSegments[0].Size);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)Header.NroSegments[1].Size);
|
||||
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)Header.NroSegments[2].Size);
|
||||
|
||||
public int TextOffset => (int)Header.NroSegments[0].FileOffset;
|
||||
public int RoOffset => (int)Header.NroSegments[1].FileOffset;
|
||||
public int DataOffset => (int)Header.NroSegments[2].FileOffset;
|
||||
public int BssOffset => DataOffset + Data.Length;
|
||||
public int BssSize => (int)Header.BssSize;
|
||||
public uint TextOffset => Header.NroSegments[0].FileOffset;
|
||||
public uint RoOffset => Header.NroSegments[1].FileOffset;
|
||||
public uint DataOffset => Header.NroSegments[2].FileOffset;
|
||||
public uint BssOffset => DataOffset + (uint)Data.Length;
|
||||
public uint BssSize => Header.BssSize;
|
||||
|
||||
public int Mod0Offset => Start.Mod0Offset;
|
||||
public int FileSize => (int)Header.Size;
|
||||
public uint Mod0Offset => (uint)Start.Mod0Offset;
|
||||
public uint FileSize => Header.Size;
|
||||
|
||||
public ulong SourceAddress { get; private set; }
|
||||
public ulong BssAddress { get; private set; }
|
||||
|
|
|
@ -13,19 +13,19 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
class NsoExecutable : IExecutable
|
||||
{
|
||||
public byte[] Program { get; }
|
||||
public Span<byte> Text => Program.AsSpan().Slice(TextOffset, TextSize);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, RoSize);
|
||||
public Span<byte> Data => Program.AsSpan().Slice(DataOffset, DataSize);
|
||||
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize);
|
||||
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize);
|
||||
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize);
|
||||
|
||||
public int TextOffset { get; }
|
||||
public int RoOffset { get; }
|
||||
public int DataOffset { get; }
|
||||
public int BssOffset => DataOffset + Data.Length;
|
||||
public uint TextOffset { get; }
|
||||
public uint RoOffset { get; }
|
||||
public uint DataOffset { get; }
|
||||
public uint BssOffset => DataOffset + (uint)Data.Length;
|
||||
|
||||
public int TextSize { get; }
|
||||
public int RoSize { get; }
|
||||
public int DataSize { get; }
|
||||
public int BssSize { get; }
|
||||
public uint TextSize { get; }
|
||||
public uint RoSize { get; }
|
||||
public uint DataSize { get; }
|
||||
public uint BssSize { get; }
|
||||
|
||||
public string Name;
|
||||
public Buffer32 BuildId;
|
||||
|
@ -36,10 +36,10 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
|
||||
reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure();
|
||||
|
||||
TextOffset = (int)reader.Header.Segments[0].MemoryOffset;
|
||||
RoOffset = (int)reader.Header.Segments[1].MemoryOffset;
|
||||
DataOffset = (int)reader.Header.Segments[2].MemoryOffset;
|
||||
BssSize = (int)reader.Header.BssSize;
|
||||
TextOffset = reader.Header.Segments[0].MemoryOffset;
|
||||
RoOffset = reader.Header.Segments[1].MemoryOffset;
|
||||
DataOffset = reader.Header.Segments[2].MemoryOffset;
|
||||
BssSize = reader.Header.BssSize;
|
||||
|
||||
reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure();
|
||||
|
||||
|
@ -55,21 +55,21 @@ namespace Ryujinx.HLE.Loaders.Executables
|
|||
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();
|
||||
|
||||
var span = Program.AsSpan().Slice(offset, (int)uncompressedSize);
|
||||
var span = Program.AsSpan().Slice((int)offset, (int)uncompressedSize);
|
||||
|
||||
reader.ReadSegment(segmentType, span).ThrowIfFailure();
|
||||
|
||||
return (int)uncompressedSize;
|
||||
return uncompressedSize;
|
||||
}
|
||||
|
||||
private void PrintRoSectionInfo()
|
||||
{
|
||||
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();
|
||||
|
||||
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(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);
|
||||
WritableRegion GetWritableRegion(ulong va, int size);
|
||||
ref T GetRef<T>(ulong va) where T : unmanaged;
|
||||
|
|
Reference in a new issue