diff --git a/source/Cosmos.Core_Plugs/CosmosRuntimeType.cs b/source/Cosmos.Core/CosmosRuntimeType.cs similarity index 99% rename from source/Cosmos.Core_Plugs/CosmosRuntimeType.cs rename to source/Cosmos.Core/CosmosRuntimeType.cs index 6957a714a0..a12633ea50 100644 --- a/source/Cosmos.Core_Plugs/CosmosRuntimeType.cs +++ b/source/Cosmos.Core/CosmosRuntimeType.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.Reflection; -using Cosmos.IL2CPU; namespace Cosmos.Core { diff --git a/source/Cosmos.Core/Memory/HeapLarge.cs b/source/Cosmos.Core/Memory/HeapLarge.cs index 7436f0e86d..f69296b21b 100644 --- a/source/Cosmos.Core/Memory/HeapLarge.cs +++ b/source/Cosmos.Core/Memory/HeapLarge.cs @@ -35,8 +35,8 @@ public static void Init() var xPtr = (uint*)RAT.AllocPages(aType, xPages); if (xPtr == null) { - Debugger.SendKernelPanic(0x67); // out of pages - while (true) { } + Debugger.DoFail(0x67); // out of pages + } xPtr[0] = xPages * RAT.PageSize - PrefixBytes; // Allocated data size xPtr[1] = aSize; // Actual data size @@ -52,7 +52,13 @@ public static void Init() /// Thrown if page type is not found. public static void Free(void* aPtr) { + var heapObject = (uint*)aPtr; var xPageIdx = RAT.GetFirstRATIndex(aPtr); + if (heapObject[-4] == 0 && xPageIdx == 0) + { + // The object is not allocated + return; + } RAT.Free(xPageIdx); } } diff --git a/source/Cosmos.Core/Memory/HeapSmall.cs b/source/Cosmos.Core/Memory/HeapSmall.cs index 664458f130..a965e81198 100644 --- a/source/Cosmos.Core/Memory/HeapSmall.cs +++ b/source/Cosmos.Core/Memory/HeapSmall.cs @@ -230,8 +230,7 @@ private static void AddRootSMTBlock(SMTPage* aPage, uint aSize) // we cant later add a block with a size smaller than an earlier block. That would break the algorithm Debugger.DoSendNumber(aSize); Debugger.DoSendNumber(ptr->Size); - Debugger.SendKernelPanic(0x83); - while (true) { } + Debugger.DoFail(0x83); } if (ptr->Size == 0) @@ -367,8 +366,7 @@ static void CreatePage(SMTPage* aPage, uint aItemSize) smtBlock = NextFreeBlock(); if (smtBlock == null) { - Debugger.SendKernelPanic(0x93); - while (true) { }; + Debugger.DoFail(0x93); } } @@ -389,6 +387,28 @@ static void CreatePage(SMTPage* aPage, uint aItemSize) smtBlock->PagePtr = xPtr; } + + + /// + /// Get the first block for this size, which has space left to allocate to And get the root block + /// + /// The size + /// the Output block + /// The parent of the block + private static RootSMTBlock* GetFirstWithSpaceAndParent(uint aSize, out SMTBlock* block) + { + var page = SMT; + RootSMTBlock* rootblock = null; + do + { + rootblock = GetFirstBlock(page, aSize); + block = GetFirstWithSpace(aSize, rootblock); + + page = page->Next; + } while (rootblock == null && page != null); + return rootblock; + } + /// /// Alloc memory block, of a given size. /// @@ -396,22 +416,22 @@ static void CreatePage(SMTPage* aPage, uint aItemSize) /// Byte pointer to the start of the block. public static byte* Alloc(ushort aSize) { - var pageBlock = GetFirstWithSpace(aSize); + var smtblock = GetFirstWithSpaceAndParent(aSize, out SMTBlock* pageBlock); if (pageBlock == null) // This happens when the page is full and we need to allocate a new page for this size { - CreatePage(GetLastPage(), GetRoundedSize(aSize)); + CreatePage(GetLastPage(), smtblock->Size); pageBlock = GetFirstWithSpace(aSize); if (pageBlock == null) { //this means that we cant allocate another page - Debugger.SendKernelPanic(0x121); + Debugger.DoAssert(0x121); } } //now find position in the block - ushort* page = (ushort*)pageBlock->PagePtr; - uint elementSize = GetRoundedSize(aSize) + PrefixItemBytes; - uint positions = RAT.PageSize / elementSize; + var page = (ushort*)pageBlock->PagePtr; + var elementSize = smtblock->Size + PrefixItemBytes; + var positions = RAT.PageSize / elementSize; for (int i = 0; i < positions; i++) { if (page[i * elementSize / 2] == 0) @@ -434,8 +454,8 @@ static void CreatePage(SMTPage* aPage, uint aItemSize) // if we get here, RAM is corrupted, since we know we had a space but it turns out we didnt Debugger.DoSendNumber((uint)pageBlock); Debugger.DoSendNumber(aSize); - Debugger.SendKernelPanic(0x122); - while (true) { } + Debugger.DoFail(0x122); + return null; } /// @@ -449,9 +469,10 @@ public static void Free(void* aPtr) if (size == 0) { // double free, this object has already been freed - Debugger.DoBochsBreak(); + //Debugger.DoBochsBreak(); Debugger.DoSendNumber((uint)heapObject); - Debugger.SendKernelPanic(0x99); + Debugger.DoAssert(true, 0x99, true); + return; } var allocated = (uint*)aPtr; @@ -483,7 +504,7 @@ public static void Free(void* aPtr) { blockPtr = blockPtr->NextBlock; } - if(blockPtr->PagePtr == allocatedOnPage) + if (blockPtr != null && blockPtr->PagePtr == allocatedOnPage) { break; } @@ -495,8 +516,7 @@ public static void Free(void* aPtr) // this shouldnt happen Debugger.DoSendNumber((uint)aPtr); Debugger.DoSendNumber((uint)SMT); - Debugger.SendKernelPanic(0x98); - while (true) { } + Debugger.DoFail(0x98); } blockPtr->SpacesLeft++; } @@ -559,4 +579,5 @@ private static int GetAllocatedObjectCount(SMTPage* aPage, uint aSize) #endregion } + } diff --git a/source/Cosmos.Core/Memory/RAT.cs b/source/Cosmos.Core/Memory/RAT.cs index b62c8c3a8f..3b6e5a87c5 100644 --- a/source/Cosmos.Core/Memory/RAT.cs +++ b/source/Cosmos.Core/Memory/RAT.cs @@ -123,8 +123,9 @@ public static void Init(byte* aStartPtr, uint aSize) if (aSize % PageSize != 0) { - Debugger.DoSendNumber(aSize % PageSize); - Debugger.SendKernelPanic(11); + + Debugger.DoSendNumber((aSize % PageSize)); + Debugger.DoAssert(11); throw new Exception("RAM size must be page aligned."); } diff --git a/source/Cosmos.Core/VTablesImpl.cs b/source/Cosmos.Core/VTablesImpl.cs index e18833f923..dba15fd835 100644 --- a/source/Cosmos.Core/VTablesImpl.cs +++ b/source/Cosmos.Core/VTablesImpl.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Cosmos.Debug.Kernel; namespace Cosmos.Core @@ -158,8 +154,7 @@ public static uint GetMethodAddressForType(uint aType, uint aMethodId) EnableDebug = true; DebugHex("Type", aType); DebugHex("MethodId", aMethodId); - Debugger.SendKernelPanic(KernelPanics.VMT_TypeIdInvalid); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_TypeIdInvalid); } var xCurrentType = aType; do @@ -172,15 +167,13 @@ public static uint GetMethodAddressForType(uint aType, uint aMethodId) { EnableDebug = true; DebugHex("MethodIndexes is null for type", aType); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodIndexesNull); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodIndexesNull); } if (xCurrentTypeInfo.MethodAddresses == null) { EnableDebug = true; DebugHex("MethodAddresses is null for type", aType); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodAddressesNull); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodAddressesNull); } for (int i = 0; i < xCurrentTypeInfo.MethodIndexes.Length; i++) @@ -198,9 +191,8 @@ public static uint GetMethodAddressForType(uint aType, uint aMethodId) DebugHex("MethodCount", xCurrentTypeInfo.MethodCount); DebugHex("MethodAddresses.Length", (uint)xCurrentTypeInfo.MethodAddresses.Length); Debug("Method found, but address is invalid!"); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodFoundButAddressInvalid); - while (true) - ; + Debugger.DoFail(KernelPanics.VMT_MethodFoundButAddressInvalid); + } Debug("Found."); return xResult; @@ -220,8 +212,7 @@ public static uint GetMethodAddressForType(uint aType, uint aMethodId) DebugHex("MethodId", aMethodId); Debug("Not FOUND!"); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodNotFound); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodNotFound); throw new Exception("Cannot find virtual method!"); } @@ -254,8 +245,8 @@ public static uint GetDeclaringTypeOfMethodForType(uint aType, uint aMethodId) DebugHex("MethodId", aMethodId); Debug("Not FOUND Declaring TYPE!"); Debugger.DoBochsBreak(); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodNotFound); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodNotFound); + return 0; } public static uint GetMethodAddressForInterfaceType(uint aType, uint aInterfaceMethodId) @@ -265,8 +256,7 @@ public static uint GetMethodAddressForInterfaceType(uint aType, uint aInterfaceM EnableDebug = true; DebugHex("Type", aType); DebugHex("InterfaceMethodId", aInterfaceMethodId); - Debugger.SendKernelPanic(KernelPanics.VMT_TypeIdInvalid); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_TypeIdInvalid); } var xTypeInfo = mTypes[aType]; @@ -275,16 +265,14 @@ public static uint GetMethodAddressForInterfaceType(uint aType, uint aInterfaceM { EnableDebug = true; DebugHex("InterfaceMethodIndexes is null for type", aType); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodIndexesNull); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodIndexesNull); } if (xTypeInfo.TargetMethodIndexes == null) { EnableDebug = true; DebugHex("TargetMethodIndexes is null for type", aType); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodAddressesNull); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodAddressesNull); } for (int i = 0; i < xTypeInfo.InterfaceMethodIndexes.Length; i++) @@ -302,8 +290,8 @@ public static uint GetMethodAddressForInterfaceType(uint aType, uint aInterfaceM DebugHex("InterfaceMethodId", aInterfaceMethodId); Debug("Not FOUND!"); - Debugger.SendKernelPanic(KernelPanics.VMT_MethodNotFound); - while (true) ; + Debugger.DoFail(KernelPanics.VMT_MethodNotFound); + return 0; } /// diff --git a/source/Cosmos.Core_Plugs/System/ArrayImpl.cs b/source/Cosmos.Core_Plugs/System/ArrayImpl.cs index 290fa494d2..e66d8d8d14 100644 --- a/source/Cosmos.Core_Plugs/System/ArrayImpl.cs +++ b/source/Cosmos.Core_Plugs/System/ArrayImpl.cs @@ -118,7 +118,7 @@ public static unsafe object GetValue(Array aThis, params int[] aIndices) } [PlugMethod(Signature = "System_Void__System_Array_SetValue_System_Object__System_Int32_")] - public static unsafe void SetValue([ObjectPointerAccess] uint* aThis, uint aValue, int aIndex) + public static unsafe void SetValue([ObjectPointerAccess] uint* aThis, [ObjectPointerAccess] uint* aValue, int aIndex) { aThis = (uint*) aThis[0]; aThis += 3; @@ -128,16 +128,16 @@ public static unsafe void SetValue([ObjectPointerAccess] uint* aThis, uint aValu switch (xElementSize) { case 1: - *(byte*) aThis = (byte) aValue; + *(byte*) aThis = (byte) *aValue; return; case 2: - *(ushort*) aThis = (ushort) aValue; + *(ushort*) aThis = (ushort) *aValue; return; case 3: - *(uint*) aThis = (uint) aValue; + *(uint*) aThis = (uint) *aValue; return; case 4: - *(uint*) aThis = (uint) aValue; + *(uint*) aThis = (uint) *aValue; return; } throw new NotSupportedException("SetValue not supported in this situation!"); diff --git a/source/Cosmos.Debug.Hosts/VMware.cs b/source/Cosmos.Debug.Hosts/VMware.cs index d90e82ba7b..12826eb84d 100644 --- a/source/Cosmos.Debug.Hosts/VMware.cs +++ b/source/Cosmos.Debug.Hosts/VMware.cs @@ -9,9 +9,12 @@ //using Vestris.VMWareLib; using Cosmos.Build.Common; +using System.Linq; -namespace Cosmos.Debug.Hosts { - public class VMware : Host { +namespace Cosmos.Debug.Hosts +{ + public class VMware : Host + { protected VMwareEdition mEdition; protected string mDir; protected string mVmxPath; @@ -21,27 +24,33 @@ public class VMware : Host { protected string mPlayerPath; protected string mHarddisk; - public VMware(Dictionary aParams, bool aUseGDB,string harddisk = "Filesystem.vmdk") : base(aParams, aUseGDB) { + public VMware(Dictionary aParams, bool aUseGDB, string harddisk = "Filesystem.vmdk") : base(aParams, aUseGDB) + { mHarddisk = harddisk; mDir = Path.Combine(CosmosPaths.Build, @"VMWare\Workstation\"); mVmxPath = Path.Combine(mDir, @"Debug.vmx"); mWorkstationPath = GetPathname("VMware Workstation", "vmware.exe"); mPlayerPath = GetPathname("VMware Player", "vmplayer.exe"); - if (mWorkstationPath == null && mPlayerPath == null) { + if (mWorkstationPath == null && mPlayerPath == null) + { throw new Exception("VMware not found."); } string xFlavor = aParams[BuildPropertyNames.VMwareEditionString].ToUpper(); mEdition = VMwareEdition.Player; - if (xFlavor == "WORKSTATION") { + if (xFlavor == "WORKSTATION") + { mEdition = VMwareEdition.Workstation; } // Try alternate if selected one is not installed - if (mEdition == VMwareEdition.Player && mPlayerPath == null && mWorkstationPath != null) { + if (mEdition == VMwareEdition.Player && mPlayerPath == null && mWorkstationPath != null) + { mEdition = VMwareEdition.Workstation; - } else if (mEdition == VMwareEdition.Workstation && mWorkstationPath == null) { + } + else if (mEdition == VMwareEdition.Workstation && mWorkstationPath == null) + { mEdition = VMwareEdition.Player; } } @@ -54,11 +63,15 @@ public VMware(Dictionary aParams, bool aUseGDB,string harddisk = // } //} - protected string GetPathname(string aKey, string aEXE) { - using (var xRegKey = Registry.LocalMachine.OpenSubKey(@"Software\WOW6432Node\VMware, Inc.\" + aKey, false)) { - if (xRegKey != null) { + protected string GetPathname(string aKey, string aEXE) + { + using (var xRegKey = Registry.LocalMachine.OpenSubKey(@"Software\WOW6432Node\VMware, Inc.\" + aKey, false)) + { + if (xRegKey != null) + { string xResult = Path.Combine(((string)xRegKey.GetValue("InstallPath")), aEXE); - if (File.Exists(xResult)) { + if (File.Exists(xResult)) + { return xResult; } } @@ -66,24 +79,31 @@ protected string GetPathname(string aKey, string aEXE) { } } - public override void Start() { + public override void Start() + { Cleanup(); CreateDebugVmx(); // Target exe or file mProcess = new Process(); var xPSI = mProcess.StartInfo; - if (mEdition == VMwareEdition.Player) { + if (mEdition == VMwareEdition.Player) + { xPSI.FileName = mPlayerPath; - } else { + } + else + { xPSI.FileName = mWorkstationPath; } var xArgSB = new StringBuilder(); string xVmxPath = "\"" + mVmxPath + "\""; - if (mEdition == VMwareEdition.Player) { + if (mEdition == VMwareEdition.Player) + { xPSI.Arguments = xVmxPath; - } else { + } + else + { // -x: Auto power on VM. Must be small x, big X means something else. // -q: Close VMWare when VM is powered off. // Options must come beore the vmx, and cannot use shellexecute @@ -129,7 +149,8 @@ private void ExitCallback(object sender, EventArgs e) } } - public override void Stop() { + public override void Stop() + { if (null != mProcess) { try @@ -152,15 +173,19 @@ public override void Stop() { Cleanup(); } - protected void DeleteFiles(string aPath, string aPattern) { + protected void DeleteFiles(string aPath, string aPattern) + { var xFiles = Directory.GetFiles(aPath, aPattern); - foreach (var xFile in xFiles) { + foreach (var xFile in xFiles) + { File.Delete(xFile); } } - protected void Cleanup() { - try { + protected void Cleanup() + { + try + { string xPath = Path.GetDirectoryName(mVmxPath); // Delete old Debug.vmx and other files that might be left over from previous run. // Especially important with newer versions of VMWare player which defaults to suspend @@ -178,50 +203,66 @@ protected void Cleanup() { File.Delete(Path.Combine(xPath, "vmware-0.log")); File.Delete(Path.Combine(xPath, "vmware-1.log")); File.Delete(Path.Combine(xPath, "vmware-2.log")); - } catch (Exception) { + } + catch (Exception) + { // Ignore errors, users can stop VS while VMware is still running and files will be locked. } } - protected void CreateDebugVmx() { + protected void CreateDebugVmx() + { // VMWare doesn't like to boot a read only VMX. // We also need to make changes based on project / debug settings. // Finally we do not want to create VCS checkins based on local user changes. // Because of this we use Cosmos.vmx as a template and output a Debug.vmx on every run. - using (var xSrc = new StreamReader(File.Open(Path.Combine(mDir, "Cosmos.vmx"), FileMode.OpenOrCreate))) { - try { + using (var xSrc = new StreamReader(File.Open(Path.Combine(mDir, "Cosmos.vmx"), FileMode.OpenOrCreate))) + { + try + { // Write out Debug.vmx - using (var xDest = new StreamWriter(File.Open(mVmxPath, FileMode.Create))) { + using (var xDest = new StreamWriter(File.Open(mVmxPath, FileMode.Create))) + { string xLine; - while ((xLine = xSrc.ReadLine()) != null) { + while ((xLine = xSrc.ReadLine()) != null) + { var xParts = xLine.Split('='); - if (xParts.Length == 2) { + if (xParts.Length == 2) + { string xName = xParts[0].Trim(); string xValue = xParts[1].Trim(); - if ((xName == "uuid.location") || (xName == "uuid.bios")) { + if ((xName == "uuid.location") || (xName == "uuid.bios")) + { // We delete uuid entries so VMWare doesnt ask the user "Did you move or copy" the file xValue = null; - } else if (xName == "ide1:0.fileName") + } + else if (xName == "ide1:0.fileName") { // Set the ISO file for booting xValue = "\"" + mParams["ISOFile"] + "\""; - } else if (xName == "ide0:0.fileName") { + } + else if (xName == "ide0:0.fileName") + { xValue = "\"" + mHarddisk + "\""; - } else if (xName == "nvram") { + } + else if (xName == "nvram") + { // Point it to an initially non-existent nvram. // This has the effect of disabling PXE so the boot is faster. xValue = "\"Debug.nvram\""; } - if (xValue != null) { + if (xValue != null) + { xDest.WriteLine(xName + " = " + xValue); } } } - if (mUseGDB) { + if (mUseGDB) + { xDest.WriteLine(); xDest.WriteLine("debugStub.listen.guest32 = \"TRUE\""); xDest.WriteLine("debugStub.hideBreakpoints = \"TRUE\""); @@ -229,8 +270,11 @@ protected void CreateDebugVmx() { xDest.WriteLine("debugStub.listen.guest32.remote = \"TRUE\""); } } - } catch (IOException ex) { - if (ex.Message.Contains(Path.GetFileName(mDir))) { + } + catch (IOException ex) + { + if (ex.Message.Contains(Path.GetFileName(mDir))) + { throw new Exception("The VMware image " + mDir + " is still in use. Please exit current Vmware session with Cosmos and try again.", ex); } throw; diff --git a/source/Cosmos.Debug.Kernel.Plugs.Asm/DebuggerAsm.cs b/source/Cosmos.Debug.Kernel.Plugs.Asm/DebuggerAsm.cs index 95fadc540d..fa5039d526 100644 --- a/source/Cosmos.Debug.Kernel.Plugs.Asm/DebuggerAsm.cs +++ b/source/Cosmos.Debug.Kernel.Plugs.Asm/DebuggerAsm.cs @@ -60,6 +60,15 @@ public static void SendKernelPanic(uint id) new LiteralAssemblerCode("%endif"); } + + [Inline] + public static void SendCoreDump() + { + new LiteralAssemblerCode("%ifdef DEBUGSTUB"); + new LiteralAssemblerCode("Call DebugStub_SendCoreDump"); + new LiteralAssemblerCode("%endif"); + } + [PlugMethod(Assembler = typeof(DoRealHalt))] public static void DoRealHalt() { } diff --git a/source/Cosmos.Debug.Kernel/Debugger.cs b/source/Cosmos.Debug.Kernel/Debugger.cs index c94095ece2..9dda28dc20 100644 --- a/source/Cosmos.Debug.Kernel/Debugger.cs +++ b/source/Cosmos.Debug.Kernel/Debugger.cs @@ -1,278 +1,366 @@ -using System.Diagnostics; - -namespace Cosmos.Debug.Kernel -{ - /// - /// Provides a simplified interface for creating new instances of the - /// class. - /// - public static class DebuggerFactory - { - /// - /// Whether the created instances should output - /// the given log inputs to the display console. - /// - public static bool WriteToConsole = false; - - /// - /// Creates a new instance. - /// - /// The virtual compile-time ring the debugger is operating in. - /// The section the debugger refers to. - public static Debugger CreateDebugger(string section = "") - { - if (WriteToConsole) - { - return new ConsoleDebugger(section); - } - else - { - return new Debugger(section); - } - } - } - - /// - /// Represents a categorized remote debugger, capable of communicating - /// with an external host machine, including virtualizers. - /// - public class Debugger - { - /// - /// Creates a new instance of the class. - /// - /// The virtual compile-time ring the debugger is operating in. - /// The section the debugger refers to. - public Debugger(string section) - { - Section = section; - } - - /// - /// The section the debugger refers to. - /// - public string Section { get; } - - /// - /// Triggers a software breakpoint. - /// - public void Break() { } - - /// - /// Triggers a Bochs breakpoint. - /// - public static void DoBochsBreak() { } - - internal static void DoRealHalt() { } - - private static unsafe void ActualSend(int aLength, char* aText) { } - - /// - /// Sends the pointer of the given object to any connected debugging hosts. - /// - public void SendPtr(object obj) { } - - /// - /// Sends a 32-bit unsigned integer to connected debugging hosts. - /// - public static void DoSendNumber(uint number) { } - - /// - /// Sends a 32-bit signed integer to connected debugging hosts. - /// - public static void DoSendNumber(int number) { } - - /// - /// Sends a 64-bit unsigned integer to connected debugging hosts. - /// - public static void DoSendNumber(ulong number) { } - - /// - /// Sends a 64-bit signed integer to connected debugging hosts. - /// - public static void DoSendNumber(long number) { } - - /// - /// Sends a 32-bit floating-point number to connected debugging hosts. - /// - public static void DoSendNumber(float number) { } - - /// - /// Sends a 64-bit floating-point number to connected debugging hosts. - /// - public static void DoSendNumber(double number) { } - - /// - public void SendNumber(uint number) => DoSendNumber(number); - - /// - public void SendNumber(int number) => DoSendNumber(number); - - /// - public void SendNumber(ulong number) => DoSendNumber(number); - - /// - public void SendNumber(long number) => DoSendNumber(number); - - /// - public void SendNumber(float number) => DoSendNumber(number); - - /// - public void SendNumber(double number) => DoSendNumber(number); - - public unsafe void SendChannelCommand(byte aChannel, byte aCommand, byte[] aData) - { - fixed (byte* xPtr = &aData[0]) - { - SendChannelCommand(aChannel, aCommand, aData.Length, xPtr); - } - } - - /// - /// Sends a command and its associated data to the given debug channel. - /// - /// The channel to send the data to. - /// The numeric command. - /// The amount of bytes in the data associated with the command. - /// The data associated with the command - public static unsafe void SendChannelCommand(byte channel, byte command, int byteCount, byte* data) { } - - /// - /// Sends a command to the given debug channel. - /// - /// The channel to send the data to. - /// The numeric command. - public static void SendChannelCommand(byte channel, byte command) { } - - internal static void DoSend(string aText) { } - - internal static void DoSend(string[] aStringArray) - { - for (int i = 0; i < aStringArray.Length; ++i) - { - DoSend(aStringArray[i]); - } - } - - /// - /// Sends a kernel panic error code to connected debugging hosts. - /// - public static void SendKernelPanic(uint id) { } - - /// - /// Sends the given string to connected debugging hosts. - /// - /// The text/message to send. - public void Send(string text) => DoSend(text); - - /// - /// Sends multiple strings to connected debugging hosts. - /// - /// The strings to send. - public void Send(string[] stringArray) => DoSend(stringArray); - - /// - /// Sends the given message to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(string text) => DoSend(text); - - /// - /// Sends the given strings to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(string[] stringArray) => DoSend(stringArray); - - /// - /// Sends the given 32-bit unsigned integer to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(uint number) => DoSendNumber(number); - - /// - /// Sends the given 32-bit signed integer to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(int number) => DoSendNumber(number); - - /// - /// Sends the given 64-bit unsigned integer to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(ulong number) => DoSendNumber(number); - - /// - /// Sends the given 64-bit signed integer to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(long number) => DoSendNumber(number); - - /// - /// Sends the given 32-bit floating-point number to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(float number) => DoSendNumber(number); - - /// - /// Sends the given 64-bit floating-point number to all connected debugging hosts. - /// - [Conditional("COSMOSDEBUG")] - public virtual void SendInternal(double number) => DoSendNumber(number); - - //public void OldSend(string aText) { - // // TODO: Need to fix this so it can send empty strings. - // // Sending empty strings locks it up right now - // if (aText.Length == 0) - // { - // return; - // } - - // var xChars = aText.ToCharArray(); - // fixed (char* xPtr = &xChars[0]) - // { - // ActualSend(xChars.Length, xPtr); - // } - //} - - /// - /// Displays a message box on connected debugging hosts. - /// - /// The length of the C-string. - /// The text to display in the message box, as a C-string. - public unsafe void SendMessageBox(int length, char* text) { } // Plugged - - /// - /// Displays a message box on connected debugging hosts. - /// - /// The text to display. - public unsafe void SendMessageBox(string text) - { - // TODO: Need to fix this so it can send empty strings. - // Sending empty strings locks it up right now - if (text.Length == 0) - { - return; - } - - var xChars = text.ToCharArray(); - fixed (char* xPtr = &xChars[0]) - { - SendMessageBox(xChars.Length, xPtr); - } - } - - private int FromHex(string p) - { - p = p.ToLower(); - string hex = "0123456789abcdef"; - - int ret = 0; - - for (int i = 0; i < p.Length; i++) - { - ret = ret * 16 + hex.IndexOf(p[i]); - } - return ret; - } - } +using System.Diagnostics; + +namespace Cosmos.Debug.Kernel +{ + + + /// + /// Provides a simplified interface for creating new instances of the + /// class. + /// + public static class DebuggerFactory + { + /// + /// Whether the created instances should output + /// the given log inputs to the display console. + /// + public static bool WriteToConsole = false; + + /// + /// Creates a new instance. + /// + /// The virtual compile-time ring the debugger is operating in. + /// The section the debugger refers to. + public static Debugger CreateDebugger(string section = "") + { + if (WriteToConsole) + { + return new ConsoleDebugger(section); + } + else + { + return new Debugger(section); + } + } + } + + public class Debugger + { + public static bool IgnoreAssert = false; + /// + /// Creates a new instance of the class. + /// + /// The virtual compile-time ring the debugger is operating in. + /// The section the debugger refers to. + public Debugger(string section) + { + Section = section; + } + + /// + /// The section the debugger refers to. + /// + public string Section { get; } + + #region Break + public void Break() { } + + public static void DoBochsBreak() { } + + internal static void DoRealHalt() { } + #endregion + + private static unsafe void ActualSend(int aLength, char* aText) { } + + /// + /// Sends the pointer of the given object to any connected debugging hosts. + /// + public void SendPtr(object obj) { } + + /// + /// Sends a 32-bit unsigned integer to connected debugging hosts. + /// + public static void DoSendNumber(uint number) { } + + /// + /// Sends a 32-bit signed integer to connected debugging hosts. + /// + public static void DoSendNumber(int number) { } + + /// + /// Sends a 64-bit unsigned integer to connected debugging hosts. + /// + public static void DoSendNumber(ulong number) { } + + /// + /// Sends a 64-bit signed integer to connected debugging hosts. + /// + public static void DoSendNumber(long number) { } + + /// + /// Sends a 32-bit floating-point number to connected debugging hosts. + /// + public static void DoSendNumber(float number) { } + + /// + /// Sends a 64-bit floating-point number to connected debugging hosts. + /// + public static void DoSendNumber(double number) { } + + /// + public void SendNumber(uint number) => DoSendNumber(number); + + /// + public void SendNumber(int number) => DoSendNumber(number); + + /// + public void SendNumber(ulong number) => DoSendNumber(number); + + /// + public void SendNumber(long number) => DoSendNumber(number); + + /// + public void SendNumber(float number) => DoSendNumber(number); + + /// + public void SendNumber(double number) => DoSendNumber(number); + + public unsafe void SendChannelCommand(byte aChannel, byte aCommand, byte[] aData) + { + fixed (byte* xPtr = &aData[0]) + { + SendChannelCommand(aChannel, aCommand, aData.Length, xPtr); + } + } + + /// + /// Sends a command and its associated data to the given debug channel. + /// + /// The channel to send the data to. + /// The numeric command. + /// The amount of bytes in the data associated with the command. + /// The data associated with the command + public static unsafe void SendChannelCommand(byte channel, byte command, int byteCount, byte* data) { } + + /// + /// Sends a command to the given debug channel. + /// + /// The channel to send the data to. + /// The numeric command. + public static void SendChannelCommand(byte channel, byte command) { } + + internal static void DoSend(string aText) { } + + internal static void DoSend(string[] aStringArray) + { + for (int i = 0; i < aStringArray.Length; ++i) + { + DoSend(aStringArray[i]); + } + } + + #region Assert + private static void SendKernelPanic(uint id) { } + + public static void SendCoreDump() { } + + #region Assert Function + + public static void DoAssert(int code) + { + DoAssert(true, code); + } + + public static void DoAssert(bool condition) + { + DoAssert(condition, -1); + } + + public static void DoAssert(bool condition, int code) + { + DoAssert(condition, code, false); + } + public static void DoAssert(bool condition, int code, string message) + { + DoAssert(condition, code, false, message); + } + public static void DoAssert(bool condition, bool DoBreak) + { + DoAssert(condition, -1, DoBreak, null); + } + public static void DoAssert(bool condition, bool DoBreak, string message) + { + DoAssert(condition, -1, DoBreak, message); + } + + public static void DoAssert(bool condition, string message) + { + DoAssert(condition, -1, false, message); + } + + public static void DoAssert(bool condition, int code, bool DoBreak) + { + DoAssert(condition, code, DoBreak, null); + } + + public static void DoAssert(bool condition, int code, bool DoBreak, string message) + { + if (condition && !IgnoreAssert) + { + if (message != null) { DoSend(message); } + if (DoBreak) + { + DoBochsBreak(); + } + if (code > -1) + { + SendKernelPanic((uint)code); + } + else { SendCoreDump(); } + } + } + + [Conditional("COSMOSDEBUG")] + public virtual void Assert(bool condition) => DoAssert(condition); + + [Conditional("COSMOSDEBUG")] + public virtual void Assert(bool condition, int code) => DoAssert(condition, code); + + [Conditional("COSMOSDEBUG")] + public virtual void Assert(bool condition, int code, string message) => DoAssert(condition, code, message); + #endregion + + #region Fail Function + + public static void DoFail(uint code) + { + DoFail((int)code); + } + + public static void DoFail(int code) + { + DoFail(code, null); + } + + public static void DoFail(string message) + { + DoFail(-1, message); + } + + public static void DoFail(int code, string message) + { + if (message != null) { DoSend(message); } + if (code > -1) + { + SendKernelPanic((uint)code); + } + else { SendCoreDump(); } // behave like assert function + // halt + while (true) { } + } + [Conditional("COSMOSDEBUG")] + public virtual void Fail(string message) => DoFail(message); + [Conditional("COSMOSDEBUG")] + public virtual void Fail(int code) => DoFail(code); + [Conditional("COSMOSDEBUG")] + public virtual void Fail(int code, string message) => DoFail(code, message); + #endregion + + #endregion + + #region Trace + + public void Send(string aText) => DoSend(aText); + + public void Send(string[] aStringArray) => DoSend(aStringArray); + + /// + /// Sends the given message to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(string text) => DoSend(text); + + /// + /// Sends the given strings to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(string[] stringArray) => DoSend(stringArray); + + /// + /// Sends the given 32-bit unsigned integer to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(uint number) => DoSendNumber(number); + + /// + /// Sends the given 32-bit signed integer to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(int number) => DoSendNumber(number); + + /// + /// Sends the given 64-bit unsigned integer to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(ulong number) => DoSendNumber(number); + + /// + /// Sends the given 64-bit signed integer to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(long number) => DoSendNumber(number); + + /// + /// Sends the given 32-bit floating-point number to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(float number) => DoSendNumber(number); + + /// + /// Sends the given 64-bit floating-point number to all connected debugging hosts. + /// + [Conditional("COSMOSDEBUG")] + public virtual void SendInternal(double number) => DoSendNumber(number); + + //public void OldSend(string aText) { + // // TODO: Need to fix this so it can send empty strings. + // // Sending empty strings locks it up right now + // if (aText.Length == 0) + // { + // return; + // } + + // var xChars = aText.ToCharArray(); + // fixed (char* xPtr = &xChars[0]) + // { + // ActualSend(xChars.Length, xPtr); + // } + //} + + public unsafe void SendMessageBox(int aLength, char* aText) { } // Plugged + + /// + /// Displays a message box on connected debugging hosts. + /// + /// The text to display. + public unsafe void SendMessageBox(string text) + { + // TODO: Need to fix this so it can send empty strings. + // Sending empty strings locks it up right now + if (text.Length == 0) + { + return; + } + + var xChars = text.ToCharArray(); + fixed (char* xPtr = &xChars[0]) + { + SendMessageBox(xChars.Length, xPtr); + } + } + #endregion + private int FromHex(string p) + { + p = p.ToLower(); + string hex = "0123456789abcdef"; + + int ret = 0; + + for (int i = 0; i < p.Length; i++) + { + ret = ret * 16 + hex.IndexOf(p[i]); + } + return ret; + } + } } \ No newline at end of file diff --git a/source/Cosmos.System2/FileSystem/Disk.cs b/source/Cosmos.System2/FileSystem/Disk.cs index 29d9476b08..010f4cbdf8 100644 --- a/source/Cosmos.System2/FileSystem/Disk.cs +++ b/source/Cosmos.System2/FileSystem/Disk.cs @@ -74,6 +74,23 @@ public List Partitions i++; } } + // Partitions is lost + if (converted.Count == 0) + { + int i = 0; + foreach (var item in FindLostPartitions()) + { + var part = new ManagedPartition(item); + if (mountedPartitions[i] != null) + { + var data = mountedPartitions[i]; + part.RootPath = data.RootPath; + part.MountedFS = data; + } + converted.Add(part); + i++; + } + } return converted; } @@ -276,6 +293,20 @@ public void FormatPartition(int index, string format, bool quick = true) } } + private List FindLostPartitions() + { + List list = new(); + foreach (var p in Partition.Partitions) + { + if (p.Host == Host) + { + // start mount + list.Add(p); + } + } + return list; + } + private readonly FileSystem[] mountedPartitions = new FileSystem[4]; /// diff --git a/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs b/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs index ad5f17c39d..cb533099e6 100644 --- a/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs +++ b/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs @@ -676,7 +676,7 @@ void DbgCmdSimpleNumber(uint nr) void DbgCmdKernelPanic(uint nr) { - AD7Util.ShowError("Kernel panic: 0x" + nr.ToString()); + AD7Util.ShowError("Kernel panic: 0x" + nr.ToString("X").ToUpper()); } void DbgCmdSimpleLongNumber(ulong nr) diff --git a/source/Cosmos.VS.DebugEngine/Utilities/Extensions.cs b/source/Cosmos.VS.DebugEngine/Utilities/Extensions.cs index 0da698e20a..85c6b71284 100644 --- a/source/Cosmos.VS.DebugEngine/Utilities/Extensions.cs +++ b/source/Cosmos.VS.DebugEngine/Utilities/Extensions.cs @@ -71,12 +71,8 @@ public static string GetFullName(this MethodBase aMethod) return String.Intern(xBuilder.ToString()); } - public static string GetFullName(this Type aType) + public static string GetFullName(this Type aType,bool checkParam=false) { - if (aType.IsGenericParameter) - { - return aType.FullName; - } var xSB = new StringBuilder(); if (aType.IsArray) { @@ -103,7 +99,24 @@ public static string GetFullName(this Type aType) { xSB.Append(aType.FullName); } - if (aType.IsGenericType) + if (aType.IsGenericParameter) + { + if (checkParam) + { + xSB.Append(aType.DeclaringType.FullName); + xSB.Append(aType.DeclaringMethod?.Name); + var paramss = aType.DeclaringMethod?.GetParameters(); + if (paramss != null) + { + foreach (var item in paramss) + { + xSB.Append(GetFullName(item.ParameterType, false)); + } + } + } + xSB.Append(aType.Name); + } + if (aType.IsGenericType && !aType.IsGenericTypeDefinition) { xSB.Append("<"); var xArgs = aType.GetGenericArguments();