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/Interpreter/Options.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/RegisterContext.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // "register read"
31 //----------------------------------------------------------------------
32 class CommandObjectRegisterRead : public CommandObject
33 {
34 public:
35     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
36         CommandObject (interpreter,
37                        "register read",
38                        "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
39                        //"register read [<reg-name1> [<reg-name2> [...]]]",
40                        NULL,
41                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
42         m_options (interpreter)
43     {
44         CommandArgumentEntry arg;
45         CommandArgumentData register_arg;
46 
47         // Define the first (and only) variant of this arg.
48         register_arg.arg_type = eArgTypeRegisterName;
49         register_arg.arg_repetition = eArgRepeatStar;
50 
51         // There is only one variant this argument could be; put it into the argument entry.
52         arg.push_back (register_arg);
53 
54         // Push the data for the first argument into the m_arguments vector.
55         m_arguments.push_back (arg);
56     }
57 
58     virtual
59     ~CommandObjectRegisterRead ()
60     {
61     }
62 
63     Options *
64     GetOptions ()
65     {
66         return &m_options;
67     }
68 
69     virtual bool
70     Execute
71     (
72         Args& command,
73         CommandReturnObject &result
74     )
75     {
76         Stream &output_stream = result.GetOutputStream();
77         DataExtractor reg_data;
78         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
79         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
80 
81         if (reg_context)
82         {
83             const RegisterInfo *reg_info = NULL;
84             if (command.GetArgumentCount() == 0)
85             {
86                 uint32_t set_idx;
87                 const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
88                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
89                 {
90                     uint32_t unavailable_count = 0;
91                     const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
92                     output_stream.Printf ("%s:\n", reg_set->name);
93                     output_stream.IndentMore ();
94                     const uint32_t num_registers = reg_set->num_registers;
95                     for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
96                     {
97                         uint32_t reg = reg_set->registers[reg_idx];
98                         reg_info = reg_context->GetRegisterInfoAtIndex(reg);
99                         if (reg_context->ReadRegisterBytes(reg, reg_data))
100                         {
101                             output_stream.Indent ();
102                             output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
103                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
104                             output_stream.EOL();
105                         }
106                         else
107                         {
108                             ++unavailable_count;
109                         }
110                     }
111                     if (unavailable_count)
112                     {
113                         output_stream.Indent ();
114                         output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
115                     }
116                     output_stream.IndentLess ();
117                     output_stream.EOL();
118                 }
119             }
120             else
121             {
122                 const char *arg_cstr;
123                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
124                 {
125                     reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
126 
127                     if (reg_info)
128                     {
129                         output_stream.Printf("%-12s = ", reg_info->name);
130                         if (reg_context->ReadRegisterBytes(reg_info->kinds[eRegisterKindLLDB], reg_data))
131                         {
132                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
133                         }
134                         else
135                         {
136                             output_stream.PutCString ("error: unavailable");
137                         }
138                         output_stream.EOL();
139                     }
140                     else
141                     {
142                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
143                     }
144                 }
145             }
146         }
147         else
148         {
149             result.AppendError ("no current frame");
150             result.SetStatus (eReturnStatusFailed);
151         }
152         return result.Succeeded();
153     }
154 
155 protected:
156     class CommandOptions : public Options
157     {
158     public:
159         CommandOptions (CommandInterpreter &interpreter) :
160             Options(interpreter)
161         {
162             OptionParsingStarting();
163         }
164 
165         virtual
166         ~CommandOptions ()
167         {
168         }
169 
170         virtual Error
171         SetOptionValue (uint32_t option_idx, const char *option_arg)
172         {
173             Error error;
174             char short_option = (char) m_getopt_table[option_idx].val;
175             switch (short_option)
176             {
177                 case 'f':
178                     error = Args::StringToFormat (option_arg, m_format);
179                     break;
180 
181                 default:
182                     error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
183                     break;
184             }
185             return error;
186         }
187 
188         void
189         OptionParsingStarting ()
190         {
191             m_format = eFormatBytes;
192         }
193 
194         const OptionDefinition*
195         GetDefinitions ()
196         {
197             return g_option_table;
198         }
199 
200         // Options table: Required for subclasses of Options.
201 
202         static OptionDefinition g_option_table[];
203 
204         // Instance variables to hold the values for command options.
205         lldb::Format m_format;
206     };
207 
208     CommandOptions m_options;
209 };
210 
211 OptionDefinition
212 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
213 {
214     //{ LLDB_OPT_SET_ALL, false, "language",   'l', required_argument, NULL, 0, "[c|c++|objc|objc++]",          "Sets the language to use when parsing the expression."},
215     //{ LLDB_OPT_SET_1, false, "format",     'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]",  "Specify the format that the expression output should use."},
216     { LLDB_OPT_SET_1, false, "format",             'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format that the expression output should use."},
217     { LLDB_OPT_SET_2, false, "object-description", 'o', no_argument,       NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."},
218     { LLDB_OPT_SET_ALL, false, "unwind-on-error",  'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
219     { LLDB_OPT_SET_ALL, false, "debug",            'g', no_argument,       NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
220     { LLDB_OPT_SET_ALL, false, "use-ir",           'i', no_argument,       NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},
221     { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
222 };
223 
224 
225 
226 //----------------------------------------------------------------------
227 // "register write"
228 //----------------------------------------------------------------------
229 class CommandObjectRegisterWrite : public CommandObject
230 {
231 public:
232     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
233         CommandObject (interpreter,
234                        "register write",
235                        "Modify a single register value.",
236                        //"register write <reg-name> <value>",
237                        NULL,
238                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
239     {
240         CommandArgumentEntry arg1;
241         CommandArgumentEntry arg2;
242         CommandArgumentData register_arg;
243         CommandArgumentData value_arg;
244 
245         // Define the first (and only) variant of this arg.
246         register_arg.arg_type = eArgTypeRegisterName;
247         register_arg.arg_repetition = eArgRepeatPlain;
248 
249         // There is only one variant this argument could be; put it into the argument entry.
250         arg1.push_back (register_arg);
251 
252         // Define the first (and only) variant of this arg.
253         value_arg.arg_type = eArgTypeValue;
254         value_arg.arg_repetition = eArgRepeatPlain;
255 
256         // There is only one variant this argument could be; put it into the argument entry.
257         arg2.push_back (value_arg);
258 
259         // Push the data for the first argument into the m_arguments vector.
260         m_arguments.push_back (arg1);
261         m_arguments.push_back (arg2);
262     }
263 
264     virtual
265     ~CommandObjectRegisterWrite ()
266     {
267     }
268 
269     virtual bool
270     Execute
271     (
272         Args& command,
273         CommandReturnObject &result
274     )
275     {
276         DataExtractor reg_data;
277         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
278         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
279 
280         if (reg_context)
281         {
282             if (command.GetArgumentCount() != 2)
283             {
284                 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
285                 result.SetStatus (eReturnStatusFailed);
286             }
287             else
288             {
289                 const char *reg_name = command.GetArgumentAtIndex(0);
290                 const char *value_str = command.GetArgumentAtIndex(1);
291                 const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
292 
293                 if (reg_info)
294                 {
295                     Scalar scalar;
296                     Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
297                     if (error.Success())
298                     {
299                         if (reg_context->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
300                         {
301                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
302                             return true;
303                         }
304                     }
305                     else
306                     {
307                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
308                                                      reg_name,
309                                                      value_str,
310                                                      error.AsCString());
311                         result.SetStatus (eReturnStatusFailed);
312                     }
313                 }
314                 else
315                 {
316                     result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
317                     result.SetStatus (eReturnStatusFailed);
318                 }
319             }
320         }
321         else
322         {
323             result.AppendError ("no current frame");
324             result.SetStatus (eReturnStatusFailed);
325         }
326         return result.Succeeded();
327     }
328 };
329 
330 
331 //----------------------------------------------------------------------
332 // CommandObjectRegister constructor
333 //----------------------------------------------------------------------
334 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
335     CommandObjectMultiword (interpreter,
336                             "register",
337                             "A set of commands to access thread registers.",
338                             "register [read|write] ...")
339 {
340     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
341     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
342 }
343 
344 
345 //----------------------------------------------------------------------
346 // Destructor
347 //----------------------------------------------------------------------
348 CommandObjectRegister::~CommandObjectRegister()
349 {
350 }
351