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