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 
1093a64300SDaniel Malea #include "lldb/lldb-python.h"
1193a64300SDaniel Malea 
1230fdc8d8SChris Lattner #include "CommandObjectRegister.h"
1330fdc8d8SChris Lattner 
1430fdc8d8SChris Lattner // C Includes
1530fdc8d8SChris Lattner // C++ Includes
1630fdc8d8SChris Lattner // Other libraries and framework includes
1730fdc8d8SChris Lattner // Project includes
1830fdc8d8SChris Lattner #include "lldb/Core/DataExtractor.h"
197349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h"
2030fdc8d8SChris Lattner #include "lldb/Core/Scalar.h"
216611103cSGreg Clayton #include "lldb/Core/Debugger.h"
226611103cSGreg Clayton #include "lldb/Interpreter/Args.h"
236611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
2430fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
25eb0103f2SGreg Clayton #include "lldb/Interpreter/Options.h"
261deb7962SGreg Clayton #include "lldb/Interpreter/OptionGroupFormat.h"
2767cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h"
28*32abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
2967cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h"
3030fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
318f7770f8SGreg Clayton #include "lldb/Target/Process.h"
3230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
33d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h"
348f7770f8SGreg Clayton #include "lldb/Target/Thread.h"
3528606954SSaleem Abdulrasool #include "llvm/ADT/STLExtras.h"
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner using namespace lldb;
3830fdc8d8SChris Lattner using namespace lldb_private;
3930fdc8d8SChris Lattner 
4030fdc8d8SChris Lattner //----------------------------------------------------------------------
4130fdc8d8SChris Lattner // "register read"
4230fdc8d8SChris Lattner //----------------------------------------------------------------------
435a988416SJim Ingham class CommandObjectRegisterRead : public CommandObjectParsed
4430fdc8d8SChris Lattner {
4530fdc8d8SChris Lattner public:
46a7015092SGreg Clayton     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
475a988416SJim Ingham         CommandObjectParsed (interpreter,
48a7015092SGreg Clayton                              "register read",
49405fe67fSCaroline Tice                              "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
50405fe67fSCaroline Tice                              NULL,
51f9fc609fSGreg Clayton                              eFlagRequiresFrame         |
52f9fc609fSGreg Clayton                              eFlagRequiresRegContext    |
53f9fc609fSGreg Clayton                              eFlagProcessMustBeLaunched |
54f9fc609fSGreg Clayton                              eFlagProcessMustBePaused   ),
551deb7962SGreg Clayton         m_option_group (interpreter),
561deb7962SGreg Clayton         m_format_options (eFormatDefault),
571deb7962SGreg Clayton         m_command_options ()
5830fdc8d8SChris Lattner     {
59405fe67fSCaroline Tice         CommandArgumentEntry arg;
60405fe67fSCaroline Tice         CommandArgumentData register_arg;
61405fe67fSCaroline Tice 
62405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
63405fe67fSCaroline Tice         register_arg.arg_type = eArgTypeRegisterName;
64405fe67fSCaroline Tice         register_arg.arg_repetition = eArgRepeatStar;
65405fe67fSCaroline Tice 
66405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
67405fe67fSCaroline Tice         arg.push_back (register_arg);
68405fe67fSCaroline Tice 
69405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
70405fe67fSCaroline Tice         m_arguments.push_back (arg);
711deb7962SGreg Clayton 
721deb7962SGreg Clayton         // Add the "--format"
735009f9d5SGreg Clayton         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
741deb7962SGreg Clayton         m_option_group.Append (&m_command_options);
751deb7962SGreg Clayton         m_option_group.Finalize();
761deb7962SGreg Clayton 
7730fdc8d8SChris Lattner     }
7830fdc8d8SChris Lattner 
7930fdc8d8SChris Lattner     virtual
8030fdc8d8SChris Lattner     ~CommandObjectRegisterRead ()
8130fdc8d8SChris Lattner     {
8230fdc8d8SChris Lattner     }
8330fdc8d8SChris Lattner 
8432e0a750SGreg Clayton     Options *
8532e0a750SGreg Clayton     GetOptions ()
8632e0a750SGreg Clayton     {
871deb7962SGreg Clayton         return &m_option_group;
8832e0a750SGreg Clayton     }
8932e0a750SGreg Clayton 
90385aa28cSGreg Clayton     bool
91385aa28cSGreg Clayton     DumpRegister (const ExecutionContext &exe_ctx,
92385aa28cSGreg Clayton                   Stream &strm,
93385aa28cSGreg Clayton                   RegisterContext *reg_ctx,
94385aa28cSGreg Clayton                   const RegisterInfo *reg_info)
95385aa28cSGreg Clayton     {
96385aa28cSGreg Clayton         if (reg_info)
97385aa28cSGreg Clayton         {
987349bd90SGreg Clayton             RegisterValue reg_value;
99385aa28cSGreg Clayton 
1007349bd90SGreg Clayton             if (reg_ctx->ReadRegister (reg_info, reg_value))
101385aa28cSGreg Clayton             {
102385aa28cSGreg Clayton                 strm.Indent ();
103385aa28cSGreg Clayton 
1049076c0ffSSean Callanan                 bool prefix_with_altname = (bool)m_command_options.alternate_name;
1059a8fa916SGreg Clayton                 bool prefix_with_name = !prefix_with_altname;
106c4392d2aSJohnny Chen                 reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
1071ac04c30SGreg Clayton                 if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
1081ac04c30SGreg Clayton                 {
1091ac04c30SGreg Clayton                     Process *process = exe_ctx.GetProcessPtr();
1101ac04c30SGreg Clayton                     if (process && reg_info->byte_size == process->GetAddressByteSize())
111385aa28cSGreg Clayton                     {
1127349bd90SGreg Clayton                         addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
1137349bd90SGreg Clayton                         if (reg_addr != LLDB_INVALID_ADDRESS)
114385aa28cSGreg Clayton                         {
115385aa28cSGreg Clayton                             Address so_reg_addr;
116c14ee32dSGreg Clayton                             if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
117385aa28cSGreg Clayton                             {
118385aa28cSGreg Clayton                                 strm.PutCString ("  ");
119385aa28cSGreg Clayton                                 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
120385aa28cSGreg Clayton                             }
121385aa28cSGreg Clayton                         }
122385aa28cSGreg Clayton                     }
1231ac04c30SGreg Clayton                 }
124385aa28cSGreg Clayton                 strm.EOL();
125385aa28cSGreg Clayton                 return true;
126385aa28cSGreg Clayton             }
127385aa28cSGreg Clayton         }
128385aa28cSGreg Clayton         return false;
129385aa28cSGreg Clayton     }
130385aa28cSGreg Clayton 
131385aa28cSGreg Clayton     bool
132385aa28cSGreg Clayton     DumpRegisterSet (const ExecutionContext &exe_ctx,
133385aa28cSGreg Clayton                      Stream &strm,
134385aa28cSGreg Clayton                      RegisterContext *reg_ctx,
135c7bece56SGreg Clayton                      size_t set_idx,
1366d4d4f7dSJohnny Chen                      bool primitive_only=false)
137385aa28cSGreg Clayton     {
138385aa28cSGreg Clayton         uint32_t unavailable_count = 0;
139385aa28cSGreg Clayton         uint32_t available_count = 0;
1404f5f39acSAshok Thirumurthi 
1414f5f39acSAshok Thirumurthi         if (!reg_ctx)
1424f5f39acSAshok Thirumurthi             return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)
1434f5f39acSAshok Thirumurthi 
144385aa28cSGreg Clayton         const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
145385aa28cSGreg Clayton         if (reg_set)
146385aa28cSGreg Clayton         {
147385aa28cSGreg Clayton             strm.Printf ("%s:\n", reg_set->name);
148385aa28cSGreg Clayton             strm.IndentMore ();
149c7bece56SGreg Clayton             const size_t num_registers = reg_set->num_registers;
150c7bece56SGreg Clayton             for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
151385aa28cSGreg Clayton             {
152385aa28cSGreg Clayton                 const uint32_t reg = reg_set->registers[reg_idx];
1536d4d4f7dSJohnny Chen                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
1546d4d4f7dSJohnny Chen                 // Skip the dumping of derived register if primitive_only is true.
1556d4d4f7dSJohnny Chen                 if (primitive_only && reg_info && reg_info->value_regs)
1566d4d4f7dSJohnny Chen                     continue;
1574f5f39acSAshok Thirumurthi 
1586d4d4f7dSJohnny Chen                 if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
159385aa28cSGreg Clayton                     ++available_count;
160385aa28cSGreg Clayton                 else
161385aa28cSGreg Clayton                     ++unavailable_count;
162385aa28cSGreg Clayton             }
163385aa28cSGreg Clayton             strm.IndentLess ();
164385aa28cSGreg Clayton             if (unavailable_count)
165385aa28cSGreg Clayton             {
166385aa28cSGreg Clayton                 strm.Indent ();
167385aa28cSGreg Clayton                 strm.Printf("%u registers were unavailable.\n", unavailable_count);
168385aa28cSGreg Clayton             }
169385aa28cSGreg Clayton             strm.EOL();
170385aa28cSGreg Clayton         }
171385aa28cSGreg Clayton         return available_count > 0;
172385aa28cSGreg Clayton     }
173385aa28cSGreg Clayton 
1745a988416SJim Ingham protected:
17530fdc8d8SChris Lattner     virtual bool
1765a988416SJim Ingham     DoExecute (Args& command, CommandReturnObject &result)
17730fdc8d8SChris Lattner     {
178385aa28cSGreg Clayton         Stream &strm = result.GetOutputStream();
179f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
18030fdc8d8SChris Lattner 
18130fdc8d8SChris Lattner         const RegisterInfo *reg_info = NULL;
18230fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
18330fdc8d8SChris Lattner         {
184c7bece56SGreg Clayton             size_t set_idx;
185385aa28cSGreg Clayton 
186c7bece56SGreg Clayton             size_t num_register_sets = 1;
187c7bece56SGreg Clayton             const size_t set_array_size = m_command_options.set_indexes.GetSize();
188385aa28cSGreg Clayton             if (set_array_size > 0)
18930fdc8d8SChris Lattner             {
190c7bece56SGreg Clayton                 for (size_t i=0; i<set_array_size; ++i)
19130fdc8d8SChris Lattner                 {
1921deb7962SGreg Clayton                     set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
1934f5f39acSAshok Thirumurthi                     if (set_idx < reg_ctx->GetRegisterSetCount())
19430fdc8d8SChris Lattner                     {
195f9fc609fSGreg Clayton                         if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
196385aa28cSGreg Clayton                         {
1974f5f39acSAshok Thirumurthi                             if (errno)
198789cefb8SSylvestre Ledru                                 result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
1994f5f39acSAshok Thirumurthi                             else
2004f5f39acSAshok Thirumurthi                                 result.AppendError ("unknown error while reading registers.\n");
201385aa28cSGreg Clayton                             result.SetStatus (eReturnStatusFailed);
202385aa28cSGreg Clayton                             break;
203385aa28cSGreg Clayton                         }
20430fdc8d8SChris Lattner                     }
20530fdc8d8SChris Lattner                     else
20630fdc8d8SChris Lattner                     {
20799fbc076SDeepak Panickal                         result.AppendErrorWithFormat("invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
208385aa28cSGreg Clayton                         result.SetStatus (eReturnStatusFailed);
209385aa28cSGreg Clayton                         break;
21030fdc8d8SChris Lattner                     }
21130fdc8d8SChris Lattner                 }
212385aa28cSGreg Clayton             }
213385aa28cSGreg Clayton             else
21430fdc8d8SChris Lattner             {
2151deb7962SGreg Clayton                 if (m_command_options.dump_all_sets)
216385aa28cSGreg Clayton                     num_register_sets = reg_ctx->GetRegisterSetCount();
217385aa28cSGreg Clayton 
218385aa28cSGreg Clayton                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
219385aa28cSGreg Clayton                 {
2206d4d4f7dSJohnny Chen                     // When dump_all_sets option is set, dump primitive as well as derived registers.
221f9fc609fSGreg Clayton                     DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
22230fdc8d8SChris Lattner                 }
22330fdc8d8SChris Lattner             }
22430fdc8d8SChris Lattner         }
22530fdc8d8SChris Lattner         else
22630fdc8d8SChris Lattner         {
2271deb7962SGreg Clayton             if (m_command_options.dump_all_sets)
228385aa28cSGreg Clayton             {
229385aa28cSGreg Clayton                 result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
230385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
231385aa28cSGreg Clayton             }
2321deb7962SGreg Clayton             else if (m_command_options.set_indexes.GetSize() > 0)
233385aa28cSGreg Clayton             {
234385aa28cSGreg Clayton                 result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
235385aa28cSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
236385aa28cSGreg Clayton             }
237385aa28cSGreg Clayton             else
238385aa28cSGreg Clayton             {
23930fdc8d8SChris Lattner                 const char *arg_cstr;
24030fdc8d8SChris Lattner                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
24130fdc8d8SChris Lattner                 {
2422f59302cSEnrico Granata                     // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
2432f59302cSEnrico Granata                     // reject it and non-existant. we should be more consistent towards the user and allow them
2442f59302cSEnrico Granata                     // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
2452f59302cSEnrico Granata                     // to call our registers $rbx in our own API
2462f59302cSEnrico Granata                     if (*arg_cstr == '$')
2472f59302cSEnrico Granata                         arg_cstr = arg_cstr+1;
248385aa28cSGreg Clayton                     reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
24930fdc8d8SChris Lattner 
25030fdc8d8SChris Lattner                     if (reg_info)
25130fdc8d8SChris Lattner                     {
252f9fc609fSGreg Clayton                         if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
253385aa28cSGreg Clayton                             strm.Printf("%-12s = error: unavailable\n", reg_info->name);
25430fdc8d8SChris Lattner                     }
25530fdc8d8SChris Lattner                     else
25630fdc8d8SChris Lattner                     {
25730fdc8d8SChris Lattner                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
25830fdc8d8SChris Lattner                     }
25930fdc8d8SChris Lattner                 }
26030fdc8d8SChris Lattner             }
26130fdc8d8SChris Lattner         }
26230fdc8d8SChris Lattner         return result.Succeeded();
26330fdc8d8SChris Lattner     }
26432e0a750SGreg Clayton 
2651deb7962SGreg Clayton     class CommandOptions : public OptionGroup
26632e0a750SGreg Clayton     {
26732e0a750SGreg Clayton     public:
2681deb7962SGreg Clayton         CommandOptions () :
2691deb7962SGreg Clayton             OptionGroup(),
270385aa28cSGreg Clayton             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
2719a8fa916SGreg Clayton             dump_all_sets (false, false), // Initial and default values are false
2729a8fa916SGreg Clayton             alternate_name (false, false)
27332e0a750SGreg Clayton         {
27432e0a750SGreg Clayton         }
27532e0a750SGreg Clayton 
27632e0a750SGreg Clayton         virtual
27732e0a750SGreg Clayton         ~CommandOptions ()
27832e0a750SGreg Clayton         {
27932e0a750SGreg Clayton         }
28032e0a750SGreg Clayton 
2811deb7962SGreg Clayton 
2821deb7962SGreg Clayton         virtual uint32_t
2831deb7962SGreg Clayton         GetNumDefinitions ();
2841deb7962SGreg Clayton 
2851deb7962SGreg Clayton         virtual const OptionDefinition*
2861deb7962SGreg Clayton         GetDefinitions ()
2871deb7962SGreg Clayton         {
2881deb7962SGreg Clayton             return g_option_table;
2891deb7962SGreg Clayton         }
2901deb7962SGreg Clayton 
2911deb7962SGreg Clayton         virtual void
2921deb7962SGreg Clayton         OptionParsingStarting (CommandInterpreter &interpreter)
2931deb7962SGreg Clayton         {
2941deb7962SGreg Clayton             set_indexes.Clear();
2951deb7962SGreg Clayton             dump_all_sets.Clear();
2961deb7962SGreg Clayton             alternate_name.Clear();
2971deb7962SGreg Clayton         }
2981deb7962SGreg Clayton 
29932e0a750SGreg Clayton         virtual Error
3001deb7962SGreg Clayton         SetOptionValue (CommandInterpreter &interpreter,
3011deb7962SGreg Clayton                         uint32_t option_idx,
3021deb7962SGreg Clayton                         const char *option_value)
30332e0a750SGreg Clayton         {
30432e0a750SGreg Clayton             Error error;
3053bcdfc0eSGreg Clayton             const int short_option = g_option_table[option_idx].short_option;
30632e0a750SGreg Clayton             switch (short_option)
30732e0a750SGreg Clayton             {
308385aa28cSGreg Clayton                 case 's':
309385aa28cSGreg Clayton                     {
3101deb7962SGreg Clayton                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
311385aa28cSGreg Clayton                         if (value_sp)
312385aa28cSGreg Clayton                             set_indexes.AppendValue (value_sp);
313385aa28cSGreg Clayton                     }
314385aa28cSGreg Clayton                     break;
315385aa28cSGreg Clayton 
316385aa28cSGreg Clayton                 case 'a':
3179a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3189a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3199a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
320385aa28cSGreg Clayton                     dump_all_sets.SetCurrentValue (true);
3219a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
3229a8fa916SGreg Clayton                     break;
3239a8fa916SGreg Clayton 
3249a8fa916SGreg Clayton                 case 'A':
3259a8fa916SGreg Clayton                     // When we don't use OptionValue::SetValueFromCString(const char *) to
3269a8fa916SGreg Clayton                     // set an option value, it won't be marked as being set in the options
3279a8fa916SGreg Clayton                     // so we make a call to let users know the value was set via option
3289a8fa916SGreg Clayton                     alternate_name.SetCurrentValue (true);
3299a8fa916SGreg Clayton                     dump_all_sets.SetOptionWasSet ();
330385aa28cSGreg Clayton                     break;
331385aa28cSGreg Clayton 
33232e0a750SGreg Clayton                 default:
33386edbf41SGreg Clayton                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
33432e0a750SGreg Clayton                     break;
33532e0a750SGreg Clayton             }
33632e0a750SGreg Clayton             return error;
33732e0a750SGreg Clayton         }
33832e0a750SGreg Clayton 
33932e0a750SGreg Clayton         // Options table: Required for subclasses of Options.
34032e0a750SGreg Clayton 
3411deb7962SGreg Clayton         static const OptionDefinition g_option_table[];
34232e0a750SGreg Clayton 
34332e0a750SGreg Clayton         // Instance variables to hold the values for command options.
344385aa28cSGreg Clayton         OptionValueArray set_indexes;
345385aa28cSGreg Clayton         OptionValueBoolean dump_all_sets;
3469a8fa916SGreg Clayton         OptionValueBoolean alternate_name;
34730fdc8d8SChris Lattner     };
34830fdc8d8SChris Lattner 
3491deb7962SGreg Clayton     OptionGroupOptions m_option_group;
3501deb7962SGreg Clayton     OptionGroupFormat m_format_options;
3511deb7962SGreg Clayton     CommandOptions m_command_options;
35232e0a750SGreg Clayton };
35332e0a750SGreg Clayton 
3543d0fcf5eSJohnny Chen const OptionDefinition
35532e0a750SGreg Clayton CommandObjectRegisterRead::CommandOptions::g_option_table[] =
35632e0a750SGreg Clayton {
357d37221dcSZachary 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."},
358d37221dcSZachary Turner     { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
359d37221dcSZachary Turner     { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone      , "Show all register sets."},
36032e0a750SGreg Clayton };
36132e0a750SGreg Clayton 
3621deb7962SGreg Clayton uint32_t
3631deb7962SGreg Clayton CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
3641deb7962SGreg Clayton {
36528606954SSaleem Abdulrasool     return llvm::array_lengthof(g_option_table);
3661deb7962SGreg Clayton }
36732e0a750SGreg Clayton 
36830fdc8d8SChris Lattner 
36930fdc8d8SChris Lattner //----------------------------------------------------------------------
37030fdc8d8SChris Lattner // "register write"
37130fdc8d8SChris Lattner //----------------------------------------------------------------------
3725a988416SJim Ingham class CommandObjectRegisterWrite : public CommandObjectParsed
37330fdc8d8SChris Lattner {
37430fdc8d8SChris Lattner public:
375a7015092SGreg Clayton     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
3765a988416SJim Ingham         CommandObjectParsed (interpreter,
377a7015092SGreg Clayton                              "register write",
37830fdc8d8SChris Lattner                              "Modify a single register value.",
379405fe67fSCaroline Tice                              NULL,
380f9fc609fSGreg Clayton                              eFlagRequiresFrame         |
381f9fc609fSGreg Clayton                              eFlagRequiresRegContext    |
382f9fc609fSGreg Clayton                              eFlagProcessMustBeLaunched |
383f9fc609fSGreg Clayton                              eFlagProcessMustBePaused)
38430fdc8d8SChris Lattner     {
385405fe67fSCaroline Tice         CommandArgumentEntry arg1;
386405fe67fSCaroline Tice         CommandArgumentEntry arg2;
387405fe67fSCaroline Tice         CommandArgumentData register_arg;
388405fe67fSCaroline Tice         CommandArgumentData value_arg;
389405fe67fSCaroline Tice 
390405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
391405fe67fSCaroline Tice         register_arg.arg_type = eArgTypeRegisterName;
392405fe67fSCaroline Tice         register_arg.arg_repetition = eArgRepeatPlain;
393405fe67fSCaroline Tice 
394405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
395405fe67fSCaroline Tice         arg1.push_back (register_arg);
396405fe67fSCaroline Tice 
397405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
398405fe67fSCaroline Tice         value_arg.arg_type = eArgTypeValue;
399405fe67fSCaroline Tice         value_arg.arg_repetition = eArgRepeatPlain;
400405fe67fSCaroline Tice 
401405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
402405fe67fSCaroline Tice         arg2.push_back (value_arg);
403405fe67fSCaroline Tice 
404405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
405405fe67fSCaroline Tice         m_arguments.push_back (arg1);
406405fe67fSCaroline Tice         m_arguments.push_back (arg2);
40730fdc8d8SChris Lattner     }
40830fdc8d8SChris Lattner 
40930fdc8d8SChris Lattner     virtual
41030fdc8d8SChris Lattner     ~CommandObjectRegisterWrite ()
41130fdc8d8SChris Lattner     {
41230fdc8d8SChris Lattner     }
41330fdc8d8SChris Lattner 
4145a988416SJim Ingham protected:
41530fdc8d8SChris Lattner     virtual bool
4165a988416SJim Ingham     DoExecute(Args& command, CommandReturnObject &result)
41730fdc8d8SChris Lattner     {
41830fdc8d8SChris Lattner         DataExtractor reg_data;
419f9fc609fSGreg Clayton         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
42030fdc8d8SChris Lattner 
42130fdc8d8SChris Lattner         if (command.GetArgumentCount() != 2)
42230fdc8d8SChris Lattner         {
42330fdc8d8SChris Lattner             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
42430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42530fdc8d8SChris Lattner         }
42630fdc8d8SChris Lattner         else
42730fdc8d8SChris Lattner         {
42830fdc8d8SChris Lattner             const char *reg_name = command.GetArgumentAtIndex(0);
42930fdc8d8SChris Lattner             const char *value_str = command.GetArgumentAtIndex(1);
4302f59302cSEnrico Granata 
4312f59302cSEnrico Granata 
4322f59302cSEnrico Granata             // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
4332f59302cSEnrico Granata             // reject it and non-existant. we should be more consistent towards the user and allow them
4342f59302cSEnrico Granata             // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
4352f59302cSEnrico Granata             // to call our registers $rbx in our own API
4362f59302cSEnrico Granata             if (reg_name && *reg_name == '$')
4372f59302cSEnrico Granata                 reg_name = reg_name+1;
4382f59302cSEnrico Granata 
439385aa28cSGreg Clayton             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
44030fdc8d8SChris Lattner 
44130fdc8d8SChris Lattner             if (reg_info)
44230fdc8d8SChris Lattner             {
4437349bd90SGreg Clayton                 RegisterValue reg_value;
4447349bd90SGreg Clayton 
4457349bd90SGreg Clayton                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
44630fdc8d8SChris Lattner                 if (error.Success())
44730fdc8d8SChris Lattner                 {
4487349bd90SGreg Clayton                     if (reg_ctx->WriteRegister (reg_info, reg_value))
44930fdc8d8SChris Lattner                     {
450fa559e5cSGreg Clayton                         // Toss all frames and anything else in the thread
451fa559e5cSGreg Clayton                         // after a register has been written.
452f9fc609fSGreg Clayton                         m_exe_ctx.GetThreadRef().Flush();
45330fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
45430fdc8d8SChris Lattner                         return true;
45530fdc8d8SChris Lattner                     }
45630fdc8d8SChris Lattner                 }
457b1ad65c5SJason Molenda                 if (error.AsCString())
45830fdc8d8SChris Lattner                 {
45930fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
46030fdc8d8SChris Lattner                                                  reg_name,
46130fdc8d8SChris Lattner                                                  value_str,
46230fdc8d8SChris Lattner                                                  error.AsCString());
46330fdc8d8SChris Lattner                 }
464b1ad65c5SJason Molenda                 else
465b1ad65c5SJason Molenda                 {
466b1ad65c5SJason Molenda                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
467b1ad65c5SJason Molenda                                                  reg_name,
468b1ad65c5SJason Molenda                                                  value_str);
469b1ad65c5SJason Molenda                 }
470b1ad65c5SJason Molenda                 result.SetStatus (eReturnStatusFailed);
47130fdc8d8SChris Lattner             }
47230fdc8d8SChris Lattner             else
47330fdc8d8SChris Lattner             {
47430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
47530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
47630fdc8d8SChris Lattner             }
47730fdc8d8SChris Lattner         }
47830fdc8d8SChris Lattner         return result.Succeeded();
47930fdc8d8SChris Lattner     }
48030fdc8d8SChris Lattner };
48130fdc8d8SChris Lattner 
48230fdc8d8SChris Lattner 
48330fdc8d8SChris Lattner //----------------------------------------------------------------------
48430fdc8d8SChris Lattner // CommandObjectRegister constructor
48530fdc8d8SChris Lattner //----------------------------------------------------------------------
4866611103cSGreg Clayton CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
487a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
488a7015092SGreg Clayton                             "register",
4893f4c09c1SCaroline Tice                             "A set of commands to access thread registers.",
49030fdc8d8SChris Lattner                             "register [read|write] ...")
49130fdc8d8SChris Lattner {
492a7015092SGreg Clayton     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
493a7015092SGreg Clayton     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
49430fdc8d8SChris Lattner }
49530fdc8d8SChris Lattner 
49630fdc8d8SChris Lattner 
49730fdc8d8SChris Lattner //----------------------------------------------------------------------
49830fdc8d8SChris Lattner // Destructor
49930fdc8d8SChris Lattner //----------------------------------------------------------------------
50030fdc8d8SChris Lattner CommandObjectRegister::~CommandObjectRegister()
50130fdc8d8SChris Lattner {
50230fdc8d8SChris Lattner }
503