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/Scalar.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Interpreter/Args.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/NamedOptionValue.h"
23 #include "lldb/Interpreter/Options.h"
24 #include "lldb/Target/ExecutionContext.h"
25 #include "lldb/Target/RegisterContext.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 //----------------------------------------------------------------------
31 // "register read"
32 //----------------------------------------------------------------------
33 class CommandObjectRegisterRead : public CommandObject
34 {
35 public:
36     CommandObjectRegisterRead (CommandInterpreter &interpreter) :
37         CommandObject (interpreter,
38                        "register read",
39                        "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
40                        //"register read [<reg-name1> [<reg-name2> [...]]]",
41                        NULL,
42                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
43         m_options (interpreter)
44     {
45         CommandArgumentEntry arg;
46         CommandArgumentData register_arg;
47 
48         // Define the first (and only) variant of this arg.
49         register_arg.arg_type = eArgTypeRegisterName;
50         register_arg.arg_repetition = eArgRepeatStar;
51 
52         // There is only one variant this argument could be; put it into the argument entry.
53         arg.push_back (register_arg);
54 
55         // Push the data for the first argument into the m_arguments vector.
56         m_arguments.push_back (arg);
57     }
58 
59     virtual
60     ~CommandObjectRegisterRead ()
61     {
62     }
63 
64     Options *
65     GetOptions ()
66     {
67         return &m_options;
68     }
69 
70     bool
71     DumpRegister (const ExecutionContext &exe_ctx,
72                   Stream &strm,
73                   RegisterContext *reg_ctx,
74                   const RegisterInfo *reg_info)
75     {
76         if (reg_info)
77         {
78             uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
79 
80             DataExtractor reg_data;
81 
82             if (reg_ctx->ReadRegisterBytes(reg, reg_data))
83             {
84                 strm.Indent ();
85                 strm.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
86                 Format format;
87                 if (m_options.format == eFormatDefault)
88                     format = reg_info->format;
89                 else
90                     format = m_options.format;
91 
92                 reg_data.Dump(&strm, 0, format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
93                 if (m_options.lookup_addresses && ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)))
94                 {
95                     addr_t reg_addr = reg_ctx->ReadRegisterAsUnsigned (reg, 0);
96                     if (reg_addr)
97                     {
98                         Address so_reg_addr;
99                         if (exe_ctx.target->GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
100                         {
101                             strm.PutCString ("  ");
102                             so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
103                         }
104                         else
105                         {
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             lookup_addresses (false, false)         // Initial and default values are 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                     dump_all_sets.SetCurrentValue(true);
281                     break;
282 
283                 case 'l':
284                     lookup_addresses.SetCurrentValue(true);
285                     break;
286 
287                 default:
288                     error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
289                     break;
290             }
291             return error;
292         }
293 
294         void
295         OptionParsingStarting ()
296         {
297             format = eFormatDefault;
298             set_indexes.Clear();
299             dump_all_sets.Clear();
300             lookup_addresses.Clear();
301         }
302 
303         const OptionDefinition*
304         GetDefinitions ()
305         {
306             return g_option_table;
307         }
308 
309         // Options table: Required for subclasses of Options.
310 
311         static OptionDefinition g_option_table[];
312 
313         // Instance variables to hold the values for command options.
314         lldb::Format format;
315         OptionValueArray set_indexes;
316         OptionValueBoolean dump_all_sets;
317         OptionValueBoolean lookup_addresses;
318     };
319 
320     CommandOptions m_options;
321 };
322 
323 OptionDefinition
324 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
325 {
326     { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format to use when dumping register values."},
327     { LLDB_OPT_SET_ALL, false, "lookup", 'l', no_argument      , NULL, 0, eArgTypeNone      , "Lookup the register values as addresses and show that each value maps to in the address space."},
328     { LLDB_OPT_SET_1  , false, "set"   , 's', required_argument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
329     { LLDB_OPT_SET_2  , false, "all"   , 'a', no_argument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
330     { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
331 };
332 
333 
334 
335 //----------------------------------------------------------------------
336 // "register write"
337 //----------------------------------------------------------------------
338 class CommandObjectRegisterWrite : public CommandObject
339 {
340 public:
341     CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
342         CommandObject (interpreter,
343                        "register write",
344                        "Modify a single register value.",
345                        //"register write <reg-name> <value>",
346                        NULL,
347                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
348     {
349         CommandArgumentEntry arg1;
350         CommandArgumentEntry arg2;
351         CommandArgumentData register_arg;
352         CommandArgumentData value_arg;
353 
354         // Define the first (and only) variant of this arg.
355         register_arg.arg_type = eArgTypeRegisterName;
356         register_arg.arg_repetition = eArgRepeatPlain;
357 
358         // There is only one variant this argument could be; put it into the argument entry.
359         arg1.push_back (register_arg);
360 
361         // Define the first (and only) variant of this arg.
362         value_arg.arg_type = eArgTypeValue;
363         value_arg.arg_repetition = eArgRepeatPlain;
364 
365         // There is only one variant this argument could be; put it into the argument entry.
366         arg2.push_back (value_arg);
367 
368         // Push the data for the first argument into the m_arguments vector.
369         m_arguments.push_back (arg1);
370         m_arguments.push_back (arg2);
371     }
372 
373     virtual
374     ~CommandObjectRegisterWrite ()
375     {
376     }
377 
378     virtual bool
379     Execute
380     (
381         Args& command,
382         CommandReturnObject &result
383     )
384     {
385         DataExtractor reg_data;
386         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
387         RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
388 
389         if (reg_ctx)
390         {
391             if (command.GetArgumentCount() != 2)
392             {
393                 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
394                 result.SetStatus (eReturnStatusFailed);
395             }
396             else
397             {
398                 const char *reg_name = command.GetArgumentAtIndex(0);
399                 const char *value_str = command.GetArgumentAtIndex(1);
400                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
401 
402                 if (reg_info)
403                 {
404                     Scalar scalar;
405                     Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
406                     if (error.Success())
407                     {
408                         if (reg_ctx->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
409                         {
410                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
411                             return true;
412                         }
413                     }
414                     else
415                     {
416                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
417                                                      reg_name,
418                                                      value_str,
419                                                      error.AsCString());
420                         result.SetStatus (eReturnStatusFailed);
421                     }
422                 }
423                 else
424                 {
425                     result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
426                     result.SetStatus (eReturnStatusFailed);
427                 }
428             }
429         }
430         else
431         {
432             result.AppendError ("no current frame");
433             result.SetStatus (eReturnStatusFailed);
434         }
435         return result.Succeeded();
436     }
437 };
438 
439 
440 //----------------------------------------------------------------------
441 // CommandObjectRegister constructor
442 //----------------------------------------------------------------------
443 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
444     CommandObjectMultiword (interpreter,
445                             "register",
446                             "A set of commands to access thread registers.",
447                             "register [read|write] ...")
448 {
449     LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
450     LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
451 }
452 
453 
454 //----------------------------------------------------------------------
455 // Destructor
456 //----------------------------------------------------------------------
457 CommandObjectRegister::~CommandObjectRegister()
458 {
459 }
460