From 9c8d48edff8e43318550a087816542391dffea83 Mon Sep 17 00:00:00 2001 From: Thog Date: Sun, 12 Jan 2020 12:06:26 +0100 Subject: [PATCH] Add 32 bits support to HleProcessDebugger (#859) Co-authored-by: riperiperi --- .../HOS/Kernel/Process/HleProcessDebugger.cs | 121 +++++++++++++----- Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs | 8 +- Ryujinx.HLE/Loaders/Elf/ElfSymbol32.cs | 12 ++ Ryujinx.HLE/Loaders/Elf/ElfSymbol64.cs | 12 ++ 4 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 Ryujinx.HLE/Loaders/Elf/ElfSymbol32.cs create mode 100644 Ryujinx.HLE/Loaders/Elf/ElfSymbol64.cs diff --git a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index 4219eb758..75f52851d 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -1,9 +1,12 @@ using ARMeilleure.Memory; +using Ryujinx.Common; using Ryujinx.HLE.HOS.Diagnostics.Demangler; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.Loaders.Elf; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -72,25 +75,43 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - // TODO: ARM32. - long framePointer = (long)context.GetX(29); - trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}"); - while (framePointer != 0) + if (context.IsAarch32) { - if ((framePointer & 7) != 0 || - !_owner.CpuMemory.IsMapped(framePointer) || - !_owner.CpuMemory.IsMapped(framePointer + 8)) + long framePointer = (long)context.GetX(11); + + while (framePointer != 0) { - break; + if ((framePointer & 3) != 0 || + !_owner.CpuMemory.IsMapped(framePointer) || + !_owner.CpuMemory.IsMapped(framePointer + 4)) + { + break; + } + + AppendTrace(_owner.CpuMemory.ReadInt32(framePointer + 4)); + + framePointer = _owner.CpuMemory.ReadInt32(framePointer); } + } + else + { + long framePointer = (long)context.GetX(29); - // Note: This is the return address, we need to subtract one instruction - // worth of bytes to get the branch instruction address. - AppendTrace(_owner.CpuMemory.ReadInt64(framePointer + 8) - 4); + while (framePointer != 0) + { + if ((framePointer & 7) != 0 || + !_owner.CpuMemory.IsMapped(framePointer) || + !_owner.CpuMemory.IsMapped(framePointer + 8)) + { + break; + } - framePointer = _owner.CpuMemory.ReadInt64(framePointer); + AppendTrace(_owner.CpuMemory.ReadInt64(framePointer + 8)); + + framePointer = _owner.CpuMemory.ReadInt64(framePointer); + } } return trace.ToString(); @@ -111,9 +132,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process ElfSymbol symbol = image.Symbols[middle]; - long endAddr = symbol.Value + symbol.Size; + ulong endAddr = symbol.Value + symbol.Size; - if ((ulong)address >= (ulong)symbol.Value && (ulong)address < (ulong)endAddr) + if ((ulong)address >= symbol.Value && (ulong)address < endAddr) { name = symbol.Name; @@ -242,13 +263,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Process long ehHdrEndOffset = memory.ReadInt32(mod0Offset + 0x14) + mod0Offset; long modObjOffset = memory.ReadInt32(mod0Offset + 0x18) + mod0Offset; - // TODO: Elf32. + bool isAArch32 = memory.ReadUInt64(dynamicOffset) > 0xFFFFFFFF || memory.ReadUInt64(dynamicOffset + 0x10) > 0xFFFFFFFF; + while (true) { - long tagVal = memory.ReadInt64(dynamicOffset + 0); - long value = memory.ReadInt64(dynamicOffset + 8); + long tagVal; + long value; + + if (isAArch32) + { + tagVal = memory.ReadInt32(dynamicOffset + 0); + value = memory.ReadInt32(dynamicOffset + 4); + + dynamicOffset += 0x8; + } + else + { + tagVal = memory.ReadInt64(dynamicOffset + 0); + value = memory.ReadInt64(dynamicOffset + 8); + + dynamicOffset += 0x10; + } - dynamicOffset += 0x10; ElfDynamicTag tag = (ElfDynamicTag)tagVal; @@ -274,7 +310,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process while ((ulong)symTblAddr < (ulong)strTblAddr) { - ElfSymbol sym = GetSymbol(memory, symTblAddr, strTblAddr); + ElfSymbol sym = isAArch32 ? GetSymbol32(memory, symTblAddr, strTblAddr) : GetSymbol64(memory, symTblAddr, strTblAddr); symbols.Add(sym); @@ -287,23 +323,42 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - private ElfSymbol GetSymbol(MemoryManager memory, long address, long strTblAddr) + private ElfSymbol GetSymbol64(MemoryManager memory, long address, long strTblAddr) { - int nameIndex = memory.ReadInt32(address + 0); - int info = memory.ReadByte (address + 4); - int other = memory.ReadByte (address + 5); - int shIdx = memory.ReadInt16(address + 6); - long value = memory.ReadInt64(address + 8); - long size = memory.ReadInt64(address + 16); - - string name = string.Empty; - - for (int chr; (chr = memory.ReadByte(strTblAddr + nameIndex++)) != 0;) + using (BinaryReader inputStream = new BinaryReader(new MemoryStream(memory.ReadBytes(address, Unsafe.SizeOf())))) { - name += (char)chr; - } + ElfSymbol64 sym = inputStream.ReadStruct(); - return new ElfSymbol(name, info, other, shIdx, value, size); + uint nameIndex = sym.NameOffset; + + string name = string.Empty; + + for (int chr; (chr = memory.ReadByte(strTblAddr + nameIndex++)) != 0;) + { + name += (char)chr; + } + + return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size); + } + } + + private ElfSymbol GetSymbol32(MemoryManager memory, long address, long strTblAddr) + { + using (BinaryReader inputStream = new BinaryReader(new MemoryStream(memory.ReadBytes(address, Unsafe.SizeOf())))) + { + ElfSymbol32 sym = inputStream.ReadStruct(); + + uint nameIndex = sym.NameOffset; + + string name = string.Empty; + + for (int chr; (chr = memory.ReadByte(strTblAddr + nameIndex++)) != 0;) + { + name += (char)chr; + } + + return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size); + } } } } \ No newline at end of file diff --git a/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs b/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs index b655816f1..9961afe19 100644 --- a/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs +++ b/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs @@ -17,16 +17,16 @@ namespace Ryujinx.HLE.Loaders.Elf Binding == ElfSymbolBinding.StbWeak; public int ShIdx { get; private set; } - public long Value { get; private set; } - public long Size { get; private set; } + public ulong Value { get; private set; } + public ulong Size { get; private set; } public ElfSymbol( string name, int info, int other, int shIdx, - long value, - long size) + ulong value, + ulong size) { Name = name; Type = (ElfSymbolType)(info & 0xf); diff --git a/Ryujinx.HLE/Loaders/Elf/ElfSymbol32.cs b/Ryujinx.HLE/Loaders/Elf/ElfSymbol32.cs new file mode 100644 index 000000000..b7d985063 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Elf/ElfSymbol32.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.HLE.Loaders.Elf +{ + struct ElfSymbol32 + { + public uint NameOffset; + public uint ValueAddress; + public uint Size; + public char Info; + public char Other; + public ushort SectionIndex; + } +} diff --git a/Ryujinx.HLE/Loaders/Elf/ElfSymbol64.cs b/Ryujinx.HLE/Loaders/Elf/ElfSymbol64.cs new file mode 100644 index 000000000..662de1ff1 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Elf/ElfSymbol64.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.HLE.Loaders.Elf +{ + struct ElfSymbol64 + { + public uint NameOffset; + public char Info; + public char Other; + public ushort SectionIndex; + public ulong ValueAddress; + public ulong Size; + } +}