https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/127566
There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 >From 9c290f5d55e888c2674030da9ea06778573332da Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Mon, 17 Feb 2025 20:44:51 -0800 Subject: [PATCH] [lldb] Store the return ValueObject in the CommandReturnObject There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 --- lldb/include/lldb/API/SBCommandReturnObject.h | 2 ++ lldb/include/lldb/API/SBValue.h | 1 + .../include/lldb/Interpreter/CommandReturnObject.h | 10 ++++++++++ lldb/source/API/SBCommandReturnObject.cpp | 14 ++++++++++++-- lldb/source/Commands/CommandObjectDWIMPrint.cpp | 3 +++ lldb/source/Commands/CommandObjectExpression.cpp | 2 ++ lldb/source/Commands/CommandObjectFrame.cpp | 5 +++-- .../TestSBCommandReturnObject.py | 13 +++++++++++++ 8 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 9a63c1f96aa70..96dda239d3c97 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject { void SetError(const char *error_cstr); + lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic); + protected: friend class SBCommandInterpreter; friend class SBOptions; diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 46ef6daa95264..75d20a4378f09 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -442,6 +442,7 @@ class LLDB_API SBValue { protected: friend class SBBlock; + friend class SBCommandReturnObject; friend class SBFrame; friend class SBModule; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 803bcd76995ed..20600ff667bb6 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -14,6 +14,7 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StreamTee.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" @@ -165,6 +166,12 @@ class CommandReturnObject { return m_diagnostic_indent; } + lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; } + + void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) { + m_value_object_sp = value_object_sp; + } + lldb::ReturnStatus GetStatus() const; void SetStatus(lldb::ReturnStatus status); @@ -197,6 +204,9 @@ class CommandReturnObject { lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; + /// An optional ValueObjectSP if the command created one. + lldb::ValueObjectSP m_value_object_sp; + bool m_did_change_process_state = false; bool m_suppress_immediate_output = false; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 6f54581e64ef4..b0de4adc6e241 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStructuredData.h" +#include "lldb/API/SBValue.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -62,8 +63,8 @@ SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) { m_opaque_up = clone(rhs.m_opaque_up); } -SBCommandReturnObject &SBCommandReturnObject:: -operator=(const SBCommandReturnObject &rhs) { +SBCommandReturnObject & +SBCommandReturnObject::operator=(const SBCommandReturnObject &rhs) { LLDB_INSTRUMENT_VA(this, rhs); if (this != &rhs) @@ -356,3 +357,12 @@ void SBCommandReturnObject::SetError(const char *error_cstr) { if (error_cstr) ref().AppendError(error_cstr); } + +SBValue +SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) { + LLDB_INSTRUMENT_VA(this, use_dynamic); + + SBValue sb_value; + sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic); + return sb_value; +} diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index d4d038d28f675..aab99441c63a3 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -205,6 +205,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, ExpressionResults expr_result = target.EvaluateExpression( expr, exe_scope, valobj_sp, eval_options, &fixed_expression); + if (valobj_sp) + result.SetValueObjectSP(valobj_sp); + // Record the position of the expression in the command. std::optional<uint16_t> indent; if (fixed_expression.empty()) { diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 7e26381c92405..b0c92d9391b13 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -434,6 +434,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, } if (result_valobj_sp) { + result.SetValueObjectSP(result_valobj_sp); + Format format = m_format_options.GetFormat(); if (result_valobj_sp->GetError().Success()) { diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index a5709b36f52ee..69bce205ddccc 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -152,6 +152,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed { return; } + result.SetValueObjectSP(valobj_sp); DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp](ConstString type, ConstString var, const DumpValueObjectOptions &opts, @@ -317,9 +318,9 @@ class CommandObjectFrameSelect : public CommandObjectParsed { } else if (*m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack // to produce an error, but rather to just go to the top. OTOH, start - // by seeing if the requested frame exists, in which case we can avoid + // by seeing if the requested frame exists, in which case we can avoid // counting the stack here... - const uint32_t frame_requested = frame_idx + const uint32_t frame_requested = frame_idx + *m_options.relative_frame_offset; StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested); if (frame_sp) diff --git a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py index 2193b7270d0b4..0fee54eb5fe1d 100644 --- a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py +++ b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py @@ -33,3 +33,16 @@ def test_get_command(self): ci.HandleCommand("help help", res) self.assertTrue(res.Succeeded()) self.assertEqual(res.GetCommand(), "help help") + + value = res.GetReturnValue(lldb.eNoDynamicValues) + self.assertFalse(value) + + def test_get_value(self): + res = lldb.SBCommandReturnObject() + ci = self.dbg.GetCommandInterpreter() + ci.HandleCommand("p 1 + 1", res) + self.assertTrue(res.Succeeded()) + + value = res.GetReturnValue(lldb.eNoDynamicValues) + self.assertTrue(value) + self.assertEqual(value.GetValue(), "2") _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits