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                     reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
232 
233                     if (reg_info)
234                     {
235                         if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
236                             strm.Printf("%-12s = error: unavailable\n", reg_info->name);
237                     }
238                     else
239                     {
240                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
241                     }
242                 }
243             }
244         }
245         return result.Succeeded();
246     }
247 
248     class CommandOptions : public OptionGroup
249     {
250     public:
251         CommandOptions () :
252             OptionGroup(),
253             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
254             dump_all_sets (false, false), // Initial and default values are false
255             alternate_name (false, false)
256         {
257         }
258 
259         virtual
260         ~CommandOptions ()
261         {
262         }
263 
264 
265         virtual uint32_t
266         GetNumDefinitions ();
267 
268         virtual const OptionDefinition*
269         GetDefinitions ()
270         {
271             return g_option_table;
272         }
273 
274         virtual void
275         OptionParsingStarting (CommandInterpreter &interpreter)
276         {
277             set_indexes.Clear();
278             dump_all_sets.Clear();
279             alternate_name.Clear();
280         }
281 
282         virtual Error
283         SetOptionValue (CommandInterpreter &interpreter,
284                         uint32_t option_idx,
285                         const char *option_value)
286         {
287             Error error;
288             const int short_option = g_option_table[option_idx].short_option;
289             switch (short_option)
290             {
291                 case 's':
292                     {
293                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
294                         if (value_sp)
295                             set_indexes.AppendValue (value_sp);
296                     }
297                     break;
298 
299                 case 'a':
300                     // When we don't use OptionValue::SetValueFromCString(const char *) to
301                     // set an option value, it won't be marked as being set in the options
302                     // so we make a call to let users know the value was set via option
303                     dump_all_sets.SetCurrentValue (true);
304                     dump_all_sets.SetOptionWasSet ();
305                     break;
306 
307                 case 'A':
308                     // When we don't use OptionValue::SetValueFromCString(const char *) to
309                     // set an option value, it won't be marked as being set in the options
310                     // so we make a call to let users know the value was set via option
311                     alternate_name.SetCurrentValue (true);
312                     dump_all_sets.SetOptionWasSet ();
313                     break;
314 
315                 default:
316                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
317                     break;
318             }
319             return error;
320         }
321 
322         // Options table: Required for subclasses of Options.
323 
324         static const OptionDefinition g_option_table[];
325 
326         // Instance variables to hold the values for command options.
327         OptionValueArray set_indexes;
328         OptionValueBoolean dump_all_sets;
329         OptionValueBoolean alternate_name;
330     };
331 
332     OptionGroupOptions m_option_group;
333     OptionGroupFormat m_format_options;
334     CommandOptions m_command_options;
335 };
336 
337 const OptionDefinition
338 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
339 {
340     { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
341     { LLDB_OPT_SET_1  , false, "set"      , 's', required_argument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
342     { LLDB_OPT_SET_2  , false, "all"      , 'a', no_argument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
343 };
344 
345 uint32_t
346 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
347 {
348     return sizeof(g_option_table)/sizeof(OptionDefinition);
349 }
350 
351 
352 //----------------------------------------------------------------------
353 // "register write"
354 //----------------------------------------------------------------------
355 class CommandObjectRegisterWrite : public CommandObjectParsed
356 {
357 public:
358     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
359         CommandObjectParsed (interpreter,
360                              "register write",
361                              "Modify a single register value.",
362                              NULL,
363                              eFlagRequiresFrame         |
364                              eFlagRequiresRegContext    |
365                              eFlagProcessMustBeLaunched |
366                              eFlagProcessMustBePaused)
367     {
368         CommandArgumentEntry arg1;
369         CommandArgumentEntry arg2;
370         CommandArgumentData register_arg;
371         CommandArgumentData value_arg;
372 
373         // Define the first (and only) variant of this arg.
374         register_arg.arg_type = eArgTypeRegisterName;
375         register_arg.arg_repetition = eArgRepeatPlain;
376 
377         // There is only one variant this argument could be; put it into the argument entry.
378         arg1.push_back (register_arg);
379 
380         // Define the first (and only) variant of this arg.
381         value_arg.arg_type = eArgTypeValue;
382         value_arg.arg_repetition = eArgRepeatPlain;
383 
384         // There is only one variant this argument could be; put it into the argument entry.
385         arg2.push_back (value_arg);
386 
387         // Push the data for the first argument into the m_arguments vector.
388         m_arguments.push_back (arg1);
389         m_arguments.push_back (arg2);
390     }
391 
392     virtual
393     ~CommandObjectRegisterWrite ()
394     {
395     }
396 
397 protected:
398     virtual bool
399     DoExecute(Args& command, CommandReturnObject &result)
400     {
401         DataExtractor reg_data;
402         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
403 
404         if (command.GetArgumentCount() != 2)
405         {
406             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
407             result.SetStatus (eReturnStatusFailed);
408         }
409         else
410         {
411             const char *reg_name = command.GetArgumentAtIndex(0);
412             const char *value_str = command.GetArgumentAtIndex(1);
413             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
414 
415             if (reg_info)
416             {
417                 RegisterValue reg_value;
418 
419                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
420                 if (error.Success())
421                 {
422                     if (reg_ctx->WriteRegister (reg_info, reg_value))
423                     {
424                         // Toss all frames and anything else in the thread
425                         // after a register has been written.
426                         m_exe_ctx.GetThreadRef().Flush();
427                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
428                         return true;
429                     }
430                 }
431                 if (error.AsCString())
432                 {
433                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
434                                                  reg_name,
435                                                  value_str,
436                                                  error.AsCString());
437                 }
438                 else
439                 {
440                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
441                                                  reg_name,
442                                                  value_str);
443                 }
444                 result.SetStatus (eReturnStatusFailed);
445             }
446             else
447             {
448                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
449                 result.SetStatus (eReturnStatusFailed);
450             }
451         }
452         return result.Succeeded();
453     }
454 };
455 
456 
457 //----------------------------------------------------------------------
458 // CommandObjectRegister constructor
459 //----------------------------------------------------------------------
460 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
461     CommandObjectMultiword (interpreter,
462                             "register",
463                             "A set of commands to access thread registers.",
464                             "register [read|write] ...")
465 {
466     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
467     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
468 }
469 
470 
471 //----------------------------------------------------------------------
472 // Destructor
473 //----------------------------------------------------------------------
474 CommandObjectRegister::~CommandObjectRegister()
475 {
476 }
477