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