130fdc8d8SChris Lattner //===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
12de6bd243SJohnny Chen #include <string>
13c8ecc2a9SEugene Zelenko 
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
16c8ecc2a9SEugene Zelenko #include "CommandObjectFrame.h"
1730fdc8d8SChris Lattner #include "lldb/Core/Debugger.h"
186d56d2ceSJim Ingham #include "lldb/Core/Module.h"
196d56d2ceSJim Ingham #include "lldb/Core/StreamFile.h"
20de6bd243SJohnny Chen #include "lldb/Core/StreamString.h"
2130fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
226d56d2ceSJim Ingham #include "lldb/Core/Value.h"
236d56d2ceSJim Ingham #include "lldb/Core/ValueObject.h"
246d56d2ceSJim Ingham #include "lldb/Core/ValueObjectVariable.h"
255548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
264d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
277fb56d0aSGreg Clayton #include "lldb/Host/Host.h"
285275aaa0SVince Harron #include "lldb/Host/StringConvert.h"
296d56d2ceSJim Ingham #include "lldb/Interpreter/Args.h"
3030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
3130fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
321deb7962SGreg Clayton #include "lldb/Interpreter/OptionGroupFormat.h"
332837b766SJim Ingham #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
34715c2365SGreg Clayton #include "lldb/Interpreter/OptionGroupVariable.h"
35b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
366d56d2ceSJim Ingham #include "lldb/Symbol/ClangASTContext.h"
37b9c1b51eSKate Stone #include "lldb/Symbol/CompilerType.h"
386754e04fSEnrico Granata #include "lldb/Symbol/Function.h"
396d56d2ceSJim Ingham #include "lldb/Symbol/ObjectFile.h"
406d56d2ceSJim Ingham #include "lldb/Symbol/SymbolContext.h"
416d56d2ceSJim Ingham #include "lldb/Symbol/Type.h"
426d56d2ceSJim Ingham #include "lldb/Symbol/Variable.h"
436d56d2ceSJim Ingham #include "lldb/Symbol/VariableList.h"
4430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
45b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
464740a734SSean Callanan #include "lldb/Target/StopInfo.h"
476d56d2ceSJim Ingham #include "lldb/Target/Target.h"
48b9c1b51eSKate Stone #include "lldb/Target/Thread.h"
494740a734SSean Callanan #include "lldb/Utility/LLDBAssert.h"
5030fdc8d8SChris Lattner 
5130fdc8d8SChris Lattner using namespace lldb;
5230fdc8d8SChris Lattner using namespace lldb_private;
5330fdc8d8SChris Lattner 
544740a734SSean Callanan #pragma mark CommandObjectFrameDiagnose
554740a734SSean Callanan 
564740a734SSean Callanan //-------------------------------------------------------------------------
574740a734SSean Callanan // CommandObjectFrameInfo
584740a734SSean Callanan //-------------------------------------------------------------------------
594740a734SSean Callanan 
604740a734SSean Callanan //-------------------------------------------------------------------------
614740a734SSean Callanan // CommandObjectFrameDiagnose
624740a734SSean Callanan //-------------------------------------------------------------------------
634740a734SSean Callanan 
64b9c1b51eSKate Stone class CommandObjectFrameDiagnose : public CommandObjectParsed {
654740a734SSean Callanan public:
66b9c1b51eSKate Stone   class CommandOptions : public Options {
674740a734SSean Callanan   public:
68b9c1b51eSKate Stone     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
694740a734SSean Callanan 
704740a734SSean Callanan     ~CommandOptions() override = default;
714740a734SSean Callanan 
72b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
73b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
744740a734SSean Callanan       Error error;
754740a734SSean Callanan       const int short_option = m_getopt_table[option_idx].val;
76b9c1b51eSKate Stone       switch (short_option) {
774740a734SSean Callanan       case 'r':
784740a734SSean Callanan         reg = ConstString(option_arg);
794740a734SSean Callanan         break;
804740a734SSean Callanan 
81b9c1b51eSKate Stone       case 'a': {
824740a734SSean Callanan         bool success = false;
834740a734SSean Callanan 
844740a734SSean Callanan         address = StringConvert::ToUInt64(option_arg, 0, 0, &success);
85b9c1b51eSKate Stone         if (!success) {
864740a734SSean Callanan           address.reset();
87b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid address argument '%s'",
88b9c1b51eSKate Stone                                          option_arg);
894740a734SSean Callanan         }
90b9c1b51eSKate Stone       } break;
914740a734SSean Callanan 
92b9c1b51eSKate Stone       case 'o': {
934740a734SSean Callanan         bool success = false;
944740a734SSean Callanan 
954740a734SSean Callanan         offset = StringConvert::ToSInt64(option_arg, 0, 0, &success);
96b9c1b51eSKate Stone         if (!success) {
974740a734SSean Callanan           offset.reset();
98b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid offset argument '%s'",
99b9c1b51eSKate Stone                                          option_arg);
1004740a734SSean Callanan         }
101b9c1b51eSKate Stone       } break;
1024740a734SSean Callanan 
1034740a734SSean Callanan       default:
104b9c1b51eSKate Stone         error.SetErrorStringWithFormat("invalid short option character '%c'",
105b9c1b51eSKate Stone                                        short_option);
1064740a734SSean Callanan         break;
1074740a734SSean Callanan       }
1084740a734SSean Callanan 
1094740a734SSean Callanan       return error;
1104740a734SSean Callanan     }
1114740a734SSean Callanan 
112b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1134740a734SSean Callanan       address.reset();
1144740a734SSean Callanan       reg.reset();
1154740a734SSean Callanan       offset.reset();
1164740a734SSean Callanan     }
1174740a734SSean Callanan 
118b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
1194740a734SSean Callanan 
1204740a734SSean Callanan     // Options table: Required for subclasses of Options.
1214740a734SSean Callanan     static OptionDefinition g_option_table[];
1224740a734SSean Callanan 
1234740a734SSean Callanan     // Options.
1244740a734SSean Callanan     llvm::Optional<lldb::addr_t> address;
1254740a734SSean Callanan     llvm::Optional<ConstString> reg;
1264740a734SSean Callanan     llvm::Optional<int64_t> offset;
1274740a734SSean Callanan   };
1284740a734SSean Callanan 
1294740a734SSean Callanan   CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
1304740a734SSean Callanan       : CommandObjectParsed(interpreter, "frame diagnose",
131b9c1b51eSKate Stone                             "Try to determine what path path the current stop "
132b9c1b51eSKate Stone                             "location used to get to a register or address",
133b9c1b51eSKate Stone                             nullptr,
134b9c1b51eSKate Stone                             eCommandRequiresThread | eCommandTryTargetAPILock |
135b9c1b51eSKate Stone                                 eCommandProcessMustBeLaunched |
1364740a734SSean Callanan                                 eCommandProcessMustBePaused),
137b9c1b51eSKate Stone         m_options() {
1384740a734SSean Callanan     CommandArgumentEntry arg;
1394740a734SSean Callanan     CommandArgumentData index_arg;
1404740a734SSean Callanan 
1414740a734SSean Callanan     // Define the first (and only) variant of this arg.
1424740a734SSean Callanan     index_arg.arg_type = eArgTypeFrameIndex;
1434740a734SSean Callanan     index_arg.arg_repetition = eArgRepeatOptional;
1444740a734SSean Callanan 
145b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
146b9c1b51eSKate Stone     // argument entry.
1474740a734SSean Callanan     arg.push_back(index_arg);
1484740a734SSean Callanan 
1494740a734SSean Callanan     // Push the data for the first argument into the m_arguments vector.
1504740a734SSean Callanan     m_arguments.push_back(arg);
1514740a734SSean Callanan   }
1524740a734SSean Callanan 
1534740a734SSean Callanan   ~CommandObjectFrameDiagnose() override = default;
1544740a734SSean Callanan 
155b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1564740a734SSean Callanan 
1574740a734SSean Callanan protected:
158b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1594740a734SSean Callanan     Thread *thread = m_exe_ctx.GetThreadPtr();
1604740a734SSean Callanan     StackFrameSP frame_sp = thread->GetSelectedFrame();
1614740a734SSean Callanan 
1624740a734SSean Callanan     ValueObjectSP valobj_sp;
1634740a734SSean Callanan 
164b9c1b51eSKate Stone     if (m_options.address.hasValue()) {
165b9c1b51eSKate Stone       if (m_options.reg.hasValue() || m_options.offset.hasValue()) {
166b9c1b51eSKate Stone         result.AppendError(
167b9c1b51eSKate Stone             "`frame diagnose --address` is incompatible with other arguments.");
1684740a734SSean Callanan         result.SetStatus(eReturnStatusFailed);
1694740a734SSean Callanan         return false;
1704740a734SSean Callanan       }
1714740a734SSean Callanan       valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
172b9c1b51eSKate Stone     } else if (m_options.reg.hasValue()) {
173b9c1b51eSKate Stone       valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
174b9c1b51eSKate Stone           m_options.reg.getValue(), m_options.offset.getValueOr(0));
175b9c1b51eSKate Stone     } else {
1764740a734SSean Callanan       StopInfoSP stop_info_sp = thread->GetStopInfo();
177b9c1b51eSKate Stone       if (!stop_info_sp) {
1784740a734SSean Callanan         result.AppendError("No arguments provided, and no stop info.");
1794740a734SSean Callanan         result.SetStatus(eReturnStatusFailed);
1804740a734SSean Callanan         return false;
1814740a734SSean Callanan       }
1824740a734SSean Callanan 
1834740a734SSean Callanan       valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
1844740a734SSean Callanan     }
1854740a734SSean Callanan 
186b9c1b51eSKate Stone     if (!valobj_sp) {
1874740a734SSean Callanan       result.AppendError("No diagnosis available.");
1884740a734SSean Callanan       result.SetStatus(eReturnStatusFailed);
1894740a734SSean Callanan       return false;
1904740a734SSean Callanan     }
1914740a734SSean Callanan 
1924740a734SSean Callanan     const bool qualify_cxx_base_classes = false;
1934740a734SSean Callanan 
194b9c1b51eSKate Stone     DumpValueObjectOptions::DeclPrintingHelper helper =
195b9c1b51eSKate Stone         [&valobj_sp, qualify_cxx_base_classes](
196b9c1b51eSKate Stone             ConstString type, ConstString var,
197b9c1b51eSKate Stone             const DumpValueObjectOptions &opts, Stream &stream) -> bool {
198b9c1b51eSKate Stone       const ValueObject::GetExpressionPathFormat format = ValueObject::
199b9c1b51eSKate Stone           GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
2004740a734SSean Callanan       valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format);
2014740a734SSean Callanan       stream.PutCString(" =");
2024740a734SSean Callanan       return true;
2034740a734SSean Callanan     };
2044740a734SSean Callanan 
2054740a734SSean Callanan     DumpValueObjectOptions options;
2064740a734SSean Callanan     options.SetDeclPrintingHelper(helper);
207b9c1b51eSKate Stone     ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
208b9c1b51eSKate Stone                                options);
2094740a734SSean Callanan     printer.PrintValueObject();
2104740a734SSean Callanan 
2114740a734SSean Callanan     return true;
2124740a734SSean Callanan   }
2134740a734SSean Callanan 
2144740a734SSean Callanan protected:
2154740a734SSean Callanan   CommandOptions m_options;
2164740a734SSean Callanan };
2174740a734SSean Callanan 
218b9c1b51eSKate Stone OptionDefinition CommandObjectFrameDiagnose::CommandOptions::g_option_table[] =
2194740a734SSean Callanan     {
2204740a734SSean Callanan         // clang-format off
2214740a734SSean Callanan     {LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegisterName,    "A register to diagnose."},
2224740a734SSean Callanan     {LLDB_OPT_SET_1, false, "address",  'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress,         "An address to diagnose."},
2234740a734SSean Callanan     {LLDB_OPT_SET_1, false, "offset",   'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,          "An optional offset.  Requires --register."},
2244740a734SSean Callanan     {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
2254740a734SSean Callanan         // clang-format on
2264740a734SSean Callanan };
2274740a734SSean Callanan 
22830fdc8d8SChris Lattner #pragma mark CommandObjectFrameInfo
22930fdc8d8SChris Lattner 
23030fdc8d8SChris Lattner //-------------------------------------------------------------------------
23130fdc8d8SChris Lattner // CommandObjectFrameInfo
23230fdc8d8SChris Lattner //-------------------------------------------------------------------------
23330fdc8d8SChris Lattner 
234b9c1b51eSKate Stone class CommandObjectFrameInfo : public CommandObjectParsed {
23530fdc8d8SChris Lattner public:
2367428a18cSKate Stone   CommandObjectFrameInfo(CommandInterpreter &interpreter)
237b9c1b51eSKate Stone       : CommandObjectParsed(
238b9c1b51eSKate Stone             interpreter, "frame info", "List information about the current "
239b9c1b51eSKate Stone                                        "stack frame in the current thread.",
240b9c1b51eSKate Stone             "frame info",
241b9c1b51eSKate Stone             eCommandRequiresFrame | eCommandTryTargetAPILock |
242b9c1b51eSKate Stone                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
24330fdc8d8SChris Lattner 
244c8ecc2a9SEugene Zelenko   ~CommandObjectFrameInfo() override = default;
24530fdc8d8SChris Lattner 
2465a988416SJim Ingham protected:
247b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
248f9fc609fSGreg Clayton     m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
24930fdc8d8SChris Lattner     result.SetStatus(eReturnStatusSuccessFinishResult);
25030fdc8d8SChris Lattner     return result.Succeeded();
25130fdc8d8SChris Lattner   }
25230fdc8d8SChris Lattner };
25330fdc8d8SChris Lattner 
25430fdc8d8SChris Lattner #pragma mark CommandObjectFrameSelect
25530fdc8d8SChris Lattner 
25630fdc8d8SChris Lattner //-------------------------------------------------------------------------
25730fdc8d8SChris Lattner // CommandObjectFrameSelect
25830fdc8d8SChris Lattner //-------------------------------------------------------------------------
25930fdc8d8SChris Lattner 
260b9c1b51eSKate Stone class CommandObjectFrameSelect : public CommandObjectParsed {
26130fdc8d8SChris Lattner public:
262b9c1b51eSKate Stone   class CommandOptions : public Options {
263864174e1SGreg Clayton   public:
264b9c1b51eSKate Stone     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
265864174e1SGreg Clayton 
266c8ecc2a9SEugene Zelenko     ~CommandOptions() override = default;
267864174e1SGreg Clayton 
268b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
269b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
270864174e1SGreg Clayton       Error error;
271864174e1SGreg Clayton       bool success = false;
2723bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
273b9c1b51eSKate Stone       switch (short_option) {
274864174e1SGreg Clayton       case 'r':
275b9c1b51eSKate Stone         relative_frame_offset =
276b9c1b51eSKate Stone             StringConvert::ToSInt32(option_arg, INT32_MIN, 0, &success);
277864174e1SGreg Clayton         if (!success)
278b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
279b9c1b51eSKate Stone                                          option_arg);
280864174e1SGreg Clayton         break;
281864174e1SGreg Clayton 
282864174e1SGreg Clayton       default:
283b9c1b51eSKate Stone         error.SetErrorStringWithFormat("invalid short option character '%c'",
284b9c1b51eSKate Stone                                        short_option);
285864174e1SGreg Clayton         break;
286864174e1SGreg Clayton       }
287864174e1SGreg Clayton 
288864174e1SGreg Clayton       return error;
289864174e1SGreg Clayton     }
290864174e1SGreg Clayton 
291b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
292864174e1SGreg Clayton       relative_frame_offset = INT32_MIN;
293864174e1SGreg Clayton     }
294864174e1SGreg Clayton 
295b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
296864174e1SGreg Clayton 
297864174e1SGreg Clayton     // Options table: Required for subclasses of Options.
298864174e1SGreg Clayton 
299e0d378b3SGreg Clayton     static OptionDefinition g_option_table[];
300864174e1SGreg Clayton     int32_t relative_frame_offset;
301864174e1SGreg Clayton   };
302864174e1SGreg Clayton 
3037428a18cSKate Stone   CommandObjectFrameSelect(CommandInterpreter &interpreter)
3047428a18cSKate Stone       : CommandObjectParsed(
305b9c1b51eSKate Stone             interpreter, "frame select", "Select the current stack frame by "
306b9c1b51eSKate Stone                                          "index from within the current thread "
307b9c1b51eSKate Stone                                          "(see 'thread backtrace'.)",
308b9c1b51eSKate Stone             nullptr,
309b9c1b51eSKate Stone             eCommandRequiresThread | eCommandTryTargetAPILock |
310b9c1b51eSKate Stone                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
311b9c1b51eSKate Stone         m_options() {
312405fe67fSCaroline Tice     CommandArgumentEntry arg;
313405fe67fSCaroline Tice     CommandArgumentData index_arg;
314405fe67fSCaroline Tice 
315405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
316405fe67fSCaroline Tice     index_arg.arg_type = eArgTypeFrameIndex;
317864174e1SGreg Clayton     index_arg.arg_repetition = eArgRepeatOptional;
318405fe67fSCaroline Tice 
319b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
320b9c1b51eSKate Stone     // argument entry.
321405fe67fSCaroline Tice     arg.push_back(index_arg);
322405fe67fSCaroline Tice 
323405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
324405fe67fSCaroline Tice     m_arguments.push_back(arg);
32530fdc8d8SChris Lattner   }
32630fdc8d8SChris Lattner 
327c8ecc2a9SEugene Zelenko   ~CommandObjectFrameSelect() override = default;
32830fdc8d8SChris Lattner 
329b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
330864174e1SGreg Clayton 
3315a988416SJim Ingham protected:
332b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
333b9c1b51eSKate Stone     // No need to check "thread" for validity as eCommandRequiresThread ensures
334b9c1b51eSKate Stone     // it is valid
335f9fc609fSGreg Clayton     Thread *thread = m_exe_ctx.GetThreadPtr();
336f9fc609fSGreg Clayton 
337864174e1SGreg Clayton     uint32_t frame_idx = UINT32_MAX;
338b9c1b51eSKate Stone     if (m_options.relative_frame_offset != INT32_MIN) {
339864174e1SGreg Clayton       // The one and only argument is a signed relative frame index
340c14ee32dSGreg Clayton       frame_idx = thread->GetSelectedFrameIndex();
341864174e1SGreg Clayton       if (frame_idx == UINT32_MAX)
342864174e1SGreg Clayton         frame_idx = 0;
343864174e1SGreg Clayton 
344b9c1b51eSKate Stone       if (m_options.relative_frame_offset < 0) {
3453985c8c6SSaleem Abdulrasool         if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset)
346864174e1SGreg Clayton           frame_idx += m_options.relative_frame_offset;
347b9c1b51eSKate Stone         else {
348b9c1b51eSKate Stone           if (frame_idx == 0) {
349b9c1b51eSKate Stone             // If you are already at the bottom of the stack, then just warn and
350b9c1b51eSKate Stone             // don't reset the frame.
3517428a18cSKate Stone             result.AppendError("Already at the bottom of the stack.");
352213b4546SJim Ingham             result.SetStatus(eReturnStatusFailed);
353213b4546SJim Ingham             return false;
354b9c1b51eSKate Stone           } else
355864174e1SGreg Clayton             frame_idx = 0;
356864174e1SGreg Clayton         }
357b9c1b51eSKate Stone       } else if (m_options.relative_frame_offset > 0) {
358b9c1b51eSKate Stone         // I don't want "up 20" where "20" takes you past the top of the stack
359b9c1b51eSKate Stone         // to produce
360b9c1b51eSKate Stone         // an error, but rather to just go to the top.  So I have to count the
361b9c1b51eSKate Stone         // stack here...
362b0c72a5fSJim Ingham         const uint32_t num_frames = thread->GetStackFrameCount();
363b9c1b51eSKate Stone         if (static_cast<int32_t>(num_frames - frame_idx) >
364b9c1b51eSKate Stone             m_options.relative_frame_offset)
365864174e1SGreg Clayton           frame_idx += m_options.relative_frame_offset;
366b9c1b51eSKate Stone         else {
367b9c1b51eSKate Stone           if (frame_idx == num_frames - 1) {
368b9c1b51eSKate Stone             // If we are already at the top of the stack, just warn and don't
369b9c1b51eSKate Stone             // reset the frame.
3707428a18cSKate Stone             result.AppendError("Already at the top of the stack.");
371213b4546SJim Ingham             result.SetStatus(eReturnStatusFailed);
372213b4546SJim Ingham             return false;
373b9c1b51eSKate Stone           } else
374864174e1SGreg Clayton             frame_idx = num_frames - 1;
375864174e1SGreg Clayton         }
376864174e1SGreg Clayton       }
377b9c1b51eSKate Stone     } else {
378b9c1b51eSKate Stone       if (command.GetArgumentCount() == 1) {
37930fdc8d8SChris Lattner         const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
380afbb0af8SJim Ingham         bool success = false;
381b9c1b51eSKate Stone         frame_idx =
382b9c1b51eSKate Stone             StringConvert::ToUInt32(frame_idx_cstr, UINT32_MAX, 0, &success);
383b9c1b51eSKate Stone         if (!success) {
384b9c1b51eSKate Stone           result.AppendErrorWithFormat("invalid frame index argument '%s'.",
385b9c1b51eSKate Stone                                        frame_idx_cstr);
386afbb0af8SJim Ingham           result.SetStatus(eReturnStatusFailed);
387afbb0af8SJim Ingham           return false;
388afbb0af8SJim Ingham         }
389b9c1b51eSKate Stone       } else if (command.GetArgumentCount() == 0) {
39082d4a2b9SJason Molenda         frame_idx = thread->GetSelectedFrameIndex();
391b9c1b51eSKate Stone         if (frame_idx == UINT32_MAX) {
39282d4a2b9SJason Molenda           frame_idx = 0;
39382d4a2b9SJason Molenda         }
394b9c1b51eSKate Stone       } else {
395b9c1b51eSKate Stone         result.AppendErrorWithFormat(
396b9c1b51eSKate Stone             "too many arguments; expected frame-index, saw '%s'.\n",
397c2961ab8SAdrian McCarthy             command.GetArgumentAtIndex(0));
398b9c1b51eSKate Stone         m_options.GenerateOptionUsage(
399b9c1b51eSKate Stone             result.GetErrorStream(), this,
400b9c1b51eSKate Stone             GetCommandInterpreter().GetDebugger().GetTerminalWidth());
401c2961ab8SAdrian McCarthy         return false;
402864174e1SGreg Clayton       }
403864174e1SGreg Clayton     }
40430fdc8d8SChris Lattner 
405b9c1b51eSKate Stone     bool success = thread->SetSelectedFrameByIndexNoisily(
406b9c1b51eSKate Stone         frame_idx, result.GetOutputStream());
407b9c1b51eSKate Stone     if (success) {
408f9fc609fSGreg Clayton       m_exe_ctx.SetFrameSP(thread->GetSelectedFrame());
40930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
410b9c1b51eSKate Stone     } else {
411b9c1b51eSKate Stone       result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
412b9c1b51eSKate Stone                                    frame_idx);
41330fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
41493208b86SJim Ingham     }
41593208b86SJim Ingham 
41693208b86SJim Ingham     return result.Succeeded();
41730fdc8d8SChris Lattner   }
418864174e1SGreg Clayton 
419c8ecc2a9SEugene Zelenko protected:
420864174e1SGreg Clayton   CommandOptions m_options;
421864174e1SGreg Clayton };
422864174e1SGreg Clayton 
423b9c1b51eSKate Stone OptionDefinition CommandObjectFrameSelect::CommandOptions::g_option_table[] = {
424ac9c3a62SKate Stone     // clang-format off
425c8ecc2a9SEugene Zelenko   {LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
426c8ecc2a9SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
427ac9c3a62SKate Stone     // clang-format on
42830fdc8d8SChris Lattner };
42930fdc8d8SChris Lattner 
4306d56d2ceSJim Ingham #pragma mark CommandObjectFrameVariable
4316d56d2ceSJim Ingham //----------------------------------------------------------------------
4326d56d2ceSJim Ingham // List images with associated information
4336d56d2ceSJim Ingham //----------------------------------------------------------------------
434b9c1b51eSKate Stone class CommandObjectFrameVariable : public CommandObjectParsed {
4356d56d2ceSJim Ingham public:
4367428a18cSKate Stone   CommandObjectFrameVariable(CommandInterpreter &interpreter)
4377428a18cSKate Stone       : CommandObjectParsed(
438b9c1b51eSKate Stone             interpreter, "frame variable",
439b9c1b51eSKate Stone             "Show variables for the current stack frame. Defaults to all "
4407428a18cSKate Stone             "arguments and local variables in scope. Names of argument, "
4417428a18cSKate Stone             "local, file static and file global variables can be specified. "
442ed8a705cSGreg Clayton             "Children of aggregate variables can be specified such as "
443973cf9e8SJohnny Chen             "'var->child.x'.",
444b9c1b51eSKate Stone             nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
445b9c1b51eSKate Stone                          eCommandProcessMustBeLaunched |
4467428a18cSKate Stone                          eCommandProcessMustBePaused | eCommandRequiresProcess),
447e1cfbc79STodd Fiala         m_option_group(),
448b9c1b51eSKate Stone         m_option_variable(
449b9c1b51eSKate Stone             true), // Include the frame specific options by passing "true"
4501deb7962SGreg Clayton         m_option_format(eFormatDefault),
451b9c1b51eSKate Stone         m_varobj_options() {
452405fe67fSCaroline Tice     CommandArgumentEntry arg;
453405fe67fSCaroline Tice     CommandArgumentData var_name_arg;
454405fe67fSCaroline Tice 
455405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
456405fe67fSCaroline Tice     var_name_arg.arg_type = eArgTypeVarName;
457405fe67fSCaroline Tice     var_name_arg.arg_repetition = eArgRepeatStar;
458405fe67fSCaroline Tice 
459b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
460b9c1b51eSKate Stone     // argument entry.
461405fe67fSCaroline Tice     arg.push_back(var_name_arg);
462405fe67fSCaroline Tice 
463405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
464405fe67fSCaroline Tice     m_arguments.push_back(arg);
4652837b766SJim Ingham 
466715c2365SGreg Clayton     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
467b9c1b51eSKate Stone     m_option_group.Append(&m_option_format,
468b9c1b51eSKate Stone                           OptionGroupFormat::OPTION_GROUP_FORMAT |
469b9c1b51eSKate Stone                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
470b9c1b51eSKate Stone                           LLDB_OPT_SET_1);
4712837b766SJim Ingham     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4722837b766SJim Ingham     m_option_group.Finalize();
4736d56d2ceSJim Ingham   }
4746d56d2ceSJim Ingham 
475c8ecc2a9SEugene Zelenko   ~CommandObjectFrameVariable() override = default;
4766d56d2ceSJim Ingham 
477b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
478f21feadcSGreg Clayton 
479b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
480f21feadcSGreg Clayton                                int &cursor_char_position,
481f21feadcSGreg Clayton                                OptionElementVector &opt_element_vector,
482b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
483f21feadcSGreg Clayton                                bool &word_complete,
484b9c1b51eSKate Stone                                StringList &matches) override {
485f21feadcSGreg Clayton     // Arguments are the standard source file completer.
486f21feadcSGreg Clayton     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
487f21feadcSGreg Clayton     completion_str.erase(cursor_char_position);
488f21feadcSGreg Clayton 
489b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
490b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
491b9c1b51eSKate Stone         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
492b9c1b51eSKate Stone         word_complete, matches);
493f21feadcSGreg Clayton     return matches.GetSize();
494f21feadcSGreg Clayton   }
4956d56d2ceSJim Ingham 
4965a988416SJim Ingham protected:
497b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
498b9c1b51eSKate Stone     // No need to check "frame" for validity as eCommandRequiresFrame ensures it
499b9c1b51eSKate Stone     // is valid
500b57e4a1bSJason Molenda     StackFrame *frame = m_exe_ctx.GetFramePtr();
5011e49e5e7SJohnny Chen 
502a134cc1bSGreg Clayton     Stream &s = result.GetOutputStream();
5036d56d2ceSJim Ingham 
504b9c1b51eSKate Stone     // Be careful about the stack frame, if any summary formatter runs code, it
505b9c1b51eSKate Stone     // might clear the StackFrameList
506b9c1b51eSKate Stone     // for the thread.  So hold onto a shared pointer to the frame so it stays
507b9c1b51eSKate Stone     // alive.
508650543f9SJim Ingham 
509b9c1b51eSKate Stone     VariableList *variable_list =
510b9c1b51eSKate Stone         frame->GetVariableList(m_option_variable.show_globals);
511a134cc1bSGreg Clayton 
5126d56d2ceSJim Ingham     VariableSP var_sp;
5136d56d2ceSJim Ingham     ValueObjectSP valobj_sp;
51478a685aaSJim Ingham 
515c8ecc2a9SEugene Zelenko     const char *name_cstr = nullptr;
5166d56d2ceSJim Ingham     size_t idx;
5176d56d2ceSJim Ingham 
518061858ceSEnrico Granata     TypeSummaryImplSP summary_format_sp;
51917b11749SEnrico Granata     if (!m_option_variable.summary.IsCurrentValueEmpty())
520b9c1b51eSKate Stone       DataVisualization::NamedSummaryFormats::GetSummaryFormat(
521b9c1b51eSKate Stone           ConstString(m_option_variable.summary.GetCurrentValue()),
522b9c1b51eSKate Stone           summary_format_sp);
52317b11749SEnrico Granata     else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
524b9c1b51eSKate Stone       summary_format_sp.reset(new StringSummaryFormat(
525b9c1b51eSKate Stone           TypeSummaryImpl::Flags(),
526b9c1b51eSKate Stone           m_option_variable.summary_string.GetCurrentValue()));
527f9fa6ee5SEnrico Granata 
528b9c1b51eSKate Stone     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
529b9c1b51eSKate Stone         eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
530b9c1b51eSKate Stone         summary_format_sp));
531379447a7SEnrico Granata 
532b9c1b51eSKate Stone     const SymbolContext &sym_ctx =
533b9c1b51eSKate Stone         frame->GetSymbolContext(eSymbolContextFunction);
5346754e04fSEnrico Granata     if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
5356754e04fSEnrico Granata       m_option_variable.show_globals = true;
5366754e04fSEnrico Granata 
537b9c1b51eSKate Stone     if (variable_list) {
5381deb7962SGreg Clayton       const Format format = m_option_format.GetFormat();
5390c489f58SEnrico Granata       options.SetFormat(format);
5401deb7962SGreg Clayton 
541b9c1b51eSKate Stone       if (command.GetArgumentCount() > 0) {
54246747022SGreg Clayton         VariableList regex_var_list;
54346747022SGreg Clayton 
5446d56d2ceSJim Ingham         // If we have any args to the variable command, we will make
5456d56d2ceSJim Ingham         // variable objects from them...
546b9c1b51eSKate Stone         for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr;
547b9c1b51eSKate Stone              ++idx) {
548b9c1b51eSKate Stone           if (m_option_variable.use_regex) {
549c7bece56SGreg Clayton             const size_t regex_start_index = regex_var_list.GetSize();
550*95eae423SZachary Turner             llvm::StringRef name_str(name_cstr);
551*95eae423SZachary Turner             RegularExpression regex(name_str);
552*95eae423SZachary Turner             if (regex.Compile(name_str)) {
55346747022SGreg Clayton               size_t num_matches = 0;
554b9c1b51eSKate Stone               const size_t num_new_regex_vars =
555b9c1b51eSKate Stone                   variable_list->AppendVariablesIfUnique(regex, regex_var_list,
55678a685aaSJim Ingham                                                          num_matches);
557b9c1b51eSKate Stone               if (num_new_regex_vars > 0) {
558b9c1b51eSKate Stone                 for (size_t regex_idx = regex_start_index,
559b9c1b51eSKate Stone                             end_index = regex_var_list.GetSize();
560b9c1b51eSKate Stone                      regex_idx < end_index; ++regex_idx) {
56146747022SGreg Clayton                   var_sp = regex_var_list.GetVariableAtIndex(regex_idx);
562b9c1b51eSKate Stone                   if (var_sp) {
563b9c1b51eSKate Stone                     valobj_sp = frame->GetValueObjectForFrameVariable(
564b9c1b51eSKate Stone                         var_sp, m_varobj_options.use_dynamic);
565b9c1b51eSKate Stone                     if (valobj_sp) {
566b9c1b51eSKate Stone                       //                                            if (format
567b9c1b51eSKate Stone                       //                                            !=
568b9c1b51eSKate Stone                       //                                            eFormatDefault)
569b9c1b51eSKate Stone                       //                                                valobj_sp->SetFormat
570b9c1b51eSKate Stone                       //                                                (format);
571ded470d3SGreg Clayton 
572b9c1b51eSKate Stone                       if (m_option_variable.show_decl &&
573b9c1b51eSKate Stone                           var_sp->GetDeclaration().GetFile()) {
57445ba8543SGreg Clayton                         bool show_fullpaths = false;
57545ba8543SGreg Clayton                         bool show_module = true;
576b9c1b51eSKate Stone                         if (var_sp->DumpDeclaration(&s, show_fullpaths,
577b9c1b51eSKate Stone                                                     show_module))
57846747022SGreg Clayton                           s.PutCString(": ");
57946747022SGreg Clayton                       }
5804d93b8cdSEnrico Granata                       valobj_sp->Dump(result.GetOutputStream(), options);
58146747022SGreg Clayton                     }
58246747022SGreg Clayton                   }
58346747022SGreg Clayton                 }
584b9c1b51eSKate Stone               } else if (num_matches == 0) {
585b9c1b51eSKate Stone                 result.GetErrorStream().Printf("error: no variables matched "
586b9c1b51eSKate Stone                                                "the regular expression '%s'.\n",
587b9c1b51eSKate Stone                                                name_cstr);
58846747022SGreg Clayton               }
589b9c1b51eSKate Stone             } else {
59046747022SGreg Clayton               char regex_error[1024];
59146747022SGreg Clayton               if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
59246747022SGreg Clayton                 result.GetErrorStream().Printf("error: %s\n", regex_error);
59346747022SGreg Clayton               else
594b9c1b51eSKate Stone                 result.GetErrorStream().Printf(
595b9c1b51eSKate Stone                     "error: unknown regex error when compiling '%s'\n",
596b9c1b51eSKate Stone                     name_cstr);
59746747022SGreg Clayton             }
598b9c1b51eSKate Stone           } else // No regex, either exact variable names or variable
599b9c1b51eSKate Stone                  // expressions.
60046747022SGreg Clayton           {
60154979cddSGreg Clayton             Error error;
602b9c1b51eSKate Stone             uint32_t expr_path_options =
603b9c1b51eSKate Stone                 StackFrame::eExpressionPathOptionCheckPtrVsMember |
60446252398SEnrico Granata                 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
60546252398SEnrico Granata                 StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
6062837b766SJim Ingham             lldb::VariableSP var_sp;
607b9c1b51eSKate Stone             valobj_sp = frame->GetValueForVariableExpressionPath(
608b9c1b51eSKate Stone                 name_cstr, m_varobj_options.use_dynamic, expr_path_options,
609b9c1b51eSKate Stone                 var_sp, error);
610b9c1b51eSKate Stone             if (valobj_sp) {
6116efba4fcSGreg Clayton               //                            if (format != eFormatDefault)
6126efba4fcSGreg Clayton               //                                valobj_sp->SetFormat (format);
613b9c1b51eSKate Stone               if (m_option_variable.show_decl && var_sp &&
614b9c1b51eSKate Stone                   var_sp->GetDeclaration().GetFile()) {
615a134cc1bSGreg Clayton                 var_sp->GetDeclaration().DumpStopContext(&s, false);
616a134cc1bSGreg Clayton                 s.PutCString(": ");
617a134cc1bSGreg Clayton               }
6180c489f58SEnrico Granata 
6190c489f58SEnrico Granata               options.SetFormat(format);
620b9c1b51eSKate Stone               options.SetVariableFormatDisplayLanguage(
621b9c1b51eSKate Stone                   valobj_sp->GetPreferredDisplayLanguage());
622887062aeSJohnny Chen 
623887062aeSJohnny Chen               Stream &output_stream = result.GetOutputStream();
624b9c1b51eSKate Stone               options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr
625b9c1b51eSKate Stone                                                                     : nullptr);
6264d93b8cdSEnrico Granata               valobj_sp->Dump(output_stream, options);
627b9c1b51eSKate Stone             } else {
628c8ecc2a9SEugene Zelenko               const char *error_cstr = error.AsCString(nullptr);
62954979cddSGreg Clayton               if (error_cstr)
63054979cddSGreg Clayton                 result.GetErrorStream().Printf("error: %s\n", error_cstr);
63154979cddSGreg Clayton               else
632b9c1b51eSKate Stone                 result.GetErrorStream().Printf("error: unable to find any "
633b9c1b51eSKate Stone                                                "variable expression path that "
634b9c1b51eSKate Stone                                                "matches '%s'.\n",
6357428a18cSKate Stone                                                name_cstr);
6366d56d2ceSJim Ingham             }
6376d56d2ceSJim Ingham           }
6386d56d2ceSJim Ingham         }
639b9c1b51eSKate Stone       } else // No command arg specified.  Use variable_list, instead.
6406d56d2ceSJim Ingham       {
641c7bece56SGreg Clayton         const size_t num_variables = variable_list->GetSize();
642b9c1b51eSKate Stone         if (num_variables > 0) {
643b9c1b51eSKate Stone           for (size_t i = 0; i < num_variables; i++) {
6441a65ae11SGreg Clayton             var_sp = variable_list->GetVariableAtIndex(i);
6456d56d2ceSJim Ingham             bool dump_variable = true;
646560558ebSEnrico Granata             std::string scope_string;
647b9c1b51eSKate Stone             switch (var_sp->GetScope()) {
6486d56d2ceSJim Ingham             case eValueTypeVariableGlobal:
6494e26dd34SGreg Clayton               // Always dump globals since we only fetched them if
6504e26dd34SGreg Clayton               // m_option_variable.show_scope was true
651715c2365SGreg Clayton               if (dump_variable && m_option_variable.show_scope)
652560558ebSEnrico Granata                 scope_string = "GLOBAL: ";
6536d56d2ceSJim Ingham               break;
6546d56d2ceSJim Ingham 
6556d56d2ceSJim Ingham             case eValueTypeVariableStatic:
6564e26dd34SGreg Clayton               // Always dump globals since we only fetched them if
6574e26dd34SGreg Clayton               // m_option_variable.show_scope was true, or this is
6584e26dd34SGreg Clayton               // a static variable from a block in the current scope
659715c2365SGreg Clayton               if (dump_variable && m_option_variable.show_scope)
660560558ebSEnrico Granata                 scope_string = "STATIC: ";
6616d56d2ceSJim Ingham               break;
6626d56d2ceSJim Ingham 
6636d56d2ceSJim Ingham             case eValueTypeVariableArgument:
664715c2365SGreg Clayton               dump_variable = m_option_variable.show_args;
665715c2365SGreg Clayton               if (dump_variable && m_option_variable.show_scope)
666560558ebSEnrico Granata                 scope_string = "   ARG: ";
6676d56d2ceSJim Ingham               break;
6686d56d2ceSJim Ingham 
6696d56d2ceSJim Ingham             case eValueTypeVariableLocal:
670715c2365SGreg Clayton               dump_variable = m_option_variable.show_locals;
671715c2365SGreg Clayton               if (dump_variable && m_option_variable.show_scope)
672560558ebSEnrico Granata                 scope_string = " LOCAL: ";
6736d56d2ceSJim Ingham               break;
6746d56d2ceSJim Ingham 
67563a27afaSGreg Clayton             case eValueTypeVariableThreadLocal:
67663a27afaSGreg Clayton               if (dump_variable && m_option_variable.show_scope)
67763a27afaSGreg Clayton                 scope_string = "THREAD: ";
67863a27afaSGreg Clayton               break;
6796d56d2ceSJim Ingham             default:
6806d56d2ceSJim Ingham               break;
6816d56d2ceSJim Ingham             }
6826d56d2ceSJim Ingham 
683b9c1b51eSKate Stone             if (dump_variable) {
684a134cc1bSGreg Clayton               // Use the variable object code to make sure we are
68558ef391fSBruce Mitchener               // using the same APIs as the public API will be
686a134cc1bSGreg Clayton               // using...
687b9c1b51eSKate Stone               valobj_sp = frame->GetValueObjectForFrameVariable(
688b9c1b51eSKate Stone                   var_sp, m_varobj_options.use_dynamic);
689b9c1b51eSKate Stone               if (valobj_sp) {
6906efba4fcSGreg Clayton                 //                                if (format != eFormatDefault)
691b9c1b51eSKate Stone                 //                                    valobj_sp->SetFormat
692b9c1b51eSKate Stone                 //                                    (format);
693ded470d3SGreg Clayton 
6946f00abd5SGreg Clayton                 // When dumping all variables, don't print any variables
6956f00abd5SGreg Clayton                 // that are not in scope to avoid extra unneeded output
696b9c1b51eSKate Stone                 if (valobj_sp->IsInScope()) {
697b9c1b51eSKate Stone                   if (!valobj_sp->GetTargetSP()
698b9c1b51eSKate Stone                            ->GetDisplayRuntimeSupportValues() &&
699c8ecc2a9SEugene Zelenko                       valobj_sp->IsRuntimeSupportValue())
700560558ebSEnrico Granata                     continue;
701560558ebSEnrico Granata 
702560558ebSEnrico Granata                   if (!scope_string.empty())
703560558ebSEnrico Granata                     s.PutCString(scope_string.c_str());
704560558ebSEnrico Granata 
705b9c1b51eSKate Stone                   if (m_option_variable.show_decl &&
706b9c1b51eSKate Stone                       var_sp->GetDeclaration().GetFile()) {
707a134cc1bSGreg Clayton                     var_sp->GetDeclaration().DumpStopContext(&s, false);
708a134cc1bSGreg Clayton                     s.PutCString(": ");
709a134cc1bSGreg Clayton                   }
7100c489f58SEnrico Granata 
7110c489f58SEnrico Granata                   options.SetFormat(format);
712b9c1b51eSKate Stone                   options.SetVariableFormatDisplayLanguage(
713b9c1b51eSKate Stone                       valobj_sp->GetPreferredDisplayLanguage());
7140c489f58SEnrico Granata                   options.SetRootValueObjectName(name_cstr);
7154d93b8cdSEnrico Granata                   valobj_sp->Dump(result.GetOutputStream(), options);
716a134cc1bSGreg Clayton                 }
717a134cc1bSGreg Clayton               }
7186d56d2ceSJim Ingham             }
7196d56d2ceSJim Ingham           }
7206d56d2ceSJim Ingham         }
7216f00abd5SGreg Clayton       }
7226d56d2ceSJim Ingham       result.SetStatus(eReturnStatusSuccessFinishResult);
7236d56d2ceSJim Ingham     }
72461a80ba6SEnrico Granata 
725b9c1b51eSKate Stone     if (m_interpreter.TruncationWarningNecessary()) {
72661a80ba6SEnrico Granata       result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
72761a80ba6SEnrico Granata                                       m_cmd_name.c_str());
72861a80ba6SEnrico Granata       m_interpreter.TruncationWarningGiven();
72961a80ba6SEnrico Granata     }
73061a80ba6SEnrico Granata 
7316d56d2ceSJim Ingham     return result.Succeeded();
7326d56d2ceSJim Ingham   }
7336d56d2ceSJim Ingham 
734c8ecc2a9SEugene Zelenko protected:
7352837b766SJim Ingham   OptionGroupOptions m_option_group;
736715c2365SGreg Clayton   OptionGroupVariable m_option_variable;
7371deb7962SGreg Clayton   OptionGroupFormat m_option_format;
7382837b766SJim Ingham   OptionGroupValueObjectDisplay m_varobj_options;
7396d56d2ceSJim Ingham };
7406d56d2ceSJim Ingham 
74130fdc8d8SChris Lattner #pragma mark CommandObjectMultiwordFrame
74230fdc8d8SChris Lattner 
74330fdc8d8SChris Lattner //-------------------------------------------------------------------------
74430fdc8d8SChris Lattner // CommandObjectMultiwordFrame
74530fdc8d8SChris Lattner //-------------------------------------------------------------------------
74630fdc8d8SChris Lattner 
747b9c1b51eSKate Stone CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
748b9c1b51eSKate Stone     CommandInterpreter &interpreter)
749b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and "
750b9c1b51eSKate Stone                                                    "examing the current "
751b9c1b51eSKate Stone                                                    "thread's stack frames.",
752b9c1b51eSKate Stone                              "frame <subcommand> [<subcommand-options>]") {
753b9c1b51eSKate Stone   LoadSubCommand("diagnose",
754b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
755b9c1b51eSKate Stone   LoadSubCommand("info",
756b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
757b9c1b51eSKate Stone   LoadSubCommand("select",
758b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
759b9c1b51eSKate Stone   LoadSubCommand("variable",
760b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
76130fdc8d8SChris Lattner }
76230fdc8d8SChris Lattner 
763c8ecc2a9SEugene Zelenko CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
764