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 // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
13*49bcfd80SEugene Zelenko #include "llvm/ADT/STLExtras.h"
14*49bcfd80SEugene Zelenko 
1530fdc8d8SChris Lattner // Project includes
16*49bcfd80SEugene Zelenko #include "CommandObjectRegister.h"
1730fdc8d8SChris Lattner #include "lldb/Core/DataExtractor.h"
187349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h"
1930fdc8d8SChris Lattner #include "lldb/Core/Scalar.h"
206611103cSGreg Clayton #include "lldb/Core/Debugger.h"
216611103cSGreg Clayton #include "lldb/Interpreter/Args.h"
226611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
2330fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
24eb0103f2SGreg Clayton #include "lldb/Interpreter/Options.h"
251deb7962SGreg Clayton #include "lldb/Interpreter/OptionGroupFormat.h"
2667cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h"
2732abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
2867cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h"
2930fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
308f7770f8SGreg Clayton #include "lldb/Target/Process.h"
3130fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
32d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h"
338f7770f8SGreg Clayton #include "lldb/Target/Thread.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.",
48*49bcfd80SEugene Zelenko                             nullptr,
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();
7430fdc8d8SChris Lattner     }
7530fdc8d8SChris Lattner 
76*49bcfd80SEugene Zelenko     ~CommandObjectRegisterRead() override = default;
7730fdc8d8SChris Lattner 
7832e0a750SGreg Clayton     Options *
7913d21e9aSBruce Mitchener     GetOptions () override
8032e0a750SGreg Clayton     {
811deb7962SGreg Clayton         return &m_option_group;
8232e0a750SGreg Clayton     }
8332e0a750SGreg Clayton 
84385aa28cSGreg Clayton     bool
85385aa28cSGreg Clayton     DumpRegister (const ExecutionContext &exe_ctx,
86385aa28cSGreg Clayton                   Stream &strm,
87385aa28cSGreg Clayton                   RegisterContext *reg_ctx,
88385aa28cSGreg Clayton                   const RegisterInfo *reg_info)
89385aa28cSGreg Clayton     {
90385aa28cSGreg Clayton         if (reg_info)
91385aa28cSGreg Clayton         {
927349bd90SGreg Clayton             RegisterValue reg_value;
93385aa28cSGreg Clayton 
947349bd90SGreg Clayton             if (reg_ctx->ReadRegister (reg_info, reg_value))
95385aa28cSGreg Clayton             {
96385aa28cSGreg Clayton                 strm.Indent ();
97385aa28cSGreg Clayton 
989076c0ffSSean Callanan                 bool prefix_with_altname = (bool)m_command_options.alternate_name;
999a8fa916SGreg Clayton                 bool prefix_with_name = !prefix_with_altname;
100c4392d2aSJohnny Chen                 reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
1011ac04c30SGreg Clayton                 if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
1021ac04c30SGreg Clayton                 {
1031ac04c30SGreg Clayton                     Process *process = exe_ctx.GetProcessPtr();
1041ac04c30SGreg Clayton                     if (process && reg_info->byte_size == process->GetAddressByteSize())
105385aa28cSGreg Clayton                     {
1067349bd90SGreg Clayton                         addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
1077349bd90SGreg Clayton                         if (reg_addr != LLDB_INVALID_ADDRESS)
108385aa28cSGreg Clayton                         {
109385aa28cSGreg Clayton                             Address so_reg_addr;
110c14ee32dSGreg Clayton                             if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
111385aa28cSGreg Clayton                             {
112385aa28cSGreg Clayton                                 strm.PutCString ("  ");
113385aa28cSGreg Clayton                                 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
114385aa28cSGreg Clayton                             }
115385aa28cSGreg Clayton                         }
116385aa28cSGreg Clayton                     }
1171ac04c30SGreg Clayton                 }
118385aa28cSGreg Clayton                 strm.EOL();
119385aa28cSGreg Clayton                 return true;
120385aa28cSGreg Clayton             }
121385aa28cSGreg Clayton         }
122385aa28cSGreg Clayton         return false;
123385aa28cSGreg Clayton     }
124385aa28cSGreg Clayton 
125385aa28cSGreg Clayton     bool
126385aa28cSGreg Clayton     DumpRegisterSet (const ExecutionContext &exe_ctx,
127385aa28cSGreg Clayton                      Stream &strm,
128385aa28cSGreg Clayton                      RegisterContext *reg_ctx,
129c7bece56SGreg Clayton                      size_t set_idx,
1306d4d4f7dSJohnny Chen                      bool primitive_only=false)
131385aa28cSGreg Clayton     {
132385aa28cSGreg Clayton         uint32_t unavailable_count = 0;
133385aa28cSGreg Clayton         uint32_t available_count = 0;
1344f5f39acSAshok Thirumurthi 
1354f5f39acSAshok Thirumurthi         if (!reg_ctx)
1364f5f39acSAshok Thirumurthi             return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)
1374f5f39acSAshok Thirumurthi 
138385aa28cSGreg Clayton         const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
139385aa28cSGreg Clayton         if (reg_set)
140385aa28cSGreg Clayton         {
141c3c95b22SColin Riley             strm.Printf ("%s:\n", (reg_set->name ? reg_set->name : "unknown") );
142385aa28cSGreg Clayton             strm.IndentMore ();
143c7bece56SGreg Clayton             const size_t num_registers = reg_set->num_registers;
144c7bece56SGreg Clayton             for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
145385aa28cSGreg Clayton             {
146385aa28cSGreg Clayton                 const uint32_t reg = reg_set->registers[reg_idx];
1476d4d4f7dSJohnny Chen                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
1486d4d4f7dSJohnny Chen                 // Skip the dumping of derived register if primitive_only is true.
1496d4d4f7dSJohnny Chen                 if (primitive_only && reg_info && reg_info->value_regs)
1506d4d4f7dSJohnny Chen                     continue;
1514f5f39acSAshok Thirumurthi 
1526d4d4f7dSJohnny Chen                 if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
153385aa28cSGreg Clayton                     ++available_count;
154385aa28cSGreg Clayton                 else
155385aa28cSGreg Clayton                     ++unavailable_count;
156385aa28cSGreg Clayton             }
157385aa28cSGreg Clayton             strm.IndentLess ();
158385aa28cSGreg Clayton             if (unavailable_count)
159385aa28cSGreg Clayton             {
160385aa28cSGreg Clayton                 strm.Indent ();
161385aa28cSGreg Clayton                 strm.Printf("%u registers were unavailable.\n", unavailable_count);
162385aa28cSGreg Clayton             }
163385aa28cSGreg Clayton             strm.EOL();
164385aa28cSGreg Clayton         }
165385aa28cSGreg Clayton         return available_count > 0;
166385aa28cSGreg Clayton     }
167385aa28cSGreg Clayton 
1685a988416SJim Ingham protected:
16913d21e9aSBruce Mitchener     bool
17013d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
17130fdc8d8SChris Lattner     {
172385aa28cSGreg Clayton         Stream &strm = result.GetOutputStream();
173f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
17430fdc8d8SChris Lattner 
175*49bcfd80SEugene Zelenko         const RegisterInfo *reg_info = nullptr;
17630fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
17730fdc8d8SChris Lattner         {
178c7bece56SGreg Clayton             size_t set_idx;
179385aa28cSGreg Clayton 
180c7bece56SGreg Clayton             size_t num_register_sets = 1;
181c7bece56SGreg Clayton             const size_t set_array_size = m_command_options.set_indexes.GetSize();
182385aa28cSGreg Clayton             if (set_array_size > 0)
18330fdc8d8SChris Lattner             {
184c7bece56SGreg Clayton                 for (size_t i = 0; i < set_array_size; ++i)
18530fdc8d8SChris Lattner                 {
186*49bcfd80SEugene Zelenko                     set_idx = m_command_options.set_indexes[i]->GetUInt64Value(UINT32_MAX, nullptr);
1874f5f39acSAshok Thirumurthi                     if (set_idx < reg_ctx->GetRegisterSetCount())
18830fdc8d8SChris Lattner                     {
189f9fc609fSGreg Clayton                         if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
190385aa28cSGreg Clayton                         {
1914f5f39acSAshok Thirumurthi                             if (errno)
192789cefb8SSylvestre Ledru                                 result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
1934f5f39acSAshok Thirumurthi                             else
1944f5f39acSAshok Thirumurthi                                 result.AppendError ("unknown error while reading registers.\n");
195385aa28cSGreg Clayton                             result.SetStatus (eReturnStatusFailed);
196385aa28cSGreg Clayton                             break;
197385aa28cSGreg Clayton                         }
19830fdc8d8SChris Lattner                     }
19930fdc8d8SChris Lattner                     else
20030fdc8d8SChris Lattner                     {
20199fbc076SDeepak Panickal                         result.AppendErrorWithFormat("invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
202385aa28cSGreg Clayton                         result.SetStatus (eReturnStatusFailed);
203385aa28cSGreg Clayton                         break;
20430fdc8d8SChris Lattner                     }
20530fdc8d8SChris Lattner                 }
206385aa28cSGreg Clayton             }
207385aa28cSGreg Clayton             else
20830fdc8d8SChris Lattner             {
2091deb7962SGreg Clayton                 if (m_command_options.dump_all_sets)
210385aa28cSGreg Clayton                     num_register_sets = reg_ctx->GetRegisterSetCount();
211385aa28cSGreg Clayton 
212385aa28cSGreg Clayton                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
213385aa28cSGreg Clayton                 {
2146d4d4f7dSJohnny Chen                     // When dump_all_sets option is set, dump primitive as well as derived registers.
215f9fc609fSGreg Clayton                     DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
21630fdc8d8SChris Lattner                 }
21730fdc8d8SChris Lattner             }
21830fdc8d8SChris Lattner         }
21930fdc8d8SChris Lattner         else
22030fdc8d8SChris Lattner         {
2211deb7962SGreg Clayton             if (m_command_options.dump_all_sets)
222385aa28cSGreg Clayton             {
223385aa28cSGreg Clayton                 result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
224385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
225385aa28cSGreg Clayton             }
2261deb7962SGreg Clayton             else if (m_command_options.set_indexes.GetSize() > 0)
227385aa28cSGreg Clayton             {
228385aa28cSGreg Clayton                 result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
229385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
230385aa28cSGreg Clayton             }
231385aa28cSGreg Clayton             else
232385aa28cSGreg Clayton             {
23330fdc8d8SChris Lattner                 const char *arg_cstr;
234*49bcfd80SEugene Zelenko                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; ++arg_idx)
23530fdc8d8SChris Lattner                 {
2362f59302cSEnrico Granata                     // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
2372f59302cSEnrico Granata                     // reject it and non-existant. we should be more consistent towards the user and allow them
2382f59302cSEnrico Granata                     // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
2392f59302cSEnrico Granata                     // to call our registers $rbx in our own API
2402f59302cSEnrico Granata                     if (*arg_cstr == '$')
2412f59302cSEnrico Granata                         arg_cstr = arg_cstr+1;
242385aa28cSGreg Clayton                     reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
24330fdc8d8SChris Lattner 
24430fdc8d8SChris Lattner                     if (reg_info)
24530fdc8d8SChris Lattner                     {
246f9fc609fSGreg Clayton                         if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
247385aa28cSGreg Clayton                             strm.Printf("%-12s = error: unavailable\n", reg_info->name);
24830fdc8d8SChris Lattner                     }
24930fdc8d8SChris Lattner                     else
25030fdc8d8SChris Lattner                     {
25130fdc8d8SChris Lattner                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
25230fdc8d8SChris Lattner                     }
25330fdc8d8SChris Lattner                 }
25430fdc8d8SChris Lattner             }
25530fdc8d8SChris Lattner         }
25630fdc8d8SChris Lattner         return result.Succeeded();
25730fdc8d8SChris Lattner     }
25832e0a750SGreg Clayton 
2591deb7962SGreg Clayton     class CommandOptions : public OptionGroup
26032e0a750SGreg Clayton     {
26132e0a750SGreg Clayton     public:
2621deb7962SGreg Clayton         CommandOptions () :
2631deb7962SGreg Clayton             OptionGroup(),
264385aa28cSGreg Clayton             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
2659a8fa916SGreg Clayton             dump_all_sets (false, false), // Initial and default values are false
2669a8fa916SGreg Clayton             alternate_name (false, false)
26732e0a750SGreg Clayton         {
26832e0a750SGreg Clayton         }
26932e0a750SGreg Clayton 
270*49bcfd80SEugene Zelenko         ~CommandOptions() override = default;
2711deb7962SGreg Clayton 
27213d21e9aSBruce Mitchener         uint32_t
27313d21e9aSBruce Mitchener         GetNumDefinitions () override;
2741deb7962SGreg Clayton 
27513d21e9aSBruce Mitchener         const OptionDefinition*
27613d21e9aSBruce Mitchener         GetDefinitions () override
2771deb7962SGreg Clayton         {
2781deb7962SGreg Clayton             return g_option_table;
2791deb7962SGreg Clayton         }
2801deb7962SGreg Clayton 
28113d21e9aSBruce Mitchener         void
28213d21e9aSBruce Mitchener         OptionParsingStarting (CommandInterpreter &interpreter) override
2831deb7962SGreg Clayton         {
2841deb7962SGreg Clayton             set_indexes.Clear();
2851deb7962SGreg Clayton             dump_all_sets.Clear();
2861deb7962SGreg Clayton             alternate_name.Clear();
2871deb7962SGreg Clayton         }
2881deb7962SGreg Clayton 
28913d21e9aSBruce Mitchener         Error
2901deb7962SGreg Clayton         SetOptionValue (CommandInterpreter &interpreter,
2911deb7962SGreg Clayton                         uint32_t option_idx,
29213d21e9aSBruce Mitchener                         const char *option_value) override
29332e0a750SGreg Clayton         {
29432e0a750SGreg Clayton             Error error;
2953bcdfc0eSGreg Clayton             const int short_option = g_option_table[option_idx].short_option;
29632e0a750SGreg Clayton             switch (short_option)
29732e0a750SGreg Clayton             {
298385aa28cSGreg Clayton                 case 's':
299385aa28cSGreg Clayton                     {
3001deb7962SGreg Clayton                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
301385aa28cSGreg Clayton                         if (value_sp)
302385aa28cSGreg Clayton                             set_indexes.AppendValue (value_sp);
303385aa28cSGreg Clayton                     }
304385aa28cSGreg Clayton                     break;
305385aa28cSGreg Clayton 
306385aa28cSGreg Clayton                 case 'a':
3079a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3089a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3099a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
310385aa28cSGreg Clayton                     dump_all_sets.SetCurrentValue (true);
3119a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
3129a8fa916SGreg Clayton                     break;
3139a8fa916SGreg Clayton 
3149a8fa916SGreg Clayton                 case 'A':
3159a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3169a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3179a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
3189a8fa916SGreg Clayton                     alternate_name.SetCurrentValue (true);
3199a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
320385aa28cSGreg Clayton                     break;
321385aa28cSGreg Clayton 
32232e0a750SGreg Clayton                 default:
32386edbf41SGreg Clayton                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
32432e0a750SGreg Clayton                     break;
32532e0a750SGreg Clayton             }
32632e0a750SGreg Clayton             return error;
32732e0a750SGreg Clayton         }
32832e0a750SGreg Clayton 
32932e0a750SGreg Clayton         // Options table: Required for subclasses of Options.
33032e0a750SGreg Clayton 
3311deb7962SGreg Clayton         static const OptionDefinition g_option_table[];
33232e0a750SGreg Clayton 
33332e0a750SGreg Clayton         // Instance variables to hold the values for command options.
334385aa28cSGreg Clayton         OptionValueArray set_indexes;
335385aa28cSGreg Clayton         OptionValueBoolean dump_all_sets;
3369a8fa916SGreg Clayton         OptionValueBoolean alternate_name;
33730fdc8d8SChris Lattner     };
33830fdc8d8SChris Lattner 
3391deb7962SGreg Clayton     OptionGroupOptions m_option_group;
3401deb7962SGreg Clayton     OptionGroupFormat m_format_options;
3411deb7962SGreg Clayton     CommandOptions m_command_options;
34232e0a750SGreg Clayton };
34332e0a750SGreg Clayton 
3443d0fcf5eSJohnny Chen const OptionDefinition
34532e0a750SGreg Clayton CommandObjectRegisterRead::CommandOptions::g_option_table[] =
34632e0a750SGreg Clayton {
347*49bcfd80SEugene Zelenko     { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument      , nullptr, nullptr, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
348*49bcfd80SEugene Zelenko     { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
349*49bcfd80SEugene Zelenko     { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , nullptr, nullptr, 0, eArgTypeNone      , "Show all register sets."},
35032e0a750SGreg Clayton };
35132e0a750SGreg Clayton 
3521deb7962SGreg Clayton uint32_t
3531deb7962SGreg Clayton CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
3541deb7962SGreg Clayton {
35528606954SSaleem Abdulrasool     return llvm::array_lengthof(g_option_table);
3561deb7962SGreg Clayton }
35732e0a750SGreg Clayton 
35830fdc8d8SChris Lattner //----------------------------------------------------------------------
35930fdc8d8SChris Lattner // "register write"
36030fdc8d8SChris Lattner //----------------------------------------------------------------------
3615a988416SJim Ingham class CommandObjectRegisterWrite : public CommandObjectParsed
36230fdc8d8SChris Lattner {
36330fdc8d8SChris Lattner public:
364a7015092SGreg Clayton     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
3655a988416SJim Ingham         CommandObjectParsed(interpreter,
366a7015092SGreg Clayton                             "register write",
36730fdc8d8SChris Lattner                             "Modify a single register value.",
368*49bcfd80SEugene Zelenko                             nullptr,
369e87764f2SEnrico Granata                             eCommandRequiresFrame         |
370e87764f2SEnrico Granata                             eCommandRequiresRegContext    |
371e87764f2SEnrico Granata                             eCommandProcessMustBeLaunched |
372e87764f2SEnrico Granata                             eCommandProcessMustBePaused)
37330fdc8d8SChris Lattner     {
374405fe67fSCaroline Tice         CommandArgumentEntry arg1;
375405fe67fSCaroline Tice         CommandArgumentEntry arg2;
376405fe67fSCaroline Tice         CommandArgumentData register_arg;
377405fe67fSCaroline Tice         CommandArgumentData value_arg;
378405fe67fSCaroline Tice 
379405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
380405fe67fSCaroline Tice         register_arg.arg_type = eArgTypeRegisterName;
381405fe67fSCaroline Tice         register_arg.arg_repetition = eArgRepeatPlain;
382405fe67fSCaroline Tice 
383405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
384405fe67fSCaroline Tice         arg1.push_back (register_arg);
385405fe67fSCaroline Tice 
386405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
387405fe67fSCaroline Tice         value_arg.arg_type = eArgTypeValue;
388405fe67fSCaroline Tice         value_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         arg2.push_back (value_arg);
392405fe67fSCaroline Tice 
393405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
394405fe67fSCaroline Tice         m_arguments.push_back (arg1);
395405fe67fSCaroline Tice         m_arguments.push_back (arg2);
39630fdc8d8SChris Lattner     }
39730fdc8d8SChris Lattner 
398*49bcfd80SEugene Zelenko     ~CommandObjectRegisterWrite() override = default;
39930fdc8d8SChris Lattner 
4005a988416SJim Ingham protected:
40113d21e9aSBruce Mitchener     bool
40213d21e9aSBruce Mitchener     DoExecute(Args& command, CommandReturnObject &result) override
40330fdc8d8SChris Lattner     {
40430fdc8d8SChris Lattner         DataExtractor reg_data;
405f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
40630fdc8d8SChris Lattner 
40730fdc8d8SChris Lattner         if (command.GetArgumentCount() != 2)
40830fdc8d8SChris Lattner         {
40930fdc8d8SChris Lattner             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
41030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
41130fdc8d8SChris Lattner         }
41230fdc8d8SChris Lattner         else
41330fdc8d8SChris Lattner         {
41430fdc8d8SChris Lattner             const char *reg_name = command.GetArgumentAtIndex(0);
41530fdc8d8SChris Lattner             const char *value_str = command.GetArgumentAtIndex(1);
4162f59302cSEnrico Granata 
4172f59302cSEnrico Granata             // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
4182f59302cSEnrico Granata             // reject it and non-existant. we should be more consistent towards the user and allow them
4192f59302cSEnrico Granata             // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
4202f59302cSEnrico Granata             // to call our registers $rbx in our own API
4212f59302cSEnrico Granata             if (reg_name && *reg_name == '$')
4222f59302cSEnrico Granata                 reg_name = reg_name+1;
4232f59302cSEnrico Granata 
424385aa28cSGreg Clayton             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
42530fdc8d8SChris Lattner 
42630fdc8d8SChris Lattner             if (reg_info)
42730fdc8d8SChris Lattner             {
4287349bd90SGreg Clayton                 RegisterValue reg_value;
4297349bd90SGreg Clayton 
4307349bd90SGreg Clayton                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
43130fdc8d8SChris Lattner                 if (error.Success())
43230fdc8d8SChris Lattner                 {
4337349bd90SGreg Clayton                     if (reg_ctx->WriteRegister (reg_info, reg_value))
43430fdc8d8SChris Lattner                     {
435fa559e5cSGreg Clayton                         // Toss all frames and anything else in the thread
436fa559e5cSGreg Clayton                         // after a register has been written.
437f9fc609fSGreg Clayton                         m_exe_ctx.GetThreadRef().Flush();
43830fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
43930fdc8d8SChris Lattner                         return true;
44030fdc8d8SChris Lattner                     }
44130fdc8d8SChris Lattner                 }
442b1ad65c5SJason Molenda                 if (error.AsCString())
44330fdc8d8SChris Lattner                 {
44430fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
44530fdc8d8SChris Lattner                                                  reg_name,
44630fdc8d8SChris Lattner                                                  value_str,
44730fdc8d8SChris Lattner                                                  error.AsCString());
44830fdc8d8SChris Lattner                 }
449b1ad65c5SJason Molenda                 else
450b1ad65c5SJason Molenda                 {
451b1ad65c5SJason Molenda                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
452b1ad65c5SJason Molenda                                                  reg_name,
453b1ad65c5SJason Molenda                                                  value_str);
454b1ad65c5SJason Molenda                 }
455b1ad65c5SJason Molenda                 result.SetStatus (eReturnStatusFailed);
45630fdc8d8SChris Lattner             }
45730fdc8d8SChris Lattner             else
45830fdc8d8SChris Lattner             {
45930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
46030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
46130fdc8d8SChris Lattner             }
46230fdc8d8SChris Lattner         }
46330fdc8d8SChris Lattner         return result.Succeeded();
46430fdc8d8SChris Lattner     }
46530fdc8d8SChris Lattner };
46630fdc8d8SChris Lattner 
46730fdc8d8SChris Lattner //----------------------------------------------------------------------
46830fdc8d8SChris Lattner // CommandObjectRegister constructor
46930fdc8d8SChris Lattner //----------------------------------------------------------------------
4706611103cSGreg Clayton CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
471a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
472a7015092SGreg Clayton                             "register",
4733f4c09c1SCaroline Tice                             "A set of commands to access thread registers.",
47430fdc8d8SChris Lattner                             "register [read|write] ...")
47530fdc8d8SChris Lattner {
476a7015092SGreg Clayton     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
477a7015092SGreg Clayton     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
47830fdc8d8SChris Lattner }
47930fdc8d8SChris Lattner 
480*49bcfd80SEugene Zelenko CommandObjectRegister::~CommandObjectRegister() = default;
481