[Lldb-commits] [lldb] [lldb-dap] Correctly detect alias commands with arguments in repl (PR #92137)
https://github.com/ashgti approved this pull request. https://github.com/llvm/llvm-project/pull/92137 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: I just checked and I'm not seeing the hover's in the same format as they were when I made the pull request. The expression context should still have the expanded forms though for example: https://github.com/llvm/llvm-project/assets/22535/28db4adc-d488-44ff-8d99-78966e0e0e05";> I think the VSCode team is working on making the Debug view more extensible for visualizations, see https://github.com/microsoft/vscode/blob/main/src/vscode-dts/vscode.proposed.debugVisualization.d.ts and https://github.com/microsoft/vscode/issues/197287 https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: Sounds good to me https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Don't send expanded descriptions for "hover" expressions (PR #92726)
https://github.com/ashgti approved this pull request. https://github.com/llvm/llvm-project/pull/92726 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/105456 Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. Resolves #105444 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
@@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { category = "telemetry"; break; } - body.try_emplace("category", category); - EmplaceSafeString(body, "output", output.str()); - event.try_emplace("body", std::move(body)); - SendJSON(llvm::json::Value(std::move(event))); + + // Send each line of output as an individual event, including the newline if + // present. + ::size_t idx = 0; + do { +::size_t end = output.find('\n', idx); +if (end == llvm::StringRef::npos) + end = output.size() - 1; +llvm::json::Object event(CreateEventObject("output")); +llvm::json::Object body; +body.try_emplace("category", category); +EmplaceSafeString(body, "output", output.slice(idx, end + 1).str()); +event.try_emplace("body", std::move(body)); +SendJSON(llvm::json::Value(std::move(event))); +idx = end + 1; + } while (idx < output.size()); ashgti wrote: VS Code append to the previous lines if the previous line don't end in a `\n` or `\r\n` (https://github.com/microsoft/vscode/blob/d193e4b6f525e90911df21f8f1820cf0fe0fda0c/src/vs/workbench/contrib/debug/common/replModel.ts#L306). With the previous version of this, if we had an output event like `abc\ndef` followed by `foo\n`, these would have been merged into a single 'output' item in the UI. With this change it will instead have `abc\n` as one output item and `deffoo\n` would become a second output item. I can also increase the buffer size for the reads. https://github.com/llvm/llvm-project/pull/105456 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix dap stacktrace perf issue (PR #104874)
@@ -3091,17 +3093,20 @@ void request_stackTrace(const llvm::json::Object &request) { // This will always return an invalid thread when // libBacktraceRecording.dylib is not loaded or if there is no extended // backtrace. -lldb::SBThread queue_backtrace_thread = -thread.GetExtendedBacktraceThread("libdispatch"); +lldb::SBThread queue_backtrace_thread; +if (g_dap.enable_display_extended_backtrace) + queue_backtrace_thread = thread.GetExtendedBacktraceThread("libdispatch"); ashgti wrote: Maybe we should check SBProcess::GetNumExtendedBacktraceTypes() / GetExtendedBacktraceTypeAtIndex() instead of hard coding the `libdispatch`? I think that is configured by the target platform. Would that solve the issue without needing an extra configuration flag? https://github.com/llvm/llvm-project/pull/104874 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105456 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH 1/2] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index c3c70e9d739846..1fd560f21904ab 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { if (output.empty()) return; - llvm::json::Object event(CreateEventObject("output")); - llvm::json::Object body; const char *category = nullptr; switch (o) { case OutputType::Console: @@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef outp
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105456 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH 1/3] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index c3c70e9d739846..1fd560f21904ab 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { if (output.empty()) return; - llvm::json::Object event(CreateEventObject("output")); - llvm::json::Object body; const char *category = nullptr; switch (o) { case OutputType::Console: @@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef outp
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
@@ -399,7 +399,7 @@ void SendProcessEvent(LaunchMethod launch_method) { // Grab any STDOUT and STDERR from the process and send it up to VS Code // via an "output" event to the "stdout" and "stderr" categories. void SendStdOutStdErr(lldb::SBProcess &process) { - char buffer[1024]; + char buffer[4096]; ashgti wrote: Moved this into a constant. https://github.com/llvm/llvm-project/pull/105456 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105456 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH 1/3] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index c3c70e9d739846..1fd560f21904ab 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { if (output.empty()) return; - llvm::json::Object event(CreateEventObject("output")); - llvm::json::Object body; const char *category = nullptr; switch (o) { case OutputType::Console: @@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef outp
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105456 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH 1/4] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index c3c70e9d739846..1fd560f21904ab 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { if (output.empty()) return; - llvm::json::Object event(CreateEventObject("output")); - llvm::json::Object body; const char *category = nullptr; switch (o) { case OutputType::Console: @@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef outp
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105456 >From 9246649c24991127b8f54ae1f21121386cef7254 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 20 Aug 2024 16:33:14 -0700 Subject: [PATCH 1/5] When sending a DAP Output Event break each message into separate lines. Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 5 +++ lldb/test/API/tools/lldb-dap/output/Makefile | 3 ++ .../tools/lldb-dap/output/TestDAP_output.py | 37 +++ lldb/test/API/tools/lldb-dap/output/main.c| 11 ++ lldb/tools/lldb-dap/DAP.cpp | 22 --- 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/output/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/output/TestDAP_output.py create mode 100644 lldb/test/API/tools/lldb-dap/output/main.c 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 a312a88ebd7e58..8341bfda748206 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 @@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None): "console", timeout_secs=timeout_secs, pattern=pattern ) +def collect_stdout(self, timeout_secs, pattern=None): +return self.dap_server.collect_output( +"stdout", timeout_secs=timeout_secs, pattern=pattern +) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/output/Makefile b/lldb/test/API/tools/lldb-dap/output/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py new file mode 100644 index 00..08d5f07f224e4c --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -0,0 +1,37 @@ +""" +Test lldb-dap output events +""" + +import dap_server +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import re + + +class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +def test_output(self): +program = self.getBuildArtifact("a.out") +self.build_and_launch(program) +source = "main.c" +main_source_path = self.getSourcePath(source) +lines = [line_number(source, "// breakpoint 1")] +breakpoint_ids = self.set_source_breakpoints(source, lines) +self.continue_to_breakpoints(breakpoint_ids) + +output = self.collect_stdout( +timeout_secs=1.0, +pattern="abcdef" +) +self.assertTrue(output and len(output) > 0, "expect no program output") + +self.continue_to_exit() + +output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval) +self.assertTrue(output and len(output) > 0, "expect no program output") +self.assertIn( +"abcdefghi\r\nhello world\r\n", +output, +'full output not found in: ' + output +) diff --git a/lldb/test/API/tools/lldb-dap/output/main.c b/lldb/test/API/tools/lldb-dap/output/main.c new file mode 100644 index 00..62a3337d865db2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/output/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main() { + printf("abc"); + printf("def"); + printf("ghi\n"); + printf("hello world\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index c3c70e9d739846..1fd560f21904ab 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { if (output.empty()) return; - llvm::json::Object event(CreateEventObject("output")); - llvm::json::Object body; const char *category = nullptr; switch (o) { case OutputType::Console: @@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef outp
[Lldb-commits] [lldb] [lldb-dap] When sending a DAP Output Event break each message into separate lines. (PR #105456)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/105456 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix dap stacktrace perf issue (PR #104874)
@@ -3111,17 +3115,20 @@ void request_stackTrace(const llvm::json::Object &request) { // This will always return an invalid thread when // libBacktraceRecording.dylib is not loaded or if there is no extended // backtrace. -lldb::SBThread queue_backtrace_thread = -thread.GetExtendedBacktraceThread("libdispatch"); +lldb::SBThread queue_backtrace_thread; +if (g_dap.enable_display_extended_backtrace) + queue_backtrace_thread = thread.GetExtendedBacktraceThread("libdispatch"); if (queue_backtrace_thread.IsValid()) { // One extra frame as a label to mark the enqueued thread. totalFrames += queue_backtrace_thread.GetNumFrames() + 1; } // This will always return an invalid thread when there is no exception in // the current thread. -lldb::SBThread exception_backtrace_thread = -thread.GetCurrentExceptionBacktrace(); +lldb::SBThread exception_backtrace_thread; +if (g_dap.enable_display_extended_backtrace) + exception_backtrace_thread = thread.GetCurrentExceptionBacktrace(); ashgti wrote: Maybe we should remove this from the stack trace and add this info to the `exceptionInfo` request (https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo) there is a field for the stack trace in the exception details (https://microsoft.github.io/debug-adapter-protocol/specification#Types_ExceptionDetails). https://github.com/llvm/llvm-project/pull/104874 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. (PR #105604)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/105604 This should fix https://lab.llvm.org/buildbot/#/builders/141/builds/1747 >From 54dcc78eace39c197f1fb762880746b569980955 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Wed, 21 Aug 2024 18:22:17 -0700 Subject: [PATCH] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. --- lldb/test/API/tools/lldb-dap/output/TestDAP_output.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py index 0d40ce993dc31c..02c34ba10321bd 100644 --- a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -8,6 +8,7 @@ class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +@skipIfWindows def test_output(self): program = self.getBuildArtifact("a.out") self.build_and_launch(program) ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. (PR #105604)
https://github.com/ashgti edited https://github.com/llvm/llvm-project/pull/105604 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. (PR #105604)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105604 >From 54dcc78eace39c197f1fb762880746b569980955 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Wed, 21 Aug 2024 18:22:17 -0700 Subject: [PATCH] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. --- lldb/test/API/tools/lldb-dap/output/TestDAP_output.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py index 0d40ce993dc31c..02c34ba10321bd 100644 --- a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -8,6 +8,7 @@ class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): +@skipIfWindows def test_output(self): program = self.getBuildArtifact("a.out") self.build_and_launch(program) ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Skip the lldb-dap output test on windows, it seems all the lldb-dap tests are disabled on windows. (PR #105604)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/105604 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix dap stacktrace perf issue (PR #104874)
@@ -3111,17 +3115,20 @@ void request_stackTrace(const llvm::json::Object &request) { // This will always return an invalid thread when // libBacktraceRecording.dylib is not loaded or if there is no extended // backtrace. -lldb::SBThread queue_backtrace_thread = -thread.GetExtendedBacktraceThread("libdispatch"); +lldb::SBThread queue_backtrace_thread; +if (g_dap.enable_display_extended_backtrace) + queue_backtrace_thread = thread.GetExtendedBacktraceThread("libdispatch"); if (queue_backtrace_thread.IsValid()) { // One extra frame as a label to mark the enqueued thread. totalFrames += queue_backtrace_thread.GetNumFrames() + 1; } // This will always return an invalid thread when there is no exception in // the current thread. -lldb::SBThread exception_backtrace_thread = -thread.GetCurrentExceptionBacktrace(); +lldb::SBThread exception_backtrace_thread; +if (g_dap.enable_display_extended_backtrace) + exception_backtrace_thread = thread.GetCurrentExceptionBacktrace(); ashgti wrote: I can take a look at moving this into the `exceptionInfo` request. https://github.com/llvm/llvm-project/pull/104874 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix dap stacktrace perf issue (PR #104874)
ashgti wrote: I'll try to work that into my refactor of the call for `thread.GetCurrentExceptionBacktrace()` https://github.com/llvm/llvm-project/pull/104874 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/105905 Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. >From 7641ce09208883f205c9a9deb19bae9d01f8cd70 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, t
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
ashgti wrote: This was based on the comments in https://github.com/llvm/llvm-project/pull/104874 LMKWYT https://github.com/llvm/llvm-project/pull/105905 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From 7641ce09208883f205c9a9deb19bae9d01f8cd70 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/2] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From 7641ce09208883f205c9a9deb19bae9d01f8cd70 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/3] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From 7641ce09208883f205c9a9deb19bae9d01f8cd70 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/4] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From ebcf4842c7d6c5ac0da4976c9cffb68bc3b22807 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/4] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
ashgti wrote: @jeffreytan81 I moved the expensive call into the `exceptionInfo` request, this is only going to be triggered if a thread has the stop event = 'exception', so it shouldn't be triggered while stepping. This does remove the option you added in the prior commit, since I think this isolated the expensive call to a place where the additional information it provides justifies the call and is only called in specific circumstances. LMKWYT https://github.com/llvm/llvm-project/pull/105905 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From ebcf4842c7d6c5ac0da4976c9cffb68bc3b22807 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/5] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
@@ -3106,80 +3228,105 @@ void request_stackTrace(const llvm::json::Object &request) { llvm::json::Array stackFrames; llvm::json::Object body; + // Threads stacks may contain runtime specific extended backtraces, when + // constructing a stack trace first report the full thread stack trace then + // perform a breadth first traversal of any extended backtrace frames. + // + // For example: + // + // Thread (id=th0) stack=[s0, s1, s2, s3] + // \ Extended backtrace "libdispatch" Thread (id=th1) stack=[s0, s1] + // \ Extended backtrace "libdispatch" Thread (id=th2) stack=[s0, s1] + // \ Extended backtrace "Application Specific Backtrace" Thread (id=th3) + // stack=[s0, s1, s2] + // + // Which will flatten into: + // + // 0. th0->s0 + // 1. th0->s1 + // 2. th0->s2 + // 3. th0->s3 + // 4. label - Enqueued from th1 + // 5. th1->s0 + // 6. th1->s1 + // 7. label - Enqueued from th2 + // 8. th2->s0 + // 9. th2->s1 + // 10. label - Application Specific Backtrace + // 11. th3->s0 + // 12. th3->s1 + // 13. th3->s2 + if (thread.IsValid()) { const auto startFrame = GetUnsigned(arguments, "startFrame", 0); const auto levels = GetUnsigned(arguments, "levels", 0); const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels); -auto totalFrames = thread.GetNumFrames(); - -// This will always return an invalid thread when -// libBacktraceRecording.dylib is not loaded or if there is no extended -// backtrace. -lldb::SBThread queue_backtrace_thread; -if (g_dap.enable_display_extended_backtrace) - queue_backtrace_thread = thread.GetExtendedBacktraceThread("libdispatch"); -if (queue_backtrace_thread.IsValid()) { - // One extra frame as a label to mark the enqueued thread. - totalFrames += queue_backtrace_thread.GetNumFrames() + 1; -} +bool done = false; +int64_t offset = 0; +lldb::SBProcess process = thread.GetProcess(); +llvm::SmallVector threadCluster{{thread}}; + +for (uint32_t i = startFrame; i < endFrame && !threadCluster.empty(); ++i) { + lldb::SBThread current = threadCluster.front(); + lldb::SBFrame frame = current.GetFrameAtIndex(i - offset); + + // If we don't have a valid frame, check if we have any extended frames to + // report. + // *NOTE*: Threads can be chained across mutliple backtraces, so we + // need to keep track of each backtrace we've traversed fully in the + // offset. + while (!frame.IsValid() && current.IsValid() && !threadCluster.empty()) { +offset += current.GetNumFrames() + + 1 /* one extra frame for a label between threads*/; +threadCluster.pop_back(); + +// Check for any extended backtraces. +for (uint32_t i = 0; i < process.GetNumExtendedBacktraceTypes(); i++) { + lldb::SBThread backtrace = current.GetExtendedBacktraceThread( + process.GetExtendedBacktraceTypeAtIndex(i)); + if (backtrace.IsValid()) { +threadCluster.emplace_back(backtrace); + } +} -// This will always return an invalid thread when there is no exception in -// the current thread. -lldb::SBThread exception_backtrace_thread; -if (g_dap.enable_display_extended_backtrace) - exception_backtrace_thread = thread.GetCurrentExceptionBacktrace(); +if (threadCluster.empty()) + break; -if (exception_backtrace_thread.IsValid()) { - // One extra frame as a label to mark the exception thread. - totalFrames += exception_backtrace_thread.GetNumFrames() + 1; -} +current = threadCluster.front(); +frame = current.GetFrameAtIndex(0); + } -for (uint32_t i = startFrame; i < endFrame; ++i) { - lldb::SBFrame frame; - std::string prefix; - if (i < thread.GetNumFrames()) { -frame = thread.GetFrameAtIndex(i); - } else if (queue_backtrace_thread.IsValid() && - i < (thread.GetNumFrames() + - queue_backtrace_thread.GetNumFrames() + 1)) { -if (i == thread.GetNumFrames()) { - const uint32_t thread_idx = - queue_backtrace_thread.GetExtendedBacktraceOriginatingIndexID(); - const char *queue_name = queue_backtrace_thread.GetQueueName(); - auto name = llvm::formatv("Enqueued from {0} (Thread {1})", -queue_name, thread_idx); - stackFrames.emplace_back( - llvm::json::Object{{"id", thread.GetThreadID() + 1}, - {"name", name}, - {"presentationHint", "label"}}); - continue; -} -frame = queue_backtrace_thread.GetFrameAtIndex( -i - thread.GetNumFrames() - 1); - } else if (exception_backtrace_thread.IsValid()) { -if (i == thread.GetNumFrames() + - (queue_backtrace_thread.IsValid
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From ebcf4842c7d6c5ac0da4976c9cffb68bc3b22807 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/6] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From ebcf4842c7d6c5ac0da4976c9cffb68bc3b22807 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/7] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
ashgti wrote: Reverted the removal of `enableDisplayExtendedBacktrace` and added `enableDisplayExtendedBacktrace` to the documentation and package.json description of the lldb-dap debugger. https://github.com/llvm/llvm-project/pull/105905 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Add feature to remember last non-empty expression. (PR #107485)
@@ -1364,6 +1364,13 @@ void request_evaluate(const llvm::json::Object &request) { std::string expression = GetString(arguments, "expression").str(); llvm::StringRef context = GetString(arguments, "context"); + // Remember the last non-empty expression from the user, and use that if + // the current expression is empty (i.e. the user hit plain 'return'). + if (!expression.empty()) +g_dap.last_nonempty_expression = expression; + else ashgti wrote: Should this be done using https://github.com/llvm/llvm-project/blob/ea2da571c761066542f8d2273933d2523279e631/lldb/include/lldb/API/SBCommandInterpreterRunOptions.h#L77-L81 on the https://github.com/llvm/llvm-project/blob/ea2da571c761066542f8d2273933d2523279e631/lldb/tools/lldb-dap/LLDBUtils.cpp#L48C14-L48C27 call? https://github.com/llvm/llvm-project/pull/107485 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From ebcf4842c7d6c5ac0da4976c9cffb68bc3b22807 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/8] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 874383a13e2bb6..167142779cf12c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
@@ -3106,80 +3235,109 @@ void request_stackTrace(const llvm::json::Object &request) { llvm::json::Array stackFrames; llvm::json::Object body; + // Threads stacks may contain runtime specific extended backtraces, when + // constructing a stack trace first report the full thread stack trace then + // perform a breadth first traversal of any extended backtrace frames. + // + // For example: + // + // Thread (id=th0) stack=[s0, s1, s2, s3] + // \ Extended backtrace "libdispatch" Thread (id=th1) stack=[s0, s1] + // \ Extended backtrace "libdispatch" Thread (id=th2) stack=[s0, s1] + // \ Extended backtrace "Application Specific Backtrace" Thread (id=th3) + // stack=[s0, s1, s2] + // + // Which will flatten into: + // + // 0. th0->s0 + // 1. th0->s1 + // 2. th0->s2 + // 3. th0->s3 + // 4. label - Enqueued from th1 + // 5. th1->s0 + // 6. th1->s1 + // 7. label - Enqueued from th2 + // 8. th2->s0 + // 9. th2->s1 + // 10. label - Application Specific Backtrace + // 11. th3->s0 + // 12. th3->s1 + // 13. th3->s2 + if (thread.IsValid()) { const auto startFrame = GetUnsigned(arguments, "startFrame", 0); const auto levels = GetUnsigned(arguments, "levels", 0); const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels); -auto totalFrames = thread.GetNumFrames(); - -// This will always return an invalid thread when -// libBacktraceRecording.dylib is not loaded or if there is no extended -// backtrace. -lldb::SBThread queue_backtrace_thread; -if (g_dap.enable_display_extended_backtrace) - queue_backtrace_thread = thread.GetExtendedBacktraceThread("libdispatch"); -if (queue_backtrace_thread.IsValid()) { - // One extra frame as a label to mark the enqueued thread. - totalFrames += queue_backtrace_thread.GetNumFrames() + 1; -} - -// This will always return an invalid thread when there is no exception in -// the current thread. -lldb::SBThread exception_backtrace_thread; -if (g_dap.enable_display_extended_backtrace) - exception_backtrace_thread = thread.GetCurrentExceptionBacktrace(); - -if (exception_backtrace_thread.IsValid()) { - // One extra frame as a label to mark the exception thread. - totalFrames += exception_backtrace_thread.GetNumFrames() + 1; -} - -for (uint32_t i = startFrame; i < endFrame; ++i) { - lldb::SBFrame frame; - std::string prefix; - if (i < thread.GetNumFrames()) { -frame = thread.GetFrameAtIndex(i); - } else if (queue_backtrace_thread.IsValid() && - i < (thread.GetNumFrames() + - queue_backtrace_thread.GetNumFrames() + 1)) { -if (i == thread.GetNumFrames()) { - const uint32_t thread_idx = - queue_backtrace_thread.GetExtendedBacktraceOriginatingIndexID(); - const char *queue_name = queue_backtrace_thread.GetQueueName(); - auto name = llvm::formatv("Enqueued from {0} (Thread {1})", -queue_name, thread_idx); - stackFrames.emplace_back( - llvm::json::Object{{"id", thread.GetThreadID() + 1}, - {"name", name}, - {"presentationHint", "label"}}); - continue; +bool done = false; +int64_t offset = 0; +lldb::SBProcess process = thread.GetProcess(); +llvm::SmallVector threadCluster{{thread}}; + +for (uint32_t i = startFrame; i < endFrame && !threadCluster.empty(); ++i) { + lldb::SBThread current = threadCluster.front(); + lldb::SBFrame frame = current.GetFrameAtIndex(i - offset); + + // If we don't have a valid frame, check if we have any extended frames to + // report. + // *NOTE*: Threads can be chained across mutliple backtraces, so we + // need to keep track of each backtrace we've traversed fully in the + // offset. + while (!frame.IsValid() && current.IsValid() && !threadCluster.empty()) { ashgti wrote: Sorry for the delay, I was out for a week. I refactored the `request_stackTrace` implementation and added some additional tests to validate the pagination behavior and ensure stack traces across thread backtraces are handled correctly. https://github.com/llvm/llvm-project/pull/105905 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From 6612efb0e51d700eeb545a421a34f7a57aafc509 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/8] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index b095171d8fd1a4..59d0f08bec9a24 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/105905 >From 6612efb0e51d700eeb545a421a34f7a57aafc509 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 23 Aug 2024 16:04:44 -0700 Subject: [PATCH 1/9] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers. Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance. Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls. Adding unit tests for exception handling and stack trace supporting. --- .../Python/lldbsuite/test/lldbplatformutil.py | 16 ++ .../test/tools/lldb-dap/dap_server.py | 11 + .../test/tools/lldb-dap/lldbdap_testcase.py | 9 +- .../API/tools/lldb-dap/exception/Makefile | 2 +- .../lldb-dap/exception/TestDAP_exception.py | 8 +- .../API/tools/lldb-dap/exception/cpp/Makefile | 3 + .../exception/cpp/TestDAP_exception_cpp.py| 26 ++ .../API/tools/lldb-dap/exception/cpp/main.cpp | 6 + .../lldb-dap/exception/{main.cpp => main.c} | 2 +- .../tools/lldb-dap/exception/objc/Makefile| 9 + .../exception/objc/TestDAP_exception_objc.py | 27 ++ .../API/tools/lldb-dap/exception/objc/main.m | 8 + .../lldb-dap/extendedStackTrace/Makefile | 5 + .../TestDAP_extendedStackTrace.py | 69 + .../tools/lldb-dap/extendedStackTrace/main.m | 28 ++ .../lldb-dap/stackTrace/TestDAP_stackTrace.py | 4 +- .../TestDAP_stackTraceMissingFunctionName.py | 5 - lldb/tools/lldb-dap/DAP.cpp | 1 - lldb/tools/lldb-dap/DAP.h | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 40 +++ lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 253 +- 22 files changed, 449 insertions(+), 88 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp rename lldb/test/API/tools/lldb-dap/exception/{main.cpp => main.c} (56%) create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py create mode 100644 lldb/test/API/tools/lldb-dap/exception/objc/main.m create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py create mode 100644 lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 602e15d207e94a..3d8c713562e9bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -181,6 +181,22 @@ def findMainThreadCheckerDylib(): return "" +def findBacktraceRecordingDylib(): +if not platformIsDarwin(): +return "" + +if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded): +return "/Developer/usr/lib/libBacktraceRecording.dylib" + +with os.popen("xcode-select -p") as output: +xcode_developer_path = output.read().strip() +mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path +if os.path.isfile(mtc_dylib_path): +return mtc_dylib_path + +return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index b095171d8fd1a4..59d0f08bec9a24 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None } return self.send_recv(command_dict) +def request_exceptionInfo(self, threadId=None): +if threadId is None: +threadId = self.get_thread_id() +args_dict = {"threadId": threadId} +command_dict = { +"command": "exceptionInfo", +"type": "request", +"arguments": args_dict, +} +return self.send_recv(command_dict) + def request_initialize(self, sourceInitFile): command_dict = { "command": "initialize", diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.
[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/105905 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/77026 When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. `FooBarType @ 0x00321`). For swift types, lldb includes a langauge runtime plugin that can generate a description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) # __str__ calls SBValue::GetDescription() Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing ` @ `. >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/2] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4fe831e0bb779a3bda255033e475dcf3979daa61 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/2] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/2] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4c3ad4b1c9363dc9fbaebe7aa005889e87ca5039 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/2] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: > Looks fine to me. Can we add a test? Updated the existing tests to check the adjusted format. One issue I did notice with tests is that the response to an expression will include a response are automatically persisted by `SBValue::GetDescription()`, so you will see the value name in the response, for example: ```swift // Example swift struct. struct Event: Identifiable, Comparable { let id: String let name: String let time: DateInterval var count = 0 } ``` ``` > self (Calendar.Event) $R1 = { id = "e1" name = "Event 1" time = (start = 2024-01-03 17:00:00 UTC, duration = Swift.Double @ 0x61754928) count = (_value = 0) } > self (Calendar.Event) $R2 = { id = "e1" name = "Event 1" time = (start = 2024-01-03 17:00:00 UTC, duration = Swift.Double @ 0x61754928) count = (_value = 0) } > $R2.count + 2 2 ``` Screenshot of how this looks in VS Code: https://github.com/llvm/llvm-project/assets/22535/4e4e2dc9-3013-4936-b621-eaa6c59d7f47";> https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: cc @walter-erquinigo since this looks like it has similar overlap to the auto generated summeries. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Create a typescript extension for lldb-dap (PR #75515)
@@ -1,7 +1,7 @@ { "name": "lldb-dap", - "displayName": "LLDB VSCode", - "version": "0.1.0", + "displayName": "LLDB DAP", ashgti wrote: This file has a mix of tabs and spaces of various sizes, should this be standardized one way or the other? https://github.com/llvm/llvm-project/pull/75515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Create a typescript extension for lldb-dap (PR #75515)
@@ -0,0 +1,57 @@ +import * as vscode from "vscode"; +import { LLDBDapOptions } from "./types"; +import { DisposableContext } from "./disposable-context"; +import { LLDBDapDescriptorFactory } from "./debug-adapter-factory"; +import * as fs from 'fs/promises' ashgti wrote: I think this import is unused https://github.com/llvm/llvm-project/pull/75515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Create a typescript extension for lldb-dap (PR #75515)
https://github.com/ashgti edited https://github.com/llvm/llvm-project/pull/75515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Create a typescript extension for lldb-dap (PR #75515)
https://github.com/ashgti approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/75515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Create a typescript extension for lldb-dap (PR #75515)
@@ -0,0 +1,57 @@ +import * as vscode from "vscode"; +import { LLDBDapOptions } from "./types"; +import { DisposableContext } from "./disposable-context"; +import { LLDBDapDescriptorFactory } from "./debug-adapter-factory"; +import * as fs from 'fs/promises' + +/** + * This creates the configurations for this project if used as a standalone + * extension. + */ +function createDefaultLLDBDapOptions(): LLDBDapOptions { + return { +debuggerType: "lldb-dap", +async createDapExecutableCommand( + session: vscode.DebugSession, + packageJSONExecutable: vscode.DebugAdapterExecutable | undefined, +): Promise { + const path = vscode.workspace +.getConfiguration("lldb-dap", session.workspaceFolder) +.get("executable-path"); + if (path) { +return new vscode.DebugAdapterExecutable(path, []); + } + return packageJSONExecutable; +}, + }; +} + +/** + * This class represents the extension and manages its life cycle. Other extensions + * using it as as library should use this class as the main entry point. + */ +export class LLDBDapExtension extends DisposableContext { + private lldbDapOptions: LLDBDapOptions; + + constructor(lldbDapOptions: LLDBDapOptions) { +super(); +this.lldbDapOptions = lldbDapOptions; + +vscode.window.showInformationMessage(this.lldbDapOptions.debuggerType); ashgti wrote: Do we need a notification each time this is created? https://github.com/llvm/llvm-project/pull/75515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/3] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4c3ad4b1c9363dc9fbaebe7aa005889e87ca5039 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/3] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -242,19 +254,57 @@ def do_test_scopes_variables_setVariable_evaluate( }, "pt": { "equals": {"type": "PointType"}, -"startswith": { -"result": "{x:11, y:22}" +"equals": { +"result": "{x:11, y:22, buffer:{...}}" if enableAutoVariableSummaries -else "PointType @ 0x" +else """(PointType) pt = { + x = 11 + y = 22 + buffer = { +[0] = 0 +[1] = 1 +[2] = 2 +[3] = 3 +[4] = 4 +[5] = 5 +[6] = 6 +[7] = 7 +[8] = 8 +[9] = 9 +[10] = 10 +[11] = 11 +[12] = 12 +[13] = 13 +[14] = 14 +[15] = 15 + } +}""" }, "hasVariablesReference": True, }, "pt.buffer": { "equals": {"type": "int[32]"}, -"startswith": { +"equals": { "result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}" if enableAutoVariableSummaries -else "int[32] @ 0x" ashgti wrote: In the UI it will look like in the variable view: https://github.com/llvm/llvm-project/assets/22535/edbc2f5e-4e54-47b5-af66-fc0e62f137f9";> Hover in the variable view: https://github.com/llvm/llvm-project/assets/22535/4a7b1d08-7475-44bf-a5d2-e36b983dbca1";> Debug Console: https://github.com/llvm/llvm-project/assets/22535/2629431d-e0b5-455f-824a-5b5eba83fbc8";> Debug Console Hover: https://github.com/llvm/llvm-project/assets/22535/a689b35e-f721-4d42-933f-47e7bddb8bf9";> https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -135,6 +135,18 @@ std::vector GetStrings(const llvm::json::Object *obj, return strs; } +static std::string GetDescriptionTrimmed(lldb::SBValue &value) { + lldb::SBStream stream; + value.GetDescription(stream); ashgti wrote: Updated `bool SBValue::GetDescription(SBStream &description)` to return `false` for the `"No value"` case and this helper should return an empty string in that situation fallback back to the ` @ ` format. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/4] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4c3ad4b1c9363dc9fbaebe7aa005889e87ca5039 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/4] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -135,6 +135,21 @@ std::vector GetStrings(const llvm::json::Object *obj, return strs; } +static std::string GetDescriptionTrimmed(lldb::SBValue &value) { ashgti wrote: Done. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -135,6 +135,21 @@ std::vector GetStrings(const llvm::json::Object *obj, return strs; } +static std::string GetDescriptionTrimmed(lldb::SBValue &value) { + lldb::SBStream stream; + if (!value.GetDescription(stream)) { +return ""; + } ashgti wrote: Removed the braces (and well simplified this function). https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: > Is there a way we can tell that the request is from the console and only > enable this feature if we are going to dump it to the debug console? Yea, the DAP has a context we can use to limit this https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Evaluate ``` /** * The context in which the evaluate request is used. * Values: * 'watch': evaluate is called from a watch view context. * 'repl': evaluate is called from a REPL context. * 'hover': evaluate is called to generate the debug hover contents. * This value should only be used if the corresponding capability * `supportsEvaluateForHovers` is true. * 'clipboard': evaluate is called to generate clipboard contents. * This value should only be used if the corresponding capability * `supportsClipboardContext` is true. * 'variables': evaluate is called from a variables view context. * etc. */ context?: 'watch' | 'repl' | 'hover' | 'clipboard' | 'variables' | string; ``` I'll work on an update to this logic to only use GetDescription for `hover` and `repl` cases. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/5] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4c3ad4b1c9363dc9fbaebe7aa005889e87ca5039 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/5] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: Sorry about the spam, I synced my branch and it looks like the pull request added reviewers from all the patches. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 7656af47e058aa7101504cb31aaa067178110351 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH 1/6] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing " @ ". --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index df17ac9d849176..f8ac53ef809e6e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1042,10 +1042,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex, os_display_value << " " << *effective_summary; } else if (effective_summary) { os_display_value << *effective_summary; - - // As last resort, we print its type and address if available. } else { - if (!raw_display_type_name.empty()) { + lldb::SBStream description; + // Try letting lldb generate a description. + if (v.GetDescription(description) && description.GetSize()) { +os_display_value << description.GetData(); + +// As last resort, we print its type and address if available. + } else if (!raw_display_type_name.empty()) { os_display_value << raw_display_type_name; lldb::addr_t address = v.GetLoadAddress(); if (address != LLDB_INVALID_ADDRESS) >From 4c3ad4b1c9363dc9fbaebe7aa005889e87ca5039 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Jan 2024 16:48:27 -0800 Subject: [PATCH 2/6] Tweaking the format to remove trailing newlines and updating tests to cover the adjusted printing. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 17 +++- .../lldb-dap/variables/TestDAP_variables.py | 93 --- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 47 ++ 4 files changed, 127 insertions(+), 32 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..d9e96b8219af34 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -60,7 +61,12 @@ def run_test_evaluate_expressions( self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate( "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" @@ -96,7 +102,12 @@ def run_test_evaluate_expressions( "non_static_int", "10" ) # different variable with the same name self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" +"struct1", +re.escape( +"{foo:15}" +if enableAutoVariableSummaries +else "(my_struct) struct1 = (foo = 15)" +), ) self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo"
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
ashgti wrote: > That will work nicely. Done, the latest revision will only use the description for hovers and repl contexts. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -1210,15 +1210,16 @@ bool SBValue::GetDescription(SBStream &description) { ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); - if (value_sp) { -DumpValueObjectOptions options; -options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); -options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); -value_sp->Dump(strm, options); - } else { + if (!value_sp) { strm.PutCString("No value"); ashgti wrote: I wasn't sure if the `No value` output was an expected behavior on the SBValue, so I didn't want to change that behavior. For example: ``` $ lldb (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> lldb.SBValue() # __str__ > __repr__ > SBValue::GetDescription No value ``` If I removed the `No value` string, then GetDescription would simply return "" or maybe None. I can update that if its appropriate, but I wasn't sure if that behavioral change was desired. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/82051 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 52d6dc8f26477b8fba839194ac1485274312a865 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH] [lldb-dap] Updating VariableDescription to use GetDescription() for hover and repl DAP evaluate requests. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change we now call SBValue::GetDescription() which will internally include a summary (if configured) or call into a language runtime to return a formatted description of the value. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 61 +-- .../lldb-dap/variables/TestDAP_variables.py | 149 +- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 49 -- lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 2 +- 6 files changed, 200 insertions(+), 66 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..7651a67b643094 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -25,6 +26,9 @@ def assertEvaluateFailure(self, expression): self.dap_server.request_evaluate(expression, context=self.context)["body"], ) +def isResultExpandedDescription(self): +return self.context == "repl" or self.context == "hover" + def isExpressionParsedExpected(self): return self.context != "hover" @@ -59,16 +63,30 @@ def run_test_evaluate_expressions( self.assertEvaluate("var2", "21") self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") -self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" -) -self.assertEvaluate( -"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" -) -self.assertEvaluate("struct3", "0x.*0") self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo", "16") +if self.isResultExpandedDescription(): +self.assertEvaluate( +"struct1", +r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)", +) +self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*") +self.assertEvaluate( +"struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr" +) +else: +self.assertEvaluate( +"struct1", +re.escape("{foo:15}") +if enableAutoVariableSummaries +else "my_struct @ 0x", +) +self.assertEvaluate( +"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" +) +self.assertEvaluate("struct3", "0x.*0") + self.assertEvaluateFailure("var") # local variable of a_function self.assertEvaluateFailure("my_struct") # type name self.assertEvaluateFailure("int") # type name @@ -95,9 +113,18 @@ def run_test_evaluate_expressions( self.assertEvaluate( "non_static_int", "10" ) # different variable with the same name -self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" -) +if self.isResultExpandedDescription(): +self.assertEvaluate( +"struct1", +r"\(my_st
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/77026 >From 56d1520f2ce7eb9a9f0c5b5c199deefab15dadfa Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 4 Jan 2024 15:42:35 -0800 Subject: [PATCH] [lldb-dap] Updating VariableDescription to use GetDescription() for hover and repl DAP evaluate requests. When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. "FooBarType @ 0x00321"). For swift types, lldb includes a langauge runtime plugin that can generate a user description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change we now call SBValue::GetDescription() which will internally include a summary (if configured) or call into a language runtime to return a formatted description of the value. --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 61 +-- .../lldb-dap/variables/TestDAP_variables.py | 149 +- .../API/tools/lldb-dap/variables/main.cpp | 2 +- lldb/tools/lldb-dap/JSONUtils.cpp | 51 -- lldb/tools/lldb-dap/JSONUtils.h | 3 + lldb/tools/lldb-dap/lldb-dap.cpp | 2 +- 6 files changed, 202 insertions(+), 66 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index de9d2c93a1109d..7651a67b643094 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -2,6 +2,7 @@ Test lldb-dap completions request """ +import re import lldbdap_testcase import dap_server @@ -10,7 +11,7 @@ from lldbsuite.test.lldbtest import * -class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): def assertEvaluate(self, expression, regex): self.assertRegexpMatches( self.dap_server.request_evaluate(expression, context=self.context)["body"][ @@ -25,6 +26,9 @@ def assertEvaluateFailure(self, expression): self.dap_server.request_evaluate(expression, context=self.context)["body"], ) +def isResultExpandedDescription(self): +return self.context == "repl" or self.context == "hover" + def isExpressionParsedExpected(self): return self.context != "hover" @@ -59,16 +63,30 @@ def run_test_evaluate_expressions( self.assertEvaluate("var2", "21") self.assertEvaluate("static_int", "42") self.assertEvaluate("non_static_int", "43") -self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" -) -self.assertEvaluate( -"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" -) -self.assertEvaluate("struct3", "0x.*0") self.assertEvaluate("struct1.foo", "15") self.assertEvaluate("struct2->foo", "16") +if self.isResultExpandedDescription(): +self.assertEvaluate( +"struct1", +r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)", +) +self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*") +self.assertEvaluate( +"struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr" +) +else: +self.assertEvaluate( +"struct1", +re.escape("{foo:15}") +if enableAutoVariableSummaries +else "my_struct @ 0x", +) +self.assertEvaluate( +"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" +) +self.assertEvaluate("struct3", "0x.*0") + self.assertEvaluateFailure("var") # local variable of a_function self.assertEvaluateFailure("my_struct") # type name self.assertEvaluateFailure("int") # type name @@ -95,9 +113,18 @@ def run_test_evaluate_expressions( self.assertEvaluate( "non_static_int", "10" ) # different variable with the same name -self.assertEvaluate( -"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x" -) +if self.isResultExpandedDescription(): +self.assertEvaluate( +"struct1", +r"\(my_st
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -173,21 +173,21 @@ TryCreateAutoSummaryForContainer(lldb::SBValue &v) { lldb::SBValue child = v.GetChildAtIndex(i); if (llvm::StringRef name = child.GetName(); !name.empty()) { - llvm::StringRef value; + llvm::StringRef desc; if (llvm::StringRef summary = child.GetSummary(); !summary.empty()) -value = summary; +desc = summary; + else if (llvm::StringRef value = child.GetValue(); !value.empty()) +desc = value; else -value = child.GetValue(); - - if (!value.empty()) { -// If the child is an indexed entry, we don't show its index to save -// characters. -if (name.starts_with("[")) - os << separator << value; -else - os << separator << name << ":" << value; -separator = ", "; - } +desc = "{...}"; // Fallback for nested types. ashgti wrote: Updated this to use the `{...}` for nested types. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -405,6 +405,9 @@ struct VariableDescription { /// Create a JSON object that represents these extensions to the DAP variable /// response. llvm::json::Object GetVariableExtensionsJSON(); + + /// Returns a description of the value appropraite for the specified context. ashgti wrote: Done. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (PR #77026)
@@ -1210,15 +1210,16 @@ bool SBValue::GetDescription(SBStream &description) { ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); - if (value_sp) { -DumpValueObjectOptions options; -options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); -options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); -value_sp->Dump(strm, options); - } else { + if (!value_sp) { strm.PutCString("No value"); ashgti wrote: I reverted this change and instead just check `IsValid()` before we call into `GetDescription()`. https://github.com/llvm/llvm-project/pull/77026 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/78005 The previous logic for determining if an expression was a command or variable expression in the repl would incorrectly identify the context in many common cases where a local variable name partially overlaps with the repl input. For example: ``` int foo() { int var = 1; // break point, evaluating "p var", previously emitted a warning } ``` Instead of checking potentially multiple conflicting values against the expression input, I updated the heuristic to only consider the first term. This is much more reliable at eliminating false positives when the input does not actually hide a local variable. Additionally, I updated the warning on conflicts to occur anytime the conflict is detected since the specific conflict can change based on the current input. This also includes additional details on how users can change the behavior. Example Debug Console output from lldb/test/API/tools/lldb-dap/evaluate/main.cpp:11 breakpoint 3. ``` lldb-dap> var + 3 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. note: This error message is only displayed once. Use '`' as a prefix ensure expressions are evaluated as lldb commands. To change the repl behavior use: '`lldb-dap repl-mode variable' to evaluate all expressions as variables. '`lldb-dap repl-mode command' to evaluate all expressions as commands. '`lldb-dap repl-mode auto' to use a heuristic to detect the mode based on the input and local variables. 45 lldb-dap> var + 1 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. 43 ``` >From 6290aaa803324f6942e642b888f41966f4cc3709 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 12 Jan 2024 16:39:47 -0800 Subject: [PATCH] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. The previous logic for determining if an expression was a command or variable expression in the repl would incorrectly identify the context in many common cases where a local variable name partially overlaps with the repl input. For example: ``` int foo() { int var = 1; // break point, evaluating "p var", previously emitted a warning } ``` Instead of checking potentially multiple conflicting values against the expression input, I updated the heuristic to only consider the first term. This is much more reliable at eliminating false positives when the input does not actually hide a local variable. Additionally, I updated the warning on conflicts to occur anytime the conflict is detected since the specific conflict can change based on the current input. This also includes additional details on how users can change the behavior. Example Debug Console output from lldb/test/API/tools/lldb-dap/evaluate/main.cpp:11 breakpoint 3. ``` lldb-dap> var + 3 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. note: This error message is only displayed once. Use '`' as a prefix ensure expressions are evaluated as lldb commands. To change the repl behavior use: '`lldb-dap repl-mode variable' to evaluate all expressions as variables. '`lldb-dap repl-mode command' to evaluate all expressions as commands. '`lldb-dap repl-mode auto' to use a heuristic to detect the mode based on the input and local variables. 45 lldb-dap> var + 1 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. 43 ``` --- .../completions/TestDAP_completions.py| 6 +- .../lldb-dap/evaluate/TestDAP_evaluate.py | 8 +- lldb/tools/lldb-dap/DAP.cpp | 94 +++ lldb/tools/lldb-dap/DAP.h | 10 +- lldb/tools/lldb-dap/lldb-dap.cpp | 35 --- 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py index 5f6d63392f4d5f..2b3ec656c107a5 100644 --- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py +++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py @@ -41,13 +41,13 @@ def test_completions(self): { "text": "var", "label": "var -- vector &", -} -], -[ +}, { "text": "var", "label": "var -- Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified.", }, +], +[
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/78005 >From 09f1556fd0615f42fe9dd49bf8c2355517f6e0da Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 12 Jan 2024 16:39:47 -0800 Subject: [PATCH] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. The previous logic for determining if an expression was a command or variable expression in the repl would incorrectly identify the context in many common cases where a local variable name partially overlaps with the repl input. For example: ``` int foo() { int var = 1; // break point, evaluating "p var", previously emitted a warning } ``` Instead of checking potentially multiple conflicting values against the expression input, I updated the heuristic to only consider the first term. This is much more reliable at eliminating false positives when the input does not actually hide a local variable. Additionally, I updated the warning on conflicts to occur anytime the conflict is detected since the specific conflict can change based on the current input. This also includes additional details on how users can change the behavior. Example Debug Console output from lldb/test/API/tools/lldb-dap/evaluate/main.cpp:11 breakpoint 3. ``` lldb-dap> var + 3 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. note: This error message is only displayed once. Use '`' as a prefix ensure expressions are evaluated as lldb commands. To change the repl behavior use: '`lldb-dap repl-mode variable' to evaluate all expressions as variables. '`lldb-dap repl-mode command' to evaluate all expressions as commands. '`lldb-dap repl-mode auto' to use a heuristic to detect the mode based on the input and local variables. 45 lldb-dap> var + 1 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. 43 ``` --- .../completions/TestDAP_completions.py| 6 +- .../lldb-dap/evaluate/TestDAP_evaluate.py | 8 +- lldb/tools/lldb-dap/DAP.cpp | 94 +++ lldb/tools/lldb-dap/DAP.h | 10 +- lldb/tools/lldb-dap/lldb-dap.cpp | 35 --- 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py index 5f6d63392f4d5f..2b3ec656c107a5 100644 --- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py +++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py @@ -41,13 +41,13 @@ def test_completions(self): { "text": "var", "label": "var -- vector &", -} -], -[ +}, { "text": "var", "label": "var -- Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified.", }, +], +[ {"text": "var1", "label": "var1 -- int &"}, ], ) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 7651a67b643094..0192746f1277b5 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -87,7 +87,13 @@ def run_test_evaluate_expressions( ) self.assertEvaluate("struct3", "0x.*0") -self.assertEvaluateFailure("var") # local variable of a_function +if context == "repl": +# In the repl context expressions may be interpreted as lldb +# commands since no variables have the same name as the command. +self.assertEvaluate("var", r"\(lldb\) var\n.*") +else: +self.assertEvaluateFailure("var") # local variable of a_function + self.assertEvaluateFailure("my_struct") # type name self.assertEvaluateFailure("int") # type name self.assertEvaluateFailure("foo") # member of my_struct diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 4b72c13f9215a8..ff2804cb0d6c6b 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -48,7 +48,7 @@ DAP::DAP() progress_event_reporter( [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }), reverse_request_seq(0), repl_mode(ReplMode::Auto), - auto_repl_mode_collision_warning(false) { + repl_mode_behavior_description_shown(false) { const char *log_file_path = getenv("LLDBDAP_LOG"); #if defined(_WIN32) // Windows opens stdout and stdin in text mode which conver
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/78005 >From f01c82be09e28c1eead4d80f4ceea67dee0318d6 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 12 Jan 2024 16:39:47 -0800 Subject: [PATCH] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. The previous logic for determining if an expression was a command or variable expression in the repl would incorrectly identify the context in many common cases where a local variable name partially overlaps with the repl input. For example: ``` int foo() { int var = 1; // break point, evaluating "p var", previously emitted a warning } ``` Instead of checking potentially multiple conflicting values against the expression input, I updated the heuristic to only consider the first term. This is much more reliable at eliminating false positives when the input does not actually hide a local variable. Additionally, I updated the warning on conflicts to occur anytime the conflict is detected since the specific conflict can change based on the current input. This also includes additional details on how users can change the behavior. Example Debug Console output from lldb/test/API/tools/lldb-dap/evaluate/main.cpp:11 breakpoint 3. ``` lldb-dap> var + 3 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. note: This error message is only displayed once. Use '`' as a prefix ensure expressions are evaluated as lldb commands. To change the repl behavior use: '`lldb-dap repl-mode variable' to evaluate all expressions as variables. '`lldb-dap repl-mode command' to evaluate all expressions as commands. '`lldb-dap repl-mode auto' to use a heuristic to detect the mode based on the input and local variables. 45 lldb-dap> var + 1 warning: Expression 'var' is both an lldb command and variable, evaluating the expression as a variable. To evaluate the lldb command, use '`' as a prefix. 43 ``` --- .../completions/TestDAP_completions.py| 6 +- .../lldb-dap/evaluate/TestDAP_evaluate.py | 8 +- lldb/tools/lldb-dap/DAP.cpp | 74 +-- lldb/tools/lldb-dap/DAP.h | 9 ++- lldb/tools/lldb-dap/lldb-dap.cpp | 35 ++--- 5 files changed, 75 insertions(+), 57 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py index 5f6d63392f4d5f..2b3ec656c107a5 100644 --- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py +++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py @@ -41,13 +41,13 @@ def test_completions(self): { "text": "var", "label": "var -- vector &", -} -], -[ +}, { "text": "var", "label": "var -- Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified.", }, +], +[ {"text": "var1", "label": "var1 -- int &"}, ], ) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 7651a67b643094..0192746f1277b5 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -87,7 +87,13 @@ def run_test_evaluate_expressions( ) self.assertEvaluate("struct3", "0x.*0") -self.assertEvaluateFailure("var") # local variable of a_function +if context == "repl": +# In the repl context expressions may be interpreted as lldb +# commands since no variables have the same name as the command. +self.assertEvaluate("var", r"\(lldb\) var\n.*") +else: +self.assertEvaluateFailure("var") # local variable of a_function + self.assertEvaluateFailure("my_struct") # type name self.assertEvaluateFailure("int") # type name self.assertEvaluateFailure("foo") # member of my_struct diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 4b72c13f9215a8..b254ddfef0d5ff 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -47,8 +47,7 @@ DAP::DAP() configuration_done_sent(false), waiting_for_run_in_terminal(false), progress_event_reporter( [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }), - reverse_request_seq(0), repl_mode(ReplMode::Auto), - auto_repl_mode_collision_warning(false) { + reverse_request_seq(0), repl_mode(ReplMode::Auto) { const char *log_file_path = getenv("LLDBDAP_LOG");
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -380,12 +380,19 @@ llvm::json::Value DAP::CreateTopLevelScopes() { return llvm::json::Value(std::move(scopes)); } -ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, - std::string &text) { +static std::string FirstTerm(llvm::StringRef input) { + if (input.empty()) +return ""; + const auto terms = llvm::getToken(input, " \t\n\v\f\r.[-("); ashgti wrote: I actually removed the extra characters and left it as whitespace. There are lldb commands like `p/t` or `x/4xw` that can include non alpha numeric characters and users can add aliases, so I think using `ResolveCommand` is the most correct thing to do here. https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -380,12 +380,19 @@ llvm::json::Value DAP::CreateTopLevelScopes() { return llvm::json::Value(std::move(scopes)); } -ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, - std::string &text) { +static std::string FirstTerm(llvm::StringRef input) { ashgti wrote: I ended up re-writing this to inline the helper. https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -395,43 +402,56 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, case ReplMode::Command: return ExpressionContext::Command; case ReplMode::Auto: -// If the frame is invalid then there is no variables to complete, assume -// this is an lldb command instead. -if (!frame.IsValid()) { - return ExpressionContext::Command; -} - +// To determine if the expression is a command or not, check if the first +// term is a variable or command. If its a variable in scope we will prefer +// that behavior and give a warning to the user if they meant to invoke the +// operation as a command. +// +// Example use case: +// int p and expression "p + 1" > variable +// int i and expression "i" > variable +// int var and expression "va" > command +const auto term = FirstTerm(expression); ashgti wrote: Done. https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -395,43 +402,56 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, case ReplMode::Command: return ExpressionContext::Command; case ReplMode::Auto: -// If the frame is invalid then there is no variables to complete, assume -// this is an lldb command instead. -if (!frame.IsValid()) { - return ExpressionContext::Command; -} - +// To determine if the expression is a command or not, check if the first +// term is a variable or command. If its a variable in scope we will prefer +// that behavior and give a warning to the user if they meant to invoke the +// operation as a command. +// +// Example use case: +// int p and expression "p + 1" > variable +// int i and expression "i" > variable +// int var and expression "va" > command +const auto term = FirstTerm(expression); +auto ci = debugger.GetCommandInterpreter(); lldb::SBCommandReturnObject result; -debugger.GetCommandInterpreter().ResolveCommand(text.data(), result); - -// If this command is a simple expression like `var + 1` check if there is -// a local variable name that is in the current expression. If so, ensure -// the expression runs in the variable context. -lldb::SBValueList variables = frame.GetVariables(true, true, true, true); -llvm::StringRef input = text; -for (uint32_t i = 0; i < variables.GetSize(); i++) { - llvm::StringRef name = variables.GetValueAtIndex(i).GetName(); - // Check both directions in case the input is a partial of a variable - // (e.g. input = `va` and local variable = `var1`). - if (input.contains(name) || name.contains(input)) { -if (!auto_repl_mode_collision_warning) { - llvm::errs() << "Variable expression '" << text - << "' is hiding an lldb command, prefix an expression " - "with '" - << g_dap.command_escape_prefix - << "' to ensure it runs as a lldb command.\n"; - auto_repl_mode_collision_warning = true; -} -return ExpressionContext::Variable; +ci.ResolveCommand(term.c_str(), result); +bool term_is_command = result.Succeeded(); +bool term_is_variable = frame.FindVariable(term.c_str()).IsValid(); + +// If we have both a variable and command, warn the user about the conflict. +if (term_is_command && term_is_variable) { + llvm::errs() + << "warning: Expression '" << term + << "' is both an lldb command and variable, evaluating the " + "expression as a variable. To evaluate the lldb command, use '" ashgti wrote: Done. https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -395,43 +402,56 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, case ReplMode::Command: return ExpressionContext::Command; case ReplMode::Auto: -// If the frame is invalid then there is no variables to complete, assume -// this is an lldb command instead. -if (!frame.IsValid()) { - return ExpressionContext::Command; -} - +// To determine if the expression is a command or not, check if the first +// term is a variable or command. If its a variable in scope we will prefer +// that behavior and give a warning to the user if they meant to invoke the +// operation as a command. +// +// Example use case: +// int p and expression "p + 1" > variable +// int i and expression "i" > variable +// int var and expression "va" > command +const auto term = FirstTerm(expression); +auto ci = debugger.GetCommandInterpreter(); lldb::SBCommandReturnObject result; -debugger.GetCommandInterpreter().ResolveCommand(text.data(), result); - -// If this command is a simple expression like `var + 1` check if there is -// a local variable name that is in the current expression. If so, ensure -// the expression runs in the variable context. -lldb::SBValueList variables = frame.GetVariables(true, true, true, true); -llvm::StringRef input = text; -for (uint32_t i = 0; i < variables.GetSize(); i++) { - llvm::StringRef name = variables.GetValueAtIndex(i).GetName(); - // Check both directions in case the input is a partial of a variable - // (e.g. input = `va` and local variable = `var1`). - if (input.contains(name) || name.contains(input)) { -if (!auto_repl_mode_collision_warning) { - llvm::errs() << "Variable expression '" << text - << "' is hiding an lldb command, prefix an expression " - "with '" - << g_dap.command_escape_prefix - << "' to ensure it runs as a lldb command.\n"; - auto_repl_mode_collision_warning = true; -} -return ExpressionContext::Variable; +ci.ResolveCommand(term.c_str(), result); +bool term_is_command = result.Succeeded(); +bool term_is_variable = frame.FindVariable(term.c_str()).IsValid(); + +// If we have both a variable and command, warn the user about the conflict. +if (term_is_command && term_is_variable) { + llvm::errs() + << "warning: Expression '" << term + << "' is both an lldb command and variable, evaluating the " + "expression as a variable. To evaluate the lldb command, use '" + << g_dap.command_escape_prefix << "' as a prefix.\n"; + if (!repl_mode_behavior_description_shown) { +repl_mode_behavior_description_shown = true; +llvm::errs() +<< "\nnote: This error message is only displayed once. Use '" +<< g_dap.command_escape_prefix +<< "' as a prefix ensure expressions are evaluated as lldb " + "commands.\n\nTo change the repl behavior use:\n'" +<< g_dap.command_escape_prefix +<< "lldb-dap repl-mode variable' to evaluate all expressions " + "as variables.\n'" +<< g_dap.command_escape_prefix +<< "lldb-dap repl-mode command' to evaluate all expressions as " + "commands.\n'" +<< g_dap.command_escape_prefix +<< "lldb-dap repl-mode auto' to use a heuristic to detect the " + "mode based on the input and local variables.\n"; ashgti wrote: Removed https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
@@ -395,43 +402,56 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, case ReplMode::Command: return ExpressionContext::Command; case ReplMode::Auto: -// If the frame is invalid then there is no variables to complete, assume -// this is an lldb command instead. -if (!frame.IsValid()) { - return ExpressionContext::Command; -} - +// To determine if the expression is a command or not, check if the first +// term is a variable or command. If its a variable in scope we will prefer ashgti wrote: Done. https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti edited https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/78005 >From c3a4cd38b41e332342aa7042d3a9c2f75416bfc3 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 12 Jan 2024 16:39:47 -0800 Subject: [PATCH] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. The previous logic for determining if an expression was a command or variable expression in the repl would incorrectly identify the context in many common cases where a local variable name partially overlaps with the repl input. For example: ``` int foo() { int var = 1; // break point, evaluating "p var", previously emitted a warning } ``` Instead of checking potentially multiple conflicting values against the expression input, I updated the heuristic to only consider the first term. This is much more reliable at eliminating false positives when the input does not actually hide a local variable. Additionally, I updated the warning on conflicts to occur anytime the conflict is detected since the specific conflict can change based on the current input. Example Debug Console output from lldb/test/API/tools/lldb-dap/evaluate/main.cpp:11 breakpoint 3. ``` lldb-dap> var + 3 Warning: Expression 'var' is both an LLDB command and variable. It will be evaluated as a variable. To evaluate the expression as an LLDB command, use '`' as a prefix. 45 lldb-dap> var + 1 Warning: Expression 'var' is both an LLDB command and variable. It will be evaluated as a variable. To evaluate the expression as an LLDB command, use '`' as a prefix. 43 ``` --- .../completions/TestDAP_completions.py| 6 +- .../lldb-dap/evaluate/TestDAP_evaluate.py | 8 +- lldb/tools/lldb-dap/DAP.cpp | 74 +-- lldb/tools/lldb-dap/DAP.h | 9 ++- lldb/tools/lldb-dap/lldb-dap.cpp | 35 ++--- 5 files changed, 75 insertions(+), 57 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py index 5f6d63392f4d5f..2b3ec656c107a5 100644 --- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py +++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py @@ -41,13 +41,13 @@ def test_completions(self): { "text": "var", "label": "var -- vector &", -} -], -[ +}, { "text": "var", "label": "var -- Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified.", }, +], +[ {"text": "var1", "label": "var1 -- int &"}, ], ) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 7651a67b643094..0192746f1277b5 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -87,7 +87,13 @@ def run_test_evaluate_expressions( ) self.assertEvaluate("struct3", "0x.*0") -self.assertEvaluateFailure("var") # local variable of a_function +if context == "repl": +# In the repl context expressions may be interpreted as lldb +# commands since no variables have the same name as the command. +self.assertEvaluate("var", r"\(lldb\) var\n.*") +else: +self.assertEvaluateFailure("var") # local variable of a_function + self.assertEvaluateFailure("my_struct") # type name self.assertEvaluateFailure("int") # type name self.assertEvaluateFailure("foo") # member of my_struct diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 4b72c13f9215a8..b254ddfef0d5ff 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -47,8 +47,7 @@ DAP::DAP() configuration_done_sent(false), waiting_for_run_in_terminal(false), progress_event_reporter( [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }), - reverse_request_seq(0), repl_mode(ReplMode::Auto), - auto_repl_mode_collision_warning(false) { + reverse_request_seq(0), repl_mode(ReplMode::Auto) { const char *log_file_path = getenv("LLDBDAP_LOG"); #if defined(_WIN32) // Windows opens stdout and stdin in text mode which converts \n to 13,10 @@ -380,12 +379,12 @@ llvm::json::Value DAP::CreateTopLevelScopes() { return llvm::json::Value(std::move(scopes)); } -ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame, - std::string &text) { +ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame frame, +
[Lldb-commits] [lldb] [lldb-dap] Removing the debugger log callback, instead use the default behavior. (PR #78343)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/78343 The logging callback prevents `lldb> log enable -f lldb api` from writing to a file and instead redirects all logging to the callback. Fixes [issues/78334](https://github.com/llvm/llvm-project/issues/78334). >From b9a063fc504ea77da2ef07121f74fa062ff793a0 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 16 Jan 2024 12:36:21 -0800 Subject: [PATCH] [lldb-dap] Removing the debugger log callback, instead use the default behavior. The logging callback prevents `lldb> log enable -f lldb api` from writing to a file and instead redirects all logging to the callback. --- lldb/tools/lldb-dap/lldb-dap.cpp | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 8c8e92146e63c0a..a51fc8326b9eb3e 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -1516,17 +1516,13 @@ void request_modules(const llvm::json::Object &request) { // }] // } void request_initialize(const llvm::json::Object &request) { - auto log_cb = [](const char *buf, void *baton) -> void { -g_dap.SendOutput(OutputType::Console, llvm::StringRef{buf}); - }; - auto arguments = request.getObject("arguments"); // sourceInitFile option is not from formal DAP specification. It is only // used by unit tests to prevent sourcing .lldbinit files from environment // which may affect the outcome of tests. bool source_init_file = GetBoolean(arguments, "sourceInitFile", true); - g_dap.debugger = lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); + g_dap.debugger = lldb::SBDebugger::Create(source_init_file); auto cmd = g_dap.debugger.GetCommandInterpreter().AddMultiwordCommand( "lldb-dap", "Commands for managing lldb-dap."); if (GetBoolean(arguments, "supportsStartDebuggingRequest", false)) { ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Adjusting how repl-mode auto determines commands vs variable expressions. (PR #78005)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/78005 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/82051 This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. This should fix #82048 >From 5e3787a61c92f002746f2437e2fc8509d787a0ce Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 16 Feb 2024 14:11:10 -0800 Subject: [PATCH] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. --- lldb/tools/lldb-dap/lldb-dap.cpp | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 67022347e6d624..cc555d33b48b53 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -22,7 +22,7 @@ // We also need to #undef GetObject (which is defined to GetObjectW) because // the JSON code we use also has methods named `GetObject()` and we conflict // against these. -#define NOMINMAX +#define NOMINMAXf #include #undef GetObject #include @@ -1779,8 +1779,10 @@ 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); -if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) +if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) { error.SetErrorString(llvm::toString(std::move(err)).c_str()); + return error; +} // 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(); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/82051 >From 300d2959e510f41607ce2487264a98814d0a1700 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 16 Feb 2024 14:11:10 -0800 Subject: [PATCH] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. --- lldb/tools/lldb-dap/lldb-dap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 67022347e6d624..78b0b4078706aa 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -1779,8 +1779,10 @@ 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); -if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) +if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) { error.SetErrorString(llvm::toString(std::move(err)).c_str()); + return error; +} // 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(); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/82051 >From f76dbe10e30c84aadaf33c597fe81bc0a285c995 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 16 Feb 2024 14:11:10 -0800 Subject: [PATCH] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 2 + .../tools/lldb-dap/launch/TestDAP_launch.py | 47 +-- lldb/tools/lldb-dap/lldb-dap.cpp | 4 +- 3 files changed, 48 insertions(+), 5 deletions(-) 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 7436b9900e98b0..264e66d7e0dab8 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 @@ -122,6 +122,8 @@ def verify_commands(self, flavor, output, commands): for cmd in commands: found = False for line in lines: +if len(cmd) > 0 and (cmd[0] == '!' or cmd[0] == '?'): +cmd = cmd[1:] if line.startswith(prefix) and cmd in line: found = True break diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index 78958612253691..d0d09c5ac74b31 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -272,9 +272,6 @@ def test_environment(self): @skipIfWindows @skipIfRemote -@skipIf( -archs=["arm", "aarch64"] -) # failed run https://lab.llvm.org/buildbot/#/builders/96/builds/6933 def test_commands(self): """ Tests the "initCommands", "preRunCommands", "stopCommands", @@ -398,7 +395,7 @@ def test_extra_launch_commands(self): # Verify all "preRunCommands" were found in console output self.verify_commands("preRunCommands", output, preRunCommands) -# Verify all "launchCommands" were founc in console output +# Verify all "launchCommands" were found in console output # After execution, program should launch self.verify_commands("launchCommands", output, launchCommands) # Verify the "stopCommands" here @@ -420,6 +417,48 @@ def test_extra_launch_commands(self): output = self.get_console(timeout=1.0) self.verify_commands("exitCommands", output, exitCommands) +@skipIfWindows +@skipIfRemote +def test_failing_launch_commands(self): +""" +Tests the "launchCommands" failing to launch a target. +""" +self.build_and_create_debug_adaptor() +program = self.getBuildArtifact("a.out") + +# Run an invalid launch command, in this case a bad path. +launchCommands = [ +'!target create "/bad/path%s"' % (program) +] + +initCommands = ["target list", "platform list"] +preRunCommands = ["image list a.out", "image dump sections a.out"] +response = self.launch( +program, +initCommands=initCommands, +preRunCommands=preRunCommands, +launchCommands=launchCommands, +expectFailure=True, +) + +self.assertFalse(response["success"]) +self.assertRegex( +response["message"], +r"Failed to run launch commands\. See the Debug Console for more details" +) + +# Get output from the console. This should contain both the +# "initCommands" and the "preRunCommands". +output = self.get_console() +# Verify all "initCommands" were found in console output +self.verify_commands("initCommands", output, initCommands) +# Verify all "preRunCommands" were found in console output +self.verify_commands("preRunCommands", output, preRunCommands) + +# Verify all "launchCommands" were founc in console output +# The launch should fail due to the invalid command. +self.verify_commands("launchCommands", output, launchCommands) + @skipIfWindows @skipIfNetBSD # Hangs on NetBSD as well @skipIf(archs=["arm", "aarch64"], oslist=["linux"]) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 67022347e6d624..78b0b4078706aa 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -1779,8 +1779,10 @@ 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); -if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands))
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/82051 >From 465abea7e445271681f5107ccbd306f63ccd0956 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 16 Feb 2024 14:11:10 -0800 Subject: [PATCH] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 2 + .../tools/lldb-dap/launch/TestDAP_launch.py | 48 ++- lldb/tools/lldb-dap/lldb-dap.cpp | 4 +- 3 files changed, 52 insertions(+), 2 deletions(-) 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 7436b9900e98b0..264e66d7e0dab8 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 @@ -122,6 +122,8 @@ def verify_commands(self, flavor, output, commands): for cmd in commands: found = False for line in lines: +if len(cmd) > 0 and (cmd[0] == '!' or cmd[0] == '?'): +cmd = cmd[1:] if line.startswith(prefix) and cmd in line: found = True break diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index 78958612253691..1f9cfecf1d952a 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -398,7 +398,7 @@ def test_extra_launch_commands(self): # Verify all "preRunCommands" were found in console output self.verify_commands("preRunCommands", output, preRunCommands) -# Verify all "launchCommands" were founc in console output +# Verify all "launchCommands" were found in console output # After execution, program should launch self.verify_commands("launchCommands", output, launchCommands) # Verify the "stopCommands" here @@ -420,6 +420,52 @@ def test_extra_launch_commands(self): output = self.get_console(timeout=1.0) self.verify_commands("exitCommands", output, exitCommands) +@skipIfWindows +@skipIfRemote +def test_failing_launch_commands(self): +""" +Tests "launchCommands" failures prevents a launch. +""" +self.build_and_create_debug_adaptor() +program = self.getBuildArtifact("a.out") + +# Run an invalid launch command, in this case a bad path. +launchCommands = [ +'!target create "/bad/path%s"' % (program) +] + +initCommands = ["target list", "platform list"] +preRunCommands = ["image list a.out", "image dump sections a.out"] +response = self.launch( +program, +initCommands=initCommands, +preRunCommands=preRunCommands, +launchCommands=launchCommands, +expectFailure=True, +) + +self.assertFalse(response["success"]) +self.assertRegex( +response["message"], +r"Failed to run launch commands\. See the Debug Console for more details" +) + +# Get output from the console. This should contain both the +# "initCommands" and the "preRunCommands". +output = self.get_console() +# Verify all "initCommands" were found in console output +self.verify_commands("initCommands", output, initCommands) +# Verify all "preRunCommands" were found in console output +self.verify_commands("preRunCommands", output, preRunCommands) + +# Verify all "launchCommands" were founc in console output +# The launch should fail due to the invalid command. +self.verify_commands("launchCommands", output, launchCommands) +self.assertRegex( +output, +r"unable to find executable for '/bad/path/" +) + @skipIfWindows @skipIfNetBSD # Hangs on NetBSD as well @skipIf(archs=["arm", "aarch64"], oslist=["linux"]) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 67022347e6d624..78b0b4078706aa 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -1779,8 +1779,10 @@ 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); -if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) +if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) { error.SetErrorString(llvm::toString(std::move(err)).c_str()); + return error; +} // The custom commands might have creat
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/82051 >From 61224ee2642e7fa2723e48e4a32c90f5ec04759a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 16 Feb 2024 14:11:10 -0800 Subject: [PATCH] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. This fixes an issue where the error is lost if a command while executing `launchCommands` when launching the debugger. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 2 + .../tools/lldb-dap/launch/TestDAP_launch.py | 44 ++- lldb/tools/lldb-dap/lldb-dap.cpp | 4 +- 3 files changed, 47 insertions(+), 3 deletions(-) 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 7436b9900e98b0..8092341a449b9f 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 @@ -122,6 +122,8 @@ def verify_commands(self, flavor, output, commands): for cmd in commands: found = False for line in lines: +if len(cmd) > 0 and (cmd[0] == "!" or cmd[0] == "?"): +cmd = cmd[1:] if line.startswith(prefix) and cmd in line: found = True break diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index 78958612253691..8ae82a01652d3b 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -2,7 +2,6 @@ Test lldb-dap setBreakpoints request """ - import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -398,7 +397,7 @@ def test_extra_launch_commands(self): # Verify all "preRunCommands" were found in console output self.verify_commands("preRunCommands", output, preRunCommands) -# Verify all "launchCommands" were founc in console output +# Verify all "launchCommands" were found in console output # After execution, program should launch self.verify_commands("launchCommands", output, launchCommands) # Verify the "stopCommands" here @@ -420,6 +419,47 @@ def test_extra_launch_commands(self): output = self.get_console(timeout=1.0) self.verify_commands("exitCommands", output, exitCommands) +@skipIfWindows +@skipIfRemote +def test_failing_launch_commands(self): +""" +Tests "launchCommands" failures prevents a launch. +""" +self.build_and_create_debug_adaptor() +program = self.getBuildArtifact("a.out") + +# Run an invalid launch command, in this case a bad path. +launchCommands = ['!target create "/bad/path%s"' % (program)] + +initCommands = ["target list", "platform list"] +preRunCommands = ["image list a.out", "image dump sections a.out"] +response = self.launch( +program, +initCommands=initCommands, +preRunCommands=preRunCommands, +launchCommands=launchCommands, +expectFailure=True, +) + +self.assertFalse(response["success"]) +self.assertRegex( +response["message"], +r"Failed to run launch commands\. See the Debug Console for more details", +) + +# Get output from the console. This should contain both the +# "initCommands" and the "preRunCommands". +output = self.get_console() +# Verify all "initCommands" were found in console output +self.verify_commands("initCommands", output, initCommands) +# Verify all "preRunCommands" were found in console output +self.verify_commands("preRunCommands", output, preRunCommands) + +# Verify all "launchCommands" were founc in console output +# The launch should fail due to the invalid command. +self.verify_commands("launchCommands", output, launchCommands) +self.assertRegex(output, r"unable to find executable for '/bad/path/") + @skipIfWindows @skipIfNetBSD # Hangs on NetBSD as well @skipIf(archs=["arm", "aarch64"], oslist=["linux"]) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 67022347e6d624..78b0b4078706aa 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -1779,8 +1779,10 @@ 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); -if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) +if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands)) { error.SetErrorString(llvm::toStrin
[Lldb-commits] [lldb] [lldb-dap] Do not write over the existing error if launchCommands fail during debugger launch. (PR #82051)
ashgti wrote: > Needs a test and this will be good to go. Done, added tests https://github.com/llvm/llvm-project/pull/82051 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Fixing a type encoding issue with dap Stopped events. (PR #72292)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/72292 Previously the type of the breakpoint id in the Stopped event was a uint64_t, however thats the wrong type for a breakpoint id, which can cause encoding issues when internal breakpoints are hit. >From 5077857569f4f6ed74feedc2afe58a1a576ce4eb Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 14 Nov 2023 10:02:41 -0800 Subject: [PATCH] [lldb-dap] Fixing a type encoding issue with dap Stopped events. Previously the type of the breakpoint id in the Stopped event was a uint64_t, however thats the wrong type for a breakpoint id, which can cause encoding issues when internal breakpoints are hit. --- lldb/tools/lldb-dap/JSONUtils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 2023291729762f1..2b96c4f21aeb04d 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -953,9 +953,9 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, } else { body.try_emplace("reason", "breakpoint"); char desc_str[64]; - uint64_t bp_id = thread.GetStopReasonDataAtIndex(0); - uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); - snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, + break_id_t bp_id = thread.GetStopReasonDataAtIndex(0); + break_id_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); + snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIo32 ".%" PRIo32, bp_id, bp_loc_id); body.try_emplace("hitBreakpointIds", llvm::json::Array{llvm::json::Value(bp_id)}); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Fixing a type encoding issue with dap Stopped events. (PR #72292)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/72292 >From ed4b044027e4ccc02bd19af394a076892baeea95 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 14 Nov 2023 10:02:41 -0800 Subject: [PATCH] [lldb-dap] Fixing a type encoding issue with dap Stopped events. Previously the type of the breakpoint id in the Stopped event was a uint64_t, however thats the wrong type for a breakpoint id, which can cause encoding issues when internal breakpoints are hit. --- lldb/tools/lldb-dap/JSONUtils.cpp | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 2023291729762f1..ebb0ba202183c28 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -13,6 +13,7 @@ #include #include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" @@ -952,11 +953,10 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, EmplaceSafeString(body, "description", exc_bp->label); } else { body.try_emplace("reason", "breakpoint"); - char desc_str[64]; - uint64_t bp_id = thread.GetStopReasonDataAtIndex(0); - uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); - snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, - bp_id, bp_loc_id); + lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(0); + lldb::break_id_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); + std::string desc_str = + llvm::formatv("breakpoint {0}.{1}", bp_id, bp_loc_id); body.try_emplace("hitBreakpointIds", llvm::json::Array{llvm::json::Value(bp_id)}); EmplaceSafeString(body, "description", desc_str); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Fixing a type encoding issue with dap Stopped events. (PR #72292)
@@ -953,9 +953,9 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, } else { body.try_emplace("reason", "breakpoint"); char desc_str[64]; - uint64_t bp_id = thread.GetStopReasonDataAtIndex(0); - uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); - snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, + break_id_t bp_id = thread.GetStopReasonDataAtIndex(0); + break_id_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); + snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIo32 ".%" PRIo32, ashgti wrote: Switched to llvm::vformat instead. https://github.com/llvm/llvm-project/pull/72292 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Fixing a type encoding issue with dap Stopped events. (PR #72292)
@@ -953,9 +953,9 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, } else { body.try_emplace("reason", "breakpoint"); char desc_str[64]; - uint64_t bp_id = thread.GetStopReasonDataAtIndex(0); - uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); - snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, + break_id_t bp_id = thread.GetStopReasonDataAtIndex(0); + break_id_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); + snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIo32 ".%" PRIo32, ashgti wrote: Switched to `llvm::vformat`. https://github.com/llvm/llvm-project/pull/72292 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Fixing a type encoding issue with dap Stopped events. (PR #72292)
@@ -953,9 +953,9 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, } else { body.try_emplace("reason", "breakpoint"); char desc_str[64]; - uint64_t bp_id = thread.GetStopReasonDataAtIndex(0); - uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); - snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, + break_id_t bp_id = thread.GetStopReasonDataAtIndex(0); ashgti wrote: These are implicitly cast here https://github.com/llvm/llvm-project/blob/e823136d43c40b0a9ba6930fd285768f1b46fcb6/lldb/source/API/SBThread.cpp#L251C35-L251C48 to uint64_t, this is converting it back to the internal type. This should be okay. https://github.com/llvm/llvm-project/pull/72292 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/112384 Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. >From 0ffb658030e1ec70545115bd32e6e53c9a486969 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 14 Oct 2024 14:52:51 -0700 Subject: [PATCH] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. --- .../test/tools/lldb-dap/dap_server.py | 2 +- .../API/tools/lldb-dap/custom-event/Makefile | 3 + .../custom-event/TestDAP_customEvent.py | 46 ++ .../API/tools/lldb-dap/custom-event/main.c| 6 ++ .../startDebugging/TestDAP_startDebugging.py | 6 +- lldb/tools/lldb-dap/DAP.cpp | 61 ++- lldb/tools/lldb-dap/DAP.h | 5 ++ lldb/tools/lldb-dap/lldb-dap.cpp | 4 +- 8 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index b095171d8fd1a4..a43dd1aa7b9496 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1230,7 +1230,7 @@ def run_vscode(dbg, args, options): def main(): parser = optparse.OptionParser( description=( -"A testing framework for the Visual Studio Code Debug " "Adaptor protocol" +"A testing framework for the Visual Studio Code Debug Adaptor protocol" ) ) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/Makefile b/lldb/test/API/tools/lldb-dap/custom-event/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py new file mode 100644 index 00..2ae02b09c9f0fc --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py @@ -0,0 +1,46 @@ +""" +Test lldb-dap custom-event integration. +""" + +import json + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbdap_testcase + + +class TestDAP_customEvent(lldbdap_testcase.DAPTestCaseBase): +def test_custom_event(self): +""" +Test sending a custom event. +""" +program = self.getBuildArtifact("a.out") +source = "main.c" +custom_event_body = { +"key": 321, +"arr": [True], +} +self.build_and_launch( +program, +stopCommands=[ +"lldb-dap custom-event my-custom-event-no-body", +"lldb-dap custom-event my-custom-event '{}'".format( +json.dumps(custom_event_body) +), +], +) + +breakpoint_line = line_number(source, "// breakpoint") + +self.set_source_breakpoints(source, [breakpoint_line]) +self.continue_to_next_stop() + +custom_event = self.dap_server.wait_for_event( +filter=["my-custom-event-no-body"] +) +self.assertEquals(custom_event["event"], "my-custom-event-no-body") +self.assertIsNone(custom_event.get("body", None)) + +custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"]) +self.assertEquals(custom_event["event"], "my-custom-event") +self.assertEquals(custom_event["body"], custom_event_body) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/main.c b/lldb/test/API/tools/lldb-dap/custom-event/main.c new file mode 100644 index 00..27bc22b94794b6 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("example\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py index fd48e69cae5e25..fd452d91e472bd 100644 --- a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py +++
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/112384 >From be42193c499f28f8b078f1b443ad09d94e7ba2c5 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 15 Oct 2024 09:13:49 -0700 Subject: [PATCH] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. --- .../test/tools/lldb-dap/dap_server.py | 2 +- .../API/tools/lldb-dap/custom-event/Makefile | 3 ++ .../custom-event/TestDAP_customEvent.py | 46 +++ .../API/tools/lldb-dap/custom-event/main.c| 6 +++ lldb/tools/lldb-dap/DAP.cpp | 38 +++ lldb/tools/lldb-dap/DAP.h | 5 ++ lldb/tools/lldb-dap/README.md | 24 ++ lldb/tools/lldb-dap/lldb-dap.cpp | 2 + 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 1d5e6e0d75c7cb..63748a71f1122d 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1267,7 +1267,7 @@ def run_vscode(dbg, args, options): def main(): parser = optparse.OptionParser( description=( -"A testing framework for the Visual Studio Code Debug " "Adaptor protocol" +"A testing framework for the Visual Studio Code Debug Adaptor protocol" ) ) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/Makefile b/lldb/test/API/tools/lldb-dap/custom-event/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py new file mode 100644 index 00..2ae02b09c9f0fc --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py @@ -0,0 +1,46 @@ +""" +Test lldb-dap custom-event integration. +""" + +import json + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbdap_testcase + + +class TestDAP_customEvent(lldbdap_testcase.DAPTestCaseBase): +def test_custom_event(self): +""" +Test sending a custom event. +""" +program = self.getBuildArtifact("a.out") +source = "main.c" +custom_event_body = { +"key": 321, +"arr": [True], +} +self.build_and_launch( +program, +stopCommands=[ +"lldb-dap custom-event my-custom-event-no-body", +"lldb-dap custom-event my-custom-event '{}'".format( +json.dumps(custom_event_body) +), +], +) + +breakpoint_line = line_number(source, "// breakpoint") + +self.set_source_breakpoints(source, [breakpoint_line]) +self.continue_to_next_stop() + +custom_event = self.dap_server.wait_for_event( +filter=["my-custom-event-no-body"] +) +self.assertEquals(custom_event["event"], "my-custom-event-no-body") +self.assertIsNone(custom_event.get("body", None)) + +custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"]) +self.assertEquals(custom_event["event"], "my-custom-event") +self.assertEquals(custom_event["body"], custom_event_body) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/main.c b/lldb/test/API/tools/lldb-dap/custom-event/main.c new file mode 100644 index 00..27bc22b94794b6 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("example\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 5e75d84cf8243e..433682b48ee857 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -969,6 +969,44 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger, return true; } +// Sends a custom DAP event with an optional body. +// +// See +// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent +bool CustomDAPEventRequestHandler::DoExecute( +lldb::SBDebugger debugger, char **co
[Lldb-commits] [lldb] [lldb-dap] Improving the naming consistency of startDebugging reverse request. (PR #112396)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/112396 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/112384 >From 61f5407be7fed86428d46e0ea0a6d418a8e25bf7 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 15 Oct 2024 09:13:49 -0700 Subject: [PATCH] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. --- .../test/tools/lldb-dap/dap_server.py | 2 +- .../API/tools/lldb-dap/custom-event/Makefile | 3 ++ .../custom-event/TestDAP_customEvent.py | 46 +++ .../API/tools/lldb-dap/custom-event/main.c| 6 +++ lldb/tools/lldb-dap/DAP.cpp | 38 +++ lldb/tools/lldb-dap/DAP.h | 5 ++ lldb/tools/lldb-dap/README.md | 24 ++ lldb/tools/lldb-dap/lldb-dap.cpp | 2 + 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 1d5e6e0d75c7cb..63748a71f1122d 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1267,7 +1267,7 @@ def run_vscode(dbg, args, options): def main(): parser = optparse.OptionParser( description=( -"A testing framework for the Visual Studio Code Debug " "Adaptor protocol" +"A testing framework for the Visual Studio Code Debug Adaptor protocol" ) ) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/Makefile b/lldb/test/API/tools/lldb-dap/custom-event/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py new file mode 100644 index 00..2ae02b09c9f0fc --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py @@ -0,0 +1,46 @@ +""" +Test lldb-dap custom-event integration. +""" + +import json + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbdap_testcase + + +class TestDAP_customEvent(lldbdap_testcase.DAPTestCaseBase): +def test_custom_event(self): +""" +Test sending a custom event. +""" +program = self.getBuildArtifact("a.out") +source = "main.c" +custom_event_body = { +"key": 321, +"arr": [True], +} +self.build_and_launch( +program, +stopCommands=[ +"lldb-dap custom-event my-custom-event-no-body", +"lldb-dap custom-event my-custom-event '{}'".format( +json.dumps(custom_event_body) +), +], +) + +breakpoint_line = line_number(source, "// breakpoint") + +self.set_source_breakpoints(source, [breakpoint_line]) +self.continue_to_next_stop() + +custom_event = self.dap_server.wait_for_event( +filter=["my-custom-event-no-body"] +) +self.assertEquals(custom_event["event"], "my-custom-event-no-body") +self.assertIsNone(custom_event.get("body", None)) + +custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"]) +self.assertEquals(custom_event["event"], "my-custom-event") +self.assertEquals(custom_event["body"], custom_event_body) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/main.c b/lldb/test/API/tools/lldb-dap/custom-event/main.c new file mode 100644 index 00..27bc22b94794b6 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("example\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 119779d7bfecba..87f7eac2fb770b 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -962,6 +962,44 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger, return true; } +// Sends a custom DAP event with an optional body. +// +// See +// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent +bool CustomDAPEventRequestHandler::DoExecute( +lldb::SBDebugger debugger, char **co
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/112384 >From 5ec5d350f78d284634ffbc7800d7f34a5017707a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 15 Oct 2024 09:13:49 -0700 Subject: [PATCH] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. --- .../test/tools/lldb-dap/dap_server.py | 2 +- .../API/tools/lldb-dap/custom-event/Makefile | 3 ++ .../custom-event/TestDAP_customEvent.py | 46 +++ .../API/tools/lldb-dap/custom-event/main.c| 6 +++ lldb/tools/lldb-dap/DAP.cpp | 38 +++ lldb/tools/lldb-dap/DAP.h | 5 ++ lldb/tools/lldb-dap/README.md | 24 ++ lldb/tools/lldb-dap/lldb-dap.cpp | 2 + 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index b095171d8fd1a4..a43dd1aa7b9496 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1230,7 +1230,7 @@ def run_vscode(dbg, args, options): def main(): parser = optparse.OptionParser( description=( -"A testing framework for the Visual Studio Code Debug " "Adaptor protocol" +"A testing framework for the Visual Studio Code Debug Adaptor protocol" ) ) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/Makefile b/lldb/test/API/tools/lldb-dap/custom-event/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py new file mode 100644 index 00..2ae02b09c9f0fc --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py @@ -0,0 +1,46 @@ +""" +Test lldb-dap custom-event integration. +""" + +import json + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbdap_testcase + + +class TestDAP_customEvent(lldbdap_testcase.DAPTestCaseBase): +def test_custom_event(self): +""" +Test sending a custom event. +""" +program = self.getBuildArtifact("a.out") +source = "main.c" +custom_event_body = { +"key": 321, +"arr": [True], +} +self.build_and_launch( +program, +stopCommands=[ +"lldb-dap custom-event my-custom-event-no-body", +"lldb-dap custom-event my-custom-event '{}'".format( +json.dumps(custom_event_body) +), +], +) + +breakpoint_line = line_number(source, "// breakpoint") + +self.set_source_breakpoints(source, [breakpoint_line]) +self.continue_to_next_stop() + +custom_event = self.dap_server.wait_for_event( +filter=["my-custom-event-no-body"] +) +self.assertEquals(custom_event["event"], "my-custom-event-no-body") +self.assertIsNone(custom_event.get("body", None)) + +custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"]) +self.assertEquals(custom_event["event"], "my-custom-event") +self.assertEquals(custom_event["body"], custom_event_body) diff --git a/lldb/test/API/tools/lldb-dap/custom-event/main.c b/lldb/test/API/tools/lldb-dap/custom-event/main.c new file mode 100644 index 00..27bc22b94794b6 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/custom-event/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("example\n"); // breakpoint 1 + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 6012ee52110b73..5a66594f17155d 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -966,6 +966,44 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger, return true; } +// Sends a custom DAP event with an optional body. +// +// See +// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent +bool CustomDAPEventRequestHandler::DoExecute( +lldb::SBDebugger debugger, char **co
[Lldb-commits] [lldb] [lldb-dap] Improving the naming consistency of startDebugging reverse request. (PR #112396)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/112396 Adjusting the name from `lldb-dap startDebugging` to `lldb-dap start-debugging` to improve consistency with other names for commands in lldb/lldb-dap. >From 2aa7abfbdeaed07a5c46068ea2533c2d20613c5f Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 15 Oct 2024 09:15:54 -0700 Subject: [PATCH] [lldb-dap] Improving the naming consistency of startDebugging reverse request. Adjusting the name from `lldb-dap startDebugging` to `lldb-dap start-debugging` to improve consistency with other names for commands in lldb/lldb-dap. --- .../startDebugging/TestDAP_startDebugging.py | 6 ++--- lldb/tools/lldb-dap/DAP.cpp | 23 +++ lldb/tools/lldb-dap/README.md | 8 +++ lldb/tools/lldb-dap/lldb-dap.cpp | 2 +- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py index fd48e69cae5e25..fd452d91e472bd 100644 --- a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py +++ b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py @@ -1,12 +1,10 @@ """ -Test lldb-dap startDebugging reverse request +Test lldb-dap start-debugging reverse requests. """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase @@ -25,7 +23,7 @@ def test_startDebugging(self): self.set_source_breakpoints(source, [breakpoint_line]) self.continue_to_next_stop() self.dap_server.request_evaluate( -"`lldb-dap startDebugging attach '{\"pid\":321}'", context="repl" +"`lldb-dap start-debugging attach '{\"pid\":321}'", context="repl" ) self.continue_to_exit() diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 6012ee52110b73..a6904e4daeec3d 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -863,42 +863,35 @@ int64_t Variables::InsertExpandableVariable(lldb::SBValue variable, bool StartDebuggingRequestHandler::DoExecute( lldb::SBDebugger debugger, char **command, lldb::SBCommandReturnObject &result) { - // Command format like: `startDebugging ` + // Command format like: `start-debugging ` if (!command) { -result.SetError("Invalid use of startDebugging"); -result.SetStatus(lldb::eReturnStatusFailed); +result.SetError("Invalid use of start-debugging, expected format " +"`start-debugging `."); return false; } if (!command[0] || llvm::StringRef(command[0]).empty()) { -result.SetError("startDebugging request type missing."); -result.SetStatus(lldb::eReturnStatusFailed); +result.SetError("start-debugging request type missing."); return false; } if (!command[1] || llvm::StringRef(command[1]).empty()) { -result.SetError("configuration missing."); -result.SetStatus(lldb::eReturnStatusFailed); +result.SetError("start-debugging debug configuration missing."); return false; } llvm::StringRef request{command[0]}; std::string raw_configuration{command[1]}; - int i = 2; - while (command[i]) { -raw_configuration.append(" ").append(command[i]); - } - llvm::Expected configuration = llvm::json::parse(raw_configuration); if (!configuration) { llvm::Error err = configuration.takeError(); -std::string msg = -"Failed to parse json configuration: " + llvm::toString(std::move(err)); +std::string msg = "Failed to parse json configuration: " + + llvm::toString(std::move(err)) + "\n\n" + + raw_configuration; result.SetError(msg.c_str()); -result.SetStatus(lldb::eReturnStatusFailed); return false; } diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md index 11a14d29ab51e2..7328c19c1718b0 100644 --- a/lldb/tools/lldb-dap/README.md +++ b/lldb/tools/lldb-dap/README.md @@ -209,9 +209,9 @@ The default hostname being used `localhost`. The `lldb-dap` tool includes additional custom commands to support the Debug Adapter Protocol features. -### startDebugging +### start-debugging -Using the command `lldb-dap startDebugging` it is possible to trigger a +Using the command `lldb-dap start-debugging` it is possible to trigger a reverse request to the client requesting a child debug session with the specified configuration. For example, this can be used to attached to forked or spawned processes. For more information see @@ -220,7 +220,7 @@ spawned processes. For more information see The custom command has the following format: ``` -lldb-dap startDebugging +lldb-dap start-debugging ``` This will launch a server and then request a child debug session for a client
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
https://github.com/ashgti closed https://github.com/llvm/llvm-project/pull/112384 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
@@ -962,6 +962,68 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger, return true; } +// Sends a DAP event with an optional body. +// +// See +// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent +bool SendEventRequestHandler::DoExecute(lldb::SBDebugger debugger, +char **command, +lldb::SBCommandReturnObject &result) { + // Command format like: `send-event ?` + if (!command || !command[0] || llvm::StringRef(command[0]).empty()) { +result.SetError("Not enough arguments found, expected format " +"`lldb-dap send-event ?`."); +return false; + } + + llvm::StringRef name{command[0]}; + // Events that are stateful and should be handled by lldb-dap internally. + const std::array internal_events{"breakpoint", "capabilities", "continued", + "exited", "initialize", "loadedSource", + "module", "process", "stopped", + "terminated", "thread"}; + if (std::find(internal_events.begin(), internal_events.end(), name) != + std::end(internal_events)) { +std::string msg = +llvm::formatv("Invalid use of lldb-dap send-event, event \"{0}\" " + "should be handled by lldb-dap internally.", + name) +.str(); +result.SetError(msg.c_str()); +return false; + } + + llvm::json::Object event(CreateEventObject(name)); + + if (command[1] && !llvm::StringRef(command[1]).empty()) { +// See if we have to unused arguments. ashgti wrote: Applied https://github.com/llvm/llvm-project/pull/112384 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. (PR #112384)
@@ -962,6 +962,68 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger, return true; } +// Sends a DAP event with an optional body. +// +// See +// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent +bool SendEventRequestHandler::DoExecute(lldb::SBDebugger debugger, +char **command, +lldb::SBCommandReturnObject &result) { + // Command format like: `send-event ?` + if (!command || !command[0] || llvm::StringRef(command[0]).empty()) { +result.SetError("Not enough arguments found, expected format " +"`lldb-dap send-event ?`."); +return false; + } + + llvm::StringRef name{command[0]}; + // Events that are stateful and should be handled by lldb-dap internally. + const std::array internal_events{"breakpoint", "capabilities", "continued", + "exited", "initialize", "loadedSource", + "module", "process", "stopped", + "terminated", "thread"}; + if (std::find(internal_events.begin(), internal_events.end(), name) != + std::end(internal_events)) { +std::string msg = +llvm::formatv("Invalid use of lldb-dap send-event, event \"{0}\" " + "should be handled by lldb-dap internally.", + name) +.str(); +result.SetError(msg.c_str()); +return false; + } + + llvm::json::Object event(CreateEventObject(name)); + + if (command[1] && !llvm::StringRef(command[1]).empty()) { +// See if we have to unused arguments. +if (command[2] && !llvm::StringRef(command[2]).empty()) { ashgti wrote: The `command` param is a `char **command` so I can't check a `.size()`. Its an array of null terminated strings with nullptr at the tail end. Updated the check to not use `.empty()` and instead just check if the pointer is not null. https://github.com/llvm/llvm-project/pull/112384 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits