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 ®_ctx, const RegisterInfo ®_info,
787fa27ce4SDimitry Andric bool print_flags) {
79f034231aSEd Maste RegisterValue reg_value;
807fa27ce4SDimitry Andric if (!reg_ctx.ReadRegister(®_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