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