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