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