diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index 654625eee..dec27704f 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -3,6 +3,7 @@ using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.Loaders.Elf; using Ryujinx.Memory; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -18,6 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process private class Image { + public string Name { get; internal set; } public ulong BaseAddress { get; } public ulong Size { get; } public ulong EndAddress => BaseAddress + Size; @@ -29,6 +31,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process BaseAddress = baseAddress; Size = size; Symbols = symbols; + Name = "(unknown)"; } } @@ -241,11 +244,66 @@ namespace Ryujinx.HLE.HOS.Kernel.Process info.SubName = ""; } - info.ImageName = GetGuessedNsoNameFromIndex(imageIndex); + info.ImageName = image.Name; return true; } + private bool GetModuleName(out string moduleName, Image image) + { + moduleName = string.Empty; + + var rodataStart = image.BaseAddress + image.Size; + + KMemoryInfo roInfo = _owner.MemoryManager.QueryMemory(rodataStart); + if (roInfo.Permission != KMemoryPermission.Read) + { + return false; + } + + var rwdataStart = roInfo.Address + roInfo.Size; + + try + { + Span rodataBuf = stackalloc byte[0x208]; + _owner.CpuMemory.Read(rodataStart, rodataBuf); + + ulong deprecatedRwDataOffset = BitConverter.ToUInt64(rodataBuf); + // no name if using old format + if (image.BaseAddress + deprecatedRwDataOffset == rwdataStart) + { + return false; + } + + uint zero = BitConverter.ToUInt32(rodataBuf); + int pathLength = BitConverter.ToInt32(rodataBuf.Slice(4)); + if (zero != 0 || pathLength <= 0) + { + // try again with 12 byte offset, 20.0.0+ + _owner.CpuMemory.Read(rodataStart + 12, rodataBuf); + zero = BitConverter.ToUInt32(rodataBuf); + pathLength = BitConverter.ToInt32(rodataBuf.Slice(4)); + } + + if (zero != 0 || pathLength <= 0) + { + return false; + } + + pathLength = Math.Min(pathLength, rodataBuf.Length - 8); + var pathBuf = rodataBuf.Slice(8, pathLength); + int lastSlash = pathBuf.LastIndexOfAny(new byte[] { (byte)'\\', (byte)'/' }); + + moduleName = Encoding.ASCII.GetString(pathBuf.Slice(lastSlash + 1).TrimEnd((byte)0)); + + return true; + } + catch (InvalidMemoryRegionException) + { + return false; + } + } + private bool AnalyzePointerFromStack(out PointerInfo info, ulong address, KThread thread) { info = default; @@ -280,31 +338,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return null; } - private string GetGuessedNsoNameFromIndex(int index) - { - if ((uint)index > 11) - { - return "???"; - } - - if (index == 0) - { - return "rtld"; - } - else if (index == 1) - { - return "main"; - } - else if (index == GetImagesCount() - 1) - { - return "sdk"; - } - else - { - return "subsdk" + (index - 2); - } - } - private int GetImagesCount() { lock (_images) @@ -426,7 +459,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process lock (_images) { - _images.Add(new Image(textOffset, textSize, symbols.OrderBy(x => x.Value).ToArray())); + var image = new Image(textOffset, textSize, symbols.OrderBy(x => x.Value).ToArray()); + + string moduleName; + if (!GetModuleName(out moduleName, image)) + { + var newIndex = _images.Count; + moduleName = $"(unknown{newIndex})"; + } + image.Name = moduleName; + + _images.Add(image); } }