diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-11-28 20:18:09 -0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-28 20:18:09 -0200 |
| commit | 00579927e43bf55ee06ae02933c1e755fb4120eb (patch) | |
| tree | 0fd06db7b28e0accf87b465ec6f4dc74691febab /Ryujinx.HLE/HOS/Process.cs | |
| parent | e7fe7d724778535f8eff390abef54274a343c0b7 (diff) | |
Better process implementation (#491)
* Initial implementation of KProcess
* Some improvements to the memory manager, implement back guest stack trace printing
* Better GetInfo implementation, improve checking in some places with information from process capabilities
* Allow the cpu to read/write from the correct memory locations for accesses crossing a page boundary
* Change long -> ulong for address/size on memory related methods to avoid unnecessary casts
* Attempt at implementing ldr:ro with new KProcess
* Allow BSS with size 0 on ldr:ro
* Add checking for memory block slab heap usage, return errors if full, exit gracefully
* Use KMemoryBlockSize const from KMemoryManager
* Allow all methods to read from non-contiguous locations
* Fix for TransactParcelAuto
* Address PR feedback, additionally fix some small issues related to the KIP loader and implement SVCs GetProcessId, GetProcessList, GetSystemInfo, CreatePort and ManageNamedPort
* Fix wrong check for source pages count from page list on MapPhysicalMemory
* Fix some issues with UnloadNro on ldr:ro
Diffstat (limited to 'Ryujinx.HLE/HOS/Process.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Process.cs | 528 |
1 files changed, 0 insertions, 528 deletions
diff --git a/Ryujinx.HLE/HOS/Process.cs b/Ryujinx.HLE/HOS/Process.cs deleted file mode 100644 index 93b2d68d..00000000 --- a/Ryujinx.HLE/HOS/Process.cs +++ /dev/null @@ -1,528 +0,0 @@ -using ChocolArm64; -using ChocolArm64.Events; -using ChocolArm64.Memory; -using ChocolArm64.State; -using LibHac; -using Ryujinx.Common.Logging; -using Ryujinx.HLE.Exceptions; -using Ryujinx.HLE.HOS.Diagnostics.Demangler; -using Ryujinx.HLE.HOS.Kernel; -using Ryujinx.HLE.HOS.Services.Nv; -using Ryujinx.HLE.HOS.SystemState; -using Ryujinx.HLE.Loaders; -using Ryujinx.HLE.Loaders.Executables; -using Ryujinx.HLE.Loaders.Npdm; -using Ryujinx.HLE.Utilities; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace Ryujinx.HLE.HOS -{ - class Process : IDisposable - { - private const int TickFreq = 19_200_000; - - public Switch Device { get; private set; } - - public bool NeedsHbAbi { get; private set; } - - public long HbAbiDataPosition { get; private set; } - - public int ProcessId { get; private set; } - - private Translator Translator; - - public MemoryManager Memory { get; private set; } - - public KMemoryManager MemoryManager { get; private set; } - - private List<KTlsPageManager> TlsPages; - - public Npdm MetaData { get; private set; } - - public Nacp ControlData { get; set; } - - public KProcessHandleTable HandleTable { get; private set; } - - public AppletStateMgr AppletState { get; private set; } - - private SvcHandler SvcHandler; - - private ConcurrentDictionary<long, KThread> Threads; - - private List<Executable> Executables; - - private long ImageBase; - - private bool Disposed; - - public Process(Switch Device, int ProcessId, Npdm MetaData) - { - this.Device = Device; - this.MetaData = MetaData; - this.ProcessId = ProcessId; - - Memory = new MemoryManager(Device.Memory.RamPointer); - - Memory.InvalidAccess += CpuInvalidAccessHandler; - - MemoryManager = new KMemoryManager(this); - - TlsPages = new List<KTlsPageManager>(); - - int HandleTableSize = 1024; - - if (MetaData != null) - { - foreach (KernelAccessControlItem Item in MetaData.ACI0.KernelAccessControl.Items) - { - if (Item.HasHandleTableSize) - { - HandleTableSize = Item.HandleTableSize; - - break; - } - } - } - - HandleTable = new KProcessHandleTable(Device.System, HandleTableSize); - - AppletState = new AppletStateMgr(Device.System); - - SvcHandler = new SvcHandler(Device, this); - - Threads = new ConcurrentDictionary<long, KThread>(); - - Executables = new List<Executable>(); - - ImageBase = MemoryManager.CodeRegionStart; - } - - public void LoadProgram(IExecutable Program) - { - if (Disposed) - { - throw new ObjectDisposedException(nameof(Process)); - } - - long ImageEnd = LoadProgram(Program, ImageBase); - - ImageBase = IntUtils.AlignUp(ImageEnd, KMemoryManager.PageSize); - } - - public long LoadProgram(IExecutable Program, long ExecutableBase) - { - if (Disposed) - { - throw new ObjectDisposedException(nameof(Process)); - } - - Logger.PrintInfo(LogClass.Loader, $"Image base at 0x{ExecutableBase:x16}."); - - Executable Executable = new Executable(Program, MemoryManager, Memory, ExecutableBase); - - Executables.Add(Executable); - - return Executable.ImageEnd; - } - - public void RemoveProgram(long ExecutableBase) - { - foreach (Executable Executable in Executables) - { - if (Executable.ImageBase == ExecutableBase) - { - Executables.Remove(Executable); - break; - } - } - } - - public void SetEmptyArgs() - { - //TODO: This should be part of Run. - ImageBase += KMemoryManager.PageSize; - } - - public bool Run(bool NeedsHbAbi = false) - { - if (Disposed) - { - throw new ObjectDisposedException(nameof(Process)); - } - - this.NeedsHbAbi = NeedsHbAbi; - - if (Executables.Count == 0) - { - return false; - } - - long MainStackTop = MemoryManager.CodeRegionEnd - KMemoryManager.PageSize; - - long MainStackSize = 1 * 1024 * 1024; - - long MainStackBottom = MainStackTop - MainStackSize; - - MemoryManager.HleMapCustom( - MainStackBottom, - MainStackSize, - MemoryState.MappedMemory, - MemoryPermission.ReadAndWrite); - - int Handle = MakeThread(Executables[0].ImageBase, MainStackTop, 0, 44, 0); - - if (Handle == -1) - { - return false; - } - - KThread MainThread = HandleTable.GetKThread(Handle); - - if (NeedsHbAbi) - { - HbAbiDataPosition = IntUtils.AlignUp(Executables[0].ImageEnd, KMemoryManager.PageSize); - - const long HbAbiDataSize = KMemoryManager.PageSize; - - MemoryManager.HleMapCustom( - HbAbiDataPosition, - HbAbiDataSize, - MemoryState.MappedMemory, - MemoryPermission.ReadAndWrite); - - string SwitchPath = Device.FileSystem.SystemPathToSwitchPath(Executables[0].FilePath); - - Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle, SwitchPath); - - MainThread.Context.ThreadState.X0 = (ulong)HbAbiDataPosition; - MainThread.Context.ThreadState.X1 = ulong.MaxValue; - } - - MainThread.TimeUp(); - - return true; - } - - private int ThreadIdCtr = 1; - - public int MakeThread( - long EntryPoint, - long StackTop, - long ArgsPtr, - int Priority, - int ProcessorId) - { - if (Disposed) - { - throw new ObjectDisposedException(nameof(Process)); - } - - CpuThread CpuThread = new CpuThread(GetTranslator(), Memory, EntryPoint); - - long Tpidr = GetFreeTls(); - - int ThreadId = ThreadIdCtr++; //(int)((Tpidr - MemoryManager.TlsIoRegionStart) / 0x200) + 1; - - KThread Thread = new KThread(CpuThread, this, Device.System, ProcessorId, Priority, ThreadId); - - Thread.LastPc = EntryPoint; - - HandleTable.GenerateHandle(Thread, out int Handle); - - CpuThread.ThreadState.CntfrqEl0 = TickFreq; - CpuThread.ThreadState.Tpidr = Tpidr; - - CpuThread.ThreadState.X0 = (ulong)ArgsPtr; - CpuThread.ThreadState.X1 = (ulong)Handle; - CpuThread.ThreadState.X31 = (ulong)StackTop; - - CpuThread.ThreadState.Interrupt += InterruptHandler; - CpuThread.ThreadState.Break += BreakHandler; - CpuThread.ThreadState.SvcCall += SvcHandler.SvcCall; - CpuThread.ThreadState.Undefined += UndefinedHandler; - - CpuThread.WorkFinished += ThreadFinished; - - Threads.TryAdd(CpuThread.ThreadState.Tpidr, Thread); - - return Handle; - } - - private long GetFreeTls() - { - long Position; - - lock (TlsPages) - { - for (int Index = 0; Index < TlsPages.Count; Index++) - { - if (TlsPages[Index].TryGetFreeTlsAddr(out Position)) - { - return Position; - } - } - - long PagePosition = MemoryManager.HleMapTlsPage(); - - KTlsPageManager TlsPage = new KTlsPageManager(PagePosition); - - TlsPages.Add(TlsPage); - - TlsPage.TryGetFreeTlsAddr(out Position); - } - - return Position; - } - - private void InterruptHandler(object sender, EventArgs e) - { - Device.System.Scheduler.ContextSwitch(); - } - - private void BreakHandler(object sender, InstExceptionEventArgs e) - { - PrintStackTraceForCurrentThread(); - - throw new GuestBrokeExecutionException(); - } - - private void UndefinedHandler(object sender, InstUndefinedEventArgs e) - { - PrintStackTraceForCurrentThread(); - - throw new UndefinedInstructionException(e.Position, e.RawOpCode); - } - - public void EnableCpuTracing() - { - Translator.EnableCpuTrace = true; - } - - public void DisableCpuTracing() - { - Translator.EnableCpuTrace = false; - } - - private void CpuTraceHandler(object sender, CpuTraceEventArgs e) - { - Executable Exe = GetExecutable(e.Position); - - if (Exe == null) - { - return; - } - - if (!TryGetSubName(Exe, e.Position, out string SubName)) - { - SubName = string.Empty; - } - - long Offset = e.Position - Exe.ImageBase; - - string ExeNameWithAddr = $"{Exe.Name}:0x{Offset:x8}"; - - Logger.PrintDebug(LogClass.Cpu, ExeNameWithAddr + " " + SubName); - } - - private Translator GetTranslator() - { - if (Translator == null) - { - Translator = new Translator(); - - Translator.CpuTrace += CpuTraceHandler; - } - - return Translator; - } - - private void CpuInvalidAccessHandler(object sender, InvalidAccessEventArgs e) - { - PrintStackTraceForCurrentThread(); - } - - private void PrintStackTraceForCurrentThread() - { - foreach (KThread Thread in Threads.Values) - { - if (Thread.Context.IsCurrentThread()) - { - PrintStackTrace(Thread.Context.ThreadState); - - break; - } - } - } - - public void PrintStackTrace(CpuThreadState ThreadState) - { - StringBuilder Trace = new StringBuilder(); - - Trace.AppendLine("Guest stack trace:"); - - void AppendTrace(long Position) - { - Executable Exe = GetExecutable(Position); - - if (Exe == null) - { - return; - } - - if (!TryGetSubName(Exe, Position, out string SubName)) - { - SubName = $"Sub{Position:x16}"; - } - else if (SubName.StartsWith("_Z")) - { - SubName = Demangler.Parse(SubName); - } - - long Offset = Position - Exe.ImageBase; - - string ExeNameWithAddr = $"{Exe.Name}:0x{Offset:x8}"; - - Trace.AppendLine(" " + ExeNameWithAddr + " " + SubName); - } - - long FramePointer = (long)ThreadState.X29; - - while (FramePointer != 0) - { - AppendTrace(Memory.ReadInt64(FramePointer + 8)); - - FramePointer = Memory.ReadInt64(FramePointer); - } - - Logger.PrintInfo(LogClass.Cpu, Trace.ToString()); - } - - 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 GetExecutable(long Position) - { - string Name = string.Empty; - - for (int Index = Executables.Count - 1; Index >= 0; Index--) - { - if ((ulong)Position >= (ulong)Executables[Index].ImageBase) - { - return Executables[Index]; - } - } - - return null; - } - - private void ThreadFinished(object sender, EventArgs e) - { - if (sender is CpuThread Thread) - { - if (Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread)) - { - Device.System.Scheduler.RemoveThread(KernelThread); - } - } - - if (Threads.Count == 0) - { - Device.System.ExitProcess(ProcessId); - } - } - - public KThread GetThread(long Tpidr) - { - if (!Threads.TryGetValue(Tpidr, out KThread Thread)) - { - throw new InvalidOperationException(); - } - - return Thread; - } - - private void Unload() - { - if (Disposed || Threads.Count > 0) - { - return; - } - - Disposed = true; - - HandleTable.Destroy(); - - INvDrvServices.UnloadProcess(this); - - if (NeedsHbAbi && Executables.Count > 0 && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix)) - { - File.Delete(Executables[0].FilePath); - } - - Logger.PrintInfo(LogClass.Loader, $"Process {ProcessId} exiting..."); - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool Disposing) - { - if (Disposing) - { - if (Threads.Count > 0) - { - foreach (KThread Thread in Threads.Values) - { - Device.System.Scheduler.StopThread(Thread); - } - } - else - { - Unload(); - } - } - } - } -}
\ No newline at end of file |
