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/Options.h"
24 #include "lldb/Interpreter/OptionGroupFormat.h"
25 #include "lldb/Interpreter/OptionValueArray.h"
26 #include "lldb/Interpreter/OptionValueUInt64.h"
27 #include "lldb/Target/ExecutionContext.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/RegisterContext.h"
30 #include "lldb/Target/Thread.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 //----------------------------------------------------------------------
36 // "register read"
37 //----------------------------------------------------------------------
38 class CommandObjectRegisterRead : public CommandObjectParsed
39 {
40 public:
41     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
42         CommandObjectParsed (interpreter,
43                              "register read",
44                              "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
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(), 8);
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 protected:
162     virtual bool
163     DoExecute (Args& command, CommandReturnObject &result)
164     {
165         Stream &strm = result.GetOutputStream();
166         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
167         RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
168 
169         if (reg_ctx)
170         {
171             const RegisterInfo *reg_info = NULL;
172             if (command.GetArgumentCount() == 0)
173             {
174                 uint32_t set_idx;
175 
176                 uint32_t num_register_sets = 1;
177                 const uint32_t set_array_size = m_command_options.set_indexes.GetSize();
178                 if (set_array_size > 0)
179                 {
180                     for (uint32_t i=0; i<set_array_size; ++i)
181                     {
182                         set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
183                         if (set_idx != UINT32_MAX)
184                         {
185                             if (!DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx))
186                             {
187                                 result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
188                                 result.SetStatus (eReturnStatusFailed);
189                                 break;
190                             }
191                         }
192                         else
193                         {
194                             result.AppendError ("invalid register set index\n");
195                             result.SetStatus (eReturnStatusFailed);
196                             break;
197                         }
198                     }
199                 }
200                 else
201                 {
202                     if (m_command_options.dump_all_sets)
203                         num_register_sets = reg_ctx->GetRegisterSetCount();
204 
205                     for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
206                     {
207                         // When dump_all_sets option is set, dump primitive as well as derived registers.
208                         DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
209                     }
210                 }
211             }
212             else
213             {
214                 if (m_command_options.dump_all_sets)
215                 {
216                     result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
217                     result.SetStatus (eReturnStatusFailed);
218                 }
219                 else if (m_command_options.set_indexes.GetSize() > 0)
220                 {
221                     result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
222                     result.SetStatus (eReturnStatusFailed);
223                 }
224                 else
225                 {
226                     const char *arg_cstr;
227                     for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
228                     {
229                         reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
230 
231                         if (reg_info)
232                         {
233                             if (!DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
234                                 strm.Printf("%-12s = error: unavailable\n", reg_info->name);
235                         }
236                         else
237                         {
238                             result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
239                         }
240                     }
241                 }
242             }
243         }
244         else
245         {
246             result.AppendError ("no current frame");
247             result.SetStatus (eReturnStatusFailed);
248         }
249         return result.Succeeded();
250     }
251 
252     class CommandOptions : public OptionGroup
253     {
254     public:
255         CommandOptions () :
256             OptionGroup(),
257             set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
258             dump_all_sets (false, false), // Initial and default values are false
259             alternate_name (false, false)
260         {
261         }
262 
263         virtual
264         ~CommandOptions ()
265         {
266         }
267 
268 
269         virtual uint32_t
270         GetNumDefinitions ();
271 
272         virtual const OptionDefinition*
273         GetDefinitions ()
274         {
275             return g_option_table;
276         }
277 
278         virtual void
279         OptionParsingStarting (CommandInterpreter &interpreter)
280         {
281             set_indexes.Clear();
282             dump_all_sets.Clear();
283             alternate_name.Clear();
284         }
285 
286         virtual Error
287         SetOptionValue (CommandInterpreter &interpreter,
288                         uint32_t option_idx,
289                         const char *option_value)
290         {
291             Error error;
292             const char short_option = (char) g_option_table[option_idx].short_option;
293             switch (short_option)
294             {
295                 case 's':
296                     {
297                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
298                         if (value_sp)
299                             set_indexes.AppendValue (value_sp);
300                     }
301                     break;
302 
303                 case 'a':
304                     // When we don't use OptionValue::SetValueFromCString(const char *) to
305                     // set an option value, it won't be marked as being set in the options
306                     // so we make a call to let users know the value was set via option
307                     dump_all_sets.SetCurrentValue (true);
308                     dump_all_sets.SetOptionWasSet ();
309                     break;
310 
311                 case 'A':
312                     // When we don't use OptionValue::SetValueFromCString(const char *) to
313                     // set an option value, it won't be marked as being set in the options
314                     // so we make a call to let users know the value was set via option
315                     alternate_name.SetCurrentValue (true);
316                     dump_all_sets.SetOptionWasSet ();
317                     break;
318 
319                 default:
320                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
321                     break;
322             }
323             return error;
324         }
325 
326         // Options table: Required for subclasses of Options.
327 
328         static const OptionDefinition g_option_table[];
329 
330         // Instance variables to hold the values for command options.
331         OptionValueArray set_indexes;
332         OptionValueBoolean dump_all_sets;
333         OptionValueBoolean alternate_name;
334     };
335 
336     OptionGroupOptions m_option_group;
337     OptionGroupFormat m_format_options;
338     CommandOptions m_command_options;
339 };
340 
341 const OptionDefinition
342 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
343 {
344     { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
345     { LLDB_OPT_SET_1  , false, "set"      , 's', required_argument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
346     { LLDB_OPT_SET_2  , false, "all"      , 'a', no_argument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
347 };
348 
349 uint32_t
350 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
351 {
352     return sizeof(g_option_table)/sizeof(OptionDefinition);
353 }
354 
355 
356 //----------------------------------------------------------------------
357 // "register write"
358 //----------------------------------------------------------------------
359 class CommandObjectRegisterWrite : public CommandObjectParsed
360 {
361 public:
362     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
363         CommandObjectParsed (interpreter,
364                              "register write",
365                              "Modify a single register value.",
366                              NULL,
367                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
368     {
369         CommandArgumentEntry arg1;
370         CommandArgumentEntry arg2;
371         CommandArgumentData register_arg;
372         CommandArgumentData value_arg;
373 
374         // Define the first (and only) variant of this arg.
375         register_arg.arg_type = eArgTypeRegisterName;
376         register_arg.arg_repetition = eArgRepeatPlain;
377 
378         // There is only one variant this argument could be; put it into the argument entry.
379         arg1.push_back (register_arg);
380 
381         // Define the first (and only) variant of this arg.
382         value_arg.arg_type = eArgTypeValue;
383         value_arg.arg_repetition = eArgRepeatPlain;
384 
385         // There is only one variant this argument could be; put it into the argument entry.
386         arg2.push_back (value_arg);
387 
388         // Push the data for the first argument into the m_arguments vector.
389         m_arguments.push_back (arg1);
390         m_arguments.push_back (arg2);
391     }
392 
393     virtual
394     ~CommandObjectRegisterWrite ()
395     {
396     }
397 
398 protected:
399     virtual bool
400     DoExecute(Args& command, CommandReturnObject &result)
401     {
402         DataExtractor reg_data;
403         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
404         RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
405 
406         if (reg_ctx)
407         {
408             if (command.GetArgumentCount() != 2)
409             {
410                 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
411                 result.SetStatus (eReturnStatusFailed);
412             }
413             else
414             {
415                 const char *reg_name = command.GetArgumentAtIndex(0);
416                 const char *value_str = command.GetArgumentAtIndex(1);
417                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
418 
419                 if (reg_info)
420                 {
421                     RegisterValue reg_value;
422 
423                     Error error (reg_value.SetValueFromCString (reg_info, value_str));
424                     if (error.Success())
425                     {
426                         if (reg_ctx->WriteRegister (reg_info, reg_value))
427                         {
428                             // Toss all frames and anything else in the thread
429                             // after a register has been written.
430                             exe_ctx.GetThreadRef().Flush();
431                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
432                             return true;
433                         }
434                     }
435                     if (error.AsCString())
436                     {
437                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
438                                                      reg_name,
439                                                      value_str,
440                                                      error.AsCString());
441                     }
442                     else
443                     {
444                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
445                                                      reg_name,
446                                                      value_str);
447                     }
448                     result.SetStatus (eReturnStatusFailed);
449                 }
450                 else
451                 {
452                     result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
453                     result.SetStatus (eReturnStatusFailed);
454                 }
455             }
456         }
457         else
458         {
459             result.AppendError ("no current frame");
460             result.SetStatus (eReturnStatusFailed);
461         }
462         return result.Succeeded();
463     }
464 };
465 
466 
467 //----------------------------------------------------------------------
468 // CommandObjectRegister constructor
469 //----------------------------------------------------------------------
470 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
471     CommandObjectMultiword (interpreter,
472                             "register",
473                             "A set of commands to access thread registers.",
474                             "register [read|write] ...")
475 {
476     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
477     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
478 }
479 
480 
481 //----------------------------------------------------------------------
482 // Destructor
483 //----------------------------------------------------------------------
484 CommandObjectRegister::~CommandObjectRegister()
485 {
486 }
487