diff --git a/src/SharpEmu.Libs/Kernel/KernelExports.cs b/src/SharpEmu.Libs/Kernel/KernelExports.cs index cba3c7e..40d1139 100644 --- a/src/SharpEmu.Libs/Kernel/KernelExports.cs +++ b/src/SharpEmu.Libs/Kernel/KernelExports.cs @@ -52,14 +52,7 @@ public static class KernelExports ExportName = "exit", Target = Generation.Gen4 | Generation.Gen5, LibraryName = "libKernel")] - public static int Exit(CpuContext ctx) - { - var status = unchecked((int)ctx[CpuRegister.Rdi]); - Console.Error.WriteLine($"[LOADER][INFO] exit(status={status})"); - GuestThreadExecution.RequestCurrentEntryExit("exit", status); - ctx[CpuRegister.Rax] = unchecked((ulong)status); - return (int)OrbisGen2Result.ORBIS_GEN2_OK; - } + public static int Exit(CpuContext ctx) => RequestProcessExit(ctx, "exit"); [SysAbiExport( Nid = "XKRegsFpEpk", @@ -172,11 +165,7 @@ public static class KernelExports ExportName = "_exit", Target = Generation.Gen4 | Generation.Gen5, LibraryName = "libKernel")] - public static int UnderscoreExit(CpuContext ctx) - { - _ = ctx; - return (int)OrbisGen2Result.ORBIS_GEN2_OK; - } + public static int UnderscoreExit(CpuContext ctx) => RequestProcessExit(ctx, "_exit"); [SysAbiExport( Nid = "Ac86z8q7T8A", @@ -437,4 +426,13 @@ public static class KernelExports { return string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_PTHREADS"), "1", StringComparison.Ordinal); } + + private static int RequestProcessExit(CpuContext ctx, string syscallName) + { + var status = unchecked((int)ctx[CpuRegister.Rdi]); + Console.Error.WriteLine($"[LOADER][INFO] {syscallName}(status={status})"); + GuestThreadExecution.RequestCurrentEntryExit(syscallName, status); + ctx[CpuRegister.Rax] = unchecked((ulong)status); + return (int)OrbisGen2Result.ORBIS_GEN2_OK; + } } diff --git a/src/SharpEmu.Libs/Kernel/KernelRuntimeCompatExports.cs b/src/SharpEmu.Libs/Kernel/KernelRuntimeCompatExports.cs index ceb4d3c..0b6efaa 100644 --- a/src/SharpEmu.Libs/Kernel/KernelRuntimeCompatExports.cs +++ b/src/SharpEmu.Libs/Kernel/KernelRuntimeCompatExports.cs @@ -1469,26 +1469,42 @@ public static class KernelRuntimeCompatExports return false; } - var bytes = new List(Math.Min(maxLength, 64)); - Span one = stackalloc byte[1]; - for (var i = 0; i < maxLength; i++) + const int pageSize = 4096; + const int inlineChunkSize = 64; + Span buffer = stackalloc byte[Math.Min(maxLength, 512)]; + var length = 0; + + for (var offset = 0; offset < maxLength && length < buffer.Length;) { - if (!ctx.Memory.TryRead(address + (ulong)i, one)) + var current = address + (ulong)offset; + var pageRemaining = pageSize - (int)(current & (pageSize - 1)); + var chunkSize = Math.Min( + buffer.Length - length, + Math.Min(maxLength - offset, Math.Min(inlineChunkSize, pageRemaining))); + + if (chunkSize <= 0) { return false; } - if (one[0] == 0) + var chunk = buffer.Slice(length, chunkSize); + if (!ctx.Memory.TryRead(current, chunk)) { - value = Encoding.UTF8.GetString(bytes.ToArray()); + return false; + } + + var nulIndex = chunk.IndexOf((byte)0); + if (nulIndex >= 0) + { + value = Encoding.UTF8.GetString(buffer[..(length + nulIndex)]); return true; } - bytes.Add(one[0]); + length += chunkSize; + offset += chunkSize; } - value = Encoding.UTF8.GetString(bytes.ToArray()); - return true; + return false; } private static ulong GetTlsScratchAddress(CpuContext ctx, ulong offset)