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