VScode now sends a "scopes" DAP request immediately after any expression evaluation.
This scopes request would clear and invalidate any non-scoped expandable variables in g_vsc.variables, causing later "variables" request to return empty result.
The symptom is that any expandable variables in VScode watch window/debug console UI to return empty content.
This diff fixes this issue by only clearing the expandable variables at process continue time. To achieve this, we have to repopulate all scoped variables
during context switch for each "scopes" request without clearing global expandable variables.
So the PR puts the scoped variables into its own locals/globals/registers; and all expandable variables into separate "expandableVariables" list.
Also, instead of using the variable index for "variableReference", it generates a new variableReference id each time as the key of "expandableVariables".
As a further new feature, this PR adds a new "expandablePermanentVariables" which has the lifetime of debug session. Any expandable variables from debug console
are added into this list. This enables users to snapshot expanable old variable in debug console and compare with new variables if desire.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D105166
When the number of shared libs is massive, there could be hundreds of
thousands of short lived progress events sent to the IDE, which makes it
irresponsive while it's processing all this data. As these small jobs
take less than a second to process, the user doesn't even see them,
because the IDE only display the progress of long operations. So it's
better not to send these events.
I'm fixing that by sending only the events that are taking longer than 5
seconds to process.
In a specific run, I got the number of events from ~500k to 100, because
there was only 1 big lib to parse.
I've tried this on several small and massive targets, and it seems to
work fine.
Differential Revision: https://reviews.llvm.org/D101128
A few users recently were trying to set environment values when using lldb-vscode and were unsure of the format of the "env" launch configuration setting. Clarify the exact format as when users add the "env" launch config setting, they can see this help string in the IDE.
Differential Revision: https://reviews.llvm.org/D104578
When the number of shared libs is massive, there could be hundreds of
thousands of short lived progress events sent to the IDE, which makes it
irresponsive while it's processing all this data. As these small jobs
take less than a second to process, the user doesn't even see them,
because the IDE only display the progress of long operations. So it's
better not to send these events.
I'm fixing that by sending only the events that are taking longer than 5
seconds to process.
In a specific run, I got the number of events from ~500k to 100, because
there was only 1 big lib to parse.
I've tried this on several small and massive targets, and it seems to
work fine.
Differential Revision: https://reviews.llvm.org/D101128
If an inferior exits prior to the processing of a disconnect request,
then the threads executing EventThreadFunction and request_discontinue
respectively may call SendTerminatedEvent simultaneously, in turn,
testing and/or setting g_vsc.sent_terminated_event without any
synchronization. In case the thread executing EventThreadFunction sets
it before the thread executing request_discontinue has had a chance to
test it, the latter would move ahead to issue a response to the
disconnect request. Said response may be dispatched ahead of the
terminated event compelling the client to terminate the debug session
without consuming any console output that might've been generated by
the execution of terminateCommands.
Reviewed By: clayborg, wallace
Differential Revision: https://reviews.llvm.org/D103609
The C headers are deprecated so as requested in D102845, this is replacing them
all with their (not deprecated) C++ equivalent.
Reviewed By: shafik
Differential Revision: https://reviews.llvm.org/D103084
As a follow up of https://reviews.llvm.org/D99989#inline-953343, I'm now
storing std::string instead of char *. I know it might never break as char *,
but if it does, chasing that bug might be dauting.
Besides, I'm also checking of the strings gotten through the SB API are
null or not.
Introduce three new stop reasons for fork, vfork and vforkdone events.
This includes server support for serializing fork/vfork events into
gdb-remote protocol. The stop infos for the two base events take a pair
of PID and TID for the newly forked process.
Differential Revision: https://reviews.llvm.org/D100196
Some linters get rather upset upon seeing
`std::unordered_map<const char*`, because it looks like a map of
strings but isn't. lldb uses interned strings so this is not a problem.
DenseMap is a better data structure for this anyways, so use that
instead.
VSCode doesn't render multiple variables with the same name in the variables view. It only renders one of them. This is a situation that happens often when there are shadowed variables.
The nodejs debugger solves this by adding a number suffix to the variable, e.g. "x", "x2", "x3" are the different x variables in nested blocks.
In this patch I'm doing something similar, but the suffix is " @ <file_name:line>), e.g. "x @ main.cpp:17", "x @ main.cpp:21". The fallback would be an address if the source and line information is not present, which should be rare.
This fix is only needed for globals and locals. Children of variables don't suffer of this problem.
When there are shadowed variables
{F16182150}
Without shadowed variables
{F16182152}
Modifying these variables through the UI works
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D99989
In certain occasions times, like when LLDB is initializing and
evaluating the .lldbinit files, it tries to print to stderr and stdout
directly. This confuses the IDE with malformed data, as it talks to
lldb-vscode using stdin and stdout following the JSON RPC protocol. This
ends up terminating the debug session with the user unaware of what's
going on. There might be other situations in which this can happen, and
they will be harder to debug than the .lldbinit case.
After several discussions with @clayborg, @yinghuitan and @aadsm, we
realized that the best course of action is to simply redirect stdout and
stderr to the console, without modifying LLDB itself. This will prove to
be resilient to future bugs or features.
I made the simplest possible redirection logic I could come up with. It
only works for POSIX, and to make it work with Windows should be merely
changing pipe and dup2 for the windows equivalents like _pipe and _dup2.
Sadly I don't have a Windows machine, so I'll do it later once my office
reopens, or maybe someone else can do it.
I'm intentionally not adding a stop-redirecting logic, as I don't see it
useful for the lldb-vscode case (why would we want to do that, really?).
I added a test.
Note: this is a simpler version of D80659. I first tried to implement a
RIIA version of it, but it was problematic to manage the state of the
thread and reverting the redirection came with some non trivial
complexities, like what to do with unflushed data after the debug
session has finished on the IDE's side.
This diff ass postRunCommands, which are the counterpart of the preRunCommands. TThey will be executed right after the target is launched or attached correctly, which means that the targets can assume that the target is running.
Differential Revision: https://reviews.llvm.org/D100340
Progress events internally have a completed count and a total count, which can mean that for a job with 20000 total counts, then there will be 20000 events fired. Sending all these events to the IDE can break it. For example, debugging a huge binary resulted in around 50 million messages, which rendered the IDE useless, as it was spending all of its resources simply parsing messages and updating the UI.
A way to fix this is to send unique percentage updates, which are at most 100 per job, which is not much. I was able to debug that big target and confirm that only unique percentage notifications are sent. I can't write a test for this because the current test is flaky. I'll figure out later how to make the test reliable, but fixing this will unblock us from deploy a new version of lldb-vscode.
Differential Revision: https://reviews.llvm.org/D100443
Consistently use return with EXIT_SUCCESS or EXIT_FAILURE instead of
mix-and-matching return, exit 0, 1 etc.
Differential revision: https://reviews.llvm.org/D99701
This implements the interactive trace start and stop methods.
This diff ended up being much larger than I anticipated because, by doing it, I found that I had implemented in the beginning many things in a non optimal way. In any case, the code is much better now.
There's a lot of boilerplate code due to the gdb-remote protocol, but the main changes are:
- New tracing packets: jLLDBTraceStop, jLLDBTraceStart, jLLDBTraceGetBinaryData. The gdb-remote packet definitions are quite comprehensive.
- Implementation of the "process trace start|stop" and "thread trace start|stop" commands.
- Implementaiton of an API in Trace.h to interact with live traces.
- Created an IntelPTDecoder for live threads, that use the debugger's stop id as checkpoint for its internal cache.
- Added a functionality to stop the process in case "process tracing" is enabled and a new thread can't traced.
- Added tests
I have some ideas to unify the code paths for post mortem and live threads, but I'll do that in another diff.
Differential Revision: https://reviews.llvm.org/D91679
Print LLVM's pretty stack trace when lldb-vscode crashes. Also removes
the unnecessary call to PrintStackTraceOnErrorSignal in lldb-server as
it's already part of InitLLVM.
Differential revision: https://reviews.llvm.org/D99535
LLDB can often appear deadlocked to users that use IDEs when it is indexing DWARF, or parsing symbol tables. These long running operations can make a debug session appear to be doing nothing even though a lot of work is going on inside LLDB. This patch adds a public API to allow clients to listen to debugger events that report progress and will allow UI to create an activity window or display that can show users what is going on and keep them informed of expensive operations that are going on inside LLDB.
Differential Revision: https://reviews.llvm.org/D97739
Summary:
The request "evaluate" supports a "context" attribute, which is sent by VSCode. The attribute is defined here https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Evaluate
The "clipboard" context is not yet supported by lldb-vscode, so we can forget about it for now. The 'repl' (i.e. Debug Console) and 'watch' (i.e. Watch Expression) contexts must use the expression parser in case the frame's variable path is not enough, as the user expects these expressions to never fail. On the other hand, the 'hover' expression is invoked whenever the user hovers on any keyword on the UI and the user is fine with the expression not being fully resolved, as they know that the 'repl' case is the fallback they can rely on.
Given that the 'hover' expression is invoked many many times without the user noticing it due to it being triggered by the mouse, I'm making it use only the frame's variable path functionality and not the expression parser. This should speed up tremendously the responsiveness of a debug session when the user only sets source breakpoints and inspect local variables, as the entire debug info is not needed to be parsed.
Regarding tests, I've tried to be as comprehensive as possible considering a multi-file project. Fortunately, the results from the "hover" case are enough most of the times.
Differential Revision: https://reviews.llvm.org/D98656
VSCode was not being informed whenever a location had been resolved (after being initated as non-resolved), so even though it was actually resolved, the IDE would show a hollow dot (instead of a red dot) because it didn't know about the change.
Differential Revision: https://reviews.llvm.org/D96680
@mstorsjo found a mistake that I made when trying to fix some Windows
compilation errors encountered by @stella.stamenova.
I was incorrectly using the LLVM_ON_UNIX macro. In any case, proper use
of
#if defined(_WIN32)
should be the actual fix.
Differential Revision: https://reviews.llvm.org/D96060
@stella.stamenova found out that lldb-vscode's Win32 macros were failing
when building on windows targetings POSIX platforms.
I'm changing these macros for LLVM_ON_UNIX, which should be more
accurate.
stella.stemenova mentioned in https://reviews.llvm.org/D93951 failures on Windows for this test.
I'm fixing the macro definitions and disabling the tests for python
versions lower than 3.7. I'll figure out that actual issue with
python3.6 after the buildbots are fine again.
Depends on D93874.
runInTerminal was using --wait-for, but it was some problems because it uses process polling looking for a single instance of the debuggee:
- it gets to know of the target late, which renders breakpoints in the main function almost impossible
- polling might fail if there are already other processes with the same name
- polling might also fail on some linux machine, as it's implemented with the ps command, and the ps command's args and output are not standard everywhere
As a better way to implement this so that it works well on Darwin and Linux, I'm using now the following process:
- lldb-vscode notices the runInTerminal, so it spawns lldb-vscode with a special flag --launch-target <target>. This flags tells lldb-vscode to wait to be attached and then it execs the target program. I'm using lldb-vscode itself to do this, because it makes finding the launcher program easier. Also no CMAKE INSTALL scripts are needed.
- Besides this, the debugger creates a temporary FIFO file where the launcher program will write its pid to. That way the debugger will be sure of which program to attach.
- Once attach happend, the debugger creates a second temporary file to notify the launcher program that it has been attached, so that it can then exec. I'm using this instead of using a signal or a similar mechanism because I don't want the launcher program to wait indefinitely to be attached in case the debugger crashed. That would pollute the process list with a lot of hanging processes. Instead, I'm setting a 20 seconds timeout (that's an overkill) and the launcher program seeks in intervals the second tepmorary file.
Some notes:
- I preferred not to use sockets because it requires a lot of code and I only need a pid. It would also require a lot of code when windows support is implemented.
- I didn't add Windows support, as I don't have a windows machine, but adding support for it should be easy, as the FIFO file can be implemented with a named pipe, which is standard on Windows and works pretty much the same way.
The existing test which didn't pass on Linux, now passes.
Differential Revision: https://reviews.llvm.org/D93951
lldb-vsdode was communicating the list of modules to the IDE with events, which in practice ended up having some drawbacks
- when debugging large targets, the number of these events were easily 10k, which polluted the messages being transmitted, which caused the following: a harder time debugging the messages, a lag after terminated the process because of these messages being processes (this could easily take several seconds). The latter was specially bad, as users were complaining about it even when they didn't check the modules view.
- these events were rarely used, as users only check the modules view when something is wrong and they try to debug things.
After getting some feedback from users, we realized that it's better to not used events but make this simply a request and is triggered by users whenever they needed.
This diff achieves that and does some small clean up in the existing code.
Differential Revision: https://reviews.llvm.org/D94033
Per the DAP spec for SetBreakpoints [1], the way to clear breakpoints is: `To clear all breakpoint for a source, specify an empty array.`
However, leaving the breakpoints field unset is also a well formed request (note the `breakpoints?:` in the `SetBreakpointsArguments` definition). If it's unset, we have a couple choices:
1. Crash (current behavior)
2. Clear breakpoints
3. Return an error response that the breakpoints field is missing.
I propose we do (2) instead of (1), and treat an unset breakpoints field the same as an empty breakpoints field.
[1] https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetBreakpoints
Reviewed By: wallace, labath
Differential Revision: https://reviews.llvm.org/D88513
The Symbol Status in modules view is simplified so that only when the module has debug info and its size is non-zero, will the status message be displayed. The symbol status message is renamed to debug info size and flag message like "Symbols not found" and "Symbols loaded" is deleted.
Differential Revision: https://reviews.llvm.org/D86662