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"
12 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Utility/Args.h"
27 #include "llvm/Support/Errno.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 // "register read"
33 #define LLDB_OPTIONS_register_read
34 #include "CommandOptions.inc"
35 
37 public:
40  interpreter, "register read",
41  "Dump the contents of one or more register values from the current "
42  "frame. If no register is specified, dumps them all.",
43  nullptr,
44  eCommandRequiresFrame | eCommandRequiresRegContext |
45  eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
46  m_option_group(), m_format_options(eFormatDefault),
47  m_command_options() {
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"
63  m_option_group.Append(&m_format_options,
64  OptionGroupFormat::OPTION_GROUP_FORMAT |
65  OptionGroupFormat::OPTION_GROUP_GDB_FMT,
67  m_option_group.Append(&m_command_options);
68  m_option_group.Finalize();
69  }
70 
71  ~CommandObjectRegisterRead() override = default;
72 
73  void
75  OptionElementVector &opt_element_vector) override {
76  if (!m_exe_ctx.HasProcessScope())
77  return;
78 
79  CommandCompletions::InvokeCommonCompletionCallbacks(
80  GetCommandInterpreter(), CommandCompletions::eRegisterCompletion,
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);
98  if ((reg_info->encoding == eEncodingUint) ||
99  (reg_info->encoding == eEncodingSint)) {
100  Process *process = exe_ctx.GetProcessPtr();
101  if (process && reg_info->byte_size == process->GetAddressByteSize()) {
102  addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
103  if (reg_addr != LLDB_INVALID_ADDRESS) {
104  Address so_reg_addr;
105  if (exe_ctx.GetTargetRef()
107  .ResolveLoadAddress(reg_addr, so_reg_addr)) {
108  strm.PutCString(" ");
109  so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(),
110  Address::DumpStyleResolvedDescription);
111  }
112  }
113  }
114  }
115  strm.EOL();
116  return true;
117  }
118  }
119  return false;
120  }
121 
122  bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm,
123  RegisterContext *reg_ctx, size_t set_idx,
124  bool primitive_only = false) {
125  uint32_t unavailable_count = 0;
126  uint32_t available_count = 0;
127 
128  if (!reg_ctx)
129  return false; // thread has no registers (i.e. core files are corrupt,
130  // incomplete crash logs...)
131 
132  const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx);
133  if (reg_set) {
134  strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
135  strm.IndentMore();
136  const size_t num_registers = reg_set->num_registers;
137  for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
138  const uint32_t reg = reg_set->registers[reg_idx];
139  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
140  // Skip the dumping of derived register if primitive_only is true.
141  if (primitive_only && reg_info && reg_info->value_regs)
142  continue;
143 
144  if (DumpRegister(exe_ctx, strm, reg_ctx, reg_info))
145  ++available_count;
146  else
147  ++unavailable_count;
148  }
149  strm.IndentLess();
150  if (unavailable_count) {
151  strm.Indent();
152  strm.Printf("%u registers were unavailable.\n", unavailable_count);
153  }
154  strm.EOL();
155  }
156  return available_count > 0;
157  }
158 
159 protected:
160  bool DoExecute(Args &command, CommandReturnObject &result) override {
161  Stream &strm = result.GetOutputStream();
162  RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
163 
164  const RegisterInfo *reg_info = nullptr;
165  if (command.GetArgumentCount() == 0) {
166  size_t set_idx;
167 
168  size_t num_register_sets = 1;
169  const size_t set_array_size = m_command_options.set_indexes.GetSize();
170  if (set_array_size > 0) {
171  for (size_t i = 0; i < set_array_size; ++i) {
172  set_idx = m_command_options.set_indexes[i]->GetUInt64Value(UINT32_MAX,
173  nullptr);
174  if (set_idx < reg_ctx->GetRegisterSetCount()) {
175  if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) {
176  if (errno)
177  result.AppendErrorWithFormatv("register read failed: {0}\n",
178  llvm::sys::StrError());
179  else
180  result.AppendError("unknown error while reading registers.\n");
182  break;
183  }
184  } else {
185  result.AppendErrorWithFormat(
186  "invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
188  break;
189  }
190  }
191  } else {
192  if (m_command_options.dump_all_sets)
193  num_register_sets = reg_ctx->GetRegisterSetCount();
194 
195  for (set_idx = 0; set_idx < num_register_sets; ++set_idx) {
196  // When dump_all_sets option is set, dump primitive as well as
197  // derived registers.
198  DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx,
199  !m_command_options.dump_all_sets.GetCurrentValue());
200  }
201  }
202  } else {
203  if (m_command_options.dump_all_sets) {
204  result.AppendError("the --all option can't be used when registers "
205  "names are supplied as arguments\n");
207  } else if (m_command_options.set_indexes.GetSize() > 0) {
208  result.AppendError("the --set <set> option can't be used when "
209  "registers names are supplied as arguments\n");
211  } else {
212  for (auto &entry : command) {
213  // in most LLDB commands we accept $rbx as the name for register RBX
214  // - and here we would reject it and non-existant. we should be more
215  // consistent towards the user and allow them to say reg read $rbx -
216  // internally, however, we should be strict and not allow ourselves
217  // to call our registers $rbx in our own API
218  auto arg_str = entry.ref();
219  arg_str.consume_front("$");
220 
221  reg_info = reg_ctx->GetRegisterInfoByName(arg_str);
222 
223  if (reg_info) {
224  if (!DumpRegister(m_exe_ctx, strm, reg_ctx, reg_info))
225  strm.Printf("%-12s = error: unavailable\n", reg_info->name);
226  } else {
227  result.AppendErrorWithFormat("Invalid register name '%s'.\n",
228  arg_str.str().c_str());
229  }
230  }
231  }
232  }
233  return result.Succeeded();
234  }
235 
236  class CommandOptions : public OptionGroup {
237  public:
239  : OptionGroup(),
240  set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)),
241  dump_all_sets(false, false), // Initial and default values are false
242  alternate_name(false, false) {}
243 
244  ~CommandOptions() override = default;
245 
246  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
247  return llvm::makeArrayRef(g_register_read_options);
248  }
249 
250  void OptionParsingStarting(ExecutionContext *execution_context) override {
251  set_indexes.Clear();
252  dump_all_sets.Clear();
253  alternate_name.Clear();
254  }
255 
256  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
257  ExecutionContext *execution_context) override {
258  Status error;
259  const int short_option = GetDefinitions()[option_idx].short_option;
260  switch (short_option) {
261  case 's': {
262  OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error));
263  if (value_sp)
264  set_indexes.AppendValue(value_sp);
265  } break;
266 
267  case 'a':
268  // When we don't use OptionValue::SetValueFromCString(const char *) to
269  // set an option value, it won't be marked as being set in the options
270  // so we make a call to let users know the value was set via option
271  dump_all_sets.SetCurrentValue(true);
272  dump_all_sets.SetOptionWasSet();
273  break;
274 
275  case 'A':
276  // When we don't use OptionValue::SetValueFromCString(const char *) to
277  // set an option value, it won't be marked as being set in the options
278  // so we make a call to let users know the value was set via option
279  alternate_name.SetCurrentValue(true);
280  dump_all_sets.SetOptionWasSet();
281  break;
282 
283  default:
284  llvm_unreachable("Unimplemented option");
285  }
286  return error;
287  }
288 
289  // Instance variables to hold the values for command options.
293  };
294 
298 };
299 
300 // "register write"
302 public:
304  : CommandObjectParsed(interpreter, "register write",
305  "Modify a single register value.", nullptr,
306  eCommandRequiresFrame | eCommandRequiresRegContext |
307  eCommandProcessMustBeLaunched |
308  eCommandProcessMustBePaused) {
311  CommandArgumentData register_arg;
312  CommandArgumentData value_arg;
313 
314  // Define the first (and only) variant of this arg.
315  register_arg.arg_type = eArgTypeRegisterName;
316  register_arg.arg_repetition = eArgRepeatPlain;
317 
318  // There is only one variant this argument could be; put it into the
319  // argument entry.
320  arg1.push_back(register_arg);
321 
322  // Define the first (and only) variant of this arg.
323  value_arg.arg_type = eArgTypeValue;
324  value_arg.arg_repetition = eArgRepeatPlain;
325 
326  // There is only one variant this argument could be; put it into the
327  // argument entry.
328  arg2.push_back(value_arg);
329 
330  // Push the data for the first argument into the m_arguments vector.
331  m_arguments.push_back(arg1);
332  m_arguments.push_back(arg2);
333  }
334 
335  ~CommandObjectRegisterWrite() override = default;
336 
337  void
339  OptionElementVector &opt_element_vector) override {
340  if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
341  return;
342 
343  CommandCompletions::InvokeCommonCompletionCallbacks(
344  GetCommandInterpreter(), CommandCompletions::eRegisterCompletion,
345  request, nullptr);
346  }
347 
348 protected:
349  bool DoExecute(Args &command, CommandReturnObject &result) override {
350  DataExtractor reg_data;
351  RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
352 
353  if (command.GetArgumentCount() != 2) {
354  result.AppendError(
355  "register write takes exactly 2 arguments: <reg-name> <value>");
357  } else {
358  auto reg_name = command[0].ref();
359  auto value_str = command[1].ref();
360 
361  // in most LLDB commands we accept $rbx as the name for register RBX -
362  // and here we would reject it and non-existant. we should be more
363  // consistent towards the user and allow them to say reg write $rbx -
364  // internally, however, we should be strict and not allow ourselves to
365  // call our registers $rbx in our own API
366  reg_name.consume_front("$");
367 
368  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
369 
370  if (reg_info) {
371  RegisterValue reg_value;
372 
373  Status error(reg_value.SetValueFromString(reg_info, value_str));
374  if (error.Success()) {
375  if (reg_ctx->WriteRegister(reg_info, reg_value)) {
376  // Toss all frames and anything else in the thread after a register
377  // has been written.
378  m_exe_ctx.GetThreadRef().Flush();
380  return true;
381  }
382  }
383  if (error.AsCString()) {
384  result.AppendErrorWithFormat(
385  "Failed to write register '%s' with value '%s': %s\n",
386  reg_name.str().c_str(), value_str.str().c_str(),
387  error.AsCString());
388  } else {
389  result.AppendErrorWithFormat(
390  "Failed to write register '%s' with value '%s'",
391  reg_name.str().c_str(), value_str.str().c_str());
392  }
394  } else {
395  result.AppendErrorWithFormat("Register not found for '%s'.\n",
396  reg_name.str().c_str());
398  }
399  }
400  return result.Succeeded();
401  }
402 };
403 
404 // CommandObjectRegister constructor
405 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter)
406  : CommandObjectMultiword(interpreter, "register",
407  "Commands to access registers for the current "
408  "thread and stack frame.",
409  "register [read|write] ...") {
410  LoadSubCommand("read",
411  CommandObjectSP(new CommandObjectRegisterRead(interpreter)));
412  LoadSubCommand("write",
413  CommandObjectSP(new CommandObjectRegisterWrite(interpreter)));
414 }
415 
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:62
std::vector< CommandArgumentData > CommandArgumentEntry
An data extractor class.
Definition: DataExtractor.h:46
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition: Stream.cpp:167
A command line argument class.
Definition: Args.h:33
A class that represents a running process on the host machine.
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:170
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX) const
Dump a description of this object to a Stream.
Definition: Address.cpp:392
virtual bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)=0
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Status SetValueFromString(const RegisterInfo *reg_info, llvm::StringRef value_str)
"lldb/Utility/ArgCompletionRequest.h"
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:41
bool 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)
#define UINT32_MAX
Definition: lldb-defines.h:31
virtual const RegisterSet * GetRegisterSet(size_t reg_set)=0
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectRegisterWrite(CommandInterpreter &interpreter)
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition: Stream.cpp:129
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1013
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3431
bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, const RegisterInfo *reg_info)
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, bool allow_section_end=false) const
unsigned integer
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
A plug-in interface definition class for debugging a process.
Definition: Process.h:362
Process * GetProcessPtr() const
Returns a pointer to the process object.
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
void AppendErrorWithFormatv(const char *format, Args &&... args)
A section + offset based address class.
Definition: Address.h:59
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, uint32_t reg_num, Format format)
A command line option parsing protocol class.
Definition: Options.h:62
bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, size_t set_idx, bool primitive_only=false)
void void AppendError(llvm::StringRef in_string)
uint64_t addr_t
Definition: lldb-types.h:83
void OptionParsingStarting(ExecutionContext *execution_context) override
Target & GetTargetRef() const
Returns a reference to the target object.
Definition: SBAddress.h:15
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:110
bool DoExecute(Args &command, CommandReturnObject &result) override
ExecutionContextScope * GetBestExecutionContextScope() const
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
virtual size_t GetRegisterSetCount()=0
void SetStatus(lldb::ReturnStatus status)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
CommandObjectRegisterRead(CommandInterpreter &interpreter)
An error handling class.
Definition: Status.h:44