mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2024-12-31 21:13:04 +00:00
Remove unused tracing functionality from the CPU
This commit is contained in:
parent
741773910d
commit
5d32e28449
7 changed files with 79 additions and 204 deletions
|
@ -4,8 +4,6 @@ public static class AOptimizations
|
|||
{
|
||||
public static bool DisableMemoryChecks = false;
|
||||
|
||||
public static bool GenerateCallStack = true;
|
||||
|
||||
private static bool UseAllSseIfAvailable = true;
|
||||
|
||||
private static bool UseSseIfAvailable = true;
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using ChocolArm64.Decoder;
|
||||
using ChocolArm64.Events;
|
||||
using ChocolArm64.Instruction;
|
||||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using ChocolArm64.Translation;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ChocolArm64
|
||||
|
@ -15,24 +12,9 @@ namespace ChocolArm64
|
|||
{
|
||||
private ConcurrentDictionary<long, ATranslatedSub> CachedSubs;
|
||||
|
||||
private ConcurrentDictionary<long, string> SymbolTable;
|
||||
|
||||
public event EventHandler<ACpuTraceEventArgs> CpuTrace;
|
||||
|
||||
public bool EnableCpuTrace { get; set; }
|
||||
|
||||
public ATranslator(IReadOnlyDictionary<long, string> SymbolTable = null)
|
||||
public ATranslator()
|
||||
{
|
||||
CachedSubs = new ConcurrentDictionary<long, ATranslatedSub>();
|
||||
|
||||
if (SymbolTable != null)
|
||||
{
|
||||
this.SymbolTable = new ConcurrentDictionary<long, string>(SymbolTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SymbolTable = new ConcurrentDictionary<long, string>();
|
||||
}
|
||||
}
|
||||
|
||||
internal void ExecuteSubroutine(AThread Thread, long Position)
|
||||
|
@ -68,16 +50,6 @@ namespace ChocolArm64
|
|||
{
|
||||
do
|
||||
{
|
||||
if (EnableCpuTrace)
|
||||
{
|
||||
if (!SymbolTable.TryGetValue(Position, out string SubName))
|
||||
{
|
||||
SubName = string.Empty;
|
||||
}
|
||||
|
||||
CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName));
|
||||
}
|
||||
|
||||
if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub))
|
||||
{
|
||||
Sub = TranslateTier0(State, Memory, Position);
|
||||
|
@ -148,8 +120,6 @@ namespace ChocolArm64
|
|||
|
||||
string SubName = GetSubName(Position);
|
||||
|
||||
PropagateName(Cfg.Graph, SubName);
|
||||
|
||||
AILEmitterCtx Context = new AILEmitterCtx(this, Cfg.Graph, Cfg.Root, SubName);
|
||||
|
||||
if (Context.CurrBlock.Position != Position)
|
||||
|
@ -185,22 +155,7 @@ namespace ChocolArm64
|
|||
|
||||
private string GetSubName(long Position)
|
||||
{
|
||||
return SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}");
|
||||
}
|
||||
|
||||
private void PropagateName(ABlock[] Graph, string Name)
|
||||
{
|
||||
foreach (ABlock Block in Graph)
|
||||
{
|
||||
AOpCode LastOp = Block.GetLastOp();
|
||||
|
||||
if (LastOp != null &&
|
||||
(LastOp.Emitter == AInstEmit.Bl ||
|
||||
LastOp.Emitter == AInstEmit.Blr))
|
||||
{
|
||||
SymbolTable.TryAdd(LastOp.Position + 4, Name);
|
||||
}
|
||||
}
|
||||
return $"Sub{Position:x16}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.Events
|
||||
{
|
||||
public class ACpuTraceEventArgs : EventArgs
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
|
||||
public string SubName { get; private set; }
|
||||
|
||||
public ACpuTraceEventArgs(long Position, string SubName)
|
||||
{
|
||||
this.Position = Position;
|
||||
this.SubName = SubName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,14 +35,6 @@ namespace ChocolArm64.Instruction
|
|||
{
|
||||
AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
|
||||
|
||||
if (AOptimizations.GenerateCallStack)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
Context.EmitLdc_I8(Op.Imm);
|
||||
|
||||
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod));
|
||||
}
|
||||
|
||||
Context.EmitLdc_I(Op.Position + 4);
|
||||
Context.EmitStint(AThreadState.LRIndex);
|
||||
Context.EmitStoreState();
|
||||
|
@ -80,14 +72,6 @@ namespace ChocolArm64.Instruction
|
|||
{
|
||||
AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
|
||||
|
||||
if (AOptimizations.GenerateCallStack)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
Context.EmitLdintzr(Op.Rn);
|
||||
|
||||
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod));
|
||||
}
|
||||
|
||||
Context.EmitLdc_I(Op.Position + 4);
|
||||
Context.EmitStint(AThreadState.LRIndex);
|
||||
Context.EmitStoreState();
|
||||
|
@ -100,14 +84,6 @@ namespace ChocolArm64.Instruction
|
|||
{
|
||||
AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
|
||||
|
||||
if (AOptimizations.GenerateCallStack)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
Context.EmitLdintzr(Op.Rn);
|
||||
|
||||
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.JumpMethod));
|
||||
}
|
||||
|
||||
Context.EmitStoreState();
|
||||
Context.EmitLdintzr(Op.Rn);
|
||||
|
||||
|
@ -129,13 +105,6 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
public static void Ret(AILEmitterCtx Context)
|
||||
{
|
||||
if (AOptimizations.GenerateCallStack)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
|
||||
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.ExitMethod));
|
||||
}
|
||||
|
||||
Context.EmitStoreState();
|
||||
Context.EmitLdint(AThreadState.LRIndex);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using ChocolArm64.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
|
@ -80,17 +79,10 @@ namespace ChocolArm64.State
|
|||
public event EventHandler<AInstExceptionEventArgs> SvcCall;
|
||||
public event EventHandler<AInstUndefinedEventArgs> Undefined;
|
||||
|
||||
private Stack<long> CallStack;
|
||||
|
||||
private static Stopwatch TickCounter;
|
||||
|
||||
private static double HostTickFreq;
|
||||
|
||||
public AThreadState()
|
||||
{
|
||||
CallStack = new Stack<long>();
|
||||
}
|
||||
|
||||
static AThreadState()
|
||||
{
|
||||
HostTickFreq = 1.0 / Stopwatch.Frequency;
|
||||
|
@ -114,27 +106,5 @@ namespace ChocolArm64.State
|
|||
{
|
||||
Undefined?.Invoke(this, new AInstUndefinedEventArgs(Position, RawOpCode));
|
||||
}
|
||||
|
||||
internal void EnterMethod(long Position)
|
||||
{
|
||||
CallStack.Push(Position);
|
||||
}
|
||||
|
||||
internal void ExitMethod()
|
||||
{
|
||||
CallStack.TryPop(out _);
|
||||
}
|
||||
|
||||
internal void JumpMethod(long Position)
|
||||
{
|
||||
CallStack.TryPop(out _);
|
||||
|
||||
CallStack.Push(Position);
|
||||
}
|
||||
|
||||
public long[] GetCallStack()
|
||||
{
|
||||
return CallStack.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,23 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.HLE.Loaders.Executables;
|
||||
using Ryujinx.HLE.OsHle;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
class Executable
|
||||
{
|
||||
private AMemory Memory;
|
||||
|
||||
private List<ElfDyn> Dynamic;
|
||||
|
||||
private Dictionary<long, string> m_SymbolTable;
|
||||
|
||||
public IReadOnlyDictionary<long, string> SymbolTable => m_SymbolTable;
|
||||
public ReadOnlyCollection<ElfSym> SymbolTable;
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
private AMemory Memory;
|
||||
|
||||
public long ImageBase { get; private set; }
|
||||
public long ImageEnd { get; private set; }
|
||||
|
||||
|
@ -24,8 +25,6 @@ namespace Ryujinx.HLE.Loaders
|
|||
{
|
||||
Dynamic = new List<ElfDyn>();
|
||||
|
||||
m_SymbolTable = new Dictionary<long, string>();
|
||||
|
||||
Name = Exe.Name;
|
||||
|
||||
this.Memory = Memory;
|
||||
|
@ -84,14 +83,18 @@ namespace Ryujinx.HLE.Loaders
|
|||
|
||||
long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
|
||||
|
||||
List<ElfSym> Symbols = new List<ElfSym>();
|
||||
|
||||
while ((ulong)SymTblAddr < (ulong)StrTblAddr)
|
||||
{
|
||||
ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr);
|
||||
|
||||
m_SymbolTable.TryAdd(Sym.Value, Sym.Name);
|
||||
Symbols.Add(Sym);
|
||||
|
||||
SymTblAddr += SymEntSize;
|
||||
}
|
||||
|
||||
SymbolTable = Array.AsReadOnly(Symbols.OrderBy(x => x.Value).ToArray());
|
||||
}
|
||||
|
||||
private void WriteData(
|
||||
|
|
|
@ -57,8 +57,6 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
private List<Executable> Executables;
|
||||
|
||||
private Dictionary<long, string> SymbolTable;
|
||||
|
||||
private long ImageBase;
|
||||
|
||||
private bool ShouldDispose;
|
||||
|
@ -133,8 +131,6 @@ namespace Ryujinx.HLE.OsHle
|
|||
return false;
|
||||
}
|
||||
|
||||
MakeSymbolTable();
|
||||
|
||||
MapRWMemRegion(
|
||||
MemoryRegions.MainStackAddress,
|
||||
MemoryRegions.MainStackSize,
|
||||
|
@ -201,7 +197,7 @@ namespace Ryujinx.HLE.OsHle
|
|||
throw new ObjectDisposedException(nameof(Process));
|
||||
}
|
||||
|
||||
AThread CpuThread = new AThread(GetTranslator(), Memory, EntryPoint);
|
||||
AThread CpuThread = new AThread(new ATranslator(), Memory, EntryPoint);
|
||||
|
||||
KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
|
||||
|
||||
|
@ -243,69 +239,22 @@ namespace Ryujinx.HLE.OsHle
|
|||
throw new UndefinedInstructionException(e.Position, e.RawOpCode);
|
||||
}
|
||||
|
||||
private void MakeSymbolTable()
|
||||
{
|
||||
SymbolTable = new Dictionary<long, string>();
|
||||
|
||||
foreach (Executable Exe in Executables)
|
||||
{
|
||||
foreach (KeyValuePair<long, string> KV in Exe.SymbolTable)
|
||||
{
|
||||
SymbolTable.TryAdd(Exe.ImageBase + KV.Key, KV.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ATranslator GetTranslator()
|
||||
{
|
||||
if (Translator == null)
|
||||
{
|
||||
Translator = new ATranslator(SymbolTable);
|
||||
|
||||
Translator.CpuTrace += CpuTraceHandler;
|
||||
}
|
||||
|
||||
return Translator;
|
||||
}
|
||||
|
||||
public void EnableCpuTracing()
|
||||
{
|
||||
Translator.EnableCpuTrace = true;
|
||||
}
|
||||
|
||||
public void DisableCpuTracing()
|
||||
{
|
||||
Translator.EnableCpuTrace = false;
|
||||
}
|
||||
|
||||
private void CpuTraceHandler(object sender, ACpuTraceEventArgs e)
|
||||
{
|
||||
string NsoName = string.Empty;
|
||||
|
||||
for (int Index = Executables.Count - 1; Index >= 0; Index--)
|
||||
{
|
||||
if (e.Position >= Executables[Index].ImageBase)
|
||||
{
|
||||
NsoName = $"{(e.Position - Executables[Index].ImageBase):x16}";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ns.Log.PrintDebug(LogClass.Cpu, $"Executing at 0x{e.Position:x16} {e.SubName} {NsoName}");
|
||||
}
|
||||
|
||||
public void PrintStackTrace(AThreadState ThreadState)
|
||||
{
|
||||
long[] Positions = ThreadState.GetCallStack();
|
||||
|
||||
StringBuilder Trace = new StringBuilder();
|
||||
|
||||
Trace.AppendLine("Guest stack trace:");
|
||||
|
||||
foreach (long Position in Positions)
|
||||
void AppendTrace(long Position)
|
||||
{
|
||||
if (!SymbolTable.TryGetValue(Position, out string SubName))
|
||||
Executable Exe = GetNsoExecutable(Position);
|
||||
|
||||
if (Exe == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetSubName(Exe, Position, out string SubName))
|
||||
{
|
||||
SubName = $"Sub{Position:x16}";
|
||||
}
|
||||
|
@ -314,13 +263,65 @@ namespace Ryujinx.HLE.OsHle
|
|||
SubName = Demangler.Parse(SubName);
|
||||
}
|
||||
|
||||
Trace.AppendLine(" " + SubName + " (" + GetNsoNameAndAddress(Position) + ")");
|
||||
long Offset = Position - Exe.ImageBase;
|
||||
|
||||
string ExeNameWithAddr = $"{Exe.Name}:{Offset:x8}";
|
||||
|
||||
Trace.AppendLine(" " + SubName + " (" + ExeNameWithAddr + ")");
|
||||
}
|
||||
|
||||
long FramePointer = (long)ThreadState.X29;
|
||||
|
||||
while (FramePointer != 0)
|
||||
{
|
||||
AppendTrace(Memory.ReadInt64(FramePointer + 8));
|
||||
|
||||
FramePointer = Memory.ReadInt64(FramePointer);
|
||||
}
|
||||
|
||||
Ns.Log.PrintInfo(LogClass.Cpu, Trace.ToString());
|
||||
}
|
||||
|
||||
private string GetNsoNameAndAddress(long Position)
|
||||
private bool TryGetSubName(Executable Exe, long Position, out string Name)
|
||||
{
|
||||
Position -= Exe.ImageBase;
|
||||
|
||||
int Left = 0;
|
||||
int Right = Exe.SymbolTable.Count - 1;
|
||||
|
||||
while (Left <= Right)
|
||||
{
|
||||
int Size = Right - Left;
|
||||
|
||||
int Middle = Left + (Size >> 1);
|
||||
|
||||
ElfSym Symbol = Exe.SymbolTable[Middle];
|
||||
|
||||
long EndPosition = Symbol.Value + Symbol.Size;
|
||||
|
||||
if ((ulong)Position >= (ulong)Symbol.Value && (ulong)Position < (ulong)EndPosition)
|
||||
{
|
||||
Name = Symbol.Name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ulong)Position < (ulong)Symbol.Value)
|
||||
{
|
||||
Right = Middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Left = Middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Name = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Executable GetNsoExecutable(long Position)
|
||||
{
|
||||
string Name = string.Empty;
|
||||
|
||||
|
@ -328,15 +329,11 @@ namespace Ryujinx.HLE.OsHle
|
|||
{
|
||||
if (Position >= Executables[Index].ImageBase)
|
||||
{
|
||||
long Offset = Position - Executables[Index].ImageBase;
|
||||
|
||||
Name = $"{Executables[Index].Name}:{Offset:x8}";
|
||||
|
||||
break;
|
||||
return Executables[Index];
|
||||
}
|
||||
}
|
||||
|
||||
return Name;
|
||||
return null;
|
||||
}
|
||||
|
||||
private int GetFreeTlsSlot(AThread Thread)
|
||||
|
|
Loading…
Reference in a new issue