130fdc8d8SChris Lattner //===-- CommandObjectRegister.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 #include "CommandObjectRegister.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1630fdc8d8SChris Lattner #include "lldb/Core/DataExtractor.h"
177349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h"
1830fdc8d8SChris Lattner #include "lldb/Core/Scalar.h"
196611103cSGreg Clayton #include "lldb/Core/Debugger.h"
206611103cSGreg Clayton #include "lldb/Interpreter/Args.h"
216611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
2230fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
23eb0103f2SGreg Clayton #include "lldb/Interpreter/Options.h"
241deb7962SGreg Clayton #include "lldb/Interpreter/OptionGroupFormat.h"
2567cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h"
2632abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
2767cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h"
2830fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
298f7770f8SGreg Clayton #include "lldb/Target/Process.h"
3030fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
31d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h"
328f7770f8SGreg Clayton #include "lldb/Target/Thread.h"
3328606954SSaleem Abdulrasool #include "llvm/ADT/STLExtras.h"
3430fdc8d8SChris Lattner 
3530fdc8d8SChris Lattner using namespace lldb;
3630fdc8d8SChris Lattner using namespace lldb_private;
3730fdc8d8SChris Lattner 
3830fdc8d8SChris Lattner //----------------------------------------------------------------------
3930fdc8d8SChris Lattner // "register read"
4030fdc8d8SChris Lattner //----------------------------------------------------------------------
415a988416SJim Ingham class CommandObjectRegisterRead : public CommandObjectParsed
4230fdc8d8SChris Lattner {
4330fdc8d8SChris Lattner public:
44a7015092SGreg Clayton     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
455a988416SJim Ingham         CommandObjectParsed (interpreter,
46a7015092SGreg Clayton                              "register read",
47405fe67fSCaroline Tice                              "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
48405fe67fSCaroline Tice                              NULL,
49e87764f2SEnrico Granata                              eCommandRequiresFrame         |
50e87764f2SEnrico Granata                              eCommandRequiresRegContext    |
51e87764f2SEnrico Granata                              eCommandProcessMustBeLaunched |
52e87764f2SEnrico Granata                              eCommandProcessMustBePaused   ),
531deb7962SGreg Clayton         m_option_group (interpreter),
541deb7962SGreg Clayton         m_format_options (eFormatDefault),
551deb7962SGreg Clayton         m_command_options ()
5630fdc8d8SChris Lattner     {
57405fe67fSCaroline Tice         CommandArgumentEntry arg;
58405fe67fSCaroline Tice         CommandArgumentData register_arg;
59405fe67fSCaroline Tice 
60405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
61405fe67fSCaroline Tice         register_arg.arg_type = eArgTypeRegisterName;
62405fe67fSCaroline Tice         register_arg.arg_repetition = eArgRepeatStar;
63405fe67fSCaroline Tice 
64405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
65405fe67fSCaroline Tice         arg.push_back (register_arg);
66405fe67fSCaroline Tice 
67405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
68405fe67fSCaroline Tice         m_arguments.push_back (arg);
691deb7962SGreg Clayton 
701deb7962SGreg Clayton         // Add the "--format"
715009f9d5SGreg Clayton         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
721deb7962SGreg Clayton         m_option_group.Append (&m_command_options);
731deb7962SGreg Clayton         m_option_group.Finalize();
741deb7962SGreg Clayton 
7530fdc8d8SChris Lattner     }
7630fdc8d8SChris Lattner 
77*13d21e9aSBruce Mitchener     ~CommandObjectRegisterRead () override
7830fdc8d8SChris Lattner     {
7930fdc8d8SChris Lattner     }
8030fdc8d8SChris Lattner 
8132e0a750SGreg Clayton     Options *
82*13d21e9aSBruce Mitchener     GetOptions () override
8332e0a750SGreg Clayton     {
841deb7962SGreg Clayton         return &m_option_group;
8532e0a750SGreg Clayton     }
8632e0a750SGreg Clayton 
87385aa28cSGreg Clayton     bool
88385aa28cSGreg Clayton     DumpRegister (const ExecutionContext &exe_ctx,
89385aa28cSGreg Clayton                   Stream &strm,
90385aa28cSGreg Clayton                   RegisterContext *reg_ctx,
91385aa28cSGreg Clayton                   const RegisterInfo *reg_info)
92385aa28cSGreg Clayton     {
93385aa28cSGreg Clayton         if (reg_info)
94385aa28cSGreg Clayton         {
957349bd90SGreg Clayton             RegisterValue reg_value;
96385aa28cSGreg Clayton 
977349bd90SGreg Clayton             if (reg_ctx->ReadRegister (reg_info, reg_value))
98385aa28cSGreg Clayton             {
99385aa28cSGreg Clayton                 strm.Indent ();
100385aa28cSGreg Clayton 
1019076c0ffSSean Callanan                 bool prefix_with_altname = (bool)m_command_options.alternate_name;
1029a8fa916SGreg Clayton                 bool prefix_with_name = !prefix_with_altname;
103c4392d2aSJohnny Chen                 reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
1041ac04c30SGreg Clayton                 if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
1051ac04c30SGreg Clayton                 {
1061ac04c30SGreg Clayton                     Process *process = exe_ctx.GetProcessPtr();
1071ac04c30SGreg Clayton                     if (process && reg_info->byte_size == process->GetAddressByteSize())
108385aa28cSGreg Clayton                     {
1097349bd90SGreg Clayton                         addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
1107349bd90SGreg Clayton                         if (reg_addr != LLDB_INVALID_ADDRESS)
111385aa28cSGreg Clayton                         {
112385aa28cSGreg Clayton                             Address so_reg_addr;
113c14ee32dSGreg Clayton                             if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
114385aa28cSGreg Clayton                             {
115385aa28cSGreg Clayton                                 strm.PutCString ("  ");
116385aa28cSGreg Clayton                                 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
117385aa28cSGreg Clayton                             }
118385aa28cSGreg Clayton                         }
119385aa28cSGreg Clayton                     }
1201ac04c30SGreg Clayton                 }
121385aa28cSGreg Clayton                 strm.EOL();
122385aa28cSGreg Clayton                 return true;
123385aa28cSGreg Clayton             }
124385aa28cSGreg Clayton         }
125385aa28cSGreg Clayton         return false;
126385aa28cSGreg Clayton     }
127385aa28cSGreg Clayton 
128385aa28cSGreg Clayton     bool
129385aa28cSGreg Clayton     DumpRegisterSet (const ExecutionContext &exe_ctx,
130385aa28cSGreg Clayton                      Stream &strm,
131385aa28cSGreg Clayton                      RegisterContext *reg_ctx,
132c7bece56SGreg Clayton                      size_t set_idx,
1336d4d4f7dSJohnny Chen                      bool primitive_only=false)
134385aa28cSGreg Clayton     {
135385aa28cSGreg Clayton         uint32_t unavailable_count = 0;
136385aa28cSGreg Clayton         uint32_t available_count = 0;
1374f5f39acSAshok Thirumurthi 
1384f5f39acSAshok Thirumurthi         if (!reg_ctx)
1394f5f39acSAshok Thirumurthi             return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)
1404f5f39acSAshok Thirumurthi 
141385aa28cSGreg Clayton         const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
142385aa28cSGreg Clayton         if (reg_set)
143385aa28cSGreg Clayton         {
144c3c95b22SColin Riley             strm.Printf ("%s:\n", (reg_set->name ? reg_set->name : "unknown") );
145385aa28cSGreg Clayton             strm.IndentMore ();
146c7bece56SGreg Clayton             const size_t num_registers = reg_set->num_registers;
147c7bece56SGreg Clayton             for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
148385aa28cSGreg Clayton             {
149385aa28cSGreg Clayton                 const uint32_t reg = reg_set->registers[reg_idx];
1506d4d4f7dSJohnny Chen                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
1516d4d4f7dSJohnny Chen                 // Skip the dumping of derived register if primitive_only is true.
1526d4d4f7dSJohnny Chen                 if (primitive_only && reg_info && reg_info->value_regs)
1536d4d4f7dSJohnny Chen                     continue;
1544f5f39acSAshok Thirumurthi 
1556d4d4f7dSJohnny Chen                 if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
156385aa28cSGreg Clayton                     ++available_count;
157385aa28cSGreg Clayton                 else
158385aa28cSGreg Clayton                     ++unavailable_count;
159385aa28cSGreg Clayton             }
160385aa28cSGreg Clayton             strm.IndentLess ();
161385aa28cSGreg Clayton             if (unavailable_count)
162385aa28cSGreg Clayton             {
163385aa28cSGreg Clayton                 strm.Indent ();
164385aa28cSGreg Clayton                 strm.Printf("%u registers were unavailable.\n", unavailable_count);
165385aa28cSGreg Clayton             }
166385aa28cSGreg Clayton             strm.EOL();
167385aa28cSGreg Clayton         }
168385aa28cSGreg Clayton         return available_count > 0;
169385aa28cSGreg Clayton     }
170385aa28cSGreg Clayton 
1715a988416SJim Ingham protected:
172*13d21e9aSBruce Mitchener     bool
173*13d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
17430fdc8d8SChris Lattner     {
175385aa28cSGreg Clayton         Stream &strm = result.GetOutputStream();
176f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
17730fdc8d8SChris Lattner 
17830fdc8d8SChris Lattner         const RegisterInfo *reg_info = NULL;
17930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
18030fdc8d8SChris Lattner         {
181c7bece56SGreg Clayton             size_t set_idx;
182385aa28cSGreg Clayton 
183c7bece56SGreg Clayton             size_t num_register_sets = 1;
184c7bece56SGreg Clayton             const size_t set_array_size = m_command_options.set_indexes.GetSize();
185385aa28cSGreg Clayton             if (set_array_size > 0)
18630fdc8d8SChris Lattner             {
187c7bece56SGreg Clayton                 for (size_t i=0; i<set_array_size; ++i)
18830fdc8d8SChris Lattner                 {
1891deb7962SGreg Clayton                     set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
1904f5f39acSAshok Thirumurthi                     if (set_idx < reg_ctx->GetRegisterSetCount())
19130fdc8d8SChris Lattner                     {
192f9fc609fSGreg Clayton                         if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
193385aa28cSGreg Clayton                         {
1944f5f39acSAshok Thirumurthi                             if (errno)
195789cefb8SSylvestre Ledru                                 result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
1964f5f39acSAshok Thirumurthi                             else
1974f5f39acSAshok Thirumurthi                                 result.AppendError ("unknown error while reading registers.\n");
198385aa28cSGreg Clayton                             result.SetStatus (eReturnStatusFailed);
199385aa28cSGreg Clayton                             break;
200385aa28cSGreg Clayton                         }
20130fdc8d8SChris Lattner                     }
20230fdc8d8SChris Lattner                     else
20330fdc8d8SChris Lattner                     {
20499fbc076SDeepak Panickal                         result.AppendErrorWithFormat("invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
205385aa28cSGreg Clayton                         result.SetStatus (eReturnStatusFailed);
206385aa28cSGreg Clayton                         break;
20730fdc8d8SChris Lattner                     }
20830fdc8d8SChris Lattner                 }
209385aa28cSGreg Clayton             }
210385aa28cSGreg Clayton             else
21130fdc8d8SChris Lattner             {
2121deb7962SGreg Clayton                 if (m_command_options.dump_all_sets)
213385aa28cSGreg Clayton                     num_register_sets = reg_ctx->GetRegisterSetCount();
214385aa28cSGreg Clayton 
215385aa28cSGreg Clayton                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
216385aa28cSGreg Clayton                 {
2176d4d4f7dSJohnny Chen                     // When dump_all_sets option is set, dump primitive as well as derived registers.
218f9fc609fSGreg Clayton                     DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
21930fdc8d8SChris Lattner                 }
22030fdc8d8SChris Lattner             }
22130fdc8d8SChris Lattner         }
22230fdc8d8SChris Lattner         else
22330fdc8d8SChris Lattner         {
2241deb7962SGreg Clayton             if (m_command_options.dump_all_sets)
225385aa28cSGreg Clayton             {
226385aa28cSGreg Clayton                 result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
227385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
228385aa28cSGreg Clayton             }
2291deb7962SGreg Clayton             else if (m_command_options.set_indexes.GetSize() > 0)
230385aa28cSGreg Clayton             {
231385aa28cSGreg Clayton                 result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
232385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
233385aa28cSGreg Clayton             }
234385aa28cSGreg Clayton             else
235385aa28cSGreg Clayton             {
23630fdc8d8SChris Lattner                 const char *arg_cstr;
23730fdc8d8SChris Lattner                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
23830fdc8d8SChris Lattner                 {
2392f59302cSEnrico Granata                     // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
2402f59302cSEnrico Granata                     // reject it and non-existant. we should be more consistent towards the user and allow them
2412f59302cSEnrico Granata                     // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
2422f59302cSEnrico Granata                     // to call our registers $rbx in our own API
2432f59302cSEnrico Granata                     if (*arg_cstr == '$')
2442f59302cSEnrico Granata                         arg_cstr = arg_cstr+1;
245385aa28cSGreg Clayton                     reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
24630fdc8d8SChris Lattner 
24730fdc8d8SChris Lattner                     if (reg_info)
24830fdc8d8SChris Lattner                     {
249f9fc609fSGreg Clayton                         if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
250385aa28cSGreg Clayton                             strm.Printf("%-12s = error: unavailable\n", reg_info->name);
25130fdc8d8SChris Lattner                     }
25230fdc8d8SChris Lattner                     else
25330fdc8d8SChris Lattner                     {
25430fdc8d8SChris Lattner                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
25530fdc8d8SChris Lattner                     }
25630fdc8d8SChris Lattner                 }
25730fdc8d8SChris Lattner             }
25830fdc8d8SChris Lattner         }
25930fdc8d8SChris Lattner         return result.Succeeded();
26030fdc8d8SChris Lattner     }
26132e0a750SGreg Clayton 
2621deb7962SGreg Clayton     class CommandOptions : public OptionGroup
26332e0a750SGreg Clayton     {
26432e0a750SGreg Clayton     public:
2651deb7962SGreg Clayton         CommandOptions () :
2661deb7962SGreg Clayton             OptionGroup(),
267385aa28cSGreg Clayton             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
2689a8fa916SGreg Clayton             dump_all_sets (false, false), // Initial and default values are false
2699a8fa916SGreg Clayton             alternate_name (false, false)
27032e0a750SGreg Clayton         {
27132e0a750SGreg Clayton         }
27232e0a750SGreg Clayton 
273*13d21e9aSBruce Mitchener         ~CommandOptions () override
27432e0a750SGreg Clayton         {
27532e0a750SGreg Clayton         }
27632e0a750SGreg Clayton 
2771deb7962SGreg Clayton 
278*13d21e9aSBruce Mitchener         uint32_t
279*13d21e9aSBruce Mitchener         GetNumDefinitions () override;
2801deb7962SGreg Clayton 
281*13d21e9aSBruce Mitchener         const OptionDefinition*
282*13d21e9aSBruce Mitchener         GetDefinitions () override
2831deb7962SGreg Clayton         {
2841deb7962SGreg Clayton             return g_option_table;
2851deb7962SGreg Clayton         }
2861deb7962SGreg Clayton 
287*13d21e9aSBruce Mitchener         void
288*13d21e9aSBruce Mitchener         OptionParsingStarting (CommandInterpreter &interpreter) override
2891deb7962SGreg Clayton         {
2901deb7962SGreg Clayton             set_indexes.Clear();
2911deb7962SGreg Clayton             dump_all_sets.Clear();
2921deb7962SGreg Clayton             alternate_name.Clear();
2931deb7962SGreg Clayton         }
2941deb7962SGreg Clayton 
295*13d21e9aSBruce Mitchener         Error
2961deb7962SGreg Clayton         SetOptionValue (CommandInterpreter &interpreter,
2971deb7962SGreg Clayton                         uint32_t option_idx,
298*13d21e9aSBruce Mitchener                         const char *option_value) override
29932e0a750SGreg Clayton         {
30032e0a750SGreg Clayton             Error error;
3013bcdfc0eSGreg Clayton             const int short_option = g_option_table[option_idx].short_option;
30232e0a750SGreg Clayton             switch (short_option)
30332e0a750SGreg Clayton             {
304385aa28cSGreg Clayton                 case 's':
305385aa28cSGreg Clayton                     {
3061deb7962SGreg Clayton                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
307385aa28cSGreg Clayton                         if (value_sp)
308385aa28cSGreg Clayton                             set_indexes.AppendValue (value_sp);
309385aa28cSGreg Clayton                     }
310385aa28cSGreg Clayton                     break;
311385aa28cSGreg Clayton 
312385aa28cSGreg Clayton                 case 'a':
3139a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3149a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3159a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
316385aa28cSGreg Clayton                     dump_all_sets.SetCurrentValue (true);
3179a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
3189a8fa916SGreg Clayton                     break;
3199a8fa916SGreg Clayton 
3209a8fa916SGreg Clayton                 case 'A':
3219a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3229a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3239a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
3249a8fa916SGreg Clayton                     alternate_name.SetCurrentValue (true);
3259a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
326385aa28cSGreg Clayton                     break;
327385aa28cSGreg Clayton 
32832e0a750SGreg Clayton                 default:
32986edbf41SGreg Clayton                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
33032e0a750SGreg Clayton                     break;
33132e0a750SGreg Clayton             }
33232e0a750SGreg Clayton             return error;
33332e0a750SGreg Clayton         }
33432e0a750SGreg Clayton 
33532e0a750SGreg Clayton         // Options table: Required for subclasses of Options.
33632e0a750SGreg Clayton 
3371deb7962SGreg Clayton         static const OptionDefinition g_option_table[];
33832e0a750SGreg Clayton 
33932e0a750SGreg Clayton         // Instance variables to hold the values for command options.
340385aa28cSGreg Clayton         OptionValueArray set_indexes;
341385aa28cSGreg Clayton         OptionValueBoolean dump_all_sets;
3429a8fa916SGreg Clayton         OptionValueBoolean alternate_name;
34330fdc8d8SChris Lattner     };
34430fdc8d8SChris Lattner 
3451deb7962SGreg Clayton     OptionGroupOptions m_option_group;
3461deb7962SGreg Clayton     OptionGroupFormat m_format_options;
3471deb7962SGreg Clayton     CommandOptions m_command_options;
34832e0a750SGreg Clayton };
34932e0a750SGreg Clayton 
3503d0fcf5eSJohnny Chen const OptionDefinition
35132e0a750SGreg Clayton CommandObjectRegisterRead::CommandOptions::g_option_table[] =
35232e0a750SGreg Clayton {
353d37221dcSZachary Turner     { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
354d37221dcSZachary Turner     { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
355d37221dcSZachary Turner     { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone      , "Show all register sets."},
35632e0a750SGreg Clayton };
35732e0a750SGreg Clayton 
3581deb7962SGreg Clayton uint32_t
3591deb7962SGreg Clayton CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
3601deb7962SGreg Clayton {
36128606954SSaleem Abdulrasool     return llvm::array_lengthof(g_option_table);
3621deb7962SGreg Clayton }
36332e0a750SGreg Clayton 
36430fdc8d8SChris Lattner 
36530fdc8d8SChris Lattner //----------------------------------------------------------------------
36630fdc8d8SChris Lattner // "register write"
36730fdc8d8SChris Lattner //----------------------------------------------------------------------
3685a988416SJim Ingham class CommandObjectRegisterWrite : public CommandObjectParsed
36930fdc8d8SChris Lattner {
37030fdc8d8SChris Lattner public:
371a7015092SGreg Clayton     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
3725a988416SJim Ingham         CommandObjectParsed (interpreter,
373a7015092SGreg Clayton                              "register write",
37430fdc8d8SChris Lattner                              "Modify a single register value.",
375405fe67fSCaroline Tice                              NULL,
376e87764f2SEnrico Granata                              eCommandRequiresFrame         |
377e87764f2SEnrico Granata                              eCommandRequiresRegContext    |
378e87764f2SEnrico Granata                              eCommandProcessMustBeLaunched |
379e87764f2SEnrico Granata                              eCommandProcessMustBePaused)
38030fdc8d8SChris Lattner     {
381405fe67fSCaroline Tice         CommandArgumentEntry arg1;
382405fe67fSCaroline Tice         CommandArgumentEntry arg2;
383405fe67fSCaroline Tice         CommandArgumentData register_arg;
384405fe67fSCaroline Tice         CommandArgumentData value_arg;
385405fe67fSCaroline Tice 
386405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
387405fe67fSCaroline Tice         register_arg.arg_type = eArgTypeRegisterName;
388405fe67fSCaroline Tice         register_arg.arg_repetition = eArgRepeatPlain;
389405fe67fSCaroline Tice 
390405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
391405fe67fSCaroline Tice         arg1.push_back (register_arg);
392405fe67fSCaroline Tice 
393405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
394405fe67fSCaroline Tice         value_arg.arg_type = eArgTypeValue;
395405fe67fSCaroline Tice         value_arg.arg_repetition = eArgRepeatPlain;
396405fe67fSCaroline Tice 
397405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
398405fe67fSCaroline Tice         arg2.push_back (value_arg);
399405fe67fSCaroline Tice 
400405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
401405fe67fSCaroline Tice         m_arguments.push_back (arg1);
402405fe67fSCaroline Tice         m_arguments.push_back (arg2);
40330fdc8d8SChris Lattner     }
40430fdc8d8SChris Lattner 
405*13d21e9aSBruce Mitchener     ~CommandObjectRegisterWrite () override
40630fdc8d8SChris Lattner     {
40730fdc8d8SChris Lattner     }
40830fdc8d8SChris Lattner 
4095a988416SJim Ingham protected:
410*13d21e9aSBruce Mitchener     bool
411*13d21e9aSBruce Mitchener     DoExecute(Args& command, CommandReturnObject &result) override
41230fdc8d8SChris Lattner     {
41330fdc8d8SChris Lattner         DataExtractor reg_data;
414f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
41530fdc8d8SChris Lattner 
41630fdc8d8SChris Lattner         if (command.GetArgumentCount() != 2)
41730fdc8d8SChris Lattner         {
41830fdc8d8SChris Lattner             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
41930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42030fdc8d8SChris Lattner         }
42130fdc8d8SChris Lattner         else
42230fdc8d8SChris Lattner         {
42330fdc8d8SChris Lattner             const char *reg_name = command.GetArgumentAtIndex(0);
42430fdc8d8SChris Lattner             const char *value_str = command.GetArgumentAtIndex(1);
4252f59302cSEnrico Granata 
4262f59302cSEnrico Granata 
4272f59302cSEnrico Granata             // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
4282f59302cSEnrico Granata             // reject it and non-existant. we should be more consistent towards the user and allow them
4292f59302cSEnrico Granata             // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
4302f59302cSEnrico Granata             // to call our registers $rbx in our own API
4312f59302cSEnrico Granata             if (reg_name && *reg_name == '$')
4322f59302cSEnrico Granata                 reg_name = reg_name+1;
4332f59302cSEnrico Granata 
434385aa28cSGreg Clayton             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
43530fdc8d8SChris Lattner 
43630fdc8d8SChris Lattner             if (reg_info)
43730fdc8d8SChris Lattner             {
4387349bd90SGreg Clayton                 RegisterValue reg_value;
4397349bd90SGreg Clayton 
4407349bd90SGreg Clayton                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
44130fdc8d8SChris Lattner                 if (error.Success())
44230fdc8d8SChris Lattner                 {
4437349bd90SGreg Clayton                     if (reg_ctx->WriteRegister (reg_info, reg_value))
44430fdc8d8SChris Lattner                     {
445fa559e5cSGreg Clayton                         // Toss all frames and anything else in the thread
446fa559e5cSGreg Clayton                         // after a register has been written.
447f9fc609fSGreg Clayton                         m_exe_ctx.GetThreadRef().Flush();
44830fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
44930fdc8d8SChris Lattner                         return true;
45030fdc8d8SChris Lattner                     }
45130fdc8d8SChris Lattner                 }
452b1ad65c5SJason Molenda                 if (error.AsCString())
45330fdc8d8SChris Lattner                 {
45430fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
45530fdc8d8SChris Lattner                                                  reg_name,
45630fdc8d8SChris Lattner                                                  value_str,
45730fdc8d8SChris Lattner                                                  error.AsCString());
45830fdc8d8SChris Lattner                 }
459b1ad65c5SJason Molenda                 else
460b1ad65c5SJason Molenda                 {
461b1ad65c5SJason Molenda                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
462b1ad65c5SJason Molenda                                                  reg_name,
463b1ad65c5SJason Molenda                                                  value_str);
464b1ad65c5SJason Molenda                 }
465b1ad65c5SJason Molenda                 result.SetStatus (eReturnStatusFailed);
46630fdc8d8SChris Lattner             }
46730fdc8d8SChris Lattner             else
46830fdc8d8SChris Lattner             {
46930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
47030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
47130fdc8d8SChris Lattner             }
47230fdc8d8SChris Lattner         }
47330fdc8d8SChris Lattner         return result.Succeeded();
47430fdc8d8SChris Lattner     }
47530fdc8d8SChris Lattner };
47630fdc8d8SChris Lattner 
47730fdc8d8SChris Lattner 
47830fdc8d8SChris Lattner //----------------------------------------------------------------------
47930fdc8d8SChris Lattner // CommandObjectRegister constructor
48030fdc8d8SChris Lattner //----------------------------------------------------------------------
4816611103cSGreg Clayton CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
482a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
483a7015092SGreg Clayton                             "register",
4843f4c09c1SCaroline Tice                             "A set of commands to access thread registers.",
48530fdc8d8SChris Lattner                             "register [read|write] ...")
48630fdc8d8SChris Lattner {
487a7015092SGreg Clayton     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
488a7015092SGreg Clayton     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
48930fdc8d8SChris Lattner }
49030fdc8d8SChris Lattner 
49130fdc8d8SChris Lattner 
49230fdc8d8SChris Lattner //----------------------------------------------------------------------
49330fdc8d8SChris Lattner // Destructor
49430fdc8d8SChris Lattner //----------------------------------------------------------------------
49530fdc8d8SChris Lattner CommandObjectRegister::~CommandObjectRegister()
49630fdc8d8SChris Lattner {
49730fdc8d8SChris Lattner }
498