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.
This commit is contained in:
José Pedro 2018-08-29 18:34:20 +01:00
parent 63257e85ef
commit 4e5e505e81
No known key found for this signature in database
GPG key ID: B8247B9301707B83
6 changed files with 152 additions and 61 deletions

View file

@ -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)

View file

@ -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]
}

View file

@ -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<uint> StackTrace { get; }
public CoreDump(
uint eax, uint ebx, uint ecx, uint edx,
uint esi, uint edi,
uint ebp, uint esp, uint eip,
Stack<uint> 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<uint>(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);
}
}
}

View file

@ -165,7 +165,7 @@ namespace Cosmos.Debug.DebugConnectors
protected void PacketCoreDump(byte[] aPacket)
{
CmdCoreDump?.Invoke(aPacket.ToArray());
CmdCoreDump?.Invoke(CoreDump.FromStackArray(aPacket));
WaitForMessage();
}

View file

@ -32,7 +32,7 @@ namespace Cosmos.Debug.DebugConnectors
public Action<byte[]> CmdStack;
public Action<byte[]> CmdPong;
public Action<byte, byte, byte[]> CmdChannel;
public Action<byte[]> CmdCoreDump;
public Action<CoreDump> CmdCoreDump;
public Action<UInt32> CmdStackCorruptionOccurred;
public Action<UInt32> CmdStackOverflowOccurred;
public Action<UInt32> CmdInterruptOccurred;

View file

@ -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<string, string> aDebugInfo, EngineCallback aCallback, AD7Engine aEngine, IDebugPort2 aPort)
{
mCallback = aCallback;