[Lldb-commits] [lldb] [lldb-dap] Implement command directives (PR #74808)
Walter Erquinigo via lldb-commits
lldb-commits at lists.llvm.org
Thu Dec 14 12:03:20 PST 2023
https://github.com/walter-erquinigo updated https://github.com/llvm/llvm-project/pull/74808
>From 4e6bfb5f26f7744db1cb4a37d0e342195ae0ff8a Mon Sep 17 00:00:00 2001
From: walter erquinigo <walter at modular.com>
Date: Fri, 8 Dec 2023 00:11:19 -0500
Subject: [PATCH 1/2] [lldb-dap] Implement quiet commands
This adds support for optionally prefixing any command with `?`, which effectively prevents the output of these commands to be printed to the console unless they fail. This comes handy when programmaticaly running commands on behalf of the user without wanting them to know unless they fail.
In a later PR I plan to implement the `!` prefix for commands that abort lldb-dap upon errors.
---
.../test/tools/lldb-dap/lldbdap_testcase.py | 7 ++
.../test/API/tools/lldb-dap/commands/Makefile | 3 +
.../lldb-dap/commands/TestDAP_commands.py | 80 +++++++++++++++++++
.../test/API/tools/lldb-dap/commands/main.cpp | 1 +
lldb/tools/lldb-dap/DAP.cpp | 50 ++++++++++--
lldb/tools/lldb-dap/DAP.h | 17 ++--
lldb/tools/lldb-dap/LLDBUtils.cpp | 77 +++++++++++++-----
lldb/tools/lldb-dap/LLDBUtils.h | 37 ++++++++-
lldb/tools/lldb-dap/lldb-dap.cpp | 51 +++++++++---
lldb/tools/lldb-dap/package.json | 24 +++---
10 files changed, 287 insertions(+), 60 deletions(-)
create mode 100644 lldb/test/API/tools/lldb-dap/commands/Makefile
create mode 100644 lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
create mode 100644 lldb/test/API/tools/lldb-dap/commands/main.cpp
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 4ccd6014e54be6..7436b9900e98b0 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -291,6 +291,7 @@ def attach(
postRunCommands=None,
sourceMap=None,
sourceInitFile=False,
+ expectFailure=False,
):
"""Build the default Makefile target, create the DAP debug adaptor,
and attach to the process.
@@ -322,6 +323,8 @@ def cleanup():
postRunCommands=postRunCommands,
sourceMap=sourceMap,
)
+ if expectFailure:
+ return response
if not (response and response["success"]):
self.assertTrue(
response["success"], "attach failed (%s)" % (response["message"])
@@ -437,6 +440,8 @@ def build_and_launch(
commandEscapePrefix=None,
customFrameFormat=None,
customThreadFormat=None,
+ launchCommands=None,
+ expectFailure=False,
):
"""Build the default Makefile target, create the DAP debug adaptor,
and launch the process.
@@ -470,4 +475,6 @@ def build_and_launch(
commandEscapePrefix=commandEscapePrefix,
customFrameFormat=customFrameFormat,
customThreadFormat=customThreadFormat,
+ launchCommands=launchCommands,
+ expectFailure=expectFailure,
)
diff --git a/lldb/test/API/tools/lldb-dap/commands/Makefile b/lldb/test/API/tools/lldb-dap/commands/Makefile
new file mode 100644
index 00000000000000..99998b20bcb050
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
new file mode 100644
index 00000000000000..226b9385fe719a
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
@@ -0,0 +1,80 @@
+import os
+
+import dap_server
+import lldbdap_testcase
+from lldbsuite.test import lldbtest, lldbutil
+from lldbsuite.test.decorators import *
+
+
+class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase):
+ def test_command_directive_quiet_on_success(self):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_not_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes true"
+ )
+ self.build_and_launch(
+ program,
+ initCommands=["?" + command_quiet, command_not_quiet],
+ terminateCommands=["?" + command_quiet, command_not_quiet],
+ stopCommands=["?" + command_quiet, command_not_quiet],
+ exitCommands=["?" + command_quiet, command_not_quiet],
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_not_quiet, full_output)
+
+ def do_test_abort_on_error(
+ self,
+ use_init_commands=False,
+ use_launch_commands=False,
+ use_pre_run_commands=False,
+ use_post_run_commands=False,
+ ):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_abort_on_error = "settings set foo bar"
+ commands = ["?!" + command_quiet, "!" + command_abort_on_error]
+ self.build_and_launch(
+ program,
+ initCommands=commands if use_init_commands else None,
+ launchCommands=commands if use_launch_commands else None,
+ preRunCommands=commands if use_pre_run_commands else None,
+ postRunCommands=commands if use_post_run_commands else None,
+ expectFailure=True,
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_abort_on_error, full_output)
+
+ def test_command_directive_abort_on_error_init_commands(self):
+ self.do_test_abort_on_error(use_init_commands=True)
+
+ def test_command_directive_abort_on_error_launch_commands(self):
+ self.do_test_abort_on_error(use_launch_commands=True)
+
+ def test_command_directive_abort_on_error_pre_run_commands(self):
+ self.do_test_abort_on_error(use_pre_run_commands=True)
+
+ def test_command_directive_abort_on_error_post_run_commands(self):
+ self.do_test_abort_on_error(use_post_run_commands=True)
+
+ def test_command_directive_abort_on_error_attach_commands(self):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_abort_on_error = "settings set foo bar"
+ self.build_and_create_debug_adaptor()
+ self.attach(
+ program,
+ attachCommands=["?!" + command_quiet, "!" + command_abort_on_error],
+ expectFailure=True,
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_abort_on_error, full_output)
diff --git a/lldb/test/API/tools/lldb-dap/commands/main.cpp b/lldb/test/API/tools/lldb-dap/commands/main.cpp
new file mode 100644
index 00000000000000..76e8197013aabc
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 49266209739765..39a68511b59065 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -434,20 +434,54 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame,
return ExpressionContext::Variable;
}
-void DAP::RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands) {
- SendOutput(OutputType::Console,
- llvm::StringRef(::RunLLDBCommands(prefix, commands)));
+bool DAP::RunLLDBCommands(llvm::StringRef prefix,
+ llvm::ArrayRef<std::string> commands) {
+ bool required_command_failed;
+ std::string output =
+ ::RunLLDBCommands(prefix, commands, required_command_failed);
+ SendOutput(OutputType::Console, output);
+ return !required_command_failed;
+}
+
+static llvm::Error createRunLLDBCommandsErrorMessage(llvm::StringRef category) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ llvm::formatv(
+ "Failed to run {0} commands. See the Debug Console for more details.",
+ category)
+ .str()
+ .c_str());
+}
+
+llvm::Error
+DAP::RunAttachCommands(llvm::ArrayRef<std::string> attach_commands) {
+ if (!RunLLDBCommands("Running attachCommands:", attach_commands))
+ return createRunLLDBCommandsErrorMessage("attach");
+ return llvm::Error::success();
}
-void DAP::RunInitCommands() {
- RunLLDBCommands("Running initCommands:", init_commands);
+llvm::Error
+DAP::RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands) {
+ if (!RunLLDBCommands("Running launchCommands:", launch_commands))
+ return createRunLLDBCommandsErrorMessage("launch");
+ return llvm::Error::success();
}
-void DAP::RunPreRunCommands() {
- RunLLDBCommands("Running preRunCommands:", pre_run_commands);
+llvm::Error DAP::RunInitCommands() {
+ if (!RunLLDBCommands("Running initCommands:", init_commands))
+ return createRunLLDBCommandsErrorMessage("initCommands");
+ return llvm::Error::success();
}
+llvm::Error DAP::RunPreRunCommands() {
+ if (!RunLLDBCommands("Running preRunCommands:", pre_run_commands))
+ return createRunLLDBCommandsErrorMessage("preRunCommands");
+ return llvm::Error::success();
+}
+
+void DAP::RunPostRunCommands() {
+ RunLLDBCommands("Running postRunCommands:", post_run_commands);
+}
void DAP::RunStopCommands() {
RunLLDBCommands("Running stopCommands:", stop_commands);
}
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index c7d56a06bfa1fd..20817194de2d8d 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -158,6 +158,7 @@ struct DAP {
std::vector<ExceptionBreakpoint> exception_breakpoints;
std::vector<std::string> init_commands;
std::vector<std::string> pre_run_commands;
+ std::vector<std::string> post_run_commands;
std::vector<std::string> exit_commands;
std::vector<std::string> stop_commands;
std::vector<std::string> terminate_commands;
@@ -227,11 +228,17 @@ struct DAP {
ExpressionContext DetectExpressionContext(lldb::SBFrame &frame,
std::string &text);
- void RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands);
-
- void RunInitCommands();
- void RunPreRunCommands();
+ /// \return
+ /// \b false if a fatal error was found while executing these commands,
+ /// according to the rules of \a LLDBUtils::RunLLDBCommands.
+ bool RunLLDBCommands(llvm::StringRef prefix,
+ llvm::ArrayRef<std::string> commands);
+
+ llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
+ llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
+ llvm::Error RunInitCommands();
+ llvm::Error RunPreRunCommands();
+ void RunPostRunCommands();
void RunStopCommands();
void RunExitCommands();
void RunTerminateCommands();
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 955c11f636895b..1d4f0a7921aaaf 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -11,40 +11,81 @@
namespace lldb_dap {
-void RunLLDBCommands(llvm::StringRef prefix,
+bool RunLLDBCommands(llvm::StringRef prefix,
const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm) {
+ llvm::raw_ostream &strm, bool parse_command_directives) {
if (commands.empty())
- return;
+ return true;
+
+ bool did_print_prefix = false;
+
lldb::SBCommandInterpreter interp = g_dap.debugger.GetCommandInterpreter();
- if (!prefix.empty())
- strm << prefix << "\n";
- for (const auto &command : commands) {
+ for (llvm::StringRef command : commands) {
lldb::SBCommandReturnObject result;
- strm << "(lldb) " << command << "\n";
- interp.HandleCommand(command.c_str(), result);
- auto output_len = result.GetOutputSize();
- if (output_len) {
- const char *output = result.GetOutput();
- strm << output;
+ bool quiet_on_success = false;
+ bool check_error = false;
+
+ while (parse_command_directives) {
+ if (command.starts_with("?")) {
+ command = command.drop_front();
+ quiet_on_success = true;
+ } else if (command.starts_with("!")) {
+ command = command.drop_front();
+ check_error = true;
+ } else {
+ break;
+ }
}
- auto error_len = result.GetErrorSize();
- if (error_len) {
- const char *error = result.GetError();
- strm << error;
+
+ interp.HandleCommand(command.str().c_str(), result);
+ const bool got_error = !result.Succeeded();
+ // The if statement below is assuming we always print out `!` prefixed
+ // lines. The only time we don't print is when we have `quiet_on_success ==
+ // true` and we don't have an error.
+ if (quiet_on_success ? got_error : true) {
+ if (!did_print_prefix && !prefix.empty()) {
+ strm << prefix << "\n";
+ did_print_prefix = true;
+ }
+ strm << "(lldb) " << command << "\n";
+ auto output_len = result.GetOutputSize();
+ if (output_len) {
+ const char *output = result.GetOutput();
+ strm << output;
+ }
+ auto error_len = result.GetErrorSize();
+ if (error_len) {
+ const char *error = result.GetError();
+ strm << error;
+ }
}
+ if (check_error && got_error)
+ return false; // Stop running commands.
}
+ return true;
}
std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands) {
+ const llvm::ArrayRef<std::string> &commands,
+ bool &required_command_failed,
+ bool parse_command_directives) {
+ required_command_failed = false;
std::string s;
llvm::raw_string_ostream strm(s);
- RunLLDBCommands(prefix, commands, strm);
+ required_command_failed =
+ !RunLLDBCommands(prefix, commands, strm, parse_command_directives);
strm.flush();
return s;
}
+std::string
+RunLLDBCommandsVerbatim(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands) {
+ bool required_command_failed;
+ return RunLLDBCommands(prefix, commands, required_command_failed,
+ /*parse_command_directives=*/false);
+}
+
bool ThreadHasStopReason(lldb::SBThread &thread) {
switch (thread.GetStopReason()) {
case lldb::eStopReasonTrace:
diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index a99f798835370d..ee701da2230fe0 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -23,6 +23,12 @@ namespace lldb_dap {
/// All output from every command, including the prompt + the command
/// is placed into the "strm" argument.
///
+/// Each individual command can be prefixed with \b ! and/or \b ? in no
+/// particular order. If \b ? is provided, then the output of that command is
+/// only emitted if it fails, and if \b ! is provided, then the output is
+/// emitted regardless, and \b false is returned without executing the
+/// remaining commands.
+///
/// \param[in] prefix
/// A string that will be printed into \a strm prior to emitting
/// the prompt + command and command output. Can be NULL.
@@ -33,9 +39,17 @@ namespace lldb_dap {
/// \param[in] strm
/// The stream that will receive the prefix, prompt + command and
/// all command output.
-void RunLLDBCommands(llvm::StringRef prefix,
+///
+/// \param[in] parse_command_directives
+/// If \b false, then command prefixes like \b ! or \b ? are not parsed and
+/// each command is executed verbatim.
+///
+/// \return
+/// \b true, unless a command prefixed with \b ! fails and parsing of
+/// command directives is enabled.
+bool RunLLDBCommands(llvm::StringRef prefix,
const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm);
+ llvm::raw_ostream &strm, bool parse_command_directives);
/// Run a list of LLDB commands in the LLDB command interpreter.
///
@@ -49,11 +63,26 @@ void RunLLDBCommands(llvm::StringRef prefix,
/// \param[in] commands
/// An array of LLDB commands to execute.
///
+/// \param[out] required_command_failed
+/// If parsing of command directives is enabled, this variable is set to
+/// \b true if one of the commands prefixed with \b ! fails.
+///
+/// \param[in] parse_command_directives
+/// If \b false, then command prefixes like \b ! or \b ? are not parsed and
+/// each command is executed verbatim.
+///
/// \return
/// A std::string that contains the prefix and all commands and
-/// command output
+/// command output.
std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands);
+ const llvm::ArrayRef<std::string> &commands,
+ bool &required_command_failed,
+ bool parse_command_directives = true);
+
+/// Similar to the method above, but without parsing command directives.
+std::string
+RunLLDBCommandsVerbatim(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands);
/// Check if a thread has a stop reason.
///
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index d6b593eba93eca..d36e9b4d1b0982 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -644,8 +644,7 @@ void request_attach(const llvm::json::Object &request) {
const uint64_t timeout_seconds = GetUnsigned(arguments, "timeout", 30);
g_dap.stop_at_entry =
core_file.empty() ? GetBoolean(arguments, "stopOnEntry", false) : true;
- std::vector<std::string> postRunCommands =
- GetStrings(arguments, "postRunCommands");
+ g_dap.post_run_commands = GetStrings(arguments, "postRunCommands");
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
g_dap.enable_auto_variable_summaries =
GetBoolean(arguments, "enableAutoVariableSummaries", false);
@@ -664,7 +663,12 @@ void request_attach(const llvm::json::Object &request) {
llvm::sys::fs::set_current_path(debuggerRoot);
// Run any initialize LLDB commands the user specified in the launch.json
- g_dap.RunInitCommands();
+ if (llvm::Error err = g_dap.RunInitCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
SetSourceMapFromArguments(*arguments);
@@ -678,7 +682,12 @@ void request_attach(const llvm::json::Object &request) {
}
// Run any pre run LLDB commands the user specified in the launch.json
- g_dap.RunPreRunCommands();
+ if (llvm::Error err = g_dap.RunPreRunCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
if (pid == LLDB_INVALID_PROCESS_ID && wait_for) {
char attach_msg[256];
@@ -703,7 +712,12 @@ void request_attach(const llvm::json::Object &request) {
// We have "attachCommands" that are a set of commands that are expected
// to execute the commands after which a process should be created. If there
// is no valid process after running these commands, we have failed.
- g_dap.RunLLDBCommands("Running attachCommands:", attachCommands);
+ if (llvm::Error err = g_dap.RunAttachCommands(attachCommands)) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
// The custom commands might have created a new target so we should use the
// selected target after these commands are run.
g_dap.target = g_dap.debugger.GetSelectedTarget();
@@ -727,7 +741,7 @@ void request_attach(const llvm::json::Object &request) {
response["success"] = llvm::json::Value(false);
EmplaceSafeString(response, "message", std::string(error.GetCString()));
} else {
- g_dap.RunLLDBCommands("Running postRunCommands:", postRunCommands);
+ g_dap.RunPostRunCommands();
}
g_dap.SendJSON(llvm::json::Value(std::move(response)));
@@ -1270,7 +1284,8 @@ void request_evaluate(const llvm::json::Object &request) {
if (frame.IsValid()) {
g_dap.focus_tid = frame.GetThread().GetThreadID();
}
- auto result = RunLLDBCommands(llvm::StringRef(), {std::string(expression)});
+ auto result =
+ RunLLDBCommandsVerbatim(llvm::StringRef(), {std::string(expression)});
EmplaceSafeString(body, "result", result);
body.try_emplace("variablesReference", (int64_t)0);
} else {
@@ -1740,7 +1755,8 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
// Set the launch info so that run commands can access the configured
// launch details.
g_dap.target.SetLaunchInfo(launch_info);
- g_dap.RunLLDBCommands("Running launchCommands:", launchCommands);
+ if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands))
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
// The custom commands might have created a new target so we should use the
// selected target after these commands are run.
g_dap.target = g_dap.debugger.GetSelectedTarget();
@@ -1797,8 +1813,7 @@ void request_launch(const llvm::json::Object &request) {
g_dap.stop_commands = GetStrings(arguments, "stopCommands");
g_dap.exit_commands = GetStrings(arguments, "exitCommands");
g_dap.terminate_commands = GetStrings(arguments, "terminateCommands");
- std::vector<std::string> postRunCommands =
- GetStrings(arguments, "postRunCommands");
+ g_dap.post_run_commands = GetStrings(arguments, "postRunCommands");
g_dap.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
g_dap.enable_auto_variable_summaries =
@@ -1820,7 +1835,12 @@ void request_launch(const llvm::json::Object &request) {
// Run any initialize LLDB commands the user specified in the launch.json.
// This is run before target is created, so commands can't do anything with
// the targets - preRunCommands are run with the target.
- g_dap.RunInitCommands();
+ if (llvm::Error err = g_dap.RunInitCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
SetSourceMapFromArguments(*arguments);
@@ -1834,7 +1854,12 @@ void request_launch(const llvm::json::Object &request) {
}
// Run any pre run LLDB commands the user specified in the launch.json
- g_dap.RunPreRunCommands();
+ if (llvm::Error err = g_dap.RunPreRunCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
status = LaunchProcess(request);
@@ -1842,7 +1867,7 @@ void request_launch(const llvm::json::Object &request) {
response["success"] = llvm::json::Value(false);
EmplaceSafeString(response, "message", std::string(status.GetCString()));
} else {
- g_dap.RunLLDBCommands("Running postRunCommands:", postRunCommands);
+ g_dap.RunPostRunCommands();
}
g_dap.SendJSON(llvm::json::Value(std::move(response)));
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index ebb1103d695e17..68cdade4439924 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -204,32 +204,32 @@
},
"initCommands": {
"type": "array",
- "description": "Initialization commands executed upon debugger startup.",
+ "description": "Initialization commands executed upon debugger startup. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"preRunCommands": {
"type": "array",
- "description": "Commands executed just before the program is launched.",
+ "description": "Commands executed just before the program is launched. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"postRunCommands": {
"type": "array",
- "description": "Commands executed just as soon as the program is successfully launched when it's in a stopped state prior to any automatic continuation.",
+ "description": "Commands executed just as soon as the program is successfully launched when it's in a stopped state prior to any automatic continuation. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"launchCommands": {
"type": "array",
- "description": "Custom commands that are executed instead of launching a process. A target will be created with the launch arguments prior to executing these commands. The commands may optionally create a new target and must perform a launch. A valid process must exist after these commands complete or the \"launch\" will fail. Launch the process with \"process launch -s\" to make the process to at the entry point since lldb-dap will auto resume if necessary.",
+ "description": "Custom commands that are executed instead of launching a process. A target will be created with the launch arguments prior to executing these commands. The commands may optionally create a new target and must perform a launch. A valid process must exist after these commands complete or the \"launch\" will fail. Launch the process with \"process launch -s\" to make the process to at the entry point since lldb-dap will auto resume if necessary. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"stopCommands": {
"type": "array",
- "description": "Commands executed each time the program stops.",
+ "description": "Commands executed each time the program stops. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"exitCommands": {
"type": "array",
- "description": "Commands executed at the end of debugging session.",
+ "description": "Commands executed at the end of debugging session. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"runInTerminal": {
@@ -309,32 +309,32 @@
},
"attachCommands": {
"type": "array",
- "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
+ "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"initCommands": {
"type": "array",
- "description": "Initialization commands executed upon debugger startup.",
+ "description": "Initialization commands executed upon debugger startup. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"preRunCommands": {
"type": "array",
- "description": "Commands executed just before the program is attached to.",
+ "description": "Commands executed just before the program is attached to. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"postRunCommands": {
"type": "array",
- "description": "Commands executed just as soon as the program is successfully attached when it's in a stopped state prior to any automatic continuation.",
+ "description": "Commands executed just as soon as the program is successfully attached when it's in a stopped state prior to any automatic continuation. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"stopCommands": {
"type": "array",
- "description": "Commands executed each time the program stops.",
+ "description": "Commands executed each time the program stops. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `attachCommands`, the `!` prefix is ignored.",
"default": []
},
"exitCommands": {
"type": "array",
- "description": "Commands executed at the end of debugging session.",
+ "description": "Commands executed at the end of debugging session. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `attachCommands`, the `!` prefix is ignored.",
"default": []
},
"coreFile": {
>From a2b49b8e62efeb878bf31f60cd56f051dcf0e198 Mon Sep 17 00:00:00 2001
From: Walter Erquinigo <a20012251 at gmail.com>
Date: Thu, 14 Dec 2023 15:03:12 -0500
Subject: [PATCH 2/2] Update DAP.cpp
---
lldb/tools/lldb-dap/DAP.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 39a68511b59065..4b72c13f9215a8 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -436,7 +436,7 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame,
bool DAP::RunLLDBCommands(llvm::StringRef prefix,
llvm::ArrayRef<std::string> commands) {
- bool required_command_failed;
+ bool required_command_failed = false;
std::string output =
::RunLLDBCommands(prefix, commands, required_command_failed);
SendOutput(OutputType::Console, output);
More information about the lldb-commits
mailing list