1 //===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CommandObjectRegister.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Interpreter/Args.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Target/ExecutionContext.h"
23 #include "lldb/Target/RegisterContext.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 //----------------------------------------------------------------------
29 // "register read"
30 //----------------------------------------------------------------------
31 class CommandObjectRegisterRead : public CommandObject
32 {
33 public:
34     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
35         CommandObject (interpreter,
36                        "register read",
37                        "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
38                        //"register read [<reg-name1> [<reg-name2> [...]]]",
39                        NULL,
40                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
41     {
42         CommandArgumentEntry arg;
43         CommandArgumentData register_arg;
44 
45         // Define the first (and only) variant of this arg.
46         register_arg.arg_type = eArgTypeRegisterName;
47         register_arg.arg_repetition = eArgRepeatStar;
48 
49         // There is only one variant this argument could be; put it into the argument entry.
50         arg.push_back (register_arg);
51 
52         // Push the data for the first argument into the m_arguments vector.
53         m_arguments.push_back (arg);
54     }
55 
56     virtual
57     ~CommandObjectRegisterRead ()
58     {
59     }
60 
61     virtual bool
62     Execute
63     (
64         Args& command,
65         CommandReturnObject &result
66     )
67     {
68         StreamString &output_stream = result.GetOutputStream();
69         DataExtractor reg_data;
70         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
71         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
72 
73         if (reg_context)
74         {
75             const RegisterInfo *reg_info = NULL;
76             if (command.GetArgumentCount() == 0)
77             {
78                 uint32_t set_idx;
79                 const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
80                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
81                 {
82                     uint32_t unavailable_count = 0;
83                     const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
84                     output_stream.Printf ("%s:\n", reg_set->name);
85                     output_stream.IndentMore ();
86                     const uint32_t num_registers = reg_set->num_registers;
87                     for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
88                     {
89                         uint32_t reg = reg_set->registers[reg_idx];
90                         reg_info = reg_context->GetRegisterInfoAtIndex(reg);
91                         if (reg_context->ReadRegisterBytes(reg, reg_data))
92                         {
93                             output_stream.Indent ();
94                             output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
95                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
96                             output_stream.EOL();
97                         }
98                         else
99                         {
100                             ++unavailable_count;
101                         }
102                     }
103                     if (unavailable_count)
104                     {
105                         output_stream.Indent ();
106                         output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
107                     }
108                     output_stream.IndentLess ();
109                     output_stream.EOL();
110                 }
111             }
112             else
113             {
114                 const char *arg_cstr;
115                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
116                 {
117                     reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
118 
119                     if (reg_info)
120                     {
121                         output_stream.Printf("%-12s = ", reg_info->name);
122                         if (reg_context->ReadRegisterBytes(reg_info->kinds[eRegisterKindLLDB], reg_data))
123                         {
124                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
125                         }
126                         else
127                         {
128                             output_stream.PutCString ("error: unavailable");
129                         }
130                         output_stream.EOL();
131                     }
132                     else
133                     {
134                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
135                     }
136                 }
137             }
138         }
139         else
140         {
141             result.AppendError ("no current frame");
142             result.SetStatus (eReturnStatusFailed);
143         }
144         return result.Succeeded();
145     }
146 };
147 
148 
149 //----------------------------------------------------------------------
150 // "register write"
151 //----------------------------------------------------------------------
152 class CommandObjectRegisterWrite : public CommandObject
153 {
154 public:
155     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
156         CommandObject (interpreter,
157                        "register write",
158                        "Modify a single register value.",
159                        //"register write <reg-name> <value>",
160                        NULL,
161                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
162     {
163         CommandArgumentEntry arg1;
164         CommandArgumentEntry arg2;
165         CommandArgumentData register_arg;
166         CommandArgumentData value_arg;
167 
168         // Define the first (and only) variant of this arg.
169         register_arg.arg_type = eArgTypeRegisterName;
170         register_arg.arg_repetition = eArgRepeatPlain;
171 
172         // There is only one variant this argument could be; put it into the argument entry.
173         arg1.push_back (register_arg);
174 
175         // Define the first (and only) variant of this arg.
176         value_arg.arg_type = eArgTypeValue;
177         value_arg.arg_repetition = eArgRepeatPlain;
178 
179         // There is only one variant this argument could be; put it into the argument entry.
180         arg2.push_back (value_arg);
181 
182         // Push the data for the first argument into the m_arguments vector.
183         m_arguments.push_back (arg1);
184         m_arguments.push_back (arg2);
185     }
186 
187     virtual
188     ~CommandObjectRegisterWrite ()
189     {
190     }
191 
192     virtual bool
193     Execute
194     (
195         Args& command,
196         CommandReturnObject &result
197     )
198     {
199         DataExtractor reg_data;
200         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
201         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
202 
203         if (reg_context)
204         {
205             if (command.GetArgumentCount() != 2)
206             {
207                 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
208                 result.SetStatus (eReturnStatusFailed);
209             }
210             else
211             {
212                 const char *reg_name = command.GetArgumentAtIndex(0);
213                 const char *value_str = command.GetArgumentAtIndex(1);
214                 const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
215 
216                 if (reg_info)
217                 {
218                     Scalar scalar;
219                     Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
220                     if (error.Success())
221                     {
222                         if (reg_context->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
223                         {
224                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
225                             return true;
226                         }
227                     }
228                     else
229                     {
230                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
231                                                      reg_name,
232                                                      value_str,
233                                                      error.AsCString());
234                         result.SetStatus (eReturnStatusFailed);
235                     }
236                 }
237                 else
238                 {
239                     result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
240                     result.SetStatus (eReturnStatusFailed);
241                 }
242             }
243         }
244         else
245         {
246             result.AppendError ("no current frame");
247             result.SetStatus (eReturnStatusFailed);
248         }
249         return result.Succeeded();
250     }
251 };
252 
253 
254 //----------------------------------------------------------------------
255 // CommandObjectRegister constructor
256 //----------------------------------------------------------------------
257 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
258     CommandObjectMultiword (interpreter,
259                             "register",
260                             "A set of commands to access thread registers.",
261                             "register [read|write] ...")
262 {
263     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
264     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
265 }
266 
267 
268 //----------------------------------------------------------------------
269 // Destructor
270 //----------------------------------------------------------------------
271 CommandObjectRegister::~CommandObjectRegister()
272 {
273 }
274