diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs
index ff0d3d078..4ec9fd469 100644
--- a/src/MICore/CommandFactories/MICommandFactory.cs
+++ b/src/MICore/CommandFactories/MICommandFactory.cs
@@ -242,6 +242,12 @@ public async Task ExecNextInstruction(int threadId, ResultClass resultClass = Re
await ThreadFrameCmdAsync(command, resultClass, threadId, 0);
}
+ ///
+ /// Jumps to a specified target location
+ ///
+ abstract public Task ExecJump(string filename, int line);
+ abstract public Task ExecJump(ulong address);
+
///
/// Tells GDB to spawn a target process previous setup with -file-exec-and-symbols or similar
///
diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs
index 4bcb24b30..5df01be1c 100644
--- a/src/MICore/CommandFactories/gdb.cs
+++ b/src/MICore/CommandFactories/gdb.cs
@@ -157,7 +157,7 @@ public override async Task ThreadInfo(uint? threadId = null)
public override async Task> StartAddressesForLine(string file, uint line)
{
- string cmd = "info line " + file + ":" + line;
+ string cmd = "info line -s " + file + " -li " + line;
var result = await _debugger.ConsoleCmdAsync(cmd, allowWhileRunning: false);
List addresses = new List();
using (StringReader stringReader = new StringReader(result))
@@ -173,7 +173,7 @@ public override async Task> StartAddressesForLine(string file, uint
{
ulong address;
string addrStr = resultLine.Substring(pos + 18);
- if (MICommandFactory.SpanNextAddr(addrStr, out address) != null)
+ if (SpanNextAddr(addrStr, out address) != null)
{
addresses.Add(address);
}
@@ -183,6 +183,28 @@ public override async Task> StartAddressesForLine(string file, uint
return addresses;
}
+ private async Task JumpInternal(string target)
+ {
+ // temporary breakpoint + jump
+ // NB: the gdb docs state: "Resume execution at line linespec. Execution stops again immediately if there is a breakpoint there."
+ // We rely on this. If another thread hits a breakpoint before that we have a UX problem
+ // and would need to handle this via scheduler-locking for all-stop mode and ??? for non-stop mode.
+ await _debugger.CmdAsync("-break-insert -t " + target, ResultClass.done);
+ await _debugger.CmdAsync("-exec-jump " + target, ResultClass.running);
+ }
+
+ public override Task ExecJump(string filename, int line)
+ {
+ string target = "--source " + filename + " --line " + line.ToString(CultureInfo.InvariantCulture);
+ return JumpInternal(target);
+ }
+
+ public override Task ExecJump(ulong address)
+ {
+ string target = "*" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address);
+ return JumpInternal(target);
+ }
+
public override Task EnableTargetAsyncOption()
{
// Linux attach TODO: GDB will fail this command when attaching. This is worked around
diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs
index 3cb2d9467..e2181942c 100644
--- a/src/MICore/CommandFactories/lldb.cs
+++ b/src/MICore/CommandFactories/lldb.cs
@@ -177,6 +177,19 @@ public override Task Catch(string name, bool onlyOnce = false, ResultClass resul
throw new NotImplementedException("lldb catch command");
}
+ // TODO: update these if they become available in lldb-mi
+ public override async Task ExecJump(string filename, int line)
+ {
+ string command = "jump " + filename + ":" + line;
+ await _debugger.CmdAsync(command, ResultClass.running);
+ }
+
+ public override async Task ExecJump(ulong address)
+ {
+ string command = "jump *" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address);
+ await _debugger.CmdAsync(command, ResultClass.running);
+ }
+
///
/// Assigns the value of an expression to a variable.
/// Since LLDB only accepts assigning values to variables, the expression may need to be evaluated.
diff --git a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs
index a99f43dd4..49e179530 100755
--- a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs
+++ b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs
@@ -182,6 +182,44 @@ public object GetMetric(string metric)
return _configStore.GetEngineMetric(metric);
}
+ public int Jump(string filename, int line)
+ {
+ try
+ {
+ _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(filename, line));
+ }
+ catch (InvalidCoreDumpOperationException)
+ {
+ return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED;
+ }
+ catch (Exception e)
+ {
+ _engineCallback.OnError(EngineUtils.GetExceptionDescription(e));
+ return Constants.E_ABORT;
+ }
+
+ return Constants.S_OK;
+ }
+
+ public int Jump(ulong address)
+ {
+ try
+ {
+ _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(address));
+ }
+ catch (InvalidCoreDumpOperationException)
+ {
+ return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED;
+ }
+ catch (Exception e)
+ {
+ _engineCallback.OnError(EngineUtils.GetExceptionDescription(e));
+ return Constants.E_ABORT;
+ }
+
+ return Constants.S_OK;
+ }
+
#region IDebugEngine2 Members
// Attach the debug engine to a program.
diff --git a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs
index 318e50e2e..09bc6a277 100644
--- a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs
+++ b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs
@@ -198,6 +198,10 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo)
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION;
}
}
+ if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0)
+ {
+ // TODO:
+ }
return Constants.S_OK;
}
diff --git a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs
index b2b0a8d35..f5457c011 100644
--- a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs
+++ b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs
@@ -282,27 +282,23 @@ int IDebugThread2.Resume(out uint suspendCount)
}
// Sets the next statement to the given stack frame and code context.
+ // https://docs.microsoft.com/en-us/visualstudio/extensibility/debugger/reference/idebugthread2-setnextstatement
int IDebugThread2.SetNextStatement(IDebugStackFrame2 stackFrame, IDebugCodeContext2 codeContext)
{
- ulong addr = ((AD7MemoryAddress)codeContext).Address;
- AD7StackFrame frame = ((AD7StackFrame)stackFrame);
- if (frame.ThreadContext.Level != 0 || frame.Thread != this || !frame.ThreadContext.pc.HasValue)
- {
+ // VS does provide a frame so at least do some sanity checks
+ AD7StackFrame frame = stackFrame as AD7StackFrame;
+ if (frame != null && (frame.ThreadContext.Level != 0 || frame.Thread != this))
return Constants.S_FALSE;
- }
- string toFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, addr);
- string fromFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, frame.ThreadContext.pc.Value);
- if (toFunc != fromFunc)
+
+ try
{
- return Constants.S_FALSE;
+ ulong addr = ((AD7MemoryAddress)codeContext).Address;
+ return _engine.Jump(addr);
}
- string result = frame.EvaluateExpression("$pc=" + EngineUtils.AsAddr(addr, _engine.DebuggedProcess.Is64BitArch));
- if (result != null)
+ catch (Exception)
{
- _engine.DebuggedProcess.ThreadCache.MarkDirty();
- return Constants.S_OK;
+ return Constants.S_FALSE;
}
- return Constants.S_FALSE;
}
// suspend a thread.
diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
index eddad0aec..219c85e7d 100755
--- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
+++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
@@ -1601,6 +1601,16 @@ public Task Continue(DebuggedThread thread)
return Execute(thread);
}
+ public async Task Jump(string filename, int line)
+ {
+ await MICommandFactory.ExecJump(filename, line);
+ }
+
+ public async Task Jump(ulong address)
+ {
+ await MICommandFactory.ExecJump(address);
+ }
+
public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit)
{
this.VerifyNotDebuggingCoreDump();
diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs
index b5eb9d671..d4c5cfbd0 100644
--- a/src/OpenDebugAD7/AD7DebugSession.cs
+++ b/src/OpenDebugAD7/AD7DebugSession.cs
@@ -1326,7 +1326,37 @@ protected override void HandlePauseRequestAsync(IRequestResponder responder)
{
- responder.SetError(new ProtocolException(AD7Resources.Error_NotImplementedSetNextStatement));
+ var response = new GotoResponse();
+ if (!m_isStopped)
+ {
+ responder.SetResponse(response);
+ return;
+ }
+
+ var builder = new ErrorBuilder(() => AD7Resources.Error_UnableToSetNextStatement);
+ IDebugThread2 thread = null;
+ try
+ {
+ if (m_gotoCodeContexts.TryGetValue(responder.Arguments.TargetId, out IDebugCodeContext2 gotoTarget))
+ {
+ lock (m_threads)
+ {
+ if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread))
+ throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture));
+ }
+ BeforeContinue();
+ builder.CheckHR(thread.SetNextStatement(null, gotoTarget));
+ }
+ }
+ catch (AD7Exception e)
+ {
+ m_isStopped = true;
+ responder.SetError(new ProtocolException(e.Message));
+ return;
+ }
+
+ responder.SetResponse(response);
+ FireStoppedEvent(thread, StoppedEvent.ReasonValue.Goto);
}
protected override void HandleGotoTargetsRequestAsync(IRequestResponder responder)
@@ -1336,6 +1366,7 @@ protected override void HandleGotoTargetsRequestAsync(IRequestResponder
- /// Looks up a localized string similar to Set next statement is not supported by the current debugger..
- ///
- internal static string Error_NotImplementedSetNextStatement {
- get {
- return ResourceManager.GetString("Error_NotImplementedSetNextStatement", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to {0}: property '{1}' is invalid..
///
@@ -406,6 +397,17 @@ internal static string Error_UnableToSetBreakpoint {
}
}
+ ///
+ /// Looks up a localized string similar to Error setting next statement. {0}.
+ ///
+ internal static string Error_UnableToSetNextStatement
+ {
+ get
+ {
+ return ResourceManager.GetString("Error_UnableToSetNextStatement", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to '{0}' cannot be assigned to.
///
diff --git a/src/OpenDebugAD7/AD7Resources.resx b/src/OpenDebugAD7/AD7Resources.resx
index bc916064d..42237a129 100644
--- a/src/OpenDebugAD7/AD7Resources.resx
+++ b/src/OpenDebugAD7/AD7Resources.resx
@@ -195,6 +195,9 @@
Error setting breakpoint. {0}
+
+ Error setting next statement. {0}
+
Unable to parse 'logMessage'.
@@ -298,7 +301,4 @@
Unable to retrieve stack trace. {0}
-
- Set next statement is not supported by the current debugger.
-
\ No newline at end of file