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