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 "lldb/lldb-python.h"
11 
12 #include "CommandObjectRegister.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Core/DataExtractor.h"
19 #include "lldb/Core/RegisterValue.h"
20 #include "lldb/Core/Scalar.h"
21 #include "lldb/Core/Debugger.h"
22 #include "lldb/Interpreter/Args.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Interpreter/Options.h"
26 #include "lldb/Interpreter/OptionGroupFormat.h"
27 #include "lldb/Interpreter/OptionValueArray.h"
28 #include "lldb/Interpreter/OptionValueUInt64.h"
29 #include "lldb/Target/ExecutionContext.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/RegisterContext.h"
32 #include "lldb/Target/Thread.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 //----------------------------------------------------------------------
38 // "register read"
39 //----------------------------------------------------------------------
40 class CommandObjectRegisterRead : public CommandObjectParsed
41 {
42 public:
43     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
44         CommandObjectParsed (interpreter,
45                              "register read",
46                              "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
47                              NULL,
48                              eFlagRequiresFrame         |
49                              eFlagRequiresRegContext    |
50                              eFlagProcessMustBeLaunched |
51                              eFlagProcessMustBePaused   ),
52         m_option_group (interpreter),
53         m_format_options (eFormatDefault),
54         m_command_options ()
55     {
56         CommandArgumentEntry arg;
57         CommandArgumentData register_arg;
58 
59         // Define the first (and only) variant of this arg.
60         register_arg.arg_type = eArgTypeRegisterName;
61         register_arg.arg_repetition = eArgRepeatStar;
62 
63         // There is only one variant this argument could be; put it into the argument entry.
64         arg.push_back (register_arg);
65 
66         // Push the data for the first argument into the m_arguments vector.
67         m_arguments.push_back (arg);
68 
69         // Add the "--format"
70         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
71         m_option_group.Append (&m_command_options);
72         m_option_group.Finalize();
73 
74     }
75 
76     virtual
77     ~CommandObjectRegisterRead ()
78     {
79     }
80 
81     Options *
82     GetOptions ()
83     {
84         return &m_option_group;
85     }
86 
87     bool
88     DumpRegister (const ExecutionContext &exe_ctx,
89                   Stream &strm,
90                   RegisterContext *reg_ctx,
91                   const RegisterInfo *reg_info)
92     {
93         if (reg_info)
94         {
95             RegisterValue reg_value;
96 
97             if (reg_ctx->ReadRegister (reg_info, reg_value))
98             {
99                 strm.Indent ();
100 
101                 bool prefix_with_altname = m_command_options.alternate_name;
102                 bool prefix_with_name = !prefix_with_altname;
103                 reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
104                 if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
105                 {
106                     Process *process = exe_ctx.GetProcessPtr();
107                     if (process && reg_info->byte_size == process->GetAddressByteSize())
108                     {
109                         addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
110                         if (reg_addr != LLDB_INVALID_ADDRESS)
111                         {
112                             Address so_reg_addr;
113                             if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
114                             {
115                                 strm.PutCString ("  ");
116                                 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
117                             }
118                         }
119                     }
120                 }
121                 strm.EOL();
122                 return true;
123             }
124         }
125         return false;
126     }
127 
128     bool
129     DumpRegisterSet (const ExecutionContext &exe_ctx,
130                      Stream &strm,
131                      RegisterContext *reg_ctx,
132                      size_t set_idx,
133                      bool primitive_only=false)
134     {
135         uint32_t unavailable_count = 0;
136         uint32_t available_count = 0;
137         const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
138         if (reg_set)
139         {
140             strm.Printf ("%s:\n", reg_set->name);
141             strm.IndentMore ();
142             const size_t num_registers = reg_set->num_registers;
143             for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
144             {
145                 const uint32_t reg = reg_set->registers[reg_idx];
146                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
147                 // Skip the dumping of derived register if primitive_only is true.
148                 if (primitive_only && reg_info && reg_info->value_regs)
149                     continue;
150                 if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
151                     ++available_count;
152                 else
153                     ++unavailable_count;
154             }
155             strm.IndentLess ();
156             if (unavailable_count)
157             {
158                 strm.Indent ();
159                 strm.Printf("%u registers were unavailable.\n", unavailable_count);
160             }
161             strm.EOL();
162         }
163         return available_count > 0;
164     }
165 
166 protected:
167     virtual bool
168     DoExecute (Args& command, CommandReturnObject &result)
169     {
170         Stream &strm = result.GetOutputStream();
171         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
172 
173         const RegisterInfo *reg_info = NULL;
174         if (command.GetArgumentCount() == 0)
175         {
176             size_t set_idx;
177 
178             size_t num_register_sets = 1;
179             const size_t set_array_size = m_command_options.set_indexes.GetSize();
180             if (set_array_size > 0)
181             {
182                 for (size_t i=0; i<set_array_size; ++i)
183                 {
184                     set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
185                     if (set_idx != UINT32_MAX)
186                     {
187                         if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
188                         {
189                             result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx);
190                             result.SetStatus (eReturnStatusFailed);
191                             break;
192                         }
193                     }
194                     else
195                     {
196                         result.AppendError ("invalid register set index\n");
197                         result.SetStatus (eReturnStatusFailed);
198                         break;
199                     }
200                 }
201             }
202             else
203             {
204                 if (m_command_options.dump_all_sets)
205                     num_register_sets = reg_ctx->GetRegisterSetCount();
206 
207                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
208                 {
209                     // When dump_all_sets option is set, dump primitive as well as derived registers.
210                     DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
211                 }
212             }
213         }
214         else
215         {
216             if (m_command_options.dump_all_sets)
217             {
218                 result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
219                 result.SetStatus (eReturnStatusFailed);
220             }
221             else if (m_command_options.set_indexes.GetSize() > 0)
222             {
223                 result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
224                 result.SetStatus (eReturnStatusFailed);
225             }
226             else
227             {
228                 const char *arg_cstr;
229                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
230                 {
231                     // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
232                     // reject it and non-existant. we should be more consistent towards the user and allow them
233                     // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
234                     // to call our registers $rbx in our own API
235                     if (*arg_cstr == '$')
236                         arg_cstr = arg_cstr+1;
237                     reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
238 
239                     if (reg_info)
240                     {
241                         if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
242                             strm.Printf("%-12s = error: unavailable\n", reg_info->name);
243                     }
244                     else
245                     {
246                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
247                     }
248                 }
249             }
250         }
251         return result.Succeeded();
252     }
253 
254     class CommandOptions : public OptionGroup
255     {
256     public:
257         CommandOptions () :
258             OptionGroup(),
259             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
260             dump_all_sets (false, false), // Initial and default values are false
261             alternate_name (false, false)
262         {
263         }
264 
265         virtual
266         ~CommandOptions ()
267         {
268         }
269 
270 
271         virtual uint32_t
272         GetNumDefinitions ();
273 
274         virtual const OptionDefinition*
275         GetDefinitions ()
276         {
277             return g_option_table;
278         }
279 
280         virtual void
281         OptionParsingStarting (CommandInterpreter &interpreter)
282         {
283             set_indexes.Clear();
284             dump_all_sets.Clear();
285             alternate_name.Clear();
286         }
287 
288         virtual Error
289         SetOptionValue (CommandInterpreter &interpreter,
290                         uint32_t option_idx,
291                         const char *option_value)
292         {
293             Error error;
294             const int short_option = g_option_table[option_idx].short_option;
295             switch (short_option)
296             {
297                 case 's':
298                     {
299                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
300                         if (value_sp)
301                             set_indexes.AppendValue (value_sp);
302                     }
303                     break;
304 
305                 case 'a':
306                     // When we don't use OptionValue::SetValueFromCString(const char *) to
307                     // set an option value, it won't be marked as being set in the options
308                     // so we make a call to let users know the value was set via option
309                     dump_all_sets.SetCurrentValue (true);
310                     dump_all_sets.SetOptionWasSet ();
311                     break;
312 
313                 case 'A':
314                     // When we don't use OptionValue::SetValueFromCString(const char *) to
315                     // set an option value, it won't be marked as being set in the options
316                     // so we make a call to let users know the value was set via option
317                     alternate_name.SetCurrentValue (true);
318                     dump_all_sets.SetOptionWasSet ();
319                     break;
320 
321                 default:
322                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
323                     break;
324             }
325             return error;
326         }
327 
328         // Options table: Required for subclasses of Options.
329 
330         static const OptionDefinition g_option_table[];
331 
332         // Instance variables to hold the values for command options.
333         OptionValueArray set_indexes;
334         OptionValueBoolean dump_all_sets;
335         OptionValueBoolean alternate_name;
336     };
337 
338     OptionGroupOptions m_option_group;
339     OptionGroupFormat m_format_options;
340     CommandOptions m_command_options;
341 };
342 
343 const OptionDefinition
344 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
345 {
346     { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
347     { LLDB_OPT_SET_1  , false, "set"      , 's', required_argument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
348     { LLDB_OPT_SET_2  , false, "all"      , 'a', no_argument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
349 };
350 
351 uint32_t
352 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
353 {
354     return sizeof(g_option_table)/sizeof(OptionDefinition);
355 }
356 
357 
358 //----------------------------------------------------------------------
359 // "register write"
360 //----------------------------------------------------------------------
361 class CommandObjectRegisterWrite : public CommandObjectParsed
362 {
363 public:
364     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
365         CommandObjectParsed (interpreter,
366                              "register write",
367                              "Modify a single register value.",
368                              NULL,
369                              eFlagRequiresFrame         |
370                              eFlagRequiresRegContext    |
371                              eFlagProcessMustBeLaunched |
372                              eFlagProcessMustBePaused)
373     {
374         CommandArgumentEntry arg1;
375         CommandArgumentEntry arg2;
376         CommandArgumentData register_arg;
377         CommandArgumentData value_arg;
378 
379         // Define the first (and only) variant of this arg.
380         register_arg.arg_type = eArgTypeRegisterName;
381         register_arg.arg_repetition = eArgRepeatPlain;
382 
383         // There is only one variant this argument could be; put it into the argument entry.
384         arg1.push_back (register_arg);
385 
386         // Define the first (and only) variant of this arg.
387         value_arg.arg_type = eArgTypeValue;
388         value_arg.arg_repetition = eArgRepeatPlain;
389 
390         // There is only one variant this argument could be; put it into the argument entry.
391         arg2.push_back (value_arg);
392 
393         // Push the data for the first argument into the m_arguments vector.
394         m_arguments.push_back (arg1);
395         m_arguments.push_back (arg2);
396     }
397 
398     virtual
399     ~CommandObjectRegisterWrite ()
400     {
401     }
402 
403 protected:
404     virtual bool
405     DoExecute(Args& command, CommandReturnObject &result)
406     {
407         DataExtractor reg_data;
408         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
409 
410         if (command.GetArgumentCount() != 2)
411         {
412             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
413             result.SetStatus (eReturnStatusFailed);
414         }
415         else
416         {
417             const char *reg_name = command.GetArgumentAtIndex(0);
418             const char *value_str = command.GetArgumentAtIndex(1);
419 
420 
421             // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
422             // reject it and non-existant. we should be more consistent towards the user and allow them
423             // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
424             // to call our registers $rbx in our own API
425             if (reg_name && *reg_name == '$')
426                 reg_name = reg_name+1;
427 
428             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
429 
430             if (reg_info)
431             {
432                 RegisterValue reg_value;
433 
434                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
435                 if (error.Success())
436                 {
437                     if (reg_ctx->WriteRegister (reg_info, reg_value))
438                     {
439                         // Toss all frames and anything else in the thread
440                         // after a register has been written.
441                         m_exe_ctx.GetThreadRef().Flush();
442                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
443                         return true;
444                     }
445                 }
446                 if (error.AsCString())
447                 {
448                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
449                                                  reg_name,
450                                                  value_str,
451                                                  error.AsCString());
452                 }
453                 else
454                 {
455                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
456                                                  reg_name,
457                                                  value_str);
458                 }
459                 result.SetStatus (eReturnStatusFailed);
460             }
461             else
462             {
463                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
464                 result.SetStatus (eReturnStatusFailed);
465             }
466         }
467         return result.Succeeded();
468     }
469 };
470 
471 
472 //----------------------------------------------------------------------
473 // CommandObjectRegister constructor
474 //----------------------------------------------------------------------
475 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
476     CommandObjectMultiword (interpreter,
477                             "register",
478                             "A set of commands to access thread registers.",
479                             "register [read|write] ...")
480 {
481     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
482     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
483 }
484 
485 
486 //----------------------------------------------------------------------
487 // Destructor
488 //----------------------------------------------------------------------
489 CommandObjectRegister::~CommandObjectRegister()
490 {
491 }
492