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