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/Options.h"
24 #include "lldb/Interpreter/OptionGroupFormat.h"
25 #include "lldb/Interpreter/OptionValueArray.h"
26 #include "lldb/Interpreter/OptionValueBoolean.h"
27 #include "lldb/Interpreter/OptionValueUInt64.h"
28 #include "lldb/Target/ExecutionContext.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SectionLoadList.h"
32 #include "lldb/Target/Thread.h"
33 #include "llvm/ADT/STLExtras.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 //----------------------------------------------------------------------
39 // "register read"
40 //----------------------------------------------------------------------
41 class CommandObjectRegisterRead : public CommandObjectParsed
42 {
43 public:
44     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
45         CommandObjectParsed (interpreter,
46                              "register read",
47                              "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
48                              NULL,
49                              eCommandRequiresFrame         |
50                              eCommandRequiresRegContext    |
51                              eCommandProcessMustBeLaunched |
52                              eCommandProcessMustBePaused   ),
53         m_option_group (interpreter),
54         m_format_options (eFormatDefault),
55         m_command_options ()
56     {
57         CommandArgumentEntry arg;
58         CommandArgumentData register_arg;
59 
60         // Define the first (and only) variant of this arg.
61         register_arg.arg_type = eArgTypeRegisterName;
62         register_arg.arg_repetition = eArgRepeatStar;
63 
64         // There is only one variant this argument could be; put it into the argument entry.
65         arg.push_back (register_arg);
66 
67         // Push the data for the first argument into the m_arguments vector.
68         m_arguments.push_back (arg);
69 
70         // Add the "--format"
71         m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
72         m_option_group.Append (&m_command_options);
73         m_option_group.Finalize();
74 
75     }
76 
77     ~CommandObjectRegisterRead () override
78     {
79     }
80 
81     Options *
82     GetOptions () override
83     {
84         return &m_option_group;
85     }
86 
87     bool
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 = (bool)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
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 ? reg_set->name : "unknown") );
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     bool
173     DoExecute (Args& command, CommandReturnObject &result) override
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: %s\n", strerror(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: %" PRIu64 "\n", (uint64_t)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:
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         ~CommandOptions () override
274         {
275         }
276 
277 
278         uint32_t
279         GetNumDefinitions () override;
280 
281         const OptionDefinition*
282         GetDefinitions () override
283         {
284             return g_option_table;
285         }
286 
287         void
288         OptionParsingStarting (CommandInterpreter &interpreter) override
289         {
290             set_indexes.Clear();
291             dump_all_sets.Clear();
292             alternate_name.Clear();
293         }
294 
295         Error
296         SetOptionValue (CommandInterpreter &interpreter,
297                         uint32_t option_idx,
298                         const char *option_value) override
299         {
300             Error error;
301             const int short_option = g_option_table[option_idx].short_option;
302             switch (short_option)
303             {
304                 case 's':
305                     {
306                         OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
307                         if (value_sp)
308                             set_indexes.AppendValue (value_sp);
309                     }
310                     break;
311 
312                 case 'a':
313                     // When we don't use OptionValue::SetValueFromCString(const char *) to
314                     // set an option value, it won't be marked as being set in the options
315                     // so we make a call to let users know the value was set via option
316                     dump_all_sets.SetCurrentValue (true);
317                     dump_all_sets.SetOptionWasSet ();
318                     break;
319 
320                 case 'A':
321                     // When we don't use OptionValue::SetValueFromCString(const char *) to
322                     // set an option value, it won't be marked as being set in the options
323                     // so we make a call to let users know the value was set via option
324                     alternate_name.SetCurrentValue (true);
325                     dump_all_sets.SetOptionWasSet ();
326                     break;
327 
328                 default:
329                     error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
330                     break;
331             }
332             return error;
333         }
334 
335         // Options table: Required for subclasses of Options.
336 
337         static const OptionDefinition g_option_table[];
338 
339         // Instance variables to hold the values for command options.
340         OptionValueArray set_indexes;
341         OptionValueBoolean dump_all_sets;
342         OptionValueBoolean alternate_name;
343     };
344 
345     OptionGroupOptions m_option_group;
346     OptionGroupFormat m_format_options;
347     CommandOptions m_command_options;
348 };
349 
350 const OptionDefinition
351 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
352 {
353     { 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."},
354     { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
355     { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone      , "Show all register sets."},
356 };
357 
358 uint32_t
359 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
360 {
361     return llvm::array_lengthof(g_option_table);
362 }
363 
364 
365 //----------------------------------------------------------------------
366 // "register write"
367 //----------------------------------------------------------------------
368 class CommandObjectRegisterWrite : public CommandObjectParsed
369 {
370 public:
371     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
372         CommandObjectParsed (interpreter,
373                              "register write",
374                              "Modify a single register value.",
375                              NULL,
376                              eCommandRequiresFrame         |
377                              eCommandRequiresRegContext    |
378                              eCommandProcessMustBeLaunched |
379                              eCommandProcessMustBePaused)
380     {
381         CommandArgumentEntry arg1;
382         CommandArgumentEntry arg2;
383         CommandArgumentData register_arg;
384         CommandArgumentData value_arg;
385 
386         // Define the first (and only) variant of this arg.
387         register_arg.arg_type = eArgTypeRegisterName;
388         register_arg.arg_repetition = eArgRepeatPlain;
389 
390         // There is only one variant this argument could be; put it into the argument entry.
391         arg1.push_back (register_arg);
392 
393         // Define the first (and only) variant of this arg.
394         value_arg.arg_type = eArgTypeValue;
395         value_arg.arg_repetition = eArgRepeatPlain;
396 
397         // There is only one variant this argument could be; put it into the argument entry.
398         arg2.push_back (value_arg);
399 
400         // Push the data for the first argument into the m_arguments vector.
401         m_arguments.push_back (arg1);
402         m_arguments.push_back (arg2);
403     }
404 
405     ~CommandObjectRegisterWrite () override
406     {
407     }
408 
409 protected:
410     bool
411     DoExecute(Args& command, CommandReturnObject &result) override
412     {
413         DataExtractor reg_data;
414         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
415 
416         if (command.GetArgumentCount() != 2)
417         {
418             result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
419             result.SetStatus (eReturnStatusFailed);
420         }
421         else
422         {
423             const char *reg_name = command.GetArgumentAtIndex(0);
424             const char *value_str = command.GetArgumentAtIndex(1);
425 
426 
427             // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
428             // reject it and non-existant. we should be more consistent towards the user and allow them
429             // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
430             // to call our registers $rbx in our own API
431             if (reg_name && *reg_name == '$')
432                 reg_name = reg_name+1;
433 
434             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
435 
436             if (reg_info)
437             {
438                 RegisterValue reg_value;
439 
440                 Error error (reg_value.SetValueFromCString (reg_info, value_str));
441                 if (error.Success())
442                 {
443                     if (reg_ctx->WriteRegister (reg_info, reg_value))
444                     {
445                         // Toss all frames and anything else in the thread
446                         // after a register has been written.
447                         m_exe_ctx.GetThreadRef().Flush();
448                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
449                         return true;
450                     }
451                 }
452                 if (error.AsCString())
453                 {
454                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
455                                                  reg_name,
456                                                  value_str,
457                                                  error.AsCString());
458                 }
459                 else
460                 {
461                     result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
462                                                  reg_name,
463                                                  value_str);
464                 }
465                 result.SetStatus (eReturnStatusFailed);
466             }
467             else
468             {
469                 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
470                 result.SetStatus (eReturnStatusFailed);
471             }
472         }
473         return result.Succeeded();
474     }
475 };
476 
477 
478 //----------------------------------------------------------------------
479 // CommandObjectRegister constructor
480 //----------------------------------------------------------------------
481 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
482     CommandObjectMultiword (interpreter,
483                             "register",
484                             "A set of commands to access thread registers.",
485                             "register [read|write] ...")
486 {
487     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
488     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
489 }
490 
491 
492 //----------------------------------------------------------------------
493 // Destructor
494 //----------------------------------------------------------------------
495 CommandObjectRegister::~CommandObjectRegister()
496 {
497 }
498