1254721Semaste//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "CommandObjectRegister.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste// C++ Includes
16254721Semaste// Other libraries and framework includes
17254721Semaste// Project includes
18254721Semaste#include "lldb/Core/DataExtractor.h"
19254721Semaste#include "lldb/Core/RegisterValue.h"
20254721Semaste#include "lldb/Core/Scalar.h"
21254721Semaste#include "lldb/Core/Debugger.h"
22254721Semaste#include "lldb/Interpreter/Args.h"
23254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
24254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
25254721Semaste#include "lldb/Interpreter/Options.h"
26254721Semaste#include "lldb/Interpreter/OptionGroupFormat.h"
27254721Semaste#include "lldb/Interpreter/OptionValueArray.h"
28254721Semaste#include "lldb/Interpreter/OptionValueUInt64.h"
29254721Semaste#include "lldb/Target/ExecutionContext.h"
30254721Semaste#include "lldb/Target/Process.h"
31254721Semaste#include "lldb/Target/RegisterContext.h"
32269024Semaste#include "lldb/Target/SectionLoadList.h"
33254721Semaste#include "lldb/Target/Thread.h"
34254721Semaste
35254721Semasteusing namespace lldb;
36254721Semasteusing namespace lldb_private;
37254721Semaste
38254721Semaste//----------------------------------------------------------------------
39254721Semaste// "register read"
40254721Semaste//----------------------------------------------------------------------
41254721Semasteclass CommandObjectRegisterRead : public CommandObjectParsed
42254721Semaste{
43254721Semastepublic:
44254721Semaste    CommandObjectRegisterRead (CommandInterpreter &interpreter) :
45254721Semaste        CommandObjectParsed (interpreter,
46254721Semaste                             "register read",
47254721Semaste                             "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
48254721Semaste                             NULL,
49254721Semaste                             eFlagRequiresFrame         |
50254721Semaste                             eFlagRequiresRegContext    |
51254721Semaste                             eFlagProcessMustBeLaunched |
52254721Semaste                             eFlagProcessMustBePaused   ),
53254721Semaste        m_option_group (interpreter),
54254721Semaste        m_format_options (eFormatDefault),
55254721Semaste        m_command_options ()
56254721Semaste    {
57254721Semaste        CommandArgumentEntry arg;
58254721Semaste        CommandArgumentData register_arg;
59254721Semaste
60254721Semaste        // Define the first (and only) variant of this arg.
61254721Semaste        register_arg.arg_type = eArgTypeRegisterName;
62254721Semaste        register_arg.arg_repetition = eArgRepeatStar;
63254721Semaste
64254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
65254721Semaste        arg.push_back (register_arg);
66254721Semaste
67254721Semaste        // Push the data for the first argument into the m_arguments vector.
68254721Semaste        m_arguments.push_back (arg);
69254721Semaste
70254721Semaste        // Add the "--format"
71254721Semaste        m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
72254721Semaste        m_option_group.Append (&m_command_options);
73254721Semaste        m_option_group.Finalize();
74254721Semaste
75254721Semaste    }
76254721Semaste
77254721Semaste    virtual
78254721Semaste    ~CommandObjectRegisterRead ()
79254721Semaste    {
80254721Semaste    }
81254721Semaste
82254721Semaste    Options *
83254721Semaste    GetOptions ()
84254721Semaste    {
85254721Semaste        return &m_option_group;
86254721Semaste    }
87254721Semaste
88254721Semaste    bool
89254721Semaste    DumpRegister (const ExecutionContext &exe_ctx,
90254721Semaste                  Stream &strm,
91254721Semaste                  RegisterContext *reg_ctx,
92254721Semaste                  const RegisterInfo *reg_info)
93254721Semaste    {
94254721Semaste        if (reg_info)
95254721Semaste        {
96254721Semaste            RegisterValue reg_value;
97254721Semaste
98254721Semaste            if (reg_ctx->ReadRegister (reg_info, reg_value))
99254721Semaste            {
100254721Semaste                strm.Indent ();
101254721Semaste
102263363Semaste                bool prefix_with_altname = (bool)m_command_options.alternate_name;
103254721Semaste                bool prefix_with_name = !prefix_with_altname;
104254721Semaste                reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
105254721Semaste                if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
106254721Semaste                {
107254721Semaste                    Process *process = exe_ctx.GetProcessPtr();
108254721Semaste                    if (process && reg_info->byte_size == process->GetAddressByteSize())
109254721Semaste                    {
110254721Semaste                        addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
111254721Semaste                        if (reg_addr != LLDB_INVALID_ADDRESS)
112254721Semaste                        {
113254721Semaste                            Address so_reg_addr;
114254721Semaste                            if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
115254721Semaste                            {
116254721Semaste                                strm.PutCString ("  ");
117254721Semaste                                so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
118254721Semaste                            }
119254721Semaste                        }
120254721Semaste                    }
121254721Semaste                }
122254721Semaste                strm.EOL();
123254721Semaste                return true;
124254721Semaste            }
125254721Semaste        }
126254721Semaste        return false;
127254721Semaste    }
128254721Semaste
129254721Semaste    bool
130254721Semaste    DumpRegisterSet (const ExecutionContext &exe_ctx,
131254721Semaste                     Stream &strm,
132254721Semaste                     RegisterContext *reg_ctx,
133254721Semaste                     size_t set_idx,
134254721Semaste                     bool primitive_only=false)
135254721Semaste    {
136254721Semaste        uint32_t unavailable_count = 0;
137254721Semaste        uint32_t available_count = 0;
138254721Semaste
139254721Semaste        if (!reg_ctx)
140254721Semaste            return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)
141254721Semaste
142254721Semaste        const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
143254721Semaste        if (reg_set)
144254721Semaste        {
145254721Semaste            strm.Printf ("%s:\n", reg_set->name);
146254721Semaste            strm.IndentMore ();
147254721Semaste            const size_t num_registers = reg_set->num_registers;
148254721Semaste            for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
149254721Semaste            {
150254721Semaste                const uint32_t reg = reg_set->registers[reg_idx];
151254721Semaste                const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
152254721Semaste                // Skip the dumping of derived register if primitive_only is true.
153254721Semaste                if (primitive_only && reg_info && reg_info->value_regs)
154254721Semaste                    continue;
155254721Semaste
156254721Semaste                if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
157254721Semaste                    ++available_count;
158254721Semaste                else
159254721Semaste                    ++unavailable_count;
160254721Semaste            }
161254721Semaste            strm.IndentLess ();
162254721Semaste            if (unavailable_count)
163254721Semaste            {
164254721Semaste                strm.Indent ();
165254721Semaste                strm.Printf("%u registers were unavailable.\n", unavailable_count);
166254721Semaste            }
167254721Semaste            strm.EOL();
168254721Semaste        }
169254721Semaste        return available_count > 0;
170254721Semaste    }
171254721Semaste
172254721Semasteprotected:
173254721Semaste    virtual bool
174254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
175254721Semaste    {
176254721Semaste        Stream &strm = result.GetOutputStream();
177254721Semaste        RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
178254721Semaste
179254721Semaste        const RegisterInfo *reg_info = NULL;
180254721Semaste        if (command.GetArgumentCount() == 0)
181254721Semaste        {
182254721Semaste            size_t set_idx;
183254721Semaste
184254721Semaste            size_t num_register_sets = 1;
185254721Semaste            const size_t set_array_size = m_command_options.set_indexes.GetSize();
186254721Semaste            if (set_array_size > 0)
187254721Semaste            {
188254721Semaste                for (size_t i=0; i<set_array_size; ++i)
189254721Semaste                {
190254721Semaste                    set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
191254721Semaste                    if (set_idx < reg_ctx->GetRegisterSetCount())
192254721Semaste                    {
193254721Semaste                        if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
194254721Semaste                        {
195254721Semaste                            if (errno)
196263363Semaste                                result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
197254721Semaste                            else
198254721Semaste                                result.AppendError ("unknown error while reading registers.\n");
199254721Semaste                            result.SetStatus (eReturnStatusFailed);
200254721Semaste                            break;
201254721Semaste                        }
202254721Semaste                    }
203254721Semaste                    else
204254721Semaste                    {
205254721Semaste                        result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx);
206254721Semaste                        result.SetStatus (eReturnStatusFailed);
207254721Semaste                        break;
208254721Semaste                    }
209254721Semaste                }
210254721Semaste            }
211254721Semaste            else
212254721Semaste            {
213254721Semaste                if (m_command_options.dump_all_sets)
214254721Semaste                    num_register_sets = reg_ctx->GetRegisterSetCount();
215254721Semaste
216254721Semaste                for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
217254721Semaste                {
218254721Semaste                    // When dump_all_sets option is set, dump primitive as well as derived registers.
219254721Semaste                    DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
220254721Semaste                }
221254721Semaste            }
222254721Semaste        }
223254721Semaste        else
224254721Semaste        {
225254721Semaste            if (m_command_options.dump_all_sets)
226254721Semaste            {
227254721Semaste                result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
228254721Semaste                result.SetStatus (eReturnStatusFailed);
229254721Semaste            }
230254721Semaste            else if (m_command_options.set_indexes.GetSize() > 0)
231254721Semaste            {
232254721Semaste                result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
233254721Semaste                result.SetStatus (eReturnStatusFailed);
234254721Semaste            }
235254721Semaste            else
236254721Semaste            {
237254721Semaste                const char *arg_cstr;
238254721Semaste                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
239254721Semaste                {
240254721Semaste                    // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
241254721Semaste                    // reject it and non-existant. we should be more consistent towards the user and allow them
242254721Semaste                    // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
243254721Semaste                    // to call our registers $rbx in our own API
244254721Semaste                    if (*arg_cstr == '$')
245254721Semaste                        arg_cstr = arg_cstr+1;
246254721Semaste                    reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
247254721Semaste
248254721Semaste                    if (reg_info)
249254721Semaste                    {
250254721Semaste                        if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
251254721Semaste                            strm.Printf("%-12s = error: unavailable\n", reg_info->name);
252254721Semaste                    }
253254721Semaste                    else
254254721Semaste                    {
255254721Semaste                        result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
256254721Semaste                    }
257254721Semaste                }
258254721Semaste            }
259254721Semaste        }
260254721Semaste        return result.Succeeded();
261254721Semaste    }
262254721Semaste
263254721Semaste    class CommandOptions : public OptionGroup
264254721Semaste    {
265254721Semaste    public:
266254721Semaste        CommandOptions () :
267254721Semaste            OptionGroup(),
268254721Semaste            set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
269254721Semaste            dump_all_sets (false, false), // Initial and default values are false
270254721Semaste            alternate_name (false, false)
271254721Semaste        {
272254721Semaste        }
273254721Semaste
274254721Semaste        virtual
275254721Semaste        ~CommandOptions ()
276254721Semaste        {
277254721Semaste        }
278254721Semaste
279254721Semaste
280254721Semaste        virtual uint32_t
281254721Semaste        GetNumDefinitions ();
282254721Semaste
283254721Semaste        virtual const OptionDefinition*
284254721Semaste        GetDefinitions ()
285254721Semaste        {
286254721Semaste            return g_option_table;
287254721Semaste        }
288254721Semaste
289254721Semaste        virtual void
290254721Semaste        OptionParsingStarting (CommandInterpreter &interpreter)
291254721Semaste        {
292254721Semaste            set_indexes.Clear();
293254721Semaste            dump_all_sets.Clear();
294254721Semaste            alternate_name.Clear();
295254721Semaste        }
296254721Semaste
297254721Semaste        virtual Error
298254721Semaste        SetOptionValue (CommandInterpreter &interpreter,
299254721Semaste                        uint32_t option_idx,
300254721Semaste                        const char *option_value)
301254721Semaste        {
302254721Semaste            Error error;
303254721Semaste            const int short_option = g_option_table[option_idx].short_option;
304254721Semaste            switch (short_option)
305254721Semaste            {
306254721Semaste                case 's':
307254721Semaste                    {
308254721Semaste                        OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
309254721Semaste                        if (value_sp)
310254721Semaste                            set_indexes.AppendValue (value_sp);
311254721Semaste                    }
312254721Semaste                    break;
313254721Semaste
314254721Semaste                case 'a':
315254721Semaste                    // When we don't use OptionValue::SetValueFromCString(const char *) to
316254721Semaste                    // set an option value, it won't be marked as being set in the options
317254721Semaste                    // so we make a call to let users know the value was set via option
318254721Semaste                    dump_all_sets.SetCurrentValue (true);
319254721Semaste                    dump_all_sets.SetOptionWasSet ();
320254721Semaste                    break;
321254721Semaste
322254721Semaste                case 'A':
323254721Semaste                    // When we don't use OptionValue::SetValueFromCString(const char *) to
324254721Semaste                    // set an option value, it won't be marked as being set in the options
325254721Semaste                    // so we make a call to let users know the value was set via option
326254721Semaste                    alternate_name.SetCurrentValue (true);
327254721Semaste                    dump_all_sets.SetOptionWasSet ();
328254721Semaste                    break;
329254721Semaste
330254721Semaste                default:
331254721Semaste                    error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
332254721Semaste                    break;
333254721Semaste            }
334254721Semaste            return error;
335254721Semaste        }
336254721Semaste
337254721Semaste        // Options table: Required for subclasses of Options.
338254721Semaste
339254721Semaste        static const OptionDefinition g_option_table[];
340254721Semaste
341254721Semaste        // Instance variables to hold the values for command options.
342254721Semaste        OptionValueArray set_indexes;
343254721Semaste        OptionValueBoolean dump_all_sets;
344254721Semaste        OptionValueBoolean alternate_name;
345254721Semaste    };
346254721Semaste
347254721Semaste    OptionGroupOptions m_option_group;
348254721Semaste    OptionGroupFormat m_format_options;
349254721Semaste    CommandOptions m_command_options;
350254721Semaste};
351254721Semaste
352254721Semasteconst OptionDefinition
353254721SemasteCommandObjectRegisterRead::CommandOptions::g_option_table[] =
354254721Semaste{
355263363Semaste    { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
356263363Semaste    { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
357263363Semaste    { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
358254721Semaste};
359254721Semaste
360254721Semasteuint32_t
361254721SemasteCommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
362254721Semaste{
363254721Semaste    return sizeof(g_option_table)/sizeof(OptionDefinition);
364254721Semaste}
365254721Semaste
366254721Semaste
367254721Semaste//----------------------------------------------------------------------
368254721Semaste// "register write"
369254721Semaste//----------------------------------------------------------------------
370254721Semasteclass CommandObjectRegisterWrite : public CommandObjectParsed
371254721Semaste{
372254721Semastepublic:
373254721Semaste    CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
374254721Semaste        CommandObjectParsed (interpreter,
375254721Semaste                             "register write",
376254721Semaste                             "Modify a single register value.",
377254721Semaste                             NULL,
378254721Semaste                             eFlagRequiresFrame         |
379254721Semaste                             eFlagRequiresRegContext    |
380254721Semaste                             eFlagProcessMustBeLaunched |
381254721Semaste                             eFlagProcessMustBePaused)
382254721Semaste    {
383254721Semaste        CommandArgumentEntry arg1;
384254721Semaste        CommandArgumentEntry arg2;
385254721Semaste        CommandArgumentData register_arg;
386254721Semaste        CommandArgumentData value_arg;
387254721Semaste
388254721Semaste        // Define the first (and only) variant of this arg.
389254721Semaste        register_arg.arg_type = eArgTypeRegisterName;
390254721Semaste        register_arg.arg_repetition = eArgRepeatPlain;
391254721Semaste
392254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
393254721Semaste        arg1.push_back (register_arg);
394254721Semaste
395254721Semaste        // Define the first (and only) variant of this arg.
396254721Semaste        value_arg.arg_type = eArgTypeValue;
397254721Semaste        value_arg.arg_repetition = eArgRepeatPlain;
398254721Semaste
399254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
400254721Semaste        arg2.push_back (value_arg);
401254721Semaste
402254721Semaste        // Push the data for the first argument into the m_arguments vector.
403254721Semaste        m_arguments.push_back (arg1);
404254721Semaste        m_arguments.push_back (arg2);
405254721Semaste    }
406254721Semaste
407254721Semaste    virtual
408254721Semaste    ~CommandObjectRegisterWrite ()
409254721Semaste    {
410254721Semaste    }
411254721Semaste
412254721Semasteprotected:
413254721Semaste    virtual bool
414254721Semaste    DoExecute(Args& command, CommandReturnObject &result)
415254721Semaste    {
416254721Semaste        DataExtractor reg_data;
417254721Semaste        RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
418254721Semaste
419254721Semaste        if (command.GetArgumentCount() != 2)
420254721Semaste        {
421254721Semaste            result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
422254721Semaste            result.SetStatus (eReturnStatusFailed);
423254721Semaste        }
424254721Semaste        else
425254721Semaste        {
426254721Semaste            const char *reg_name = command.GetArgumentAtIndex(0);
427254721Semaste            const char *value_str = command.GetArgumentAtIndex(1);
428254721Semaste
429254721Semaste
430254721Semaste            // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
431254721Semaste            // reject it and non-existant. we should be more consistent towards the user and allow them
432254721Semaste            // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
433254721Semaste            // to call our registers $rbx in our own API
434254721Semaste            if (reg_name && *reg_name == '$')
435254721Semaste                reg_name = reg_name+1;
436254721Semaste
437254721Semaste            const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
438254721Semaste
439254721Semaste            if (reg_info)
440254721Semaste            {
441254721Semaste                RegisterValue reg_value;
442254721Semaste
443254721Semaste                Error error (reg_value.SetValueFromCString (reg_info, value_str));
444254721Semaste                if (error.Success())
445254721Semaste                {
446254721Semaste                    if (reg_ctx->WriteRegister (reg_info, reg_value))
447254721Semaste                    {
448254721Semaste                        // Toss all frames and anything else in the thread
449254721Semaste                        // after a register has been written.
450254721Semaste                        m_exe_ctx.GetThreadRef().Flush();
451254721Semaste                        result.SetStatus (eReturnStatusSuccessFinishNoResult);
452254721Semaste                        return true;
453254721Semaste                    }
454254721Semaste                }
455254721Semaste                if (error.AsCString())
456254721Semaste                {
457254721Semaste                    result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
458254721Semaste                                                 reg_name,
459254721Semaste                                                 value_str,
460254721Semaste                                                 error.AsCString());
461254721Semaste                }
462254721Semaste                else
463254721Semaste                {
464254721Semaste                    result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
465254721Semaste                                                 reg_name,
466254721Semaste                                                 value_str);
467254721Semaste                }
468254721Semaste                result.SetStatus (eReturnStatusFailed);
469254721Semaste            }
470254721Semaste            else
471254721Semaste            {
472254721Semaste                result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
473254721Semaste                result.SetStatus (eReturnStatusFailed);
474254721Semaste            }
475254721Semaste        }
476254721Semaste        return result.Succeeded();
477254721Semaste    }
478254721Semaste};
479254721Semaste
480254721Semaste
481254721Semaste//----------------------------------------------------------------------
482254721Semaste// CommandObjectRegister constructor
483254721Semaste//----------------------------------------------------------------------
484254721SemasteCommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
485254721Semaste    CommandObjectMultiword (interpreter,
486254721Semaste                            "register",
487254721Semaste                            "A set of commands to access thread registers.",
488254721Semaste                            "register [read|write] ...")
489254721Semaste{
490254721Semaste    LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
491254721Semaste    LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
492254721Semaste}
493254721Semaste
494254721Semaste
495254721Semaste//----------------------------------------------------------------------
496254721Semaste// Destructor
497254721Semaste//----------------------------------------------------------------------
498254721SemasteCommandObjectRegister::~CommandObjectRegister()
499254721Semaste{
500254721Semaste}
501