blob: da1d15068ce9bd6e5b3fa89796e4d08fac046a7a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/Scalar.h"
Greg Clayton63094e02010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
19#include "lldb/Interpreter/Args.h"
20#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Target/ExecutionContext.h"
23#include "lldb/Target/RegisterContext.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//----------------------------------------------------------------------
29// "register read"
30//----------------------------------------------------------------------
31class CommandObjectRegisterRead : public CommandObject
32{
33public:
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
Greg Clayton63094e02010-06-23 01:19:29 +000048 Execute
49 (
50 CommandInterpreter &interpreter,
51 Args& command,
52 CommandReturnObject &result
53 )
Chris Lattner24943d22010-06-08 16:52:24 +000054 {
55 StreamString &output_stream = result.GetOutputStream();
56 DataExtractor reg_data;
Greg Clayton63094e02010-06-23 01:19:29 +000057 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +000058 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//----------------------------------------------------------------------
139class CommandObjectRegisterWrite : public CommandObject
140{
141public:
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
Greg Clayton63094e02010-06-23 01:19:29 +0000156 Execute
157 (
158 CommandInterpreter &interpreter,
159 Args& command,
160 CommandReturnObject &result
161 )
Chris Lattner24943d22010-06-08 16:52:24 +0000162 {
163 DataExtractor reg_data;
Greg Clayton63094e02010-06-23 01:19:29 +0000164 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000165 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//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000221CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000222 CommandObjectMultiword ("register",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000223 "A set of commands to access thread registers.",
Chris Lattner24943d22010-06-08 16:52:24 +0000224 "register [read|write] ...")
225{
Greg Clayton63094e02010-06-23 01:19:29 +0000226 LoadSubCommand (interpreter, "read", CommandObjectSP (new CommandObjectRegisterRead ()));
227 LoadSubCommand (interpreter, "write", CommandObjectSP (new CommandObjectRegisterWrite ()));
Chris Lattner24943d22010-06-08 16:52:24 +0000228}
229
230
231//----------------------------------------------------------------------
232// Destructor
233//----------------------------------------------------------------------
234CommandObjectRegister::~CommandObjectRegister()
235{
236}