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