Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement Jump to Line #1042

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

implement Jump to Line #1042

wants to merge 2 commits into from

Conversation

Trass3r
Copy link
Contributor

@Trass3r Trass3r commented Sep 6, 2020

src/MICore/CommandFactories/gdb.cs Outdated Show resolved Hide resolved
src/MICore/CommandFactories/gdb.cs Outdated Show resolved Hide resolved
src/MICore/CommandFactories/lldb.cs Show resolved Hide resolved
src/OpenDebugAD7/AD7DebugSession.cs Outdated Show resolved Hide resolved
src/OpenDebugAD7/AD7DebugSession.cs Outdated Show resolved Hide resolved
@Trass3r
Copy link
Contributor Author

Trass3r commented Sep 6, 2020

Done.
Interestingly it won't return multiple targets as gdb's info line only returns one for:

template <typename T>
int foo(T t)
{
    return 0;
}

var response = new GotoTargetsResponse();

var source = responder.Arguments.Source;
// TODO: handle this for disassembly debugging
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// TODO: handle this for disassembly debugging [](start = 12, length = 46)

I feel like the right want to handle disassembly is to add a gotoInstruction request which would take a instructionReference and offset (like "InstructionBreakpoint")

/// <summary>
/// Jumps to a specified target location
/// </summary>
abstract public Task ExecJump(string filename, int line);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abstract public Task ExecJump(string filename, int line); [](start = 8, length = 57)

Same

@WardenGnaw WardenGnaw changed the base branch from master to main September 11, 2020 21:29
@WardenGnaw WardenGnaw self-assigned this Oct 28, 2020
Copy link
Member

@WardenGnaw WardenGnaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some fixes in 9696770

@gregg-miskelly

We get some weirdness since GoToRequest assumes the process is always stopped but the way GDB handles -exec-jump, it causes it to resume the process, so a temporary breakpoint is used.
However, in between the GoTo Request and before we get stopped at the temporary breakpoint, we get a StackTraceRequest. But since we are not stopped, we return no frames.

Thoughts on how to address this issue and my other comment about freezing other threads in a comment below?

private async Task JumpInternal(string target)
{
// temporary breakpoint + jump
await _debugger.CmdAsync("-break-insert -t " + target, ResultClass.done);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this temporary breakpoint not registered, when we get a stopping event it will be unknown and returned as an exception.

_callback.OnException(thread, "Unknown breakpoint", "", 0);

I think we need to treat this as an async break.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by not registered?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On stopping and when it is a breakpoint, we go through a list of breakpoints:

AD7BoundBreakpoint[] bkpt = _breakpointManager.FindHitBreakpoints(bkptno, addr, frame, out fContinue);

If if there are none, we assume it is an entrypoint breakpoint, embedded, we hit a bp pending deletion, or it is an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. It does receive a breakpoint-modified event and disp is "del" fwiw.

<-1067-break-insert -t *0x5555555573B1
->1067^done,bkpt={number="3",type="breakpoint",disp="del",enabled="y",addr="0x00005555555573b1",func="main(int, "...
<-1068-exec-jump *0x5555555573B1
->1068^running
->*running,thread-id="all"
->=breakpoint-modified,bkpt={number="3",type="breakpoint",disp="del",enabled="y",addr="0x00005555555573b1",func="main(int, "...
->*stopped,reason="breakpoint-hit",disp="del",bkptno="3",frame={addr="0x00005555555573b1",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffdb68"}],file="../test.cpp",fullname="/tmp/test.cpp",line="28",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="6"
->=breakpoint-deleted,id="3"

src/MICore/CommandFactories/gdb.cs Show resolved Hide resolved
}
targets.Add(new GotoTarget(m_gotoCodeContexts.Create(codeContext), contextName, line));

int codeContextId = m_nextContextId++;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this need to be atomic if multiple simultaneous requests are expected?

public async Task Jump(string filename, int line)
{
await MICommandFactory.ExecJump(filename, line);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to remove all the overloads that use filename and line number since we always seem to use the overload that take the address.

}
BeforeContinue();
builder.CheckHR(thread.SetNextStatement(null, gotoTarget));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} [](start = 16, length = 1)

We need to throw if this if is false.

@WardenGnaw
Copy link
Member

We are looking into splitting GoToTargets and the GoTo Request.

@Trass3r
Copy link
Contributor Author

Trass3r commented Jan 29, 2021

@WardenGnaw Squashed and also removed the obsolete resource string.

I also added a test commit using set $pc = instead of the jump command (see https://sourceware.org/gdb/current/onlinedocs/gdb/Jumping.html).
This avoids all the potential temporary breakpoint problems discussed earlier but lacks the sanity checks that lead to Unreasonable jump request if jumping to a different function for example. We have some checks in SetNextStatement/CanSetNextStatement which are VS-only though. I guess that filtering should be done in the GotoTargets request already.

Other than that gdb's jump cmd is equal to set $pc + continue it seems and lldb's is just set $pc under the hood.

@@ -216,6 +216,7 @@ public int Jump(ulong address)
_engineCallback.OnError(EngineUtils.GetExceptionDescription(e));
return Constants.E_ABORT;
}
DebuggedProcess.ThreadCache.MarkDirty();
Copy link
Contributor Author

@Trass3r Trass3r Jan 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed to update the current line in the UI. Is it the right place?

@@ -1344,7 +1344,7 @@ protected override void HandleGotoRequestAsync(IRequestResponder<GotoArguments>
if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread))
throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture));
}
BeforeContinue();
//BeforeContinue();
builder.CheckHR(thread.SetNextStatement(null, gotoTarget));
Copy link
Contributor Author

@Trass3r Trass3r Jan 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to remove?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want BeforeContinue. The other debug adapter that the VS debugger team owns currently doesn't clear our handle collections on SetNextStatement, but you are probably correct that it should. But we should check VS Code and make sure it is happy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah idk technically it doesn't run the program but on the other hand the current line of code needs to be updated. The thread cache invalidation worked in VSCode.

@@ -201,6 +201,8 @@ public override Task ExecJump(string filename, int line)

public override Task ExecJump(ulong address)
{
return _debugger.ConsoleCmdAsync("set $pc = " + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address), false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is if some kind of error handling is needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally yes, but since this is a non-MI command, there aren't wonderful options for knowing it is succeeded. I am not sure if GDB supports assigning to $pc through MI commands instead (-var-assign?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it but requires a variable object incl. creation/deletion (possibly just once): https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html

@FabianoGK
Copy link

If I may ask, what is the state of this pull request? Is there additional things to discuss?
I'm really excited to see this ready for vscode-cppdbg!

@Trass3r
Copy link
Contributor Author

Trass3r commented Mar 12, 2021

See all the comments after my last commit.

@FabianoGK
Copy link

Eclipse GDB debugger has two commands around -exec-jump: Move to Line, and Resume at Line.

In the Move to Line, it does insert a breakpoint and then jumps:

480,319 100-break-insert -t -p 1 -f /projects/test/test.cpp:160
480,326 100^done,bkpt={number="7",type="breakpoint",disp="del",enabled="y",addr="0x0004fb78",func="main(int, char**)",file="../src/test.cpp",fullname="/projects/test/test.cpp",line="160",thread-groups=["i1"],thread="1",thread="1",times="0",original-location="/projects/test/test.cpp:160"}
480,326 (gdb) 
480,327 101-exec-jump --thread 1 /projects/test/test.cpp:160
480,333 101^running
480,333 *running,thread-id="all"
480,333 (gdb) 
480,345 =breakpoint-modified,bkpt={number="7",type="breakpoint",disp="del",enabled="y",addr="0x0004fb78",func="main(int, char**)",file="../src/test.cpp",fullname="/projects/test/test.cpp",line="160",thread-groups=["i1"],thread="1",thread="1",times="1",original-location="/projects/test/test.cpp:160"}
480,365 ~"\nTemporary breakpoint "
480,366 ~"7, main (argc=1, argv=0xbefffd94) at ../src/test.cpp:160\n"
480,367 ~"160\t\tTest();\n"
480,367 *stopped,reason="breakpoint-hit",disp="del",bkptno="7",frame={addr="0x0004fb78",func="main",args=[{name="argc",value="1"},{name="argv",value="0xbefffd94"}],file="../src/test.cpp",fullname="/projects/test/test.cpp",line="160"},thread-id="1",stopped-threads="all",core="0"
480,367 =breakpoint-deleted,id="7"

In the Resume at Line, it just does the jump:

688,000 171-exec-jump --thread 1 /projects/test/test.cpp:131
688,009 171^running
688,009 *running,thread-id="all"
688,009 (gdb)

Visual Studio Set Next Statement behavior is the same as Eclipse's Move to Line. In other words, it does not continue the program execution.

@Trass3r
Copy link
Contributor Author

Trass3r commented May 4, 2021

480,327 101-exec-jump --thread 1 /projects/test/test.cpp:160
480,333 101^running
480,333 *running,thread-id="all"

That --thread parameter doesn't seem to exist:
https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Program-Execution.html

@Trass3r Trass3r requested a review from WardenGnaw May 4, 2021 21:49
@FabianoGK
Copy link

The Context Management talks about the ‘--thread’ parameter:

each MI command should explicitly specify which thread and frame to operate on. To make it possible, each MI command accepts the ‘--thread’ and ‘--frame’ options, the value to each is GDB global identifier for thread and frame to operate on.

https://sourceware.org/gdb/current/onlinedocs/gdb/Context-management.html#Context-management

@Trass3r
Copy link
Contributor Author

Trass3r commented May 5, 2021

Interesting. But it doesn't make a difference here as it still runs all threads:

*running,thread-id="all"

So it could still theoretically break in another thread first.
But if Eclipse is using the same temp bp method it probably doesn't happen in practice.

@FabianoGK
Copy link

Interesting. But it doesn't make a difference here as it still runs all threads:

*running,thread-id="all"

So it could still theoretically break in another thread first.
But if Eclipse is using the same temp bp method it probably doesn't happen in practice.

Interesting observation indeed. I had to turn on non-stop mode in order to behave as expected:

1: (53481) <-1151-exec-jump --thread 2 test.cpp:24
1: (53483) ->1151^running
1: (53483) ->*running,thread-id="2"

@Trass3r
Copy link
Contributor Author

Trass3r commented May 6, 2021

And there's also scheduler-locking mode, very convoluted.

@aallrd
Copy link

aallrd commented Nov 5, 2021

Hello,
What is still required to merge this development?

@Trass3r
Copy link
Contributor Author

Trass3r commented Nov 5, 2021

See all the open discussions. There were some points without final resolution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support "set-next-statement" with cppdbg
6 participants