mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
copy gdb client on every build to install path if registry key found remove hardcoded gdb.exe path optimize vspackage, no cache refresh for every item
161 lines
No EOL
5.9 KiB
C#
161 lines
No EOL
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using Registry = Microsoft.Win32.Registry;
|
|
using Path = System.IO.Path;
|
|
|
|
namespace Cosmos.Debug.GDB {
|
|
public class GDB {
|
|
public class Response {
|
|
public string Command = string.Empty;
|
|
public string Reply = string.Empty;
|
|
public bool Error = false;
|
|
public string ErrorMsg = string.Empty;
|
|
public List<string> Text = new List<string>();
|
|
|
|
public override string ToString() {
|
|
return Command;
|
|
}
|
|
}
|
|
|
|
protected Queue<string> mLastCmd = new Queue<string>();
|
|
protected System.Diagnostics.Process mGDBProcess;
|
|
protected Action<Response> mOnResponse;
|
|
protected List<string> mBuffer = new List<string>();
|
|
|
|
// DO NOT change to sync reads.. with process output there are SERIOUS bugs in the StreamReader..
|
|
// Unforunately the .NET implementation when no more data exists
|
|
// sticks forever and there seems to be no way to abort it including closing the stream.
|
|
// StreamReader in general has other issues on non seekable streams as well and accounts for why even our
|
|
// implementation looks poor in places.
|
|
void mGDBProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) {
|
|
string xData = e.Data.Trim();
|
|
if (xData == "(gdb)") {
|
|
ProcessResponse();
|
|
} else {
|
|
mBuffer.Add(xData);
|
|
}
|
|
}
|
|
|
|
protected void ProcessResponse() {
|
|
var xResponse = new Response();
|
|
lock (mLastCmd) {
|
|
xResponse.Command = mLastCmd.Dequeue();
|
|
}
|
|
|
|
foreach (string xLine in mBuffer) {
|
|
var xType = xLine[0];
|
|
// & echo of a command or reply
|
|
// ~ text response
|
|
// ^ done
|
|
|
|
//&target remote :8832
|
|
//&:8832: No connection could be made because the target machine actively refused it.
|
|
//^error,msg=":8832: No connection could be made because the target machine actively refused it."
|
|
|
|
//&target remote :8832
|
|
//~Remote debugging using :8832
|
|
//~[New Thread 1]
|
|
//~0x000ffff0 in ?? ()
|
|
//^done
|
|
|
|
string sData = Unescape(xLine.Substring(1));
|
|
if (xType == '&') {
|
|
xResponse.Reply = sData;
|
|
} else if (xType == '^') {
|
|
xResponse.Error = sData != "done";
|
|
} else if (xType == '~') {
|
|
xResponse.Text.Add(Unescape(sData));
|
|
}
|
|
}
|
|
|
|
mBuffer.Clear();
|
|
Windows.mMainForm.Invoke(mOnResponse, new object[] { xResponse });
|
|
}
|
|
|
|
static public string Unescape(string aInput) {
|
|
// Remove surrounding ", /n, then unescape and trim
|
|
string xResult = aInput;
|
|
if (xResult.StartsWith("\"")) {
|
|
xResult = xResult.Substring(1, aInput.Length - 2);
|
|
xResult = xResult.Replace('\n', ' ');
|
|
xResult = Regex.Unescape(xResult);
|
|
}
|
|
return xResult.Trim();
|
|
}
|
|
|
|
public void SendCmd(string aCmd) {
|
|
lock (mLastCmd) {
|
|
mLastCmd.Enqueue(aCmd);
|
|
}
|
|
mGDBProcess.StandardInput.WriteLine(aCmd);
|
|
}
|
|
|
|
protected bool mConnected = false;
|
|
public bool Connected {
|
|
get { return mConnected; }
|
|
}
|
|
|
|
static readonly string mGDBExePath;
|
|
|
|
static GDB()
|
|
{
|
|
using (var xReg = Registry.LocalMachine.OpenSubKey("Software\\Cosmos", false))
|
|
{
|
|
if(xReg == null)
|
|
throw new Exception("The Key \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Cosmos\" does not exist! Are you install Cosmos Kit?");
|
|
var xPathToInstalled = (string)xReg.GetValue(null);
|
|
mGDBExePath = Path.Combine(xPathToInstalled, @"Build\Tools\gdb.exe");
|
|
}
|
|
}
|
|
|
|
public GDB(int aRetry, Action<Response> aOnResponse) {
|
|
mOnResponse = aOnResponse;
|
|
// To handle greeting from GDB since its not associated with any command
|
|
mLastCmd.Enqueue(string.Empty);
|
|
|
|
var xStartInfo = new ProcessStartInfo();
|
|
xStartInfo.FileName = mGDBExePath;
|
|
xStartInfo.Arguments = @"--interpreter=mi2";
|
|
xStartInfo.WorkingDirectory = Settings.OutputPath;
|
|
xStartInfo.CreateNoWindow = true;
|
|
xStartInfo.UseShellExecute = false;
|
|
xStartInfo.RedirectStandardError = true;
|
|
xStartInfo.RedirectStandardInput = true;
|
|
xStartInfo.RedirectStandardOutput = true;
|
|
mGDBProcess = System.Diagnostics.Process.Start(xStartInfo);
|
|
mGDBProcess.StandardInput.AutoFlush = true;
|
|
|
|
mGDBProcess.OutputDataReceived += new DataReceivedEventHandler(mGDBProcess_OutputDataReceived);
|
|
mGDBProcess.BeginOutputReadLine();
|
|
|
|
mConnected = true;
|
|
|
|
SendCmd("symbol-file " + Settings.ObjFile);
|
|
SendCmd("target remote :8832");
|
|
|
|
//while (!mConnected) {
|
|
// var x = SendCmd("target remote :8832");
|
|
// mConnected = !x.Error;
|
|
// aRetry--;
|
|
// if (aRetry == 0) {
|
|
// return;
|
|
// }
|
|
|
|
// System.Threading.Thread.Sleep(1000);
|
|
// System.Windows.Forms.Application.DoEvents();
|
|
//}
|
|
|
|
SendCmd("set architecture i386");
|
|
SendCmd("set language asm");
|
|
SendCmd("set disassembly-flavor intel");
|
|
SendCmd("break Kernel_Start");
|
|
SendCmd("continue");
|
|
SendCmd("delete 1");
|
|
}
|
|
}
|
|
} |