* service/dap: remove deadlock in TestLaunchDebugRequest
Fixes#2746
* terminal: fix TestScopePrefix flakiness
When there are more than 10 frames api.PrintStack will prefix the
output with spaces to right justify the frame number, which confuses
TestScopePrefix.
* _scripts: pass -buildvcs for Go 1.18 and later on TeamCity
Go 1.18 will try to stamp builds with the VCS version, this doesn't
work on TeamCity because the checkout isn't a valid repository (but
looks like it).
Pass -buildvcs=false to disable this feature.
* proc: switch to goroutine stack if first frame's func can not be found
If the first frame on the system stack can not be resolved to a
function switch directly to the goroutine stack.
Normally calls can't be performed on recorded processes, becuase the
future instructions executed by the target are predetermined. The rr
debugger however has a mechanism that allows this by taking the current
state of the recording and allowing it to diverge from the recording,
temporarily.
This commit adds support for starting and ending such diversions around
function calls.
Note: this requires rr version 5.5 of later to work, see:
https://github.com/rr-debugger/rr/pull/2748
This adds a new `--client-addr=host:port` flag to `dlv dap`.
If it is supplied, the dap process will dial into the tcp port where
a DAP client is waiting, and work with only the DAP client.
The DAP client is supposed to start the normal DAP message
exchange starting with the 'initialize' request after the dlv dap
process dials in and the connection is set up.
VS Code Go extension plans to use this mode for
* reliably detecting `dlv dap` readiness. Currently it depends on
watching the log stream. After this PR, it can listen on a network port.
* running `dlv dap` from any terminal (part of RunInTerminal workflow
implementation).
A set breakpoints request could come in while the program is running. For a seamless user experience, the server should set the breakpoint and then continue program execution.
Updates golang/vscode-go#1676
* proc/native: always stop after RequestManualStop on Windows
On Windows RequestManualStop will generate an exception on a special
DbgUiRemoteBreakin thread, sometimes this thread will die before we
finish stopping the process. We need to account for that and still stop
even if the thread is gone and no other thread hit a breakpoint.
Fixes flakiness of TestIssue419.
* proc/native: fix watchpoints with new threads on Windows
When a new thread is created we must reapply all watchpoints to it,
like we do on linux.
* tests: be lenient on goroutinestackprog tests on Windows
We can not guarantee that we find all goroutines stopped in a good
place and sometimes the stacktrace fails on Windows.
* service/dap: refactor the server into two layers
* Add delay before setting debugger in remote tests
Co-authored-by: Polina Sokolova <polinasok@users.noreply.github.com>
Change debug_info type reader and proc to convert parametric types into
their real types by reading the corresponding dictionary entry and
using the same method used for interfaces to retrieve the DIE from a
runtime._type address.
'2586e9b1'.
With generics a single function can have multiple concrete
instantiations, the old version of FindFileLocation supported at most
one concrete instantiation per function and any number of inlined
calls, this supports any number of inlined calls and concrete
functions.
Internal breakpoints do not need IDs and assigning them from a counter
separate from the user ID counter can be a cause of confusion.
If a user breakpoint is overlayed on top of a pre-existing internal
breakpoint the temporary ID will be surfaced as if it was a user ID,
possibly conflicting with another user ID.
If a temporary breakpoint is overlayed on top of a pre-existing user
breakpoint and the user breakpoint is first deleted and then
re-created, the user ID will be resurrected along with the breakpoint,
instead of allocating a fresh one.
This change removes internal breakpoint IDs entirely, only user
breakpoints receive an ID.
Right now, if (*compositeMemory).WriteMemory needs to write a value to
a register that's smaller than the full size of the register (say, a
uint32 being passed as an argument), then (*AMD64Registers).SetReg can
later fail a sanity check that ensures the passed DwarfRegister is a
full size register.
Fix this by reading the old value of the register and overwriting just
the relevant parts with the new register. For the purposes of an
argument, it would probably be fine to just pad with zeroes, but merging
with the existing value is what gdb does.
Fixes#2698
Log points are special kinds of breakpoints that do not 'break' but instead log a message and then continue. This change implements basic log points that simply log the provided message, without any interpolation.
In order to resume execution after hitting a breakpoint, I added a new lock resumeMu and tracked the running state within the DAP server. resumeMu must be held in order to issue a debugger request that would start execution. This means it can be used to make sure that another goroutine does not resume execution while you are holding the lock.
Most of the synchronization logic is taken from PR #2530
Updates golang/vscode-go#123
When we set a limit on the number of threads that would be
returned, it was possible that the selected thread was not
included in the list of threads. This could cause issues
because the stopped reason is associated with the selected
goroutine, so users could be missing out on important info.
This change makes sure that the selected goroutine is included
by adding it to the end of the list.
Formally define these types and document their meaning.
We will auto-generate the dlv-dap documentation from these Go type doc.
mapToStruct is a helper that sets the given struct's fields with the
info in map[string]interface{} (launch/attach's Arguments). We achieve
this by reencoding map[string]interface{} to json and decoding back to
the target struct. If go-dap left the implementation-specific arguments
as json.RawMessage and let the implementation decode as needed, this
reencoding could've been avoided.
encoding/json itself does not have mean to enforce required fields.
There was a test case that checks substitutePath elements must set
both from/to fields. Path.UnmarshalJSON implements the check.
I am not yet sure about the need for distinction between missing
'from/to' and empty strings yet. (empty value is useful when dealing with
a binary built with trimpath, right?)
A minor behavior change - previously, if noDebug is not a boolean type,
we ignored the attribute silently. Since we use json decoding, any
mismatched types will cause an error and this non-boolean type noDebug
attribute will result in launch failure.
This patch enables the eBPF tracer backend to parse the ID of the
Goroutine which hit the uprobe. This implementation is specific to AMD64
and will have to be generalized further in order to be used on other
architectures.
* service/dap: add test verifying handling of relative program path
* Add exec test, log build dir and document in --help
Co-authored-by: Polina Sokolova <polinasok@users.noreply.github.com>
* service/dap: add test that verifies output path is relative to wd
* Use cleanExeName to get the right output name on Win
Co-authored-by: Polina Sokolova <polinasok@users.noreply.github.com>
Change the socket search to check both the remote and local fields of the
socket match the socket we want to find.
Sockets are identified by the 4-uple
local_addr, local_port, remote_addr, remote_port
Two socket can differ by a single one of this four elements.
It is possible for the same local_port to be used by two different sockets,
as long as they are connecting to different remote addresses (or remote
ports).
An example of this bug in action can be seen at:
https://github.com/golang/vscode-go/runs/3141270564?check_suite_focus=true
There the server starts listening on 127.0.0.1:46011 and rejects a valid
client connection by finding the following socket:
60: 0100007F:DD82 0100007F:962D 06 00000000:00000000 03:00000133 00000000 0 0 0 3 0000000000000000
the local address of this socket is 0100007F:DD82 (127.0.0.1:56706), and the
remote address is 0100007F:962D (127.0.0.1:38445).
The reported error is:
closing connection from different user (127.0.0.1:56706): connections to localhost are only accepted from the same UNIX user for security reasons
note how the local port does match the socket line (56706) but the remote
port is wrong (38445 instead of 46011).
Note also that the state of this socket is 06, or TIME_WAIT, which would be
impossible if this was the right socket, since the right socket would still
be open.
Fixes https://github.com/golang/vscode-go/issues/1555
In order for DAP to support halting the program (either manually or on a breakpoint) performing some action and then resuming execution, there needs to be a way to stop the program without clearing the internal breakpoints. This is necessary for log points and stopping the program to set breakpoints.
The debugging UI makes it seem like a user should be able to set or clear a breakpoint at any time. Adding this ability to complete synchronous requests while the program is running is thus important to create a seamless user experience.
This change just adds a configuration to determine whether the target should clear the stepping breakpoints, and changes the server to use this new mode. Using the new mode means that the DAP server must determine when it expect the next to be canceled and do this manually.