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