This commit adds support for starting debug sessions through special
`vscode://llvm-vs-code-extensions.lldb-dap/start?config={launch-config}`
URIs. This allows tighter integration with custom scripts. One potential
use case is providing similar functionality to `xcdebug`, see #125777
for some discussion on that use case.
The functionality was inspired by @vadimcn's CodeLLDB extension, which
[provides similar
functionality](https://github.com/vadimcn/codelldb/blob/master/MANUAL.md#debugging-externally-launched-code).
The mutex in RNBRemote::CommDataReceived protects m_rx_packets and
should extend to the end of the function to cover the read where we
check if the list is empty.
This PR fixes a race condition in debugserver where the main thread
calls MachProcess::Interrupt, setting `m_sent_interrupt_signo` while the
exception monitoring thread is checking the value of the variable.
I was on the fence between introducing a new mutex and reusing the
existing exception mutex. With the notable exception of
MachProcess::Interrupt, all the other places where we were already
locking this mutex before accessing the variable. I renamed the mutex to
make it clear that it's now protecting more than the exception messages.
Jason, while investigating a real issue, had a suspicion there was race
condition related to interrupts and I was able to narrow it down by
building debugserver with TSan.
Instead of having two discrete InputStream and OutputStream helpers,
this merges the two into a unifed 'Transport' handler.
This handler is responsible for reading the DAP message headers, parsing
the resulting JSON and converting the messages into
`lldb_dap::protocol::Message`s for both input and output.
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
This should ensure the extension only uses server mode if the binary
supports the feature, otherwise it will fallback to the existing
behavior.
Fixes#130854
Improving logging by defining new helpers for more uniform log handling.
This should help us clearly identify log messages and helps abstract the
underlying log type within the macro in case we want to update the log
handler in the future.
Per the DAP spec, the event 'body' field should contain any additional
data related to the event. I updated the lldb-dap 'statistics' extension
into the terminated event's body like:
```
{
"type": "event",
"seq": 0,
"event": "terminated",
"body": {
"$__lldb_statistics": {...}
}
}
```
This allows us to more uniformly handle event messages.
While running lldb-dap over stdin/stdout the `stdout` and `stderr` FD's
are replaced with a pipe that is reading the output to forward to the
dap client. During shutdown we were not properly restoring those FDs,
which means if any component attempted to write to stderr it would
trigger a SIGPIPE due to the pipe being closed during the shutdown
process. This can happen if we have an error reported from the
`DAP::Loop` call that would then log to stderr, such as an error parsing
a malformed DAP message or if lldb-dap crashed and it was trying to
write the stack trace to stderr.
There is one place we were not handling an `llvm::Error` if there was no
logging setup that could trigger this condition.
To address this, I updated the OutputRedirector to restore the FD to the
prior state when `Stop` is called.
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Replace Get{Signed,Unsigned} with GetInteger<T> and return std::optional
so you can distinguish between the value not being present and it being
explicitly set to the previous fail_value. All existing uses are
replaced by calling value_or(fail_value).
Continuation of #129818
This implements a memory monitor for macOS, Linux and Windows. It
registers a callback that invokes `SBDebugger::MemoryPressureDetected`
when a low memory event is detected. This is motivated by the new
server mode, where the lldb-dap process will live across multiple
debug sessions and will use more memory due to caching.
Return a std::optional<bool> from GetBoolean so you can distinguish
between the value not being present and it being explicitly set to true
or false. All existing uses are replaced by calling
`value_or(fail_value`).
Motivated by #129753
This adds a new `Protocol.{h,cpp}` for defining structured types that
represent Debug Adapter Protocol messages.
This adds static types to define well structure messages for the
protocol. This iteration includes only the basic `Event`, `Request` and
`Response` types.
These types help simplify and improve the validation of messages and
give us additional static type checks on the overall structure of DAP
messages, compared to today where we tend to use `llvm::json::Value`
directly.
In a follow-up patch I plan on adding more types as need to allow for
incrementally migrating raw `llvm::json::Value` usage to well defined
types.
---------
Co-authored-by: Adrian Vogelsgesang <adrian.vogelsgesang@tum.de>
On macOS, breakpoints are briefly unresolved between process launch and
when the dynamic loader has informed us about the loaded libraries. This
information was being forwarded by lldb-dap, but only partially. In the
event handler, we were listening for the `LocationsAdded` and
`LocationsRemoved` breakpoint events. For the scenario described above,
the latter would trigger and we'd send an event reporting the breakpoint
as unresolved. The problem is that when the breakpoint location is
resolved again, you receive a `LocationsResolved` event, not a
`LocationsAdded` event. As a result, the breakpoint would continue to
show up as unresolved in the DAP client.
I found a test that tried to test part of this behavior, but the test
was broken and disabled. I revived the test and added coverage for the
situation described above.
Fixes#112629
rdar://137968318
This adds support for launching lldb-dap in server mode. The extension
will start lldb-dap in server mode on-demand and retain the server until
the VSCode window is closed (when the extension context is disposed).
While running in server mode, launch performance for binaries is greatly
improved by improving caching between debug sessions.
For example, on my local M1 Max laptop it takes ~5s to attach for the
first attach to an iOS Simulator process and ~0.5s to attach each time
after the first.
Both spellings are considered correct and acceptable, with adapter being
more common in American English. Given that DAP stands for Debug Adapter
Protocol (with an e) let's go with that as the canonical spelling.
The main motivation for this was the inconsistency in handling of
partial reads/writes between the windows and posix implementations
(windows was returning partial reads, posix was trying to fill the
buffer completely). I settle on the windows implementation, as that's
the more common behavior, and the "eager" version can be implemented on
top of that (in most cases, it isn't necessary, since we're writing just
a single byte).
Since this also required auditing the callers to make sure they're
handling partial reads/writes correctly, I used the opportunity to
modernize the function signatures as a forcing function. They now use
the `Timeout` class (basically an `optional<duration>`) to support both
polls (timeout=0) and blocking (timeout=nullopt) operations in a single
function, and use an `Expected` instead of a by-ref result to return the
number of bytes read/written.
As a drive-by, I also fix a problem with the windows implementation
where we were rounding the timeout value down, which meant that calls
could time out slightly sooner than expected.
This simplifies the IOStream.cpp implementation by building on top of
the existing lldb::IOObjectSP.
Additionally, this should help ensure clients connected of a
`--connection` specifier properly detect shutdown requests when the
Socket is closed. Previously, the StreamDescriptor was just accessing
the underlying native handle and was not aware of the `Close()` call to
the Socket itself.
This is both nice to have for simplifying the existing code and this
unblocks an upcoming refactor to support the cancel request.
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
This refactors the response handlers for reverse request to follow the
same architecture as the request handlers. With only two implementation
that might be overkill, but it reduces code duplication and improves
error reporting by storing the sequence ID. This PR also fixes an
unchecked Expected in the old callback for unknown sequence IDs.
The TestDAP_ouput test is flaky due to the order of events during
shutdown. We were stopping the output and error handle redirection after
we finished the disconnect request, which can cause us to miss output
events due to timing. Moving when we stop the redirection to ensure we
have consistent output prior to disconnect responding.
Fixes#128567
Currently, all request handlers are implemented as free functions in
lldb-dap.cpp. That file has grown to over 5000 lines and is starting to
become hard to maintain. This PR moves the request handlers into their
own class (and file), together with their documentation.
This PR migrates about a third of the request handlers and the rest will
be migrated in subsequent commits. I'm merging this in an incomplete
state because almost any lldb-dap change is going to result in merge
conflicts and migrating request handlers one by one is easier to review.
This patch fixes:
lldb/tools/lldb-dap/lldb-dap.cpp:5184:9: error: 'scoped_lock' may
not intend to support class template argument deduction
[-Werror,-Wctad-maybe-unsupported]
lldb/tools/lldb-dap/lldb-dap.cpp:5200:7: error: 'unique_lock' may
not intend to support class template argument deduction
[-Werror,-Wctad-maybe-unsupported]
lldb/tools/lldb-dap/lldb-dap.cpp:5222:5: error: 'scoped_lock' may
not intend to support class template argument deduction
[-Werror,-Wctad-maybe-unsupported]
lldb/tools/lldb-dap/lldb-dap.cpp:5236:3: error: 'unique_lock' may
not intend to support class template argument deduction
[-Werror,-Wctad-maybe-unsupported]
This adjusts the lldb-dap listening mode to accept multiple clients.
Each client initializes a new instance of DAP and an associated
`lldb::SBDebugger` instance.
The listening mode is configured with the `--connection` option and
supports listening on a port or a unix socket on supported platforms.
When running in server mode launch and attach performance should
be improved by lldb sharing symbols for core libraries between debug
sessions.
If you have an lldb-dap log file you'll almost always see a final
message like:
```
<--
Content-Length: 94
{
"body": {
"category": "stdout",
"output": "\u0000\u0000"
},
"event": "output",
"seq": 0,
"type": "event"
}
<--
Content-Length: 94
{
"body": {
"category": "stderr",
"output": "\u0000\u0000"
},
"event": "output",
"seq": 0,
"type": "event"
}
```
The OutputRedirect is always writing the `"\0"` byte as a final stdout
message during shutdown. Instead, I adjusted this to detect the sentinel
value and break out of the read loop as if we detected EOF.
---------
Co-authored-by: Pavel Labath <pavel@labath.sk>
The Swift extension for VS Code requires that the `lldb-dap` executable
come from the Swift toolchain which may or may not be configured in
`PATH`. At the moment, this can be configured via LLDB DAP's extension
settings, but experience has shown that modifying other extensions'
settings on behalf of the user (especially those subject to change
whenever a new toolchain is selected) causes issues. Instead, it would
be easier to have this configurable in the launch configuration and let
the Swift extension (or any other extension that wanted to, really)
configure the path to `lldb-dap` that way. This allows the Swift
extension to have its own launch configuration type that delegates to
the LLDB DAP extension in order to provide a more seamless debugging
experience for Swift executables.
This PR adds a new property to the launch configuration object called
`debugAdapterExecutable` which allows overriding the `lldb-dap`
executable path for a specific debug session.
Recognize the visionOS Triple::OSType::XROS os type. Some of these have
already been landed on main, but I reviewed the downstream sources and
there were a few that still needed to be landed upstream.
This commit upgrades our npm dependencies to the latest available
version.
I was prompted to this change because `npm run package` failed for me
with an error. The error disappeared after upgrading `@vscode/vsce`. I
also upgraded the other dependencies because I think it's generally
preferable to stay up-to-date.
I did not bump the `@types/vscode` and `@types/node` versions, since
this would effectively make older VS-Code versions unsupported. I also
changed `@types/vscode` to be a precise version match, since we are
claiming compatibility with that version via the `enginges.vscode`
property.
This commit adds support for column breakpoints to lldb-dap
To do so, support for the `breakpointLocations` request was
added. To find all available breakpoint positions, we iterate over
the line table.
The `setBreakpoints` request already forwarded the column correctly to
`SBTarget::BreakpointCreateByLocation`. However, `SourceBreakpointMap`
did not keep track of multiple breakpoints in the same line. To do so,
the `SourceBreakpointMap` is now indexed by line+column instead of by
line only.
This was previously submitted as #113787, but got reverted due to
failures on ARM and macOS. This second attempt has less strict test
case expectations. Also, I added a release note.