xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- CommandObjectRegister.cpp -----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "CommandObjectRegister.h"
1014f1b3e8SDimitry Andric #include "lldb/Core/Debugger.h"
117fa27ce4SDimitry Andric #include "lldb/Core/DumpRegisterInfo.h"
12f73363f1SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
1374a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
147fa27ce4SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
154b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
16f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
17f034231aSEd Maste #include "lldb/Interpreter/OptionGroupFormat.h"
18f034231aSEd Maste #include "lldb/Interpreter/OptionValueArray.h"
195e95aa85SEd Maste #include "lldb/Interpreter/OptionValueBoolean.h"
20f034231aSEd Maste #include "lldb/Interpreter/OptionValueUInt64.h"
2114f1b3e8SDimitry Andric #include "lldb/Interpreter/Options.h"
22f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
23f034231aSEd Maste #include "lldb/Target/Process.h"
24f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
25866dcdacSEd Maste #include "lldb/Target/SectionLoadList.h"
26f034231aSEd Maste #include "lldb/Target/Thread.h"
27f73363f1SDimitry Andric #include "lldb/Utility/Args.h"
2874a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
2994994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
30f1d04915SDimitry Andric #include "llvm/Support/Errno.h"
31f034231aSEd Maste 
32f034231aSEd Maste using namespace lldb;
33f034231aSEd Maste using namespace lldb_private;
34f034231aSEd Maste 
35f034231aSEd Maste // "register read"
36ead24645SDimitry Andric #define LLDB_OPTIONS_register_read
37ead24645SDimitry Andric #include "CommandOptions.inc"
3814f1b3e8SDimitry Andric 
3914f1b3e8SDimitry Andric class CommandObjectRegisterRead : public CommandObjectParsed {
40f034231aSEd Maste public:
CommandObjectRegisterRead(CommandInterpreter & interpreter)4114f1b3e8SDimitry Andric   CommandObjectRegisterRead(CommandInterpreter &interpreter)
4214f1b3e8SDimitry Andric       : CommandObjectParsed(
4314f1b3e8SDimitry Andric             interpreter, "register read",
4414f1b3e8SDimitry Andric             "Dump the contents of one or more register values from the current "
4514f1b3e8SDimitry Andric             "frame.  If no register is specified, dumps them all.",
46f3fbd1c0SDimitry Andric             nullptr,
4714f1b3e8SDimitry Andric             eCommandRequiresFrame | eCommandRequiresRegContext |
4814f1b3e8SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
497fa27ce4SDimitry Andric         m_format_options(eFormatDefault, UINT64_MAX, UINT64_MAX,
507fa27ce4SDimitry Andric                          {{CommandArgumentType::eArgTypeFormat,
517fa27ce4SDimitry Andric                            "Specify a format to be used for display. If this "
527fa27ce4SDimitry Andric                            "is set, register fields will not be displayed."}}) {
53ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRegisterName, eArgRepeatStar);
54f034231aSEd Maste 
55f034231aSEd Maste     // Add the "--format"
5614f1b3e8SDimitry Andric     m_option_group.Append(&m_format_options,
5714f1b3e8SDimitry Andric                           OptionGroupFormat::OPTION_GROUP_FORMAT |
5814f1b3e8SDimitry Andric                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
5914f1b3e8SDimitry Andric                           LLDB_OPT_SET_ALL);
60f034231aSEd Maste     m_option_group.Append(&m_command_options);
61f034231aSEd Maste     m_option_group.Finalize();
62f034231aSEd Maste   }
63f034231aSEd Maste 
64f3fbd1c0SDimitry Andric   ~CommandObjectRegisterRead() override = default;
65f034231aSEd Maste 
66cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)67cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
68cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
69cfca06d7SDimitry Andric     if (!m_exe_ctx.HasProcessScope())
70cfca06d7SDimitry Andric       return;
71ac9a064cSDimitry Andric     CommandObject::HandleArgumentCompletion(request, opt_element_vector);
72cfca06d7SDimitry Andric   }
73cfca06d7SDimitry Andric 
GetOptions()7414f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
75f034231aSEd Maste 
DumpRegister(const ExecutionContext & exe_ctx,Stream & strm,RegisterContext & reg_ctx,const RegisterInfo & reg_info,bool print_flags)7614f1b3e8SDimitry Andric   bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
777fa27ce4SDimitry Andric                     RegisterContext &reg_ctx, const RegisterInfo &reg_info,
787fa27ce4SDimitry Andric                     bool print_flags) {
79f034231aSEd Maste     RegisterValue reg_value;
807fa27ce4SDimitry Andric     if (!reg_ctx.ReadRegister(&reg_info, reg_value))
817fa27ce4SDimitry Andric       return false;
82f034231aSEd Maste 
83f034231aSEd Maste     strm.Indent();
84f034231aSEd Maste 
85f21a844fSEd Maste     bool prefix_with_altname = (bool)m_command_options.alternate_name;
86f034231aSEd Maste     bool prefix_with_name = !prefix_with_altname;
877fa27ce4SDimitry Andric     DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name,
88e3b55780SDimitry Andric                       prefix_with_altname, m_format_options.GetFormat(), 8,
897fa27ce4SDimitry Andric                       exe_ctx.GetBestExecutionContextScope(), print_flags,
907fa27ce4SDimitry Andric                       exe_ctx.GetTargetSP());
917fa27ce4SDimitry Andric     if ((reg_info.encoding == eEncodingUint) ||
927fa27ce4SDimitry Andric         (reg_info.encoding == eEncodingSint)) {
93f034231aSEd Maste       Process *process = exe_ctx.GetProcessPtr();
947fa27ce4SDimitry Andric       if (process && reg_info.byte_size == process->GetAddressByteSize()) {
95f034231aSEd Maste         addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
9614f1b3e8SDimitry Andric         if (reg_addr != LLDB_INVALID_ADDRESS) {
97f034231aSEd Maste           Address so_reg_addr;
987fa27ce4SDimitry Andric           if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(
997fa27ce4SDimitry Andric                   reg_addr, so_reg_addr)) {
100f034231aSEd Maste             strm.PutCString("  ");
10114f1b3e8SDimitry Andric             so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(),
10214f1b3e8SDimitry Andric                              Address::DumpStyleResolvedDescription);
103f034231aSEd Maste           }
104f034231aSEd Maste         }
105f034231aSEd Maste       }
106f034231aSEd Maste     }
107f034231aSEd Maste     strm.EOL();
108f034231aSEd Maste     return true;
109f034231aSEd Maste   }
110f034231aSEd Maste 
DumpRegisterSet(const ExecutionContext & exe_ctx,Stream & strm,RegisterContext * reg_ctx,size_t set_idx,bool primitive_only=false)11114f1b3e8SDimitry Andric   bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm,
11214f1b3e8SDimitry Andric                        RegisterContext *reg_ctx, size_t set_idx,
11314f1b3e8SDimitry Andric                        bool primitive_only = false) {
114f034231aSEd Maste     uint32_t unavailable_count = 0;
115f034231aSEd Maste     uint32_t available_count = 0;
116f034231aSEd Maste 
117f034231aSEd Maste     if (!reg_ctx)
11814f1b3e8SDimitry Andric       return false; // thread has no registers (i.e. core files are corrupt,
11914f1b3e8SDimitry Andric                     // incomplete crash logs...)
120f034231aSEd Maste 
121f034231aSEd Maste     const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx);
12214f1b3e8SDimitry Andric     if (reg_set) {
1235e95aa85SEd Maste       strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
124f034231aSEd Maste       strm.IndentMore();
125f034231aSEd Maste       const size_t num_registers = reg_set->num_registers;
12614f1b3e8SDimitry Andric       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
127f034231aSEd Maste         const uint32_t reg = reg_set->registers[reg_idx];
128f034231aSEd Maste         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
129f034231aSEd Maste         // Skip the dumping of derived register if primitive_only is true.
130f034231aSEd Maste         if (primitive_only && reg_info && reg_info->value_regs)
131f034231aSEd Maste           continue;
132f034231aSEd Maste 
1337fa27ce4SDimitry Andric         if (reg_info && DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info,
1347fa27ce4SDimitry Andric                                      /*print_flags=*/false))
135f034231aSEd Maste           ++available_count;
136f034231aSEd Maste         else
137f034231aSEd Maste           ++unavailable_count;
138f034231aSEd Maste       }
139f034231aSEd Maste       strm.IndentLess();
14014f1b3e8SDimitry Andric       if (unavailable_count) {
141f034231aSEd Maste         strm.Indent();
142f034231aSEd Maste         strm.Printf("%u registers were unavailable.\n", unavailable_count);
143f034231aSEd Maste       }
144f034231aSEd Maste       strm.EOL();
145f034231aSEd Maste     }
146f034231aSEd Maste     return available_count > 0;
147f034231aSEd Maste   }
148f034231aSEd Maste 
149f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)150b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
151f034231aSEd Maste     Stream &strm = result.GetOutputStream();
152f034231aSEd Maste     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
153f034231aSEd Maste 
15414f1b3e8SDimitry Andric     if (command.GetArgumentCount() == 0) {
155f034231aSEd Maste       size_t set_idx;
156f034231aSEd Maste 
157f034231aSEd Maste       size_t num_register_sets = 1;
158f034231aSEd Maste       const size_t set_array_size = m_command_options.set_indexes.GetSize();
15914f1b3e8SDimitry Andric       if (set_array_size > 0) {
16014f1b3e8SDimitry Andric         for (size_t i = 0; i < set_array_size; ++i) {
1617fa27ce4SDimitry Andric           set_idx =
1627fa27ce4SDimitry Andric               m_command_options.set_indexes[i]->GetValueAs<uint64_t>().value_or(
1637fa27ce4SDimitry Andric                   UINT32_MAX);
16414f1b3e8SDimitry Andric           if (set_idx < reg_ctx->GetRegisterSetCount()) {
16514f1b3e8SDimitry Andric             if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) {
166f034231aSEd Maste               if (errno)
167f1d04915SDimitry Andric                 result.AppendErrorWithFormatv("register read failed: {0}\n",
168f1d04915SDimitry Andric                                               llvm::sys::StrError());
169f034231aSEd Maste               else
170f034231aSEd Maste                 result.AppendError("unknown error while reading registers.\n");
171f034231aSEd Maste               break;
172f034231aSEd Maste             }
17314f1b3e8SDimitry Andric           } else {
17414f1b3e8SDimitry Andric             result.AppendErrorWithFormat(
17514f1b3e8SDimitry Andric                 "invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx);
176f034231aSEd Maste             break;
177f034231aSEd Maste           }
178f034231aSEd Maste         }
17914f1b3e8SDimitry Andric       } else {
180f034231aSEd Maste         if (m_command_options.dump_all_sets)
181f034231aSEd Maste           num_register_sets = reg_ctx->GetRegisterSetCount();
182f034231aSEd Maste 
18314f1b3e8SDimitry Andric         for (set_idx = 0; set_idx < num_register_sets; ++set_idx) {
184f73363f1SDimitry Andric           // When dump_all_sets option is set, dump primitive as well as
185f73363f1SDimitry Andric           // derived registers.
18614f1b3e8SDimitry Andric           DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx,
18714f1b3e8SDimitry Andric                           !m_command_options.dump_all_sets.GetCurrentValue());
188f034231aSEd Maste         }
189f034231aSEd Maste       }
19014f1b3e8SDimitry Andric     } else {
19114f1b3e8SDimitry Andric       if (m_command_options.dump_all_sets) {
19214f1b3e8SDimitry Andric         result.AppendError("the --all option can't be used when registers "
19314f1b3e8SDimitry Andric                            "names are supplied as arguments\n");
19414f1b3e8SDimitry Andric       } else if (m_command_options.set_indexes.GetSize() > 0) {
19514f1b3e8SDimitry Andric         result.AppendError("the --set <set> option can't be used when "
19614f1b3e8SDimitry Andric                            "registers names are supplied as arguments\n");
19714f1b3e8SDimitry Andric       } else {
19814f1b3e8SDimitry Andric         for (auto &entry : command) {
199f73363f1SDimitry Andric           // in most LLDB commands we accept $rbx as the name for register RBX
200f73363f1SDimitry Andric           // - and here we would reject it and non-existant. we should be more
20114f1b3e8SDimitry Andric           // consistent towards the user and allow them to say reg read $rbx -
20214f1b3e8SDimitry Andric           // internally, however, we should be strict and not allow ourselves
203f034231aSEd Maste           // to call our registers $rbx in our own API
204ead24645SDimitry Andric           auto arg_str = entry.ref();
20514f1b3e8SDimitry Andric           arg_str.consume_front("$");
206f034231aSEd Maste 
2077fa27ce4SDimitry Andric           if (const RegisterInfo *reg_info =
2087fa27ce4SDimitry Andric                   reg_ctx->GetRegisterInfoByName(arg_str)) {
2097fa27ce4SDimitry Andric             // If they have asked for a specific format don't obscure that by
2107fa27ce4SDimitry Andric             // printing flags afterwards.
2117fa27ce4SDimitry Andric             bool print_flags =
2127fa27ce4SDimitry Andric                 !m_format_options.GetFormatValue().OptionWasSet();
2137fa27ce4SDimitry Andric             if (!DumpRegister(m_exe_ctx, strm, *reg_ctx, *reg_info,
2147fa27ce4SDimitry Andric                               print_flags))
215f034231aSEd Maste               strm.Printf("%-12s = error: unavailable\n", reg_info->name);
21614f1b3e8SDimitry Andric           } else {
21714f1b3e8SDimitry Andric             result.AppendErrorWithFormat("Invalid register name '%s'.\n",
21814f1b3e8SDimitry Andric                                          arg_str.str().c_str());
219f034231aSEd Maste           }
220f034231aSEd Maste         }
221f034231aSEd Maste       }
222f034231aSEd Maste     }
223f034231aSEd Maste   }
224f034231aSEd Maste 
22514f1b3e8SDimitry Andric   class CommandOptions : public OptionGroup {
226f034231aSEd Maste   public:
CommandOptions()22714f1b3e8SDimitry Andric     CommandOptions()
2286f8fc217SDimitry Andric         : set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)),
229f034231aSEd Maste           dump_all_sets(false, false), // Initial and default values are false
23014f1b3e8SDimitry Andric           alternate_name(false, false) {}
231f034231aSEd Maste 
232f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
233f034231aSEd Maste 
GetDefinitions()23414f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
235e3b55780SDimitry Andric       return llvm::ArrayRef(g_register_read_options);
236f034231aSEd Maste     }
237f034231aSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)23814f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
239f034231aSEd Maste       set_indexes.Clear();
240f034231aSEd Maste       dump_all_sets.Clear();
241f034231aSEd Maste       alternate_name.Clear();
242f034231aSEd Maste     }
243f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_value,ExecutionContext * execution_context)244b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
24514f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
246b76161e4SDimitry Andric       Status error;
24714f1b3e8SDimitry Andric       const int short_option = GetDefinitions()[option_idx].short_option;
24814f1b3e8SDimitry Andric       switch (short_option) {
24914f1b3e8SDimitry Andric       case 's': {
250f034231aSEd Maste         OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error));
251f034231aSEd Maste         if (value_sp)
252f034231aSEd Maste           set_indexes.AppendValue(value_sp);
25314f1b3e8SDimitry Andric       } break;
254f034231aSEd Maste 
255f034231aSEd Maste       case 'a':
256f034231aSEd Maste         // When we don't use OptionValue::SetValueFromCString(const char *) to
257f034231aSEd Maste         // set an option value, it won't be marked as being set in the options
258f034231aSEd Maste         // so we make a call to let users know the value was set via option
259f034231aSEd Maste         dump_all_sets.SetCurrentValue(true);
260f034231aSEd Maste         dump_all_sets.SetOptionWasSet();
261f034231aSEd Maste         break;
262f034231aSEd Maste 
263f034231aSEd Maste       case 'A':
264f034231aSEd Maste         // When we don't use OptionValue::SetValueFromCString(const char *) to
265f034231aSEd Maste         // set an option value, it won't be marked as being set in the options
266f034231aSEd Maste         // so we make a call to let users know the value was set via option
267f034231aSEd Maste         alternate_name.SetCurrentValue(true);
268f034231aSEd Maste         dump_all_sets.SetOptionWasSet();
269f034231aSEd Maste         break;
270f034231aSEd Maste 
271f034231aSEd Maste       default:
272ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
273f034231aSEd Maste       }
274f034231aSEd Maste       return error;
275f034231aSEd Maste     }
276f034231aSEd Maste 
277f034231aSEd Maste     // Instance variables to hold the values for command options.
278f034231aSEd Maste     OptionValueArray set_indexes;
279f034231aSEd Maste     OptionValueBoolean dump_all_sets;
280f034231aSEd Maste     OptionValueBoolean alternate_name;
281f034231aSEd Maste   };
282f034231aSEd Maste 
283f034231aSEd Maste   OptionGroupOptions m_option_group;
284f034231aSEd Maste   OptionGroupFormat m_format_options;
285f034231aSEd Maste   CommandOptions m_command_options;
286f034231aSEd Maste };
287f034231aSEd Maste 
288f034231aSEd Maste // "register write"
28914f1b3e8SDimitry Andric class CommandObjectRegisterWrite : public CommandObjectParsed {
290f034231aSEd Maste public:
CommandObjectRegisterWrite(CommandInterpreter & interpreter)29114f1b3e8SDimitry Andric   CommandObjectRegisterWrite(CommandInterpreter &interpreter)
29214f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "register write",
29314f1b3e8SDimitry Andric                             "Modify a single register value.", nullptr,
29414f1b3e8SDimitry Andric                             eCommandRequiresFrame | eCommandRequiresRegContext |
2955e95aa85SEd Maste                                 eCommandProcessMustBeLaunched |
29614f1b3e8SDimitry Andric                                 eCommandProcessMustBePaused) {
297f034231aSEd Maste     CommandArgumentEntry arg1;
298f034231aSEd Maste     CommandArgumentEntry arg2;
299f034231aSEd Maste     CommandArgumentData register_arg;
300f034231aSEd Maste     CommandArgumentData value_arg;
301f034231aSEd Maste 
302f034231aSEd Maste     // Define the first (and only) variant of this arg.
303f034231aSEd Maste     register_arg.arg_type = eArgTypeRegisterName;
304f034231aSEd Maste     register_arg.arg_repetition = eArgRepeatPlain;
305f034231aSEd Maste 
30614f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
30714f1b3e8SDimitry Andric     // argument entry.
308f034231aSEd Maste     arg1.push_back(register_arg);
309f034231aSEd Maste 
310f034231aSEd Maste     // Define the first (and only) variant of this arg.
311f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
312f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
313f034231aSEd Maste 
31414f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
31514f1b3e8SDimitry Andric     // argument entry.
316f034231aSEd Maste     arg2.push_back(value_arg);
317f034231aSEd Maste 
318f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
319f034231aSEd Maste     m_arguments.push_back(arg1);
320f034231aSEd Maste     m_arguments.push_back(arg2);
321f034231aSEd Maste   }
322f034231aSEd Maste 
323f3fbd1c0SDimitry Andric   ~CommandObjectRegisterWrite() override = default;
324f034231aSEd Maste 
325cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)326cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
327cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
328cfca06d7SDimitry Andric     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
329cfca06d7SDimitry Andric       return;
330cfca06d7SDimitry Andric 
3317fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
3327fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr);
333cfca06d7SDimitry Andric   }
334cfca06d7SDimitry Andric 
335f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)336b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
337f034231aSEd Maste     DataExtractor reg_data;
338f034231aSEd Maste     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
339f034231aSEd Maste 
34014f1b3e8SDimitry Andric     if (command.GetArgumentCount() != 2) {
34114f1b3e8SDimitry Andric       result.AppendError(
34214f1b3e8SDimitry Andric           "register write takes exactly 2 arguments: <reg-name> <value>");
34314f1b3e8SDimitry Andric     } else {
344ead24645SDimitry Andric       auto reg_name = command[0].ref();
345ead24645SDimitry Andric       auto value_str = command[1].ref();
346f034231aSEd Maste 
347f73363f1SDimitry Andric       // in most LLDB commands we accept $rbx as the name for register RBX -
348f73363f1SDimitry Andric       // and here we would reject it and non-existant. we should be more
349f73363f1SDimitry Andric       // consistent towards the user and allow them to say reg write $rbx -
350f73363f1SDimitry Andric       // internally, however, we should be strict and not allow ourselves to
351f73363f1SDimitry Andric       // call our registers $rbx in our own API
35214f1b3e8SDimitry Andric       reg_name.consume_front("$");
353f034231aSEd Maste 
354f034231aSEd Maste       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
355f034231aSEd Maste 
35614f1b3e8SDimitry Andric       if (reg_info) {
357f034231aSEd Maste         RegisterValue reg_value;
358f034231aSEd Maste 
359b76161e4SDimitry Andric         Status error(reg_value.SetValueFromString(reg_info, value_str));
36014f1b3e8SDimitry Andric         if (error.Success()) {
36114f1b3e8SDimitry Andric           if (reg_ctx->WriteRegister(reg_info, reg_value)) {
362f73363f1SDimitry Andric             // Toss all frames and anything else in the thread after a register
363f73363f1SDimitry Andric             // has been written.
364f034231aSEd Maste             m_exe_ctx.GetThreadRef().Flush();
365f034231aSEd Maste             result.SetStatus(eReturnStatusSuccessFinishNoResult);
366b1c73532SDimitry Andric             return;
367f034231aSEd Maste           }
368f034231aSEd Maste         }
36914f1b3e8SDimitry Andric         if (error.AsCString()) {
37014f1b3e8SDimitry Andric           result.AppendErrorWithFormat(
37114f1b3e8SDimitry Andric               "Failed to write register '%s' with value '%s': %s\n",
37214f1b3e8SDimitry Andric               reg_name.str().c_str(), value_str.str().c_str(),
373f034231aSEd Maste               error.AsCString());
37414f1b3e8SDimitry Andric         } else {
37514f1b3e8SDimitry Andric           result.AppendErrorWithFormat(
37614f1b3e8SDimitry Andric               "Failed to write register '%s' with value '%s'",
37714f1b3e8SDimitry Andric               reg_name.str().c_str(), value_str.str().c_str());
378f034231aSEd Maste         }
37914f1b3e8SDimitry Andric       } else {
38014f1b3e8SDimitry Andric         result.AppendErrorWithFormat("Register not found for '%s'.\n",
38114f1b3e8SDimitry Andric                                      reg_name.str().c_str());
382f034231aSEd Maste       }
383f034231aSEd Maste     }
384f034231aSEd Maste   }
385f034231aSEd Maste };
386f034231aSEd Maste 
3877fa27ce4SDimitry Andric // "register info"
3887fa27ce4SDimitry Andric class CommandObjectRegisterInfo : public CommandObjectParsed {
3897fa27ce4SDimitry Andric public:
CommandObjectRegisterInfo(CommandInterpreter & interpreter)3907fa27ce4SDimitry Andric   CommandObjectRegisterInfo(CommandInterpreter &interpreter)
3917fa27ce4SDimitry Andric       : CommandObjectParsed(interpreter, "register info",
3927fa27ce4SDimitry Andric                             "View information about a register.", nullptr,
393b1c73532SDimitry Andric                             eCommandRequiresFrame | eCommandRequiresRegContext |
394b1c73532SDimitry Andric                                 eCommandProcessMustBeLaunched |
395b1c73532SDimitry Andric                                 eCommandProcessMustBePaused) {
3967fa27ce4SDimitry Andric     SetHelpLong(R"(
3977fa27ce4SDimitry Andric Name             The name lldb uses for the register, optionally with an alias.
3987fa27ce4SDimitry Andric Size             The size of the register in bytes and again in bits.
3997fa27ce4SDimitry Andric Invalidates (*)  The registers that would be changed if you wrote this
4007fa27ce4SDimitry Andric                  register. For example, writing to a narrower alias of a wider
4017fa27ce4SDimitry Andric                  register would change the value of the wider register.
4027fa27ce4SDimitry Andric Read from   (*)  The registers that the value of this register is constructed
4037fa27ce4SDimitry Andric                  from. For example, a narrower alias of a wider register will be
4047fa27ce4SDimitry Andric                  read from the wider register.
4057fa27ce4SDimitry Andric In sets     (*)  The register sets that contain this register. For example the
4067fa27ce4SDimitry Andric                  PC will be in the "General Purpose Register" set.
4077fa27ce4SDimitry Andric Fields      (*)  A table of the names and bit positions of the values contained
4087fa27ce4SDimitry Andric                  in this register.
4097fa27ce4SDimitry Andric 
4107fa27ce4SDimitry Andric Fields marked with (*) may not always be present. Some information may be
4117fa27ce4SDimitry Andric different for the same register when connected to different debug servers.)");
4127fa27ce4SDimitry Andric 
413ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRegisterName);
4147fa27ce4SDimitry Andric   }
4157fa27ce4SDimitry Andric 
4167fa27ce4SDimitry Andric   ~CommandObjectRegisterInfo() override = default;
4177fa27ce4SDimitry Andric 
4187fa27ce4SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4197fa27ce4SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
4207fa27ce4SDimitry Andric                            OptionElementVector &opt_element_vector) override {
4217fa27ce4SDimitry Andric     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
4227fa27ce4SDimitry Andric       return;
423ac9a064cSDimitry Andric     CommandObject::HandleArgumentCompletion(request, opt_element_vector);
4247fa27ce4SDimitry Andric   }
4257fa27ce4SDimitry Andric 
4267fa27ce4SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)427b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
4287fa27ce4SDimitry Andric     if (command.GetArgumentCount() != 1) {
4297fa27ce4SDimitry Andric       result.AppendError("register info takes exactly 1 argument: <reg-name>");
430b1c73532SDimitry Andric       return;
4317fa27ce4SDimitry Andric     }
4327fa27ce4SDimitry Andric 
4337fa27ce4SDimitry Andric     llvm::StringRef reg_name = command[0].ref();
4347fa27ce4SDimitry Andric     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
4357fa27ce4SDimitry Andric     const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
4367fa27ce4SDimitry Andric     if (reg_info) {
4377fa27ce4SDimitry Andric       DumpRegisterInfo(
4387fa27ce4SDimitry Andric           result.GetOutputStream(), *reg_ctx, *reg_info,
4397fa27ce4SDimitry Andric           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
4407fa27ce4SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
4417fa27ce4SDimitry Andric     } else
4427fa27ce4SDimitry Andric       result.AppendErrorWithFormat("No register found with name '%s'.\n",
4437fa27ce4SDimitry Andric                                    reg_name.str().c_str());
4447fa27ce4SDimitry Andric   }
4457fa27ce4SDimitry Andric };
4467fa27ce4SDimitry Andric 
447f034231aSEd Maste // CommandObjectRegister constructor
CommandObjectRegister(CommandInterpreter & interpreter)448f3fbd1c0SDimitry Andric CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter)
449f3fbd1c0SDimitry Andric     : CommandObjectMultiword(interpreter, "register",
45014f1b3e8SDimitry Andric                              "Commands to access registers for the current "
45114f1b3e8SDimitry Andric                              "thread and stack frame.",
4527fa27ce4SDimitry Andric                              "register [read|write|info] ...") {
45314f1b3e8SDimitry Andric   LoadSubCommand("read",
45414f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectRegisterRead(interpreter)));
45514f1b3e8SDimitry Andric   LoadSubCommand("write",
45614f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectRegisterWrite(interpreter)));
4577fa27ce4SDimitry Andric   LoadSubCommand("info",
4587fa27ce4SDimitry Andric                  CommandObjectSP(new CommandObjectRegisterInfo(interpreter)));
459f034231aSEd Maste }
460f034231aSEd Maste 
461f3fbd1c0SDimitry Andric CommandObjectRegister::~CommandObjectRegister() = default;
462