Skip to content

[🍒 stable/20240723] [lldb] Store the return SBValueList in the CommandReturnObject (#127566) #10065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions lldb/bindings/python/static-binding/LLDBWrapPython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20113,6 +20113,41 @@ SWIGINTERN PyObject *_wrap_SBCommandReturnObject_SetError(PyObject *self, PyObje
}


SWIGINTERN PyObject *_wrap_SBCommandReturnObject_GetValues(PyObject *self, PyObject *args) {
PyObject *resultobj = 0;
lldb::SBCommandReturnObject *arg1 = (lldb::SBCommandReturnObject *) 0 ;
lldb::DynamicValueType arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
int val2 ;
int ecode2 = 0 ;
PyObject *swig_obj[2] ;
lldb::SBValueList result;

(void)self;
if (!SWIG_Python_UnpackTuple(args, "SBCommandReturnObject_GetValues", 2, 2, swig_obj)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_lldb__SBCommandReturnObject, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBCommandReturnObject_GetValues" "', argument " "1"" of type '" "lldb::SBCommandReturnObject *""'");
}
arg1 = reinterpret_cast< lldb::SBCommandReturnObject * >(argp1);
ecode2 = SWIG_AsVal_int(swig_obj[1], &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SBCommandReturnObject_GetValues" "', argument " "2"" of type '" "lldb::DynamicValueType""'");
}
arg2 = static_cast< lldb::DynamicValueType >(val2);
{
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
result = (arg1)->GetValues(arg2);
SWIG_PYTHON_THREAD_END_ALLOW;
}
resultobj = SWIG_NewPointerObj((new lldb::SBValueList(result)), SWIGTYPE_p_lldb__SBValueList, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
return NULL;
}


SWIGINTERN PyObject *_wrap_SBCommandReturnObject___repr__(PyObject *self, PyObject *args) {
PyObject *resultobj = 0;
lldb::SBCommandReturnObject *arg1 = (lldb::SBCommandReturnObject *) 0 ;
Expand Down Expand Up @@ -96661,6 +96696,7 @@ static PyMethodDef SwigMethods[] = {
"SBCommandReturnObject_SetError(SBCommandReturnObject self, SBError error, char const * fallback_error_cstr=None)\n"
"SBCommandReturnObject_SetError(SBCommandReturnObject self, char const * error_cstr)\n"
""},
{ "SBCommandReturnObject_GetValues", _wrap_SBCommandReturnObject_GetValues, METH_VARARGS, "SBCommandReturnObject_GetValues(SBCommandReturnObject self, lldb::DynamicValueType use_dynamic) -> SBValueList"},
{ "SBCommandReturnObject___repr__", _wrap_SBCommandReturnObject___repr__, METH_O, "SBCommandReturnObject___repr__(SBCommandReturnObject self) -> std::string"},
{ "SBCommandReturnObject_SetImmediateOutputFile", _wrap_SBCommandReturnObject_SetImmediateOutputFile, METH_VARARGS, "\n"
"SBCommandReturnObject_SetImmediateOutputFile(SBCommandReturnObject self, SBFile file)\n"
Expand Down
4 changes: 4 additions & 0 deletions lldb/bindings/python/static-binding/lldb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3858,6 +3858,10 @@ def SetError(self, *args):
"""
return _lldb.SBCommandReturnObject_SetError(self, *args)

def GetValues(self, use_dynamic):
r"""GetValues(SBCommandReturnObject self, lldb::DynamicValueType use_dynamic) -> SBValueList"""
return _lldb.SBCommandReturnObject_GetValues(self, use_dynamic)

def __repr__(self):
r"""__repr__(SBCommandReturnObject self) -> std::string"""
return _lldb.SBCommandReturnObject___repr__(self)
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/API/SBCommandReturnObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject {

void SetError(const char *error_cstr);

lldb::SBValueList GetValues(lldb::DynamicValueType use_dynamic);

protected:
friend class SBCommandInterpreter;
friend class SBOptions;
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/API/SBValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ class LLDB_API SBValue {

protected:
friend class SBBlock;
friend class SBCommandReturnObject;
friend class SBFrame;
friend class SBModule;
friend class SBTarget;
Expand Down
12 changes: 10 additions & 2 deletions lldb/include/lldb/Interpreter/CommandReturnObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StreamTee.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/ValueObject/ValueObjectList.h"
#include "lldb/lldb-private.h"

#include "llvm/ADT/StringRef.h"
Expand Down Expand Up @@ -129,7 +130,7 @@ class CommandReturnObject {
__attribute__((format(printf, 2, 3)));

template <typename... Args>
void AppendMessageWithFormatv(const char *format, Args &&... args) {
void AppendMessageWithFormatv(const char *format, Args &&...args) {
AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str());
}

Expand All @@ -139,7 +140,7 @@ class CommandReturnObject {
}

template <typename... Args>
void AppendErrorWithFormatv(const char *format, Args &&... args) {
void AppendErrorWithFormatv(const char *format, Args &&...args) {
AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
}

Expand All @@ -155,6 +156,10 @@ class CommandReturnObject {
return m_diagnostic_indent;
}

const ValueObjectList &GetValueObjectList() const { return m_value_objects; }

ValueObjectList &GetValueObjectList() { return m_value_objects; }

lldb::ReturnStatus GetStatus() const;

void SetStatus(lldb::ReturnStatus status);
Expand Down Expand Up @@ -187,6 +192,9 @@ class CommandReturnObject {

lldb::ReturnStatus m_status = lldb::eReturnStatusStarted;

/// An optionally empty list of values produced by this command.
ValueObjectList m_value_objects;

bool m_did_change_process_state = false;
bool m_suppress_immediate_output = false;

Expand Down
2 changes: 0 additions & 2 deletions lldb/include/lldb/ValueObject/ValueObjectList.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ class ValueObject;
/// A collection of ValueObject values that.
class ValueObjectList {
public:
const ValueObjectList &operator=(const ValueObjectList &rhs);

void Append(const lldb::ValueObjectSP &val_obj_sp);

void Append(const ValueObjectList &valobj_list);
Expand Down
18 changes: 18 additions & 0 deletions lldb/source/API/SBCommandReturnObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
#include "lldb/API/SBFile.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBValue.h"
#include "lldb/API/SBValueList.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-forward.h"

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -356,3 +359,18 @@ void SBCommandReturnObject::SetError(const char *error_cstr) {
if (error_cstr)
ref().AppendError(error_cstr);
}

SBValueList
SBCommandReturnObject::GetValues(lldb::DynamicValueType use_dynamic) {
LLDB_INSTRUMENT_VA(this, use_dynamic);

SBValueList value_list;
for (ValueObjectSP value_object_sp :
ref().GetValueObjectList().GetObjects()) {
SBValue value_sb;
value_sb.SetSP(value_object_sp, use_dynamic);
value_list.Append(value_sb);
}

return value_list;
}
3 changes: 3 additions & 0 deletions lldb/source/Commands/CommandObjectDWIMPrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
ExpressionResults expr_result = target.EvaluateExpression(
expr, exe_scope, valobj_sp, eval_options, &fixed_expression);

if (valobj_sp)
result.GetValueObjectList().Append(valobj_sp);

// Record the position of the expression in the command.
std::optional<uint16_t> indent;
if (fixed_expression.empty()) {
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Commands/CommandObjectExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
}

if (result_valobj_sp) {
result.GetValueObjectList().Append(result_valobj_sp);

Format format = m_format_options.GetFormat();

if (result_valobj_sp->GetError().Success()) {
Expand Down
16 changes: 12 additions & 4 deletions lldb/source/Commands/CommandObjectFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
return;
}

result.GetValueObjectList().Append(valobj_sp);
DumpValueObjectOptions::DeclPrintingHelper helper =
[&valobj_sp](ConstString type, ConstString var,
const DumpValueObjectOptions &opts,
Expand Down Expand Up @@ -317,10 +318,10 @@ 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
+ *m_options.relative_frame_offset;
const uint32_t frame_requested =
frame_idx + *m_options.relative_frame_offset;
StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
if (frame_sp)
frame_idx = frame_requested;
Expand Down Expand Up @@ -515,8 +516,8 @@ may even involve JITing and running code in the target program.)");

if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
result.AppendError(error.AsCString());

}

ValueObjectSP valobj_sp;

TypeSummaryImplSP summary_format_sp;
Expand Down Expand Up @@ -564,6 +565,8 @@ may even involve JITing and running code in the target program.)");
valobj_sp = frame->GetValueObjectForFrameVariable(
var_sp, m_varobj_options.use_dynamic);
if (valobj_sp) {
result.GetValueObjectList().Append(valobj_sp);

std::string scope_string;
if (m_option_variable.show_scope)
scope_string = GetScopeString(var_sp).str();
Expand Down Expand Up @@ -604,6 +607,8 @@ may even involve JITing and running code in the target program.)");
entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
var_sp, error);
if (valobj_sp) {
result.GetValueObjectList().Append(valobj_sp);

std::string scope_string;
if (m_option_variable.show_scope)
scope_string = GetScopeString(var_sp).str();
Expand Down Expand Up @@ -653,6 +658,8 @@ may even involve JITing and running code in the target program.)");
valobj_sp = frame->GetValueObjectForFrameVariable(
var_sp, m_varobj_options.use_dynamic);
if (valobj_sp) {
result.GetValueObjectList().Append(valobj_sp);

// When dumping all variables, don't print any variables that are
// not in scope to avoid extra unneeded output
if (valobj_sp->IsInScope()) {
Expand Down Expand Up @@ -694,6 +701,7 @@ may even involve JITing and running code in the target program.)");
recognized_frame->GetRecognizedArguments();
if (recognized_arg_list) {
for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
result.GetValueObjectList().Append(rec_value_sp);
options.SetFormat(m_option_format.GetFormat());
options.SetVariableFormatDisplayLanguage(
rec_value_sp->GetPreferredDisplayLanguage());
Expand Down
19 changes: 12 additions & 7 deletions lldb/source/Commands/CommandObjectTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,9 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
protected:
void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
const SymbolContext &sc,
const VariableList &variable_list, Stream &s) {
const VariableList &variable_list,
CommandReturnObject &result) {
Stream &s = result.GetOutputStream();
if (variable_list.Empty())
return;
if (sc.module_sp) {
Expand All @@ -824,15 +826,16 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
ValueObjectSP valobj_sp(ValueObjectVariable::Create(
exe_ctx.GetBestExecutionContextScope(), var_sp));

if (valobj_sp)
if (valobj_sp) {
result.GetValueObjectList().Append(valobj_sp);
DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
}
}
}

void DoExecute(Args &args, CommandReturnObject &result) override {
Target *target = m_exe_ctx.GetTargetPtr();
const size_t argc = args.GetArgumentCount();
Stream &s = result.GetOutputStream();

if (argc > 0) {
for (const Args::ArgEntry &arg : args) {
Expand Down Expand Up @@ -874,7 +877,7 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
m_exe_ctx.GetBestExecutionContextScope(), var_sp);

if (valobj_sp)
DumpValueObject(s, var_sp, valobj_sp,
DumpValueObject(result.GetOutputStream(), var_sp, valobj_sp,
use_var_name ? var_sp->GetName().GetCString()
: arg.c_str());
}
Expand Down Expand Up @@ -903,7 +906,8 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
if (comp_unit_varlist_sp) {
size_t count = comp_unit_varlist_sp->GetSize();
if (count > 0) {
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
result);
success = true;
}
}
Expand Down Expand Up @@ -964,15 +968,16 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
VariableListSP comp_unit_varlist_sp(
sc.comp_unit->GetVariableList(can_create));
if (comp_unit_varlist_sp)
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
result);
} else if (sc.module_sp) {
// Get all global variables for this module
lldb_private::RegularExpression all_globals_regex(
llvm::StringRef(".")); // Any global with at least one character
VariableList variable_list;
sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
variable_list);
DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
DumpGlobalVariableList(m_exe_ctx, sc, variable_list, result);
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions lldb/source/ValueObject/ValueObjectList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@
using namespace lldb;
using namespace lldb_private;

const ValueObjectList &ValueObjectList::operator=(const ValueObjectList &rhs) {
if (this != &rhs)
m_value_objects = rhs.m_value_objects;
return *this;
}

void ValueObjectList::Append(const ValueObjectSP &val_obj_sp) {
m_value_objects.push_back(val_obj_sp);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_list = res.GetValues(lldb.eNoDynamicValues)
self.assertEqual(value_list.GetSize(), 0)

def test_get_value(self):
res = lldb.SBCommandReturnObject()
ci = self.dbg.GetCommandInterpreter()
ci.HandleCommand("p 1 + 1", res)
self.assertTrue(res.Succeeded())

value_list = res.GetValues(lldb.eNoDynamicValues)
self.assertEqual(value_list.GetSize(), 1)
self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "2")
9 changes: 8 additions & 1 deletion lldb/test/API/commands/frame/var/TestFrameVar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Make sure the frame variable -g, -a, and -l flags work.
"""


import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.decorators import *
Expand Down Expand Up @@ -79,6 +78,14 @@ def do_test(self):
self.assertNotIn("test_var", output, "Args found a local")
self.assertNotIn("g_var", output, "Args found a global")

value_list = command_result.GetValues(lldb.eNoDynamicValues)
self.assertGreaterEqual(value_list.GetSize(), 2)
value_names = []
for value in value_list:
value_names.append(value.GetName())
self.assertIn("argc", value_names)
self.assertIn("argv", value_names)

# Just get locals:
result = interp.HandleCommand("frame var -a", command_result)
self.assertEqual(
Expand Down
9 changes: 9 additions & 0 deletions lldb/test/API/functionalities/target_var/TestTargetVar.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,12 @@ def testTargetVarExpr(self):
error=True,
substrs=["can't find global variable 'var[0]'"],
)

command_result = lldb.SBCommandReturnObject()
result = self.ci.HandleCommand("target var", command_result)
value_list = command_result.GetValues(lldb.eNoDynamicValues)
self.assertGreaterEqual(value_list.GetSize(), 2)
value_names = []
for value in value_list:
value_names.append(value.GetName())
self.assertIn("i", value_names)