Add 32 bits support to HleProcessDebugger (#859)

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
This commit is contained in:
Thog 2020-01-12 12:06:26 +01:00 committed by GitHub
parent 78f6b1d396
commit 9c8d48edff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 37 deletions

View file

@ -1,9 +1,12 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Diagnostics.Demangler; using Ryujinx.HLE.HOS.Diagnostics.Demangler;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.Loaders.Elf; using Ryujinx.HLE.Loaders.Elf;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading; 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}"); trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}");
while (framePointer != 0) if (context.IsAarch32)
{ {
if ((framePointer & 7) != 0 || long framePointer = (long)context.GetX(11);
!_owner.CpuMemory.IsMapped(framePointer) ||
!_owner.CpuMemory.IsMapped(framePointer + 8)) 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 while (framePointer != 0)
// worth of bytes to get the branch instruction address. {
AppendTrace(_owner.CpuMemory.ReadInt64(framePointer + 8) - 4); 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(); return trace.ToString();
@ -111,9 +132,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
ElfSymbol symbol = image.Symbols[middle]; 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; name = symbol.Name;
@ -242,13 +263,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
long ehHdrEndOffset = memory.ReadInt32(mod0Offset + 0x14) + mod0Offset; long ehHdrEndOffset = memory.ReadInt32(mod0Offset + 0x14) + mod0Offset;
long modObjOffset = memory.ReadInt32(mod0Offset + 0x18) + mod0Offset; long modObjOffset = memory.ReadInt32(mod0Offset + 0x18) + mod0Offset;
// TODO: Elf32. bool isAArch32 = memory.ReadUInt64(dynamicOffset) > 0xFFFFFFFF || memory.ReadUInt64(dynamicOffset + 0x10) > 0xFFFFFFFF;
while (true) while (true)
{ {
long tagVal = memory.ReadInt64(dynamicOffset + 0); long tagVal;
long value = memory.ReadInt64(dynamicOffset + 8); 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; ElfDynamicTag tag = (ElfDynamicTag)tagVal;
@ -274,7 +310,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
while ((ulong)symTblAddr < (ulong)strTblAddr) 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); 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); using (BinaryReader inputStream = new BinaryReader(new MemoryStream(memory.ReadBytes(address, Unsafe.SizeOf<ElfSymbol64>()))))
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;)
{ {
name += (char)chr; ElfSymbol64 sym = inputStream.ReadStruct<ElfSymbol64>();
}
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>()))))
{
ElfSymbol32 sym = inputStream.ReadStruct<ElfSymbol32>();
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);
}
} }
} }
} }

View file

@ -17,16 +17,16 @@ namespace Ryujinx.HLE.Loaders.Elf
Binding == ElfSymbolBinding.StbWeak; Binding == ElfSymbolBinding.StbWeak;
public int ShIdx { get; private set; } public int ShIdx { get; private set; }
public long Value { get; private set; } public ulong Value { get; private set; }
public long Size { get; private set; } public ulong Size { get; private set; }
public ElfSymbol( public ElfSymbol(
string name, string name,
int info, int info,
int other, int other,
int shIdx, int shIdx,
long value, ulong value,
long size) ulong size)
{ {
Name = name; Name = name;
Type = (ElfSymbolType)(info & 0xf); Type = (ElfSymbolType)(info & 0xf);

View file

@ -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;
}
}

View file

@ -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;
}
}