From 4e5e505e815d7c21ee0035f049caeba24d1d5268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Wed, 29 Aug 2018 18:34:20 +0100 Subject: [PATCH] Fixed core dump. Fixed test runner core dump handler. Implemented debug engine core dump handler. Added SendCoreDump calls for null reference, stack corruption and stack overflow exceptions. --- .../Cosmos.TestRunner.Core/Engine.Running.cs | 77 +++++-------------- source/Cosmos.Core.DebugStub/CmdSend.xs | 12 ++- .../Cosmos.Debug.DebugConnectors/CoreDump.cs | 59 ++++++++++++++ .../DebugConnector.Receiving.cs | 2 +- .../DebugConnector.cs | 2 +- .../AD7.Impl/AD7Process.cs | 61 +++++++++++++++ 6 files changed, 152 insertions(+), 61 deletions(-) create mode 100644 source/Cosmos.Debug.DebugConnectors/CoreDump.cs diff --git a/Tests/Cosmos.TestRunner.Core/Engine.Running.cs b/Tests/Cosmos.TestRunner.Core/Engine.Running.cs index 4c96ee3bb..635ef0a06 100644 --- a/Tests/Cosmos.TestRunner.Core/Engine.Running.cs +++ b/Tests/Cosmos.TestRunner.Core/Engine.Running.cs @@ -88,72 +88,37 @@ namespace Cosmos.TestRunner.Core aDebugConnector.CmdNullReferenceOccurred = a => AbortTestAndLogError( "Null Reference Exception occurred at: 0x" + a.ToString("X8")); - aDebugConnector.CmdCoreDump = b => + aDebugConnector.CmdCoreDump = dump => { - string xCallStack = ""; - int i = 0; - OutputHandler.LogMessage("Core dump:"); - string eax = "EAX = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string ebx = "EBX = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string ecx = "ECX = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string edx = "EDX = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string edi = "EDI = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string esi = "ESI = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string ebp = "EBP = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string eip = "EIP = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; - string esp = "ESP = 0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - i += 4; + + string eax = "EAX = 0x" + dump.EAX.ToString("X8"); + string ebx = "EBX = 0x" + dump.EBX.ToString("X8"); + string ecx = "ECX = 0x" + dump.ECX.ToString("X8"); + string edx = "EDX = 0x" + dump.EDX.ToString("X8"); + + string edi = "EDI = 0x" + dump.EDI.ToString("X8"); + string esi = "ESI = 0x" + dump.ESI.ToString("X8"); + + string ebp = "EBP = 0x" + dump.EBP.ToString("X8"); + string esp = "ESP = 0x" + dump.ESP.ToString("X8"); + string eip = "EIP = 0x" + dump.EIP.ToString("X8"); OutputHandler.LogMessage(eax + " " + ebx + " " + ecx + " " + edx); OutputHandler.LogMessage(edi + " " + esi); OutputHandler.LogMessage(ebp + " " + esp + " " + eip); OutputHandler.LogMessage(""); - while (i < b.Length) + OutputHandler.LogMessage("Call stack:"); + OutputHandler.LogMessage(""); + + while (dump.StackTrace.Count > 0) { - string xAddress = "0x" + - b[i + 3].ToString("X2") + b[i + 2].ToString("X2") + - b[i + 0].ToString("X2") + b[i + 1].ToString("X2"); - xCallStack += xAddress + " "; - if ((i != 0) && (i % 12 == 0)) - { - OutputHandler.LogMessage(xCallStack.Trim()); - xCallStack = ""; - } - i += 4; - } - if (xCallStack != "") - { - OutputHandler.LogMessage(xCallStack.Trim()); - xCallStack = ""; + var xAddress = "0x" + dump.StackTrace.Pop().ToString("X8"); + OutputHandler.LogMessage("at " + xAddress); } + + OutputHandler.LogMessage(""); }; if (RunWithGDB) diff --git a/source/Cosmos.Core.DebugStub/CmdSend.xs b/source/Cosmos.Core.DebugStub/CmdSend.xs index d7e1cb927..06f718f9f 100644 --- a/source/Cosmos.Core.DebugStub/CmdSend.xs +++ b/source/Cosmos.Core.DebugStub/CmdSend.xs @@ -321,6 +321,8 @@ function SendStackCorruptionOccurred { // pointer value ESI = @.CallerEIP ComWrite32() + + SendCoreDump() } // Input: Stack @@ -334,6 +336,8 @@ function SendStackOverflowOccurred { // pointer value ESI = @.CallerEIP ComWrite32() + + SendCoreDump() } // Input: None @@ -361,6 +365,8 @@ function SendNullReferenceOccurred { // pointer value ESI = @.CallerEIP ComWrite32() + + SendCoreDump() } // Input: Stack @@ -405,9 +411,9 @@ function SendCoreDump { ECX = 36 EAX = EBP while EAX != 0 { - EBX = EAX - 4 - +EAX - ECX = ECX + 4 + EBX = [EAX + 4] + +EBX + ECX + 4 EAX = [EAX] } diff --git a/source/Cosmos.Debug.DebugConnectors/CoreDump.cs b/source/Cosmos.Debug.DebugConnectors/CoreDump.cs new file mode 100644 index 000000000..47d78fbf6 --- /dev/null +++ b/source/Cosmos.Debug.DebugConnectors/CoreDump.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace Cosmos.Debug.DebugConnectors +{ + public class CoreDump + { + public uint EAX { get; } + public uint EBX { get; } + public uint ECX { get; } + public uint EDX { get; } + + public uint ESI { get; } + public uint EDI { get; } + + public uint EBP { get; } + public uint ESP { get; } + public uint EIP { get; } + + public Stack StackTrace { get; } + + public CoreDump( + uint eax, uint ebx, uint ecx, uint edx, + uint esi, uint edi, + uint ebp, uint esp, uint eip, + Stack stackTrace) + { + EAX = eax; + EBX = ebx; + ECX = ecx; + EDX = edx; + + ESI = esi; + EDI = edi; + + EBP = ebp; + ESP = esp; + EIP = eip; + + StackTrace = stackTrace; + } + + internal static CoreDump FromStackArray(byte[] stackBytes) + { + var stack = new Stack(stackBytes.Length / 4); + + for (int i = 0; i < stackBytes.Length; i += 4) + { + stack.Push(BitConverter.ToUInt32(stackBytes, i)); + } + + return new CoreDump( + stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), + stack.Pop(), stack.Pop(), + stack.Pop(), stack.Pop(), stack.Pop(), + stack); + } + } +} diff --git a/source/Cosmos.Debug.DebugConnectors/DebugConnector.Receiving.cs b/source/Cosmos.Debug.DebugConnectors/DebugConnector.Receiving.cs index 1bf90f822..ebdb1d6ca 100644 --- a/source/Cosmos.Debug.DebugConnectors/DebugConnector.Receiving.cs +++ b/source/Cosmos.Debug.DebugConnectors/DebugConnector.Receiving.cs @@ -165,7 +165,7 @@ namespace Cosmos.Debug.DebugConnectors protected void PacketCoreDump(byte[] aPacket) { - CmdCoreDump?.Invoke(aPacket.ToArray()); + CmdCoreDump?.Invoke(CoreDump.FromStackArray(aPacket)); WaitForMessage(); } diff --git a/source/Cosmos.Debug.DebugConnectors/DebugConnector.cs b/source/Cosmos.Debug.DebugConnectors/DebugConnector.cs index 8eb4fda5e..991400a2d 100644 --- a/source/Cosmos.Debug.DebugConnectors/DebugConnector.cs +++ b/source/Cosmos.Debug.DebugConnectors/DebugConnector.cs @@ -32,7 +32,7 @@ namespace Cosmos.Debug.DebugConnectors public Action CmdStack; public Action CmdPong; public Action CmdChannel; - public Action CmdCoreDump; + public Action CmdCoreDump; public Action CmdStackCorruptionOccurred; public Action CmdStackOverflowOccurred; public Action CmdInterruptOccurred; diff --git a/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs b/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs index 61eb55f04..041b48895 100644 --- a/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs +++ b/source/Cosmos.VS.DebugEngine/AD7.Impl/AD7Process.cs @@ -359,6 +359,7 @@ namespace Cosmos.VS.DebugEngine.AD7.Impl mDbgConnector.CmdNullReferenceOccurred += DbgCmdNullReferenceOccurred; mDbgConnector.CmdMessageBox += DbgCmdMessageBox; mDbgConnector.CmdChannel += DbgCmdChannel; + mDbgConnector.CmdCoreDump += DbgCmdCoreDump; } private void DbgCmdChannel(byte aChannel, byte aCommand, byte[] aData) @@ -407,6 +408,66 @@ namespace Cosmos.VS.DebugEngine.AD7.Impl AD7Util.MessageBox("Message from your Cosmos operating system:\r\n\r\n" + message); } + private void DbgCmdCoreDump(CoreDump dump) + { + var eax = GetRegister("EAX", dump.EAX); + var ebx = GetRegister("EBX", dump.EBX); + var ecx = GetRegister("ECX", dump.ECX); + var edx = GetRegister("EDX", dump.EDX); + + var edi = GetRegister("EDI", dump.EDI); + var esi = GetRegister("ESI", dump.ESI); + + var ebp = GetRegister("EBP", dump.EBP); + var esp = GetRegister("ESP", dump.ESP); + var eip = GetRegister("EIP", dump.EIP); + + var message = "Core dump:" + Environment.NewLine + + $"{eax} {ebx} {ecx} {edx}" + Environment.NewLine + + $"{edi} {esi}" + Environment.NewLine + + $"{ebp} {esp} {eip}" + Environment.NewLine + + Environment.NewLine + + "Call stack:" + + Environment.NewLine; + + while (dump.StackTrace.Count > 0) + { + message += GetStackTraceEntry(dump.StackTrace.Pop()) + Environment.NewLine; + } + + AD7Util.MessageBox(message); + + string GetRegister(string name, uint value) => $"{name} = 0x{value:X8}"; + + string GetStackTraceEntry(uint address) + { + var entry = $"at 0x{address:X8}"; + + if (mDebugInfo.TryGetValue(BuildPropertyNames.DebugModeString, out var xDebugMode)) + { + if (xDebugMode == "Source") + { + try + { + var xMethod = mDebugInfoDb.GetMethod(address); + var xDocument = mDebugInfoDb.GetDocumentById(xMethod.DocumentID); + var xLabel = mDebugInfoDb.GetLabels(address)[0]; + var xMethodIlOp = mDebugInfoDb.TryGetFirstMethodIlOpByLabelName(xLabel.Remove(xLabel.LastIndexOf('.'))).IlOffset; + var xSequencePoints = mDebugInfoDb.GetSequencePoints(mDebugInfoDb.GetAssemblyFileById(xMethod.AssemblyFileID).Pathname, xMethod.MethodToken); + var xLine = xSequencePoints.Where(q => q.Offset <= xMethodIlOp).Last().LineStart; + + entry += $"in {xDocument.Pathname}:line {xLine}"; + } + catch (InvalidOperationException) + { + } + } + } + + return entry; + } + } + internal AD7Process(Dictionary aDebugInfo, EngineCallback aCallback, AD7Engine aEngine, IDebugPort2 aPort) { mCallback = aCallback;