32-bit debugger support
This commit is contained in:
parent
bca3939a65
commit
20e5eeb39e
7 changed files with 323 additions and 46 deletions
|
@ -51,30 +51,14 @@ namespace Ryujinx.HLE.Debugger
|
|||
private KThread[] GetThreads() => DebugProcess.GetThreadUids().Select(x => DebugProcess.GetThread(x)).ToArray();
|
||||
private KernelContext KernelContext => Device.System.KernelContext;
|
||||
|
||||
const int GdbRegisterCount = 68;
|
||||
const int GdbRegisterCount64 = 68;
|
||||
const int GdbRegisterCount32 = 66;
|
||||
/* FPCR = FPSR & ~FpcrMask
|
||||
All of FPCR's bits are reserved in FPCR and vice versa,
|
||||
see ARM's documentation. */
|
||||
private const uint FpcrMask = 0xfc1fffff;
|
||||
|
||||
private int GdbRegisterHexSize(int gdbRegId)
|
||||
{
|
||||
switch (gdbRegId)
|
||||
{
|
||||
case >= 0 and <= 31:
|
||||
return 16;
|
||||
case 32:
|
||||
return 16;
|
||||
case 33:
|
||||
return 8;
|
||||
case >= 34 and <= 65:
|
||||
return 32;
|
||||
case 66:
|
||||
return 8;
|
||||
case 67:
|
||||
return 8;
|
||||
default:
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private string GdbReadRegister(IExecutionContext state, int gdbRegId)
|
||||
private string GdbReadRegister64(IExecutionContext state, int gdbRegId)
|
||||
{
|
||||
switch (gdbRegId)
|
||||
{
|
||||
|
@ -95,7 +79,7 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
private bool GdbWriteRegister(IExecutionContext state, int gdbRegId, StringStream ss)
|
||||
private bool GdbWriteRegister64(IExecutionContext state, int gdbRegId, StringStream ss)
|
||||
{
|
||||
switch (gdbRegId)
|
||||
{
|
||||
|
@ -107,7 +91,7 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
case 32:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(8);
|
||||
ulong value = ss.ReadLengthAsHex(16);
|
||||
state.DebugPc = value;
|
||||
return true;
|
||||
}
|
||||
|
@ -141,6 +125,83 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
private string GdbReadRegister32(IExecutionContext state, int gdbRegId)
|
||||
{
|
||||
switch (gdbRegId)
|
||||
{
|
||||
case >= 0 and <= 14:
|
||||
return ToHex(BitConverter.GetBytes((uint)state.GetX(gdbRegId)));
|
||||
case 15:
|
||||
return ToHex(BitConverter.GetBytes((uint)state.DebugPc));
|
||||
case 16:
|
||||
return ToHex(BitConverter.GetBytes((uint)state.Pstate));
|
||||
case >= 17 and <= 32:
|
||||
return ToHex(state.GetV(gdbRegId - 17).ToArray());
|
||||
case >= 33 and <= 64:
|
||||
int reg = (gdbRegId - 33);
|
||||
int n = reg / 2;
|
||||
int shift = reg % 2;
|
||||
ulong value = state.GetV(n).Extract<ulong>(shift);
|
||||
return ToHex(BitConverter.GetBytes(value));
|
||||
case 65:
|
||||
uint fpscr = (uint)state.Fpsr | (uint)state.Fpcr;
|
||||
return ToHex(BitConverter.GetBytes(fpscr));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool GdbWriteRegister32(IExecutionContext state, int gdbRegId, StringStream ss)
|
||||
{
|
||||
switch (gdbRegId)
|
||||
{
|
||||
case >= 0 and <= 14:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(8);
|
||||
state.SetX(gdbRegId, value);
|
||||
return true;
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(8);
|
||||
state.DebugPc = value;
|
||||
return true;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(8);
|
||||
state.Pstate = (uint)value;
|
||||
return true;
|
||||
}
|
||||
case >= 17 and <= 32:
|
||||
{
|
||||
ulong value0 = ss.ReadLengthAsHex(16);
|
||||
ulong value1 = ss.ReadLengthAsHex(16);
|
||||
state.SetV(gdbRegId - 17, new V128(value0, value1));
|
||||
return true;
|
||||
}
|
||||
case >= 33 and <= 64:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(16);
|
||||
int regId = (gdbRegId - 33);
|
||||
int regNum = regId / 2;
|
||||
int shift = regId % 2;
|
||||
V128 reg = state.GetV(regNum);
|
||||
reg.Insert(shift, value);
|
||||
return true;
|
||||
}
|
||||
case 65:
|
||||
{
|
||||
ulong value = ss.ReadLengthAsHex(8);
|
||||
state.Fpsr = (uint)value & FpcrMask;
|
||||
state.Fpcr = (uint)value & ~FpcrMask;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MessageHandlerMain()
|
||||
{
|
||||
while (!_shuttingDown)
|
||||
|
@ -266,16 +327,32 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
|
||||
if (ss.ConsumeRemaining("HostInfo"))
|
||||
{
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
Reply(
|
||||
$"triple:{ToHex("arm-unknown-linux-android")};endian:little;ptrsize:4;hostname:{ToHex("Ryujinx")};");
|
||||
}
|
||||
else
|
||||
{
|
||||
Reply(
|
||||
$"triple:{ToHex("aarch64-unknown-linux-android")};endian:little;ptrsize:8;hostname:{ToHex("Ryujinx")};");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ss.ConsumeRemaining("ProcessInfo"))
|
||||
{
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
Reply(
|
||||
$"pid:1;cputype:12;cpusubtype:0;triple:{ToHex("arm-unknown-linux-android")};ostype:unknown;vendor:none;endian:little;ptrsize:4;");
|
||||
}
|
||||
else
|
||||
{
|
||||
Reply(
|
||||
$"pid:1;cputype:100000c;cpusubtype:0;triple:{ToHex("aarch64-unknown-linux-android")};ostype:unknown;vendor:none;endian:little;ptrsize:8;");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -323,6 +400,11 @@ namespace Ryujinx.HLE.Debugger
|
|||
ulong addr = ss.ReadUntilAsHex(',');
|
||||
ulong len = ss.ReadRemainingAsHex();
|
||||
|
||||
if (feature == "target.xml")
|
||||
{
|
||||
feature = IsProcessAarch32() ? "target32.xml" : "target64.xml";
|
||||
}
|
||||
|
||||
string data;
|
||||
if (RegisterInformation.Features.TryGetValue(feature, out data))
|
||||
{
|
||||
|
@ -410,9 +492,19 @@ namespace Ryujinx.HLE.Debugger
|
|||
|
||||
var ctx = DebugProcess.GetThread(gThread.Value).Context;
|
||||
string registers = "";
|
||||
for (int i = 0; i < GdbRegisterCount; i++)
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
registers += GdbReadRegister(ctx, i);
|
||||
for (int i = 0; i < GdbRegisterCount32; i++)
|
||||
{
|
||||
registers += GdbReadRegister32(ctx, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < GdbRegisterCount64; i++)
|
||||
{
|
||||
registers += GdbReadRegister64(ctx, i);
|
||||
}
|
||||
}
|
||||
|
||||
Reply(registers);
|
||||
|
@ -427,14 +519,28 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
|
||||
var ctx = DebugProcess.GetThread(gThread.Value).Context;
|
||||
for (int i = 0; i < GdbRegisterCount; i++)
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
if (!GdbWriteRegister(ctx, i, ss))
|
||||
for (int i = 0; i < GdbRegisterCount32; i++)
|
||||
{
|
||||
if (!GdbWriteRegister32(ctx, i, ss))
|
||||
{
|
||||
ReplyError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < GdbRegisterCount64; i++)
|
||||
{
|
||||
if (!GdbWriteRegister64(ctx, i, ss))
|
||||
{
|
||||
ReplyError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ss.IsEmpty())
|
||||
{
|
||||
|
@ -512,7 +618,10 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
|
||||
var ctx = DebugProcess.GetThread(gThread.Value).Context;
|
||||
string result = GdbReadRegister(ctx, gdbRegId);
|
||||
string result;
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
result = GdbReadRegister32(ctx, gdbRegId);
|
||||
if (result != null)
|
||||
{
|
||||
Reply(result);
|
||||
|
@ -522,6 +631,19 @@ namespace Ryujinx.HLE.Debugger
|
|||
ReplyError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GdbReadRegister64(ctx, gdbRegId);
|
||||
if (result != null)
|
||||
{
|
||||
Reply(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandWriteRegister(int gdbRegId, StringStream ss)
|
||||
{
|
||||
|
@ -532,7 +654,9 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
|
||||
var ctx = DebugProcess.GetThread(gThread.Value).Context;
|
||||
if (GdbWriteRegister(ctx, gdbRegId, ss) && ss.IsEmpty())
|
||||
if (IsProcessAarch32())
|
||||
{
|
||||
if (GdbWriteRegister32(ctx, gdbRegId, ss) && ss.IsEmpty())
|
||||
{
|
||||
ReplyOK();
|
||||
}
|
||||
|
@ -541,6 +665,18 @@ namespace Ryujinx.HLE.Debugger
|
|||
ReplyError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GdbWriteRegister64(ctx, gdbRegId, ss) && ss.IsEmpty())
|
||||
{
|
||||
ReplyOK();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CommandStep(ulong? newPc)
|
||||
{
|
||||
|
@ -675,6 +811,11 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
private bool IsProcessAarch32()
|
||||
{
|
||||
return DebugProcess.GetThread(gThread.Value).Context.IsAarch32;
|
||||
}
|
||||
|
||||
private byte CalculateChecksum(string cmd)
|
||||
{
|
||||
byte checksum = 0;
|
||||
|
|
27
src/Ryujinx.HLE/Debugger/GdbXml/arm-core.xml
Normal file
27
src/Ryujinx.HLE/Debugger/GdbXml/arm-core.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.arm.core">
|
||||
<reg name="r0" bitsize="32"/>
|
||||
<reg name="r1" bitsize="32"/>
|
||||
<reg name="r2" bitsize="32"/>
|
||||
<reg name="r3" bitsize="32"/>
|
||||
<reg name="r4" bitsize="32"/>
|
||||
<reg name="r5" bitsize="32"/>
|
||||
<reg name="r6" bitsize="32"/>
|
||||
<reg name="r7" bitsize="32"/>
|
||||
<reg name="r8" bitsize="32"/>
|
||||
<reg name="r9" bitsize="32"/>
|
||||
<reg name="r10" bitsize="32"/>
|
||||
<reg name="r11" bitsize="32"/>
|
||||
<reg name="r12" bitsize="32"/>
|
||||
<reg name="sp" bitsize="32" type="data_ptr"/>
|
||||
<reg name="lr" bitsize="32"/>
|
||||
<reg name="pc" bitsize="32" type="code_ptr"/>
|
||||
<reg name="cpsr" bitsize="32" />
|
||||
</feature>
|
86
src/Ryujinx.HLE/Debugger/GdbXml/arm-neon.xml
Normal file
86
src/Ryujinx.HLE/Debugger/GdbXml/arm-neon.xml
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.arm.vfp">
|
||||
<vector id="neon_uint8x8" type="uint8" count="8"/>
|
||||
<vector id="neon_uint16x4" type="uint16" count="4"/>
|
||||
<vector id="neon_uint32x2" type="uint32" count="2"/>
|
||||
<vector id="neon_float32x2" type="ieee_single" count="2"/>
|
||||
<union id="neon_d">
|
||||
<field name="u8" type="neon_uint8x8"/>
|
||||
<field name="u16" type="neon_uint16x4"/>
|
||||
<field name="u32" type="neon_uint32x2"/>
|
||||
<field name="u64" type="uint64"/>
|
||||
<field name="f32" type="neon_float32x2"/>
|
||||
<field name="f64" type="ieee_double"/>
|
||||
</union>
|
||||
<vector id="neon_uint8x16" type="uint8" count="16"/>
|
||||
<vector id="neon_uint16x8" type="uint16" count="8"/>
|
||||
<vector id="neon_uint32x4" type="uint32" count="4"/>
|
||||
<vector id="neon_uint64x2" type="uint64" count="2"/>
|
||||
<vector id="neon_float32x4" type="ieee_single" count="4"/>
|
||||
<vector id="neon_float64x2" type="ieee_double" count="2"/>
|
||||
<union id="neon_q">
|
||||
<field name="u8" type="neon_uint8x16"/>
|
||||
<field name="u16" type="neon_uint16x8"/>
|
||||
<field name="u32" type="neon_uint32x4"/>
|
||||
<field name="u64" type="neon_uint64x2"/>
|
||||
<field name="f32" type="neon_float32x4"/>
|
||||
<field name="f64" type="neon_float64x2"/>
|
||||
</union>
|
||||
<reg name="d0" bitsize="64" type="neon_d"/>
|
||||
<reg name="d1" bitsize="64" type="neon_d"/>
|
||||
<reg name="d2" bitsize="64" type="neon_d"/>
|
||||
<reg name="d3" bitsize="64" type="neon_d"/>
|
||||
<reg name="d4" bitsize="64" type="neon_d"/>
|
||||
<reg name="d5" bitsize="64" type="neon_d"/>
|
||||
<reg name="d6" bitsize="64" type="neon_d"/>
|
||||
<reg name="d7" bitsize="64" type="neon_d"/>
|
||||
<reg name="d8" bitsize="64" type="neon_d"/>
|
||||
<reg name="d9" bitsize="64" type="neon_d"/>
|
||||
<reg name="d10" bitsize="64" type="neon_d"/>
|
||||
<reg name="d11" bitsize="64" type="neon_d"/>
|
||||
<reg name="d12" bitsize="64" type="neon_d"/>
|
||||
<reg name="d13" bitsize="64" type="neon_d"/>
|
||||
<reg name="d14" bitsize="64" type="neon_d"/>
|
||||
<reg name="d15" bitsize="64" type="neon_d"/>
|
||||
<reg name="d16" bitsize="64" type="neon_d"/>
|
||||
<reg name="d17" bitsize="64" type="neon_d"/>
|
||||
<reg name="d18" bitsize="64" type="neon_d"/>
|
||||
<reg name="d19" bitsize="64" type="neon_d"/>
|
||||
<reg name="d20" bitsize="64" type="neon_d"/>
|
||||
<reg name="d21" bitsize="64" type="neon_d"/>
|
||||
<reg name="d22" bitsize="64" type="neon_d"/>
|
||||
<reg name="d23" bitsize="64" type="neon_d"/>
|
||||
<reg name="d24" bitsize="64" type="neon_d"/>
|
||||
<reg name="d25" bitsize="64" type="neon_d"/>
|
||||
<reg name="d26" bitsize="64" type="neon_d"/>
|
||||
<reg name="d27" bitsize="64" type="neon_d"/>
|
||||
<reg name="d28" bitsize="64" type="neon_d"/>
|
||||
<reg name="d29" bitsize="64" type="neon_d"/>
|
||||
<reg name="d30" bitsize="64" type="neon_d"/>
|
||||
<reg name="d31" bitsize="64" type="neon_d"/>
|
||||
|
||||
<reg name="q0" bitsize="128" type="neon_q"/>
|
||||
<reg name="q1" bitsize="128" type="neon_q"/>
|
||||
<reg name="q2" bitsize="128" type="neon_q"/>
|
||||
<reg name="q3" bitsize="128" type="neon_q"/>
|
||||
<reg name="q4" bitsize="128" type="neon_q"/>
|
||||
<reg name="q5" bitsize="128" type="neon_q"/>
|
||||
<reg name="q6" bitsize="128" type="neon_q"/>
|
||||
<reg name="q7" bitsize="128" type="neon_q"/>
|
||||
<reg name="q8" bitsize="128" type="neon_q"/>
|
||||
<reg name="q9" bitsize="128" type="neon_q"/>
|
||||
<reg name="q10" bitsize="128" type="neon_q"/>
|
||||
<reg name="q11" bitsize="128" type="neon_q"/>
|
||||
<reg name="q12" bitsize="128" type="neon_q"/>
|
||||
<reg name="q13" bitsize="128" type="neon_q"/>
|
||||
<reg name="q14" bitsize="128" type="neon_q"/>
|
||||
<reg name="q15" bitsize="128" type="neon_q"/>
|
||||
|
||||
<reg name="fpscr" bitsize="32" type="int" group="float"/>
|
||||
</feature>
|
14
src/Ryujinx.HLE/Debugger/GdbXml/target32.xml
Normal file
14
src/Ryujinx.HLE/Debugger/GdbXml/target32.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2009-2013 Free Software Foundation, Inc.
|
||||
Contributed by ARM Ltd.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
||||
<target>
|
||||
<architecture>arm</architecture>
|
||||
<xi:include href="arm-core.xml"/>
|
||||
<xi:include href="arm-neon.xml"/>
|
||||
</target>
|
|
@ -7,9 +7,12 @@ namespace Ryujinx.HLE.Debugger
|
|||
{
|
||||
public static readonly Dictionary<string, string> Features = new()
|
||||
{
|
||||
{ "target.xml", GetEmbeddedResourceContent("target.xml") },
|
||||
{ "target64.xml", GetEmbeddedResourceContent("target64.xml") },
|
||||
{ "target32.xml", GetEmbeddedResourceContent("target32.xml") },
|
||||
{ "aarch64-core.xml", GetEmbeddedResourceContent("aarch64-core.xml") },
|
||||
{ "aarch64-fpu.xml", GetEmbeddedResourceContent("aarch64-fpu.xml") },
|
||||
{ "arm-core.xml", GetEmbeddedResourceContent("arm-core.xml") },
|
||||
{ "arm-neon.xml", GetEmbeddedResourceContent("arm-neon.xml") },
|
||||
};
|
||||
|
||||
private static string GetEmbeddedResourceContent(string resourceName)
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
<ItemGroup>
|
||||
<None Remove="Debugger\GdbXml\aarch64-core.xml" />
|
||||
<None Remove="Debugger\GdbXml\aarch64-fpu.xml" />
|
||||
<None Remove="Debugger\GdbXml\target.xml" />
|
||||
<None Remove="Debugger\GdbXml\arm-core.xml" />
|
||||
<None Remove="Debugger\GdbXml\arm-neon.xml" />
|
||||
<None Remove="Debugger\GdbXml\target64.xml" />
|
||||
<None Remove="Debugger\GdbXml\target32.xml" />
|
||||
<None Remove="Homebrew.npdm" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />
|
||||
|
@ -44,7 +47,10 @@
|
|||
<ItemGroup>
|
||||
<EmbeddedResource Include="Debugger\GdbXml\aarch64-core.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\aarch64-fpu.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\target.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\arm-core.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\arm-neon.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\target64.xml" />
|
||||
<EmbeddedResource Include="Debugger\GdbXml\target32.xml" />
|
||||
<EmbeddedResource Include="Homebrew.npdm" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />
|
||||
|
|
Loading…
Reference in a new issue