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/Args.h"
17 #include "lldb/Core/DataExtractor.h"
18 #include "lldb/Core/Scalar.h"
19 #include "lldb/Interpreter/CommandContext.h"
20 #include "lldb/Interpreter/CommandReturnObject.h"
21 #include "lldb/Target/ExecutionContext.h"
22 #include "lldb/Target/RegisterContext.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // "register read"
29 //----------------------------------------------------------------------
30 class CommandObjectRegisterRead : public CommandObject
31 {
32 public:
33     CommandObjectRegisterRead () :
34         CommandObject ("register read",
35                        "Dump the one or more register values from the current frame.",
36                        "register read [<reg-name1> [<reg-name2> [...]]]",
37                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
38     {
39     }
40 
41     virtual
42     ~CommandObjectRegisterRead ()
43     {
44     }
45 
46     virtual bool
47     Execute (Args& command,
48              CommandContext *context,
49              CommandInterpreter *interpreter,
50              CommandReturnObject &result)
51     {
52         StreamString &output_stream = result.GetOutputStream();
53         DataExtractor reg_data;
54         ExecutionContext exe_ctx(context->GetExecutionContext());
55         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
56 
57         if (reg_context)
58         {
59             const RegisterInfo *reg_info = NULL;
60             if (command.GetArgumentCount() == 0)
61             {
62                 uint32_t set_idx;
63                 const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
64                 for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
65                 {
66                     uint32_t unavailable_count = 0;
67                     const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
68                     output_stream.Printf ("%s:\n", reg_set->name);
69                     output_stream.IndentMore ();
70                     const uint32_t num_registers = reg_set->num_registers;
71                     for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
72                     {
73                         uint32_t reg = reg_set->registers[reg_idx];
74                         reg_info = reg_context->GetRegisterInfoAtIndex(reg);
75                         if (reg_context->ReadRegisterBytes(reg, reg_data))
76                         {
77                             output_stream.Indent ();
78                             output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
79                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
80                             output_stream.EOL();
81                         }
82                         else
83                         {
84                             ++unavailable_count;
85                         }
86                     }
87                     if (unavailable_count)
88                     {
89                         output_stream.Indent ();
90                         output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
91                     }
92                     output_stream.IndentLess ();
93                     output_stream.EOL();
94                 }
95             }
96             else
97             {
98                 const char *arg_cstr;
99                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
100                 {
101                     reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
102 
103                     if (reg_info)
104                     {
105                         output_stream.Printf("%-12s = ", reg_info->name);
106                         if (reg_context->ReadRegisterBytes(reg_info->reg, reg_data))
107                         {
108                             reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
109                         }
110                         else
111                         {
112                             output_stream.PutCString ("error: unavailable");
113                         }
114                         output_stream.EOL();
115                     }
116                     else
117                     {
118                         result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
119                     }
120                 }
121             }
122         }
123         else
124         {
125             result.AppendError ("no current frame");
126             result.SetStatus (eReturnStatusFailed);
127         }
128         return result.Succeeded();
129     }
130 };
131 
132 
133 //----------------------------------------------------------------------
134 // "register write"
135 //----------------------------------------------------------------------
136 class CommandObjectRegisterWrite : public CommandObject
137 {
138 public:
139     CommandObjectRegisterWrite () :
140         CommandObject ("register write",
141                        "Modify a single register value.",
142                        "register write <reg-name> <value>",
143                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
144     {
145     }
146 
147     virtual
148     ~CommandObjectRegisterWrite ()
149     {
150     }
151 
152     virtual bool
153     Execute (Args& command,
154              CommandContext *context,
155              CommandInterpreter *interpreter,
156              CommandReturnObject &result)
157     {
158         DataExtractor reg_data;
159         ExecutionContext exe_ctx(context->GetExecutionContext());
160         RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
161 
162         if (reg_context)
163         {
164             if (command.GetArgumentCount() != 2)
165             {
166                 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
167                 result.SetStatus (eReturnStatusFailed);
168             }
169             else
170             {
171                 const char *reg_name = command.GetArgumentAtIndex(0);
172                 const char *value_str = command.GetArgumentAtIndex(1);
173                 const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
174 
175                 if (reg_info)
176                 {
177                     Scalar scalar;
178                     Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
179                     if (error.Success())
180                     {
181                         if (reg_context->WriteRegisterValue(reg_info->reg, scalar))
182                         {
183                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
184                             return true;
185                         }
186                     }
187                     else
188                     {
189                         result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
190                                                      reg_name,
191                                                      value_str,
192                                                      error.AsCString());
193                         result.SetStatus (eReturnStatusFailed);
194                     }
195                 }
196                 else
197                 {
198                     result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
199                     result.SetStatus (eReturnStatusFailed);
200                 }
201             }
202         }
203         else
204         {
205             result.AppendError ("no current frame");
206             result.SetStatus (eReturnStatusFailed);
207         }
208         return result.Succeeded();
209     }
210 };
211 
212 
213 //----------------------------------------------------------------------
214 // CommandObjectRegister constructor
215 //----------------------------------------------------------------------
216 CommandObjectRegister::CommandObjectRegister(CommandInterpreter *interpreter) :
217     CommandObjectMultiword ("register",
218                             "Access thread registers.",
219                             "register [read|write] ...")
220 {
221     LoadSubCommand (CommandObjectSP (new CommandObjectRegisterRead ()), "read", interpreter);
222     LoadSubCommand (CommandObjectSP (new CommandObjectRegisterWrite ()), "write", interpreter);
223 }
224 
225 
226 //----------------------------------------------------------------------
227 // Destructor
228 //----------------------------------------------------------------------
229 CommandObjectRegister::~CommandObjectRegister()
230 {
231 }
232