LLDB mainline
CommandObjectRegister.cpp
Go to the documentation of this file.
1//===-- CommandObjectRegister.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "lldb/Core/Debugger.h"
21#include "lldb/Target/Process.h"
24#include "lldb/Target/Thread.h"
25#include "lldb/Utility/Args.h"
28#include "llvm/Support/Errno.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33// "register read"
34#define LLDB_OPTIONS_register_read
35#include "CommandOptions.inc"
36
38public:
41 interpreter, "register read",
42 "Dump the contents of one or more register values from the current "
43 "frame. If no register is specified, dumps them all.",
44 nullptr,
45 eCommandRequiresFrame | eCommandRequiresRegContext |
46 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
49 CommandArgumentData register_arg;
50
51 // Define the first (and only) variant of this arg.
52 register_arg.arg_type = eArgTypeRegisterName;
53 register_arg.arg_repetition = eArgRepeatStar;
54
55 // There is only one variant this argument could be; put it into the
56 // argument entry.
57 arg.push_back(register_arg);
58
59 // Push the data for the first argument into the m_arguments vector.
60 m_arguments.push_back(arg);
61
62 // Add the "--format"
69 }
70
71 ~CommandObjectRegisterRead() override = default;
72
73 void
75 OptionElementVector &opt_element_vector) override {
77 return;
78
81 request, nullptr);
82 }
83
84 Options *GetOptions() override { return &m_option_group; }
85
86 bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
87 RegisterContext *reg_ctx, const RegisterInfo *reg_info) {
88 if (reg_info) {
89 RegisterValue reg_value;
90
91 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
92 strm.Indent();
93
94 bool prefix_with_altname = (bool)m_command_options.alternate_name;
95 bool prefix_with_name = !prefix_with_altname;
96 DumpRegisterValue(reg_value, &strm, reg_info, prefix_with_name,
97 prefix_with_altname, m_format_options.GetFormat(), 8,
99 if ((reg_info->encoding == eEncodingUint) ||
100 (reg_info->encoding == eEncodingSint)) {
101 Process *process = exe_ctx.GetProcessPtr();
102 if (process && reg_info->byte_size == process->GetAddressByteSize()) {
103 addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
104 if (reg_addr != LLDB_INVALID_ADDRESS) {
105 Address so_reg_addr;
106 if (exe_ctx.GetTargetRef()
108 .ResolveLoadAddress(reg_addr, so_reg_addr)) {
109 strm.PutCString(" ");
110 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(),
112 }
113 }
114 }
115 }
116 strm.EOL();
117 return true;
118 }
119 }
120 return false;
121 }
122
123 bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm,
124 RegisterContext *reg_ctx, size_t set_idx,
125 bool primitive_only = false) {
126 uint32_t unavailable_count = 0;
127 uint32_t available_count = 0;
128
129 if (!reg_ctx)
130 return false; // thread has no registers (i.e. core files are corrupt,
131 // incomplete crash logs...)
132
133 const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx);
134 if (reg_set) {
135 strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
136 strm.IndentMore();
137 const size_t num_registers = reg_set->num_registers;
138 for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
139 const uint32_t reg = reg_set->registers[reg_idx];
140 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
141 // Skip the dumping of derived register if primitive_only is true.
142 if (primitive_only && reg_info && reg_info->value_regs)
143 continue;
144
145 if (DumpRegister(exe_ctx, strm, reg_ctx, reg_info))
146 ++available_count;
147 else
148 ++unavailable_count;
149 }
150 strm.IndentLess();
151 if (unavailable_count) {
152 strm.Indent();
153 strm.Printf("%u registers were unavailable.\n", unavailable_count);
154 }
155 strm.EOL();
156 }
157 return available_count > 0;
158 }
159
160protected:
161 bool DoExecute(Args &command, CommandReturnObject &result) override {
162 Stream &strm = result.GetOutputStream();
164
165 const RegisterInfo *reg_info = nullptr;
166 if (command.GetArgumentCount() == 0) {
167 size_t set_idx;
168
169 size_t num_register_sets = 1;
170 const size_t set_array_size = m_command_options.set_indexes.GetSize();
171 if (set_array_size > 0) {
172 for (size_t i = 0; i < set_array_size; ++i) {
174 nullptr);
175 if (set_idx < reg_ctx->GetRegisterSetCount()) {
176 if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) {
177 if (errno)
178 result.AppendErrorWithFormatv("register read failed: {0}\n",
179 llvm::sys::StrError());
180 else
181 result.AppendError("unknown error while reading registers.\n");
182 break;
183 }
184 } else {
186 "invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
187 break;
188 }
189 }
190 } else {
192 num_register_sets = reg_ctx->GetRegisterSetCount();
193
194 for (set_idx = 0; set_idx < num_register_sets; ++set_idx) {
195 // When dump_all_sets option is set, dump primitive as well as
196 // derived registers.
197 DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx,
199 }
200 }
201 } else {
203 result.AppendError("the --all option can't be used when registers "
204 "names are supplied as arguments\n");
205 } else if (m_command_options.set_indexes.GetSize() > 0) {
206 result.AppendError("the --set <set> option can't be used when "
207 "registers names are supplied as arguments\n");
208 } else {
209 for (auto &entry : command) {
210 // in most LLDB commands we accept $rbx as the name for register RBX
211 // - and here we would reject it and non-existant. we should be more
212 // consistent towards the user and allow them to say reg read $rbx -
213 // internally, however, we should be strict and not allow ourselves
214 // to call our registers $rbx in our own API
215 auto arg_str = entry.ref();
216 arg_str.consume_front("$");
217
218 reg_info = reg_ctx->GetRegisterInfoByName(arg_str);
219
220 if (reg_info) {
221 if (!DumpRegister(m_exe_ctx, strm, reg_ctx, reg_info))
222 strm.Printf("%-12s = error: unavailable\n", reg_info->name);
223 } else {
224 result.AppendErrorWithFormat("Invalid register name '%s'.\n",
225 arg_str.str().c_str());
226 }
227 }
228 }
229 }
230 return result.Succeeded();
231 }
232
234 public:
236 : set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)),
237 dump_all_sets(false, false), // Initial and default values are false
238 alternate_name(false, false) {}
239
240 ~CommandOptions() override = default;
241
242 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
243 return llvm::ArrayRef(g_register_read_options);
244 }
245
246 void OptionParsingStarting(ExecutionContext *execution_context) override {
250 }
251
252 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
253 ExecutionContext *execution_context) override {
255 const int short_option = GetDefinitions()[option_idx].short_option;
256 switch (short_option) {
257 case 's': {
258 OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error));
259 if (value_sp)
260 set_indexes.AppendValue(value_sp);
261 } break;
262
263 case 'a':
264 // When we don't use OptionValue::SetValueFromCString(const char *) to
265 // set an option value, it won't be marked as being set in the options
266 // so we make a call to let users know the value was set via option
269 break;
270
271 case 'A':
272 // When we don't use OptionValue::SetValueFromCString(const char *) to
273 // set an option value, it won't be marked as being set in the options
274 // so we make a call to let users know the value was set via option
277 break;
278
279 default:
280 llvm_unreachable("Unimplemented option");
281 }
282 return error;
283 }
284
285 // Instance variables to hold the values for command options.
289 };
290
294};
295
296// "register write"
298public:
300 : CommandObjectParsed(interpreter, "register write",
301 "Modify a single register value.", nullptr,
302 eCommandRequiresFrame | eCommandRequiresRegContext |
303 eCommandProcessMustBeLaunched |
304 eCommandProcessMustBePaused) {
307 CommandArgumentData register_arg;
308 CommandArgumentData value_arg;
309
310 // Define the first (and only) variant of this arg.
311 register_arg.arg_type = eArgTypeRegisterName;
312 register_arg.arg_repetition = eArgRepeatPlain;
313
314 // There is only one variant this argument could be; put it into the
315 // argument entry.
316 arg1.push_back(register_arg);
317
318 // Define the first (and only) variant of this arg.
319 value_arg.arg_type = eArgTypeValue;
321
322 // There is only one variant this argument could be; put it into the
323 // argument entry.
324 arg2.push_back(value_arg);
325
326 // Push the data for the first argument into the m_arguments vector.
327 m_arguments.push_back(arg1);
328 m_arguments.push_back(arg2);
329 }
330
331 ~CommandObjectRegisterWrite() override = default;
332
333 void
335 OptionElementVector &opt_element_vector) override {
336 if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
337 return;
338
341 request, nullptr);
342 }
343
344protected:
345 bool DoExecute(Args &command, CommandReturnObject &result) override {
346 DataExtractor reg_data;
348
349 if (command.GetArgumentCount() != 2) {
350 result.AppendError(
351 "register write takes exactly 2 arguments: <reg-name> <value>");
352 } else {
353 auto reg_name = command[0].ref();
354 auto value_str = command[1].ref();
355
356 // in most LLDB commands we accept $rbx as the name for register RBX -
357 // and here we would reject it and non-existant. we should be more
358 // consistent towards the user and allow them to say reg write $rbx -
359 // internally, however, we should be strict and not allow ourselves to
360 // call our registers $rbx in our own API
361 reg_name.consume_front("$");
362
363 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
364
365 if (reg_info) {
366 RegisterValue reg_value;
367
368 Status error(reg_value.SetValueFromString(reg_info, value_str));
369 if (error.Success()) {
370 if (reg_ctx->WriteRegister(reg_info, reg_value)) {
371 // Toss all frames and anything else in the thread after a register
372 // has been written.
375 return true;
376 }
377 }
378 if (error.AsCString()) {
380 "Failed to write register '%s' with value '%s': %s\n",
381 reg_name.str().c_str(), value_str.str().c_str(),
382 error.AsCString());
383 } else {
385 "Failed to write register '%s' with value '%s'",
386 reg_name.str().c_str(), value_str.str().c_str());
387 }
388 } else {
389 result.AppendErrorWithFormat("Register not found for '%s'.\n",
390 reg_name.str().c_str());
391 }
392 }
393 return result.Succeeded();
394 }
395};
396
397// CommandObjectRegister constructor
399 : CommandObjectMultiword(interpreter, "register",
400 "Commands to access registers for the current "
401 "thread and stack frame.",
402 "register [read|write] ...") {
403 LoadSubCommand("read",
404 CommandObjectSP(new CommandObjectRegisterRead(interpreter)));
405 LoadSubCommand("write",
406 CommandObjectSP(new CommandObjectRegisterWrite(interpreter)));
407}
408
static llvm::raw_ostream & error(Stream &strm)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, size_t set_idx, bool primitive_only=false)
bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, const RegisterInfo *reg_info)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectRegisterRead() override=default
CommandObjectRegisterRead(CommandInterpreter &interpreter)
bool DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectRegisterWrite() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectRegisterWrite(CommandInterpreter &interpreter)
A section + offset based address class.
Definition: Address.h:59
@ DumpStyleResolvedDescription
Display the details about what an address resolves to.
Definition: Address.h:101
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX, bool all_ranges=false) const
Dump a description of this object to a Stream.
Definition: Address.cpp:406
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectRegister(CommandInterpreter &interpreter)
std::vector< CommandArgumentData > CommandArgumentEntry
ExecutionContext m_exe_ctx
std::vector< CommandArgumentEntry > m_arguments
CommandInterpreter & GetCommandInterpreter()
void AppendErrorWithFormatv(const char *format, Args &&... args)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
"lldb/Utility/ArgCompletionRequest.h"
An data extractor class.
Definition: DataExtractor.h:48
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool HasProcessScope() const
Returns true the ExecutionContext object contains a valid target and process.
ExecutionContextScope * GetBestExecutionContextScope() const
Target & GetTargetRef() const
Returns a reference to the target object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
Thread & GetThreadRef() const
Returns a reference to the thread object.
RegisterContext * GetRegisterContext() const
static const uint32_t OPTION_GROUP_GDB_FMT
static const uint32_t OPTION_GROUP_FORMAT
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition: Options.cpp:755
bool AppendValue(const lldb::OptionValueSP &value_sp)
static lldb::OptionValueSP Create(llvm::StringRef value_str, Status &error)
uint64_t GetUInt64Value(uint64_t fail_value, bool *success_ptr)
Definition: OptionValue.cpp:20
A command line option parsing protocol class.
Definition: Options.h:58
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3383
virtual const RegisterSet * GetRegisterSet(size_t reg_set)=0
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
virtual bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)=0
virtual size_t GetRegisterSetCount()=0
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
Status SetValueFromString(const RegisterInfo *reg_info, llvm::StringRef value_str)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, bool allow_section_end=false) const
An error handling class.
Definition: Status.h:44
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition: Stream.cpp:130
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:171
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition: Stream.cpp:168
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1103
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:101
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
#define UINT32_MAX
Definition: lldb-defines.h:19
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
void DumpRegisterValue(const RegisterValue &reg_val, Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, uint32_t reg_name_right_align_at=0, ExecutionContextScope *exe_scope=nullptr)
Definition: SBAddress.h:15
@ eEncodingUint
unsigned integer
@ eEncodingSint
signed integer
@ eReturnStatusSuccessFinishNoResult
@ eArgTypeRegisterName
uint64_t addr_t
Definition: lldb-types.h:83
Used to build individual command argument lists.
Definition: CommandObject.h:93