202 Commits

Author SHA1 Message Date
fb2d9542d0 Fix bug in DAP handling of 'pause' requests
While working on cancellation, I noticed that a DAP 'pause' request
would set the "do not emit the continue" flag.  This meant that a
subsequent request that should provoke a 'continue' event would
instead suppress the event.

I then tried writing a more obvious test case for this, involving an
inferior call -- and discovered that gdb.events.cont does not fire for
an inferior call.

This patch installs a new event listener for gdb.events.inferior_call
and arranges for this to emit continue and stop events when
appropriate.  It also fixes the original bug, by adding a check to
exec_and_expect_stop.

(cherry picked from commit c618a1c548193d2a6a8c3d909a3d1c620a156b5d)
2023-11-27 09:16:46 -07:00
17f2cab5f8 Ignore static members in NoOpStructPrinter
Hannes' patch to show local variables in the TUI pointed out that
NoOpStructPrinter should ignore static members.  This patch implements
this.

(cherry picked from commit 4a1b9a4badc8954221926b231b81392fa625653c)
2023-11-17 08:43:04 -07:00
fa2cc08fdd Implement the notStopped DAP response
DAP specifies that a request can fail with the "notStopped" message if
the inferior is running but the request requires that it first be
stopped.

This patch implements this for gdb.  Most requests are assumed to
require a stopped inferior, and the exceptions are noted by a new
'request' parameter.

You may notice that the implementation is a bit racy.  I think this is
inherent -- unless the client waits for a stop event before sending a
request, the request may be processed at any time relative to a stop.

https://sourceware.org/bugzilla/show_bug.cgi?id=31037

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>

(cherry picked from commit cfd00e8050a58aacc6489ec0379908be1a12be73)
2023-11-17 08:43:04 -07:00
c558c8d5f6 Remove ExecutionInvoker
ExecutionInvoker is no longer really needed, due to the previous DAP
refactoring.  This patch removes it in favor of an ordinary function.
One spot (the 'continue' request) could still have used it, but is
more succinctly expressed as a lambda.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>

(cherry picked from commit 68caad9d0b06d0ac231ce083ff62410a5a1806c1)
2023-11-17 08:43:04 -07:00
de5b5fcb89 Automatically run (most) DAP requests in gdb thread
Nearly every DAP request implementation forwards its work to the gdb
thread, using send_gdb_with_response.  This patch refactors the
'request' decorator to make this automatic, and to provide some
parameters so that the unusual requests can express their needs as
well.

In a few spots this simplifies the code by removing an unnecessary
helper function.  This could be done in more places as well if we
wanted.

The main motivation for this patch is that I thought it would be
helpful for cancellation.  I am still working on that, but meanwhile
the parameterization of 'request' makes it easy to handle the
'notStopped' response as well.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
(cherry picked from commit c98921b258b55272c5b4066d96441e4e07626eb2)
2023-11-17 08:43:04 -07:00
45b2be6618 Handle StackFrameFormat in DAP
DAP specifies a StackFrameFormat object that can be used to change how
the "name" part of a stack frame is constructed.  While this output
can already be done in a nicer way (and also letting the client choose
the formatting), nevertheless it is in the spec, so I figured I'd
implement it.

While implementing this, I discovered that the current code does not
correctly preserve frame IDs across requests.  I rewrote frame
iteration to preserve this, and it turned out to be simpler to combine
these patches.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30475

(cherry picked from commit 1920148904fe5ca0035c1addf2376f9ab13ffd3d)
2023-11-17 07:16:39 -07:00
add31fcb87 Handle the static link in FrameDecorator
A co-worker requested that the DAP scope for a nested function's frame
also show the variables from outer frames.  DAP doesn't directly
support this notion, so this patch arranges to put these variables
into the inner frames "Locals" scope.

I chose to do this only for DAP.  For CLI and MI, gdb currently does
not do this, so this preserves the behavior.

Note that an earlier patch (see commit 4a1311ba) removed some code
that seemed to do something similar.  However, that code did not
actually work.

(cherry picked from commit ebea770b19c09489fe5e2cb5c1fd568f0f21e17e)
2023-11-14 08:49:55 -07:00
d31566acb7 Fix a bug in DAP scopes code
While working on static links, I noticed that the DAP scopes code does
not handle the scenario where a frame decorator returns None.  This
situation should be handled identically to a frame decorator returning
an empty iterator.

(cherry picked from commit e9dacb1d6caa5770d3e1722adc0ec74ff13a7a89)
2023-11-14 08:49:55 -07:00
618bc9302e Implement DAP setVariable request
This patch implements the DAP setVariable request.

setVariable is a bit odd in that it specifies the variable to modify
by passing in the variable's container and the name of the variable.
This approach can't handle variable shadowing (there are a couple of
open DAP bugs on this topic), so this patch renames duplicates to
avoid the problem.

(cherry picked from commit 87e3cc466e8ea352639beb6db40a36e339d608d1)
2023-10-31 11:54:48 -06:00
2aabf131da Have DAP handle non-Value results from 'children'
A pretty-printer's 'children' method may return values other than a
gdb.Value -- it may return any value that can be converted to a
gdb.Value.

I noticed that this case did not work for DAP.  This patch fixes the
problem.
2023-10-16 09:49:02 -06:00
ba0725dfa0 Handle gdb.LazyString in DAP
Andry pointed out that the DAP code did not properly handle
gdb.LazyString results from a pretty-printer, yielding:

    TypeError: Object of type LazyString is not JSON serializable

This patch fixes the problem, partly with a small patch in varref.py,
but mainly by implementing tp_str for LazyString.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-10-16 09:28:22 -06:00
c1edbcf2ba Add DAP scope cache
Andry Ogorodnik, a co-worker, noticed that multiple "scopes" requests
with the same frame would yield different variableReference values in
the response.

This patch adds a regression test for this, and adds a scope cache in
scopes.py, ensuring that multiple identical requests will get the same
response.

Tested-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
2023-10-16 09:06:17 -06:00
54e053874d Remove some unnecessary qualification from printing.py
printing.py references "gdb.printing" in a few spots, but there's no
need for this.  I think this is leftover from when this code was
(briefly) in some other module.  This patch removes the unnecessary
qualifications.  Tested on x86-64 Fedora 36.
2023-09-26 09:51:56 -06:00
f35baff348 Add two new pretty-printer methods
This adds two new pretty-printer methods, to support random access to
children.  The methods are implemented for the no-op array printer,
and DAP is updated to use this.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-09-26 09:29:14 -06:00
fb28257699 Introduce gdb.ValuePrinter
There was an earlier thread about adding new methods to
pretty-printers:

https://sourceware.org/pipermail/gdb-patches/2023-June/200503.html

We've known about the need for printer extensibility for a while, but
have been hampered by backward-compatibilty concerns: gdb never
documented that printers might acquire new methods, and so existing
printers may have attribute name clashes.

To solve this problem, this patch adds a new pretty-printer tag class
that signals to gdb that the printer follows new extensibility rules.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30816
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-09-26 09:29:14 -06:00
fc21e0f029 [gdb/dap] Fix dap for python < 3.8
With any gdb.dap test and python 3.6 I run into:
...
Error occurred in Python: 'code' object has no attribute 'co_posonlyargcount'
ERROR: eof reading json header
...

The attribute is not supported before python 3.8, which introduced the
"Positional−only Parameters" concept.

Fix this by using try/except AttributeError.

Tested on x86_64-linux:
- openSUSE Leap 15.4 with python 3.6, and
- openSUSE Tumbleweed with python 3.11.5.

Approved-By: Tom Tromey <tom@tromey.com>
2023-09-26 15:51:27 +02:00
2bcbfaeadc Remove stray trailing "," from DAP breakpoint.py
The buildbot pointed out that the last DAP series I checked in had an
issue.  Looking into it, it seems there is a stray trailing "," in
breakpoint.py.  This patch removes it.

This seems to point out a test suite deficiency.  I will look into
fixing that.
2023-09-20 17:09:13 -06:00
0b7de6d3ee gdb/dap: only include sourceReference if file path does not exist
According to the DAP specification if the "sourceReference" field is
included in a Source object, then the DAP client _must_ make a "source"
request to the debugger to retrieve file contents, even if the Source
object also includes path information.

If the Source's path field is a valid path that the DAP client is able
to read from the filesystem, having to make another request to the
debugger to get the file contents is wasteful and leads to incorrect
results (DAP clients will try to get the contents from the server and
display those contents as a file with the name in "source.path", but
this will conflict with the _acutal_ existing file at "source.path").

Instead, only set "sourceReference" if the source file path does not
exist.

Approved-By: Tom Tromey <tom@tromey.com>
2023-09-20 10:59:47 -06:00
61830fcb31 gdb/dap: use breakpoint fullname to resolve source
If the breakpoint has a fullname, use that as the source path when
resolving the breakpoint source information. This is consistent with
other callers of make_source which also use "fullname" if it exists (see
e.g. DAPFrameDecorator which returns the symtab's fullname).

Approved-By: Tom Tromey <tom@tromey.com>
2023-09-20 10:59:43 -06:00
d2266b2305 gdb/dap: ignore unused keyword args in step_out
Some DAP clients may send additional parameters in the stepOut command
(e.g. "granularity") which are not used by GDB, but should nonetheless
be accepted without error.

Approved-By: Tom Tromey <tom@tromey.com>
2023-09-20 10:59:38 -06:00
155f5df517 gdb/dap: check for breakpoint source before unpacking
Not all breakpoints have a source location. For example, a breakpoint
set on a raw address will have only the "address" field populated, but
"source" will be None, which leads to a RuntimeError when attempting to
unpack the filename and line number.

Before attempting to unpack the filename and line number from the
breakpoint, ensure that the source information is not None. Also
populate the source and line information separately from the
"instructionReference" field, so that breakpoints that include only an
address are still included.

Approved-By: Tom Tromey <tom@tromey.com>
2023-09-20 10:59:32 -06:00
4abf53c991 Run 'black' on printing.py
The buildbot pointed out that I neglected to re-run 'black' after
making some changes.  This patch fixes the oversight.
2023-09-20 10:43:04 -06:00
a56e5dce69 Handle pointers and references correctly in DAP
A user pointed out that the current DAP variable code does not let the
client deference a pointer.  Oops!

Fixing this oversight is simple enough -- adding a new no-op
pretty-printer for pointers and references is quite simple.

However, doing this naive caused a regession in scopes.exp, which
expected there to be no children of a 'const char *' variable.  This
problem was fixed by the preceding patches in the series, which ensure
that a C type of this kind is recognized as a string.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30821
2023-09-19 13:28:42 -06:00
f8ab027008 Avoid spurious breakpoint-setting failure in DAP
A user pointed out that if a DAP setBreakpoints request has a 'source'
field in a SourceBreakpoint object, then the gdb DAP implementation
will throw an exception.

While SourceBreakpoint does not allow 'source' in the spec, it seems
better to me to accept it.  I don't think we should fully go down the
"Postel's Law" path -- after all, we have the type-checker -- but at
the same time, if we do send errors, they should be intentional and
not artifacts of the implementation.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30820
2023-09-12 10:31:26 -06:00
708cedb722 Handle array- and string-like values in no-op pretty printers
This changes the no-op pretty printers -- used by DAP -- to handle
array- and string-like objects known by the gdb core.  Two new tests
are added, one for Ada and one for Rust.
2023-09-05 11:10:24 -06:00
91c7233d2d Select frame when fetching a frame variable in DAP
Right now, if a program uses multiple languages, DAP value formatting
will always use the language of the innermost frame.  However, it is
better to use the variable's defining frame instead.  This patch does
this by selecting the frame first.

This also fixes a possibly latent bug in the "stepOut" command --
"finish" is sensitive to the selected frame, but the DAP code may
already select other frames when convenient.  The DAP stepOut request
only works on the newest frame, so be sure to select it before
invoking "finish".
2023-09-05 11:03:02 -06:00
100dbc6de5 Implement DAP module-removed event
DAP specifies an event that should be sent when a module is removed.
This patch implements this.

Tested-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
2023-08-16 09:55:10 -06:00
5c9adb880e Remove f-string from DAP
One more f-string snuck into the DAP code, in breakpoint.py.  Most of
them were removed here:

    https://sourceware.org/pipermail/gdb-patches/2023-June/200023.html

but I think this one landed after that patch.

While DAP only supports Python 3.5 and later, f-strings were added in
3.6, so remove this.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30708
2023-08-03 10:27:00 -06:00
30baee6865 Use frame.name() in FrameDecorator
A co-worker pointed out that gdb's DAP implementation might return an
integer for the name of a stack frame, like:

    {"id": 1, "name": 93824992310799, ...}

This can be seen currently in the logs of the bt-nodebug.exp test
case.

What is happening is that FrameDecorator falls back on returning the
PC when the frame's function symbol cannot be found, relying on the
gdb core to look up the minsym and print its name.

This can actually yield the wrong answer sometimes, because it falls
into the get_frame_pc / get_frame_address_in_block problem -- if the
frame is at a call to a noreturn function, the PC in this case might
appear to be in the next function in memory.  For more on this, see:

    https://sourceware.org/bugzilla/show_bug.cgi?id=8416

and related bugs.

However, there's a different approach we can take: the code here can
simply use Frame.name.  This handles the PC problem correctly, and
gets us the information we need.
2023-08-03 09:35:38 -06:00
13bd1a9175 Implement DAP "source" request
This implements the DAP "source" request.  I renamed the
"loadedSources" function from "sources" to "loaded_sources" to avoid
any confusion.  I also moved the loadedSources test to the new
sources.exp.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30691
2023-08-01 13:14:47 -06:00
4b6521cf69 Handle Source in DAP breakpointLocations
This changes the DAP breakpointLocations request to accept a Source
and to decode it properly.
2023-08-01 13:12:24 -06:00
c64cba1b56 Introduce sourceReference handling in DAP
This changes the gdb DAP implementation to emit a real
sourceReference, rather than emitting 0.  Sources are tracked in some
maps in sources.py, and a new helper function is introduced to compute
the "Source" object that can be sent to the client.
2023-08-01 13:12:22 -06:00
7b4a5561e4 Don't supply DAP 'path' for non-file shared libraries
The DAP 'module' event may include a 'path' component.  I noticed that
this is supplied even when the module in question does not come from a
file.

This patch only emits this field when the objfile corresponds to a
real file.

No test case, because I wasn't sure how to write a portable one.
However, it's clear from gdb.log on Linux:

{"type": "event", "event": "module", "body": {"reason": "new", "module": {"id": "system-supplied DSO at 0x7ffff7fc4000", "name": "system-supplied DSO at 0x7ffff7fc4000"}}, "seq": 21}

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30676
2023-08-01 13:06:53 -06:00
e137699884 Implement ValueFormat for DAP
This patch implements ValueFormat for DAP.  Currently this only means
supporting "hex".

Note that StackFrameFormat is defined to have many more options, but
none are currently recognized.  It isn't entirely clear how these
should be handled.  I'll file a new gdb bug for this, and perhaps an
upstream DAP bug as well.

New in v2:
- I realized that the "hover" context was broken, and furthermore
  that we only had tests for "hover" failing, not for it succeeding.
  This version fixes the oversight and adds a test.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30469
2023-08-01 13:03:31 -06:00
2128d888b8 Respect supportsMemoryReferences in DAP
I noticed that the support for memoryReference in the "variables"
output is gated on the client "supportsMemoryReferences" capability.

This patch implements this and makes some other changes to the DAP
memory reference code:

* Remove the memoryReference special case from _SetResult.
  Upstream DAP fixed this oversight in response to
  https://github.com/microsoft/debug-adapter-protocol/issues/414

* Don't use the address of a variable as its memoryReference -- only
  emit this for pointer types.  There's no spec support for the
  previous approach.

* Use strip_typedefs to handle typedefs of pointers.
2023-08-01 13:00:57 -06:00
af93035b27 Add DAP support for C++ exceptions
This adds DAP support for the various C++ exception-catching
operations.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30682
2023-08-01 12:59:02 -06:00
21db866dc6 Implement DAP 'terminated' event
This implements the DAP 'terminated' event.  Vladimir Makaev noticed
that VSCode will not report the debug session as over unless this is
sent.

It's not completely clear when exactly this event ought to be sent.
Here I've done it when the inferior exits.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30681
2023-08-01 12:56:52 -06:00
8a8a5ccadd Do not send "new breakpoint" event when breakpoint is set
When the DAP client sets a breakpoint, gdb currently sends a "new
breakpoint" event.  However, Vladimir Makaev discovered that this
causes VSCode to think there are two breakpoints.

This patch changes gdb to suppress the event in this case.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30678
2023-08-01 12:54:52 -06:00
e982d96cd6 Move DAP breakpoint event code to breakpoint.py
A subsequent patch will add the ability to suppress breakpoint events
to DAP.  My first attempt at this ended up with recurse imports,
causing Python failures.  So, this patch moves all the DAP breakpoint
event code to breakpoint.py in preparation for the change.

I've renamed breakpoint_descriptor here as well, because it can now be
private to breakpoint.py.
2023-08-01 12:54:44 -06:00
65403bd0ed Full paths in DAP stackTrace responses
Vladimir Makaev noticed that, in some cases, a DAP stackTrace response
would include a relative path name for the "path" component.

This patch changes the frame decorator code to add a new DAP-specific
decorator, and changes the DAP entry point to frame filters to use it.
This decorator prefers the symtab's full name, and does not fall back
to the solib's name.

I'm not entirely happy with this patch, because if a user frame filter
uses FrameDecorator, it may still do the wrong thing.  It would be
better to have frame filters return symtab-like objects instead, or to
have a separate method to return the full path to the source file.

I also tend to think that the solib fallback behavior of
FrameDecorator is a mistake.  If this is ever needed, it seems to me
that it should be a separate method.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30665
2023-08-01 12:52:26 -06:00
f131a57908 Add "cwd" parameter to DAP launch request
This adds the "cwd" parameter to the DAP launch request.

This came up here:
    https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/90
... and seemed like a good idea.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-08-01 12:52:26 -06:00
f3337b1e94 Rename private member of FrameDecorator
In Python, a member name starting with "__" is specially handled to
make it "more private" to the class -- it isn't truly private, but it
is renamed to make it less likely to be reused by mistake.  This patch
ensures that this is done for the private method of FrameDecorator.
2023-08-01 12:52:26 -06:00
a18b53a8f6 Add thread exited event
Reports a thread exit according to the DAP spec:
https://microsoft.github.io/debug-adapter-protocol/specification#Events_Thread

This patch requires the ThreadExitedEvent to be checked in,
in order to work. That patch is found here https://sourceware.org/pipermail/gdb-patches/2023-June/200071.html

Formatted correctly using black

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30474

Approved-By: Tom Tromey <tom@tromey.com>
2023-08-01 18:14:59 +02:00
30c01bb104 Restore previous sigmask in gdb.block_signals
Tom de Vries found a bug where, sometimes, a SIGCHLD would be
delivered to a non-main thread, wreaking havoc.

The problem is that gdb.block_signals after first blocking a set of
signals, then unblocked the same set rather than restoring the initial
situation.  This function being called from the DAP thread lead to
SIGCHLD being unblocked there.

This patch fixes the problem by restoring the previous set of signals
instead.

Tested-by: Tom de Vries <tdevries@suse.de>
Reviewed-By: Tom de Vries <tdevries@suse.de>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30680
2023-07-31 06:35:32 -06:00
2f01a2b9ea Report supportsBreakpointLocationsRequest
While looking at the DAP spec, I noticed that the breakpointLocations
request is gated behind a capability.  This patch changes gdb to
report this capability.

I've also added a comment to explain the fact that arguments to
breakpointLocations are not optional, even though the spec says they
are.
2023-07-27 10:35:00 -06:00
338b21b088 Use 'name' in DAP start_thread function
The DAP start_thread helper function has a 'name' parameter that is
unused.  Apparently I forgot to hook it up to the thread constructor.
This patch fixes the oversight.
2023-07-23 15:08:40 -06:00
560c121c20 Export gdb.block_signals and create gdb.Thread
While working on an experiment, I realized that I needed the DAP
block_signals function.  I figured other developers may need it as
well, so this patch moves it from DAP to the gdb module and exports
it.

I also added a new subclass of threading.Thread that ensures that
signals are blocked in the new thread.

Finally, this patch slightly rearranges the documentation so that
gdb-side threading issues and functions are all discussed in a single
node.
2023-07-23 14:33:44 -06:00
8a35f6b30a Implement DAP modules request
This implements the DAP "modules" request, and also arranges to add
the module ID to stack frames.
2023-07-21 12:05:30 -06:00
672c55ddcf Remove unused imports
I noticed an unused import in dap/evaluate.py; and also I found out
that my recent changes to use frame filters from DAP left some unused
imports in dap/bt.py.
2023-07-21 12:05:30 -06:00
812e7caf60 Add instruction bytes to DAP disassembly response
The DAP disassemble command lets the client return the underlying
bytes of the instruction in an implementation-defined format.  This
patch updates gdb to return this, and simply uses a hex string of the
bytes as the format.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-07-21 09:30:12 -06:00