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