[Lldb-commits] [lldb] [LLDB]Provide clearer error message for invalid commands. (PR #111891)
https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/111891 >From 4493bf07c8b18dac39a2a421f97fa34cd15a6031 Mon Sep 17 00:00:00 2001 From: Vy Nguyen Date: Thu, 10 Oct 2024 14:48:08 -0400 Subject: [PATCH 1/3] [LLDB]Provide clearer error message for invalid commands. Sometimes users (esp. gdb-longtime users) accidentally use GDB syntax, such as `breakpoint foo`, and they would get an error message from LLDB saying simply `Invalid command "breakpoint foo"`, which is not very helpful. This change provides additional suggestions to help correcting the mistake. --- .../lldb/Interpreter/CommandObjectMultiword.h | 2 + .../Commands/CommandObjectMultiword.cpp | 42 ++- .../Commands/command-breakpoint-col.test | 2 + 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h index bceb7f0e51edb6..cee118c3f454b5 100644 --- a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h @@ -70,6 +70,8 @@ class CommandObjectMultiword : public CommandObject { return m_subcommand_dict; } + std::string GetTopSubcommands(int count); + CommandObject::CommandMap m_subcommand_dict; bool m_can_be_removed; }; diff --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp index 4efa5652a71703..f7bb58187895b4 100644 --- a/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/lldb/source/Commands/CommandObjectMultiword.cpp @@ -194,28 +194,50 @@ void CommandObjectMultiword::Execute(const char *args_string, std::string error_msg; const size_t num_subcmd_matches = matches.GetSize(); - if (num_subcmd_matches > 0) + if (num_subcmd_matches > 0) { error_msg.assign("ambiguous command "); - else -error_msg.assign("invalid command "); - - error_msg.append("'"); - error_msg.append(std::string(GetCommandName())); - error_msg.append(" "); - error_msg.append(std::string(sub_command)); - error_msg.append("'."); +error_msg.append("'"); +error_msg.append(std::string(GetCommandName())); +error_msg.append(" "); +error_msg.append(std::string(sub_command)); +error_msg.append("'."); - if (num_subcmd_matches > 0) { error_msg.append(" Possible completions:"); for (const std::string &match : matches) { error_msg.append("\n\t"); error_msg.append(match); } + } else { +// Rather than simply complaining about the invalid (sub) command, +// try to offer some alternatives. +// This is especially useful for cases where the user types something +// seamingly trivial, such as `breakpoint foo`. +error_msg.assign( +llvm::Twine("'" + sub_command + "' is not a valid subcommand of \"" + +GetCommandName() + "\". Valid subcommands are " + +GetTopSubcommands(/*count=*/5) + ". Use \"help " + +GetCommandName() + "\" to find out more.") +.str()); } error_msg.append("\n"); result.AppendRawError(error_msg.c_str()); } +std::string CommandObjectMultiword::GetTopSubcommands(int count) { + if (m_subcommand_dict.empty()) +return ""; + std::string buffer = "{"; + CommandMap::iterator pos; + for (pos = m_subcommand_dict.begin(); + pos != m_subcommand_dict.end() && count > 0; ++pos, --count) { +buffer.append("'"); +buffer.append(pos->first); +buffer.append("',"); + } + buffer.append("...}"); + return buffer; +} + void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) { // First time through here, generate the help text for the object and push it // to the return result object as well diff --git a/lldb/test/Shell/Commands/command-breakpoint-col.test b/lldb/test/Shell/Commands/command-breakpoint-col.test index 65c1e220794303..fecb773d2b4c66 100644 --- a/lldb/test/Shell/Commands/command-breakpoint-col.test +++ b/lldb/test/Shell/Commands/command-breakpoint-col.test @@ -3,8 +3,10 @@ # RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out # RUN: %lldb -b -o 'help breakpoint set' -o 'breakpoint set -f main.c -l 2 -u 21' %t.out | FileCheck %s --check-prefix HELP --check-prefix CHECK # RUN: %lldb -b -o 'help _regexp-break' -o 'b main.c:2:21' %t.out | FileCheck %s --check-prefix HELP-REGEX --check-prefix CHECK +# RUN: not %lldb -b -o 'breakpoint foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix ERROR-MSG # HELP: -u ( --column ) # HELP: Specifies the column number on which to set this breakpoint. # HELP-REGEX: _regexp-break :: # HELP-REGEX: main.c:12:21{{.*}}Break at line 12 and column 21 of main.c # CHECK: at main.c:2:21 +# ERROR-MSG: 'foo' is not a valid subcommand of "breakpoint". Valid subcommands are {'clear','command','delete','disable','enable',...}. Use "help breakpoint" to find out more. >From 8dfb266f7eed943f7d9c4bd00e09ef86ae1c5d6e Mon
[Lldb-commits] [lldb] [LLDB]Provide clearer error message for invalid commands. (PR #111891)
@@ -3,8 +3,10 @@ # RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out # RUN: %lldb -b -o 'help breakpoint set' -o 'breakpoint set -f main.c -l 2 -u 21' %t.out | FileCheck %s --check-prefix HELP --check-prefix CHECK # RUN: %lldb -b -o 'help _regexp-break' -o 'b main.c:2:21' %t.out | FileCheck %s --check-prefix HELP-REGEX --check-prefix CHECK +# RUN: not %lldb -b -o 'breakpoint foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix ERROR-MSG oontvoo wrote: done https://github.com/llvm/llvm-project/pull/111891 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Escape ? for zsh (PR #112107)
https://github.com/JDevlieghere approved this pull request. https://github.com/llvm/llvm-project/pull/112107 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
@@ -9,6 +9,7 @@ #ifndef LLDB_API_SBSTRUCTUREDDATA_H #define LLDB_API_SBSTRUCTUREDDATA_H +#include "SBCommandReturnObject.h" JDevlieghere wrote: ```suggestion #include "lldb/API/SBCommandReturnObject.h" ``` https://github.com/llvm/llvm-project/pull/112109 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
@@ -45,13 +45,14 @@ class LLDB_API SBCommandReturnObject { const char *GetOutput(); const char *GetError(); + SBStructuredData GetErrorData(); #ifndef SWIG LLDB_DEPRECATED_FIXME("Use PutOutput(SBFile) or PutOutput(FileSP)", "PutOutput(SBFile)") size_t PutOutput(FILE *fh); #endif - +\ JDevlieghere wrote: ? https://github.com/llvm/llvm-project/pull/112109 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
@@ -123,30 +123,80 @@ void CommandReturnObject::SetError(llvm::Error error) { } } -llvm::StringRef +std::string CommandReturnObject::GetInlineDiagnosticString(unsigned indent) { - RenderDiagnosticDetails(m_diag_stream, indent, true, m_diagnostics); + StreamString diag_stream(m_colors); + RenderDiagnosticDetails(diag_stream, indent, true, m_diagnostics); // Duplex the diagnostics to the secondary stream (but not inlined). - if (auto stream_sp = m_err_stream.GetStreamAtIndex(eStreamStringIndex)) + if (auto stream_sp = m_err_stream.GetStreamAtIndex(eImmediateStreamIndex)) RenderDiagnosticDetails(*stream_sp, std::nullopt, false, m_diagnostics); - // Clear them so GetErrorData() doesn't render them again. - m_diagnostics.clear(); - return m_diag_stream.GetString(); + return diag_stream.GetString().str(); } -llvm::StringRef CommandReturnObject::GetErrorString() { - // Diagnostics haven't been fetched; render them now (not inlined). - if (!m_diagnostics.empty()) { -RenderDiagnosticDetails(GetErrorStream(), std::nullopt, false, -m_diagnostics); -m_diagnostics.clear(); - } +std::string CommandReturnObject::GetErrorString(bool with_diagnostics) { + StreamString stream(m_colors); + if (with_diagnostics) +RenderDiagnosticDetails(stream, std::nullopt, false, m_diagnostics); lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex)); if (stream_sp) -return std::static_pointer_cast(stream_sp)->GetString(); - return llvm::StringRef(); +stream << std::static_pointer_cast(stream_sp)->GetString(); + return stream.GetString().str(); +} + +StructuredData::ObjectSP CommandReturnObject::GetErrorData() { + auto make_array = []() { return std::make_unique(); }; + auto make_bool = [](bool b) { +return std::make_unique(b); + }; + auto make_dict = []() { +return std::make_unique(); + }; + auto make_int = [](unsigned i) { +return std::make_unique(i); JDevlieghere wrote: Should this be `StructuredData::UnsignedInteger` or `StructuredData::SignedInteger`? https://github.com/llvm/llvm-project/pull/112109 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff c2750807ba2a419425ee90dadda09ad5121517fe cf7ea7aa4d458ad82c39afb2b0879ec32a88a2db --extensions h,cpp -- lldb/include/lldb/API/SBCommandReturnObject.h lldb/include/lldb/API/SBStructuredData.h lldb/include/lldb/Interpreter/CommandReturnObject.h lldb/source/API/SBCommandReturnObject.cpp lldb/source/Commands/CommandObjectExpression.cpp lldb/source/Interpreter/CommandInterpreter.cpp lldb/source/Interpreter/CommandReturnObject.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index f0a4738cc3..e8e20a3f30 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -52,7 +52,7 @@ public: "PutOutput(SBFile)") size_t PutOutput(FILE *fh); #endif -\ + size_t PutOutput(SBFile file); size_t PutOutput(FileSP BORROWED); diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp index 8cd798f62f..6855c6fcb6 100644 --- a/lldb/source/Interpreter/CommandReturnObject.cpp +++ b/lldb/source/Interpreter/CommandReturnObject.cpp @@ -123,8 +123,7 @@ void CommandReturnObject::SetError(llvm::Error error) { } } -std::string -CommandReturnObject::GetInlineDiagnosticString(unsigned indent) { +std::string CommandReturnObject::GetInlineDiagnosticString(unsigned indent) { StreamString diag_stream(m_colors); RenderDiagnosticDetails(diag_stream, indent, true, m_diagnostics); // Duplex the diagnostics to the secondary stream (but not inlined). `` https://github.com/llvm/llvm-project/pull/112109 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
github-actions[bot] wrote: :warning: Python code formatter, darker found issues in your code. :warning: You can test this locally with the following command: ``bash darker --check --diff -r c2750807ba2a419425ee90dadda09ad5121517fe...cf7ea7aa4d458ad82c39afb2b0879ec32a88a2db lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py `` View the diff from darker here. ``diff --- TestExprDiagnostics.py 2024-10-12 20:37:19.00 + +++ TestExprDiagnostics.py 2024-10-12 20:41:04.212598 + @@ -256,6 +256,5 @@ self.assertIn("user expression", str(sloc.GetValueForKey("file"))) self.assertFalse(sloc.GetValueForKey("hidden").GetBooleanValue()) self.assertTrue(sloc.GetValueForKey("in_user_input").GetBooleanValue()) diag = details.GetItemAtIndex(1) self.assertIn("undeclared identifier 'b'", str(diag.GetValueForKey("message"))) - `` https://github.com/llvm/llvm-project/pull/112109 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add early CMake check for 'make' tool (PR #111531)
weliveindetail wrote: In fact, I ran into that on Friday myself. I checked `LLDB_INCLUDE_TESTS=Off` in my setup and it appeared to be incompatible with `LLDB_ENABLE_PYTHON=On` if `lldb-python` is part of `LLVM_DISTRIBUTION_COMPONENTS`. The error said something like `lldb-python-scripts` is lacking an `install-stripped` target. I couldn't fix that quickly and just wired up the `LLDB_TEST_MAKE` config. @zeroomega Any similar experiences with `LLDB_INCLUDE_TESTS=Off`? https://github.com/llvm/llvm-project/pull/111531 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] c275080 - [lldb] Rename CommandReturnObject::Get.*Data -> Get.*String (#112062)
Author: Adrian Prantl Date: 2024-10-12T13:36:33-07:00 New Revision: c2750807ba2a419425ee90dadda09ad5121517fe URL: https://github.com/llvm/llvm-project/commit/c2750807ba2a419425ee90dadda09ad5121517fe DIFF: https://github.com/llvm/llvm-project/commit/c2750807ba2a419425ee90dadda09ad5121517fe.diff LOG: [lldb] Rename CommandReturnObject::Get.*Data -> Get.*String (#112062) In a later commit, I want to add a method to access diagnostics as actual structured data, which will make these function names rather confusing. Added: Modified: lldb/include/lldb/Interpreter/CommandReturnObject.h lldb/source/API/SBCommandReturnObject.cpp lldb/source/Commands/CommandObjectCommands.cpp lldb/source/Core/Debugger.cpp lldb/source/Interpreter/CommandInterpreter.cpp lldb/source/Interpreter/CommandReturnObject.cpp lldb/tools/lldb-test/lldb-test.cpp Removed: diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index e13c3b7b8e0437..eda841869ba432 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -30,16 +30,17 @@ class CommandReturnObject { ~CommandReturnObject() = default; - llvm::StringRef GetInlineDiagnosticsData(unsigned indent); + /// Format any inline diagnostics with an indentation of \c indent. + llvm::StringRef GetInlineDiagnosticString(unsigned indent); - llvm::StringRef GetOutputData() { + llvm::StringRef GetOutputString() { lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); if (stream_sp) return std::static_pointer_cast(stream_sp)->GetString(); return llvm::StringRef(); } - llvm::StringRef GetErrorData(); + llvm::StringRef GetErrorString(); Stream &GetOutputStream() { // Make sure we at least have our normal string stream output stream diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index d0cdebe8c64911..a94eff75ffcb9e 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -85,27 +85,27 @@ SBCommandReturnObject::operator bool() const { const char *SBCommandReturnObject::GetOutput() { LLDB_INSTRUMENT_VA(this); - ConstString output(ref().GetOutputData()); + ConstString output(ref().GetOutputString()); return output.AsCString(/*value_if_empty*/ ""); } const char *SBCommandReturnObject::GetError() { LLDB_INSTRUMENT_VA(this); - ConstString output(ref().GetErrorData()); + ConstString output(ref().GetErrorString()); return output.AsCString(/*value_if_empty*/ ""); } size_t SBCommandReturnObject::GetOutputSize() { LLDB_INSTRUMENT_VA(this); - return ref().GetOutputData().size(); + return ref().GetOutputString().size(); } size_t SBCommandReturnObject::GetErrorSize() { LLDB_INSTRUMENT_VA(this); - return ref().GetErrorData().size(); + return ref().GetErrorString().size(); } size_t SBCommandReturnObject::PutOutput(FILE *fh) { diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 845b89a75b7b39..f069b2feb5cb7b 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1099,7 +1099,7 @@ class CommandObjectPythonFunction : public CommandObjectRaw { } else { // Don't change the status if the command already set it... if (result.GetStatus() == eReturnStatusInvalid) { -if (result.GetOutputData().empty()) +if (result.GetOutputString().empty()) result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1205,7 +1205,7 @@ class CommandObjectScriptingObjectRaw : public CommandObjectRaw { } else { // Don't change the status if the command already set it... if (result.GetStatus() == eReturnStatusInvalid) { -if (result.GetOutputData().empty()) +if (result.GetOutputString().empty()) result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusSuccessFinishResult); @@ -2137,7 +2137,7 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { } else { // Don't change the status if the command already set it... if (result.GetStatus() == eReturnStatusInvalid) { -if (result.GetOutputData().empty()) +if (result.GetOutputString().empty()) result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusSuccessFinishResult); diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index e6b9eedd89b4e3..c666a753343c9d 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@
[Lldb-commits] [lldb] [lldb] Rename CommandReturnObject::Get.*Data -> Get.*String (PR #112062)
https://github.com/adrian-prantl closed https://github.com/llvm/llvm-project/pull/112062 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
https://github.com/adrian-prantl created https://github.com/llvm/llvm-project/pull/112109 This allows IDEs to render LLDB expression diagnostics to their liking without relying on characterprecise ASCII art from LLDB. It is exposed as a versioned SBStructuredData object, since it is expected that this may need to be tweaked based on actual usage. >From cf7ea7aa4d458ad82c39afb2b0879ec32a88a2db Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 11 Oct 2024 19:27:37 -0700 Subject: [PATCH] [lldb] Expose structured command diagnostics via the SBAPI. This allows IDEs to render LLDB expression diagnostics to their liking without relying on characterprecise ASCII art from LLDB. It is exposed as a versioned SBStructuredData object, since it is expected that this may need to be tweaked based on actual usage. --- lldb/include/lldb/API/SBCommandReturnObject.h | 3 +- lldb/include/lldb/API/SBStructuredData.h | 2 + .../lldb/Interpreter/CommandReturnObject.h| 13 ++- lldb/source/API/SBCommandReturnObject.cpp | 11 +++ .../Commands/CommandObjectExpression.cpp | 29 +-- .../source/Interpreter/CommandInterpreter.cpp | 23 +++--- .../Interpreter/CommandReturnObject.cpp | 82 +++ .../diagnostics/TestExprDiagnostics.py| 25 ++ 8 files changed, 128 insertions(+), 60 deletions(-) diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index f96384a4710b16..f0a4738cc346e4 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -45,13 +45,14 @@ class LLDB_API SBCommandReturnObject { const char *GetOutput(); const char *GetError(); + SBStructuredData GetErrorData(); #ifndef SWIG LLDB_DEPRECATED_FIXME("Use PutOutput(SBFile) or PutOutput(FileSP)", "PutOutput(SBFile)") size_t PutOutput(FILE *fh); #endif - +\ size_t PutOutput(SBFile file); size_t PutOutput(FileSP BORROWED); diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h index fc6e1ec95c7b86..c309e28a190691 100644 --- a/lldb/include/lldb/API/SBStructuredData.h +++ b/lldb/include/lldb/API/SBStructuredData.h @@ -9,6 +9,7 @@ #ifndef LLDB_API_SBSTRUCTUREDDATA_H #define LLDB_API_SBSTRUCTUREDDATA_H +#include "SBCommandReturnObject.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBModule.h" #include "lldb/API/SBScriptObject.h" @@ -110,6 +111,7 @@ class SBStructuredData { protected: friend class SBAttachInfo; + friend class SBCommandReturnObject; friend class SBLaunchInfo; friend class SBDebugger; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index eda841869ba432..a491a6c1535b11 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -13,6 +13,7 @@ #include "lldb/Utility/DiagnosticsRendering.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StreamTee.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" @@ -31,7 +32,7 @@ class CommandReturnObject { ~CommandReturnObject() = default; /// Format any inline diagnostics with an indentation of \c indent. - llvm::StringRef GetInlineDiagnosticString(unsigned indent); + std::string GetInlineDiagnosticString(unsigned indent); llvm::StringRef GetOutputString() { lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); @@ -40,7 +41,13 @@ class CommandReturnObject { return llvm::StringRef(); } - llvm::StringRef GetErrorString(); + /// Return the errors as a string. + /// + /// If \c with_diagnostics is true, all diagnostics are also + /// rendered into the string. Otherwise the expectation is that they + /// are fetched with \ref GetInlineDiagnosticString(). + std::string GetErrorString(bool with_diagnostics = true); + StructuredData::ObjectSP GetErrorData(); Stream &GetOutputStream() { // Make sure we at least have our normal string stream output stream @@ -168,7 +175,6 @@ class CommandReturnObject { StreamTee m_out_stream; StreamTee m_err_stream; std::vector m_diagnostics; - StreamString m_diag_stream; std::optional m_diagnostic_indent; lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; @@ -178,6 +184,7 @@ class CommandReturnObject { /// If true, then the input handle from the debugger will be hooked up. bool m_interactive = true; + bool m_colors; }; } // namespace lldb_private diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index a94eff75ffcb9e..9df8aa48b99366 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -11,6 +11,8 @@ #include "lldb/API/SBError.h" #include "lldb/API/SBFile.h" #include
[Lldb-commits] [lldb] [lldb] Expose structured command diagnostics via the SBAPI. (PR #112109)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Adrian Prantl (adrian-prantl) Changes This allows IDEs to render LLDB expression diagnostics to their liking without relying on characterprecise ASCII art from LLDB. It is exposed as a versioned SBStructuredData object, since it is expected that this may need to be tweaked based on actual usage. --- Full diff: https://github.com/llvm/llvm-project/pull/112109.diff 8 Files Affected: - (modified) lldb/include/lldb/API/SBCommandReturnObject.h (+2-1) - (modified) lldb/include/lldb/API/SBStructuredData.h (+2) - (modified) lldb/include/lldb/Interpreter/CommandReturnObject.h (+10-3) - (modified) lldb/source/API/SBCommandReturnObject.cpp (+11) - (modified) lldb/source/Commands/CommandObjectExpression.cpp (+1-28) - (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+11-12) - (modified) lldb/source/Interpreter/CommandReturnObject.cpp (+66-16) - (modified) lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py (+25) ``diff diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index f96384a4710b16..f0a4738cc346e4 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -45,13 +45,14 @@ class LLDB_API SBCommandReturnObject { const char *GetOutput(); const char *GetError(); + SBStructuredData GetErrorData(); #ifndef SWIG LLDB_DEPRECATED_FIXME("Use PutOutput(SBFile) or PutOutput(FileSP)", "PutOutput(SBFile)") size_t PutOutput(FILE *fh); #endif - +\ size_t PutOutput(SBFile file); size_t PutOutput(FileSP BORROWED); diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h index fc6e1ec95c7b86..c309e28a190691 100644 --- a/lldb/include/lldb/API/SBStructuredData.h +++ b/lldb/include/lldb/API/SBStructuredData.h @@ -9,6 +9,7 @@ #ifndef LLDB_API_SBSTRUCTUREDDATA_H #define LLDB_API_SBSTRUCTUREDDATA_H +#include "SBCommandReturnObject.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBModule.h" #include "lldb/API/SBScriptObject.h" @@ -110,6 +111,7 @@ class SBStructuredData { protected: friend class SBAttachInfo; + friend class SBCommandReturnObject; friend class SBLaunchInfo; friend class SBDebugger; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index eda841869ba432..a491a6c1535b11 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -13,6 +13,7 @@ #include "lldb/Utility/DiagnosticsRendering.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StreamTee.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" @@ -31,7 +32,7 @@ class CommandReturnObject { ~CommandReturnObject() = default; /// Format any inline diagnostics with an indentation of \c indent. - llvm::StringRef GetInlineDiagnosticString(unsigned indent); + std::string GetInlineDiagnosticString(unsigned indent); llvm::StringRef GetOutputString() { lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); @@ -40,7 +41,13 @@ class CommandReturnObject { return llvm::StringRef(); } - llvm::StringRef GetErrorString(); + /// Return the errors as a string. + /// + /// If \c with_diagnostics is true, all diagnostics are also + /// rendered into the string. Otherwise the expectation is that they + /// are fetched with \ref GetInlineDiagnosticString(). + std::string GetErrorString(bool with_diagnostics = true); + StructuredData::ObjectSP GetErrorData(); Stream &GetOutputStream() { // Make sure we at least have our normal string stream output stream @@ -168,7 +175,6 @@ class CommandReturnObject { StreamTee m_out_stream; StreamTee m_err_stream; std::vector m_diagnostics; - StreamString m_diag_stream; std::optional m_diagnostic_indent; lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; @@ -178,6 +184,7 @@ class CommandReturnObject { /// If true, then the input handle from the debugger will be hooked up. bool m_interactive = true; + bool m_colors; }; } // namespace lldb_private diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index a94eff75ffcb9e..9df8aa48b99366 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -11,6 +11,8 @@ #include "lldb/API/SBError.h" #include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Instrumentation.h" @@ -96,6 +98,15 @@ const char *SBCommandReturnObject::GetError() { return output.
[Lldb-commits] [lldb] [lldb] Speed up FindInMemory tests (PR #111951)
https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/111951 >From e027444340be4020002126da0d2c8a705c2c7e3f Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Thu, 10 Oct 2024 20:27:10 -0700 Subject: [PATCH 1/2] [lldb] Speed up FindInMemory tests A memory region can be relatively large. Searching for a value in the entire region is time-consuming, especially when running tests against a remote target, because the memory data is transferred in small chunks over a relatively slow GDB Remote Protocol. The patch limits the address range to be searched to 2K, which seems sufficient for these tests. In my setup, for local runs, these tests now take half the time they did before the patch. For a remote target, the improvement is even more significant. --- .../find_in_memory/TestFindInMemory.py| 10 ++-- .../find_in_memory/TestFindRangesInMemory.py | 16 +++--- .../find_in_memory/address_ranges_helper.py | 50 --- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py b/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py index 9ab4619b1f8f4f..04e807c5c6201d 100644 --- a/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py +++ b/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py @@ -55,7 +55,7 @@ def test_find_in_memory_ok(self): error = lldb.SBError() addr = self.process.FindInMemory( SINGLE_INSTANCE_PATTERN_STACK, -GetStackRange(self), +GetStackRange(self, True), 1, error, ) @@ -70,7 +70,7 @@ def test_find_in_memory_double_instance_ok(self): error = lldb.SBError() addr = self.process.FindInMemory( DOUBLE_INSTANCE_PATTERN_HEAP, -GetHeapRanges(self)[0], +GetHeapRanges(self, True)[0], 1, error, ) @@ -86,7 +86,7 @@ def test_find_in_memory_invalid_alignment(self): error = lldb.SBError() addr = self.process.FindInMemory( SINGLE_INSTANCE_PATTERN_STACK, -GetStackRange(self), +GetStackRange(self, True), 0, error, ) @@ -118,7 +118,7 @@ def test_find_in_memory_invalid_buffer(self): error = lldb.SBError() addr = self.process.FindInMemory( "", -GetStackRange(self), +GetStackRange(self, True), 1, error, ) @@ -131,7 +131,7 @@ def test_find_in_memory_unaligned(self): self.assertTrue(self.process, PROCESS_IS_VALID) self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) error = lldb.SBError() -range = GetAlignedRange(self) +range = GetAlignedRange(self, True) # First we make sure the pattern is found with alignment 1 addr = self.process.FindInMemory( diff --git a/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py b/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py index 31bc0e99f4914f..895c527430f218 100644 --- a/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py +++ b/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py @@ -30,7 +30,7 @@ def test_find_ranges_in_memory_two_matches(self): self.assertTrue(self.process, PROCESS_IS_VALID) self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) -addr_ranges = GetHeapRanges(self) +addr_ranges = GetHeapRanges(self, True) error = lldb.SBError() matches = self.process.FindRangesInMemory( DOUBLE_INSTANCE_PATTERN_HEAP, @@ -48,7 +48,7 @@ def test_find_ranges_in_memory_one_match(self): self.assertTrue(self.process, PROCESS_IS_VALID) self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) -addr_ranges = GetStackRanges(self) +addr_ranges = GetStackRanges(self, True) error = lldb.SBError() matches = self.process.FindRangesInMemory( SINGLE_INSTANCE_PATTERN_STACK, @@ -66,7 +66,7 @@ def test_find_ranges_in_memory_one_match_multiple_ranges(self): self.assertTrue(self.process, PROCESS_IS_VALID) self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) -addr_ranges = GetRanges(self) +addr_ranges = GetRanges(self, True) addr_ranges.Append(lldb.SBAddressRange()) self.assertGreater(addr_ranges.GetSize(), 2) error = lldb.SBError() @@ -86,7 +86,7 @@ def test_find_ranges_in_memory_one_match_max(self): self.assertTrue(self.process, PROCESS_IS_VALID) self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) -addr_ranges = GetHeapRanges(self) +addr_ranges = GetHeapRanges(self, True) error = lldb.SBError() matches = self.proces
[Lldb-commits] [lldb] [lldb] Escape ? for zsh (PR #112107)
https://github.com/keith created https://github.com/llvm/llvm-project/pull/112107 Previously on macOS with lldb-argdumper if you ran: ``` lldb -o r -- /tmp/foo "some arg?" ``` It would fail with this error: ``` error: shell expansion failed (reason: lldb-argdumper exited with error 1). consider launching with 'process launch'. ``` stderr is silenced here but the underlying error if you print it for debugging is: ``` zsh: no matches found: ? ``` This change escapes the `?` so this argument works as expected. >From 2cd6a6726373e8b499aba4e41dafad5780f2134f Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Sat, 12 Oct 2024 11:25:16 -0700 Subject: [PATCH] [lldb] Escape ? for zsh Previously on macOS with lldb-argdumper if you ran: ``` lldb -o r -- /tmp/foo "some arg?" ``` It would fail with this error: ``` error: shell expansion failed (reason: lldb-argdumper exited with error 1). consider launching with 'process launch'. ``` stderr is silenced here but the underlying error if you print it for debugging is: ``` zsh: no matches found: ? ``` This change escapes the `?` so this argument works as expected. --- lldb/source/Utility/Args.cpp| 2 +- lldb/unittests/Utility/ArgsTest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/source/Utility/Args.cpp b/lldb/source/Utility/Args.cpp index 8ba40bae4d67e5..92a7ef03273fbc 100644 --- a/lldb/source/Utility/Args.cpp +++ b/lldb/source/Utility/Args.cpp @@ -401,7 +401,7 @@ std::string Args::GetShellSafeArgument(const FileSpec &shell, static ShellDescriptor g_Shells[] = {{"bash", " '\"<>()&;"}, {"fish", " '\"<>()&\\|;"}, {"tcsh", " '\"<>()&;"}, - {"zsh", " '\"<>()&;\\|"}, + {"zsh", " '\"<>()&;\\|?"}, {"sh", " '\"<>()&;"}}; // safe minimal set diff --git a/lldb/unittests/Utility/ArgsTest.cpp b/lldb/unittests/Utility/ArgsTest.cpp index 8d2b625f524d67..34d6b4dd7c95a0 100644 --- a/lldb/unittests/Utility/ArgsTest.cpp +++ b/lldb/unittests/Utility/ArgsTest.cpp @@ -292,8 +292,8 @@ TEST(ArgsTest, GetShellSafeArgument) { EXPECT_EQ(Args::GetShellSafeArgument(bash, "a\"b"), "a\\\"b"); FileSpec zsh("/bin/zsh", FileSpec::Style::posix); - EXPECT_EQ(Args::GetShellSafeArgument(zsh, R"('";()<>&|\)"), -R"(\'\"\;\(\)\<\>\&\|\\)"); + EXPECT_EQ(Args::GetShellSafeArgument(zsh, R"('"?;()<>&|\)"), +R"(\'\"\?\;\(\)\<\>\&\|\\)"); // Normal characters and expressions that shouldn't be escaped. EXPECT_EQ(Args::GetShellSafeArgument(zsh, "aA$1*"), "aA$1*"); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Escape ? for zsh (PR #112107)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Keith Smiley (keith) Changes Previously on macOS with lldb-argdumper if you ran: ``` lldb -o r -- /tmp/foo "some arg?" ``` It would fail with this error: ``` error: shell expansion failed (reason: lldb-argdumper exited with error 1). consider launching with 'process launch'. ``` stderr is silenced here but the underlying error if you print it for debugging is: ``` zsh: no matches found: ? ``` This change escapes the `?` so this argument works as expected. --- Full diff: https://github.com/llvm/llvm-project/pull/112107.diff 2 Files Affected: - (modified) lldb/source/Utility/Args.cpp (+1-1) - (modified) lldb/unittests/Utility/ArgsTest.cpp (+2-2) ``diff diff --git a/lldb/source/Utility/Args.cpp b/lldb/source/Utility/Args.cpp index 8ba40bae4d67e5..92a7ef03273fbc 100644 --- a/lldb/source/Utility/Args.cpp +++ b/lldb/source/Utility/Args.cpp @@ -401,7 +401,7 @@ std::string Args::GetShellSafeArgument(const FileSpec &shell, static ShellDescriptor g_Shells[] = {{"bash", " '\"<>()&;"}, {"fish", " '\"<>()&\\|;"}, {"tcsh", " '\"<>()&;"}, - {"zsh", " '\"<>()&;\\|"}, + {"zsh", " '\"<>()&;\\|?"}, {"sh", " '\"<>()&;"}}; // safe minimal set diff --git a/lldb/unittests/Utility/ArgsTest.cpp b/lldb/unittests/Utility/ArgsTest.cpp index 8d2b625f524d67..34d6b4dd7c95a0 100644 --- a/lldb/unittests/Utility/ArgsTest.cpp +++ b/lldb/unittests/Utility/ArgsTest.cpp @@ -292,8 +292,8 @@ TEST(ArgsTest, GetShellSafeArgument) { EXPECT_EQ(Args::GetShellSafeArgument(bash, "a\"b"), "a\\\"b"); FileSpec zsh("/bin/zsh", FileSpec::Style::posix); - EXPECT_EQ(Args::GetShellSafeArgument(zsh, R"('";()<>&|\)"), -R"(\'\"\;\(\)\<\>\&\|\\)"); + EXPECT_EQ(Args::GetShellSafeArgument(zsh, R"('"?;()<>&|\)"), +R"(\'\"\?\;\(\)\<\>\&\|\\)"); // Normal characters and expressions that shouldn't be escaped. EXPECT_EQ(Args::GetShellSafeArgument(zsh, "aA$1*"), "aA$1*"); `` https://github.com/llvm/llvm-project/pull/112107 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits