CommandObjectRegister.cpp revision 263363
1//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "CommandObjectRegister.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/DataExtractor.h"
19#include "lldb/Core/RegisterValue.h"
20#include "lldb/Core/Scalar.h"
21#include "lldb/Core/Debugger.h"
22#include "lldb/Interpreter/Args.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
25#include "lldb/Interpreter/Options.h"
26#include "lldb/Interpreter/OptionGroupFormat.h"
27#include "lldb/Interpreter/OptionValueArray.h"
28#include "lldb/Interpreter/OptionValueUInt64.h"
29#include "lldb/Target/ExecutionContext.h"
30#include "lldb/Target/Process.h"
31#include "lldb/Target/RegisterContext.h"
32#include "lldb/Target/Thread.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37//----------------------------------------------------------------------
38// "register read"
39//----------------------------------------------------------------------
40class CommandObjectRegisterRead : public CommandObjectParsed
41{
42public:
43    CommandObjectRegisterRead (CommandInterpreter &interpreter) :
44        CommandObjectParsed (interpreter,
45                             "register read",
46                             "Dump the contents of one or more register values from the current frame.  If no register is specified, dumps them all.",
47                             NULL,
48                             eFlagRequiresFrame         |
49                             eFlagRequiresRegContext    |
50                             eFlagProcessMustBeLaunched |
51                             eFlagProcessMustBePaused   ),
52        m_option_group (interpreter),
53        m_format_options (eFormatDefault),
54        m_command_options ()
55    {
56        CommandArgumentEntry arg;
57        CommandArgumentData register_arg;
58
59        // Define the first (and only) variant of this arg.
60        register_arg.arg_type = eArgTypeRegisterName;
61        register_arg.arg_repetition = eArgRepeatStar;
62
63        // There is only one variant this argument could be; put it into the argument entry.
64        arg.push_back (register_arg);
65
66        // Push the data for the first argument into the m_arguments vector.
67        m_arguments.push_back (arg);
68
69        // Add the "--format"
70        m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_ALL);
71        m_option_group.Append (&m_command_options);
72        m_option_group.Finalize();
73
74    }
75
76    virtual
77    ~CommandObjectRegisterRead ()
78    {
79    }
80
81    Options *
82    GetOptions ()
83    {
84        return &m_option_group;
85    }
86
87    bool
88    DumpRegister (const ExecutionContext &exe_ctx,
89                  Stream &strm,
90                  RegisterContext *reg_ctx,
91                  const RegisterInfo *reg_info)
92    {
93        if (reg_info)
94        {
95            RegisterValue reg_value;
96
97            if (reg_ctx->ReadRegister (reg_info, reg_value))
98            {
99                strm.Indent ();
100
101                bool prefix_with_altname = (bool)m_command_options.alternate_name;
102                bool prefix_with_name = !prefix_with_altname;
103                reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8);
104                if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint))
105                {
106                    Process *process = exe_ctx.GetProcessPtr();
107                    if (process && reg_info->byte_size == process->GetAddressByteSize())
108                    {
109                        addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
110                        if (reg_addr != LLDB_INVALID_ADDRESS)
111                        {
112                            Address so_reg_addr;
113                            if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress(reg_addr, so_reg_addr))
114                            {
115                                strm.PutCString ("  ");
116                                so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
117                            }
118                        }
119                    }
120                }
121                strm.EOL();
122                return true;
123            }
124        }
125        return false;
126    }
127
128    bool
129    DumpRegisterSet (const ExecutionContext &exe_ctx,
130                     Stream &strm,
131                     RegisterContext *reg_ctx,
132                     size_t set_idx,
133                     bool primitive_only=false)
134    {
135        uint32_t unavailable_count = 0;
136        uint32_t available_count = 0;
137
138        if (!reg_ctx)
139            return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)
140
141        const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
142        if (reg_set)
143        {
144            strm.Printf ("%s:\n", reg_set->name);
145            strm.IndentMore ();
146            const size_t num_registers = reg_set->num_registers;
147            for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
148            {
149                const uint32_t reg = reg_set->registers[reg_idx];
150                const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
151                // Skip the dumping of derived register if primitive_only is true.
152                if (primitive_only && reg_info && reg_info->value_regs)
153                    continue;
154
155                if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
156                    ++available_count;
157                else
158                    ++unavailable_count;
159            }
160            strm.IndentLess ();
161            if (unavailable_count)
162            {
163                strm.Indent ();
164                strm.Printf("%u registers were unavailable.\n", unavailable_count);
165            }
166            strm.EOL();
167        }
168        return available_count > 0;
169    }
170
171protected:
172    virtual bool
173    DoExecute (Args& command, CommandReturnObject &result)
174    {
175        Stream &strm = result.GetOutputStream();
176        RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
177
178        const RegisterInfo *reg_info = NULL;
179        if (command.GetArgumentCount() == 0)
180        {
181            size_t set_idx;
182
183            size_t num_register_sets = 1;
184            const size_t set_array_size = m_command_options.set_indexes.GetSize();
185            if (set_array_size > 0)
186            {
187                for (size_t i=0; i<set_array_size; ++i)
188                {
189                    set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
190                    if (set_idx < reg_ctx->GetRegisterSetCount())
191                    {
192                        if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
193                        {
194                            if (errno)
195                                result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno));
196                            else
197                                result.AppendError ("unknown error while reading registers.\n");
198                            result.SetStatus (eReturnStatusFailed);
199                            break;
200                        }
201                    }
202                    else
203                    {
204                        result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx);
205                        result.SetStatus (eReturnStatusFailed);
206                        break;
207                    }
208                }
209            }
210            else
211            {
212                if (m_command_options.dump_all_sets)
213                    num_register_sets = reg_ctx->GetRegisterSetCount();
214
215                for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
216                {
217                    // When dump_all_sets option is set, dump primitive as well as derived registers.
218                    DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
219                }
220            }
221        }
222        else
223        {
224            if (m_command_options.dump_all_sets)
225            {
226                result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
227                result.SetStatus (eReturnStatusFailed);
228            }
229            else if (m_command_options.set_indexes.GetSize() > 0)
230            {
231                result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
232                result.SetStatus (eReturnStatusFailed);
233            }
234            else
235            {
236                const char *arg_cstr;
237                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
238                {
239                    // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
240                    // reject it and non-existant. we should be more consistent towards the user and allow them
241                    // to say reg read $rbx - internally, however, we should be strict and not allow ourselves
242                    // to call our registers $rbx in our own API
243                    if (*arg_cstr == '$')
244                        arg_cstr = arg_cstr+1;
245                    reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
246
247                    if (reg_info)
248                    {
249                        if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
250                            strm.Printf("%-12s = error: unavailable\n", reg_info->name);
251                    }
252                    else
253                    {
254                        result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
255                    }
256                }
257            }
258        }
259        return result.Succeeded();
260    }
261
262    class CommandOptions : public OptionGroup
263    {
264    public:
265        CommandOptions () :
266            OptionGroup(),
267            set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)),
268            dump_all_sets (false, false), // Initial and default values are false
269            alternate_name (false, false)
270        {
271        }
272
273        virtual
274        ~CommandOptions ()
275        {
276        }
277
278
279        virtual uint32_t
280        GetNumDefinitions ();
281
282        virtual const OptionDefinition*
283        GetDefinitions ()
284        {
285            return g_option_table;
286        }
287
288        virtual void
289        OptionParsingStarting (CommandInterpreter &interpreter)
290        {
291            set_indexes.Clear();
292            dump_all_sets.Clear();
293            alternate_name.Clear();
294        }
295
296        virtual Error
297        SetOptionValue (CommandInterpreter &interpreter,
298                        uint32_t option_idx,
299                        const char *option_value)
300        {
301            Error error;
302            const int short_option = g_option_table[option_idx].short_option;
303            switch (short_option)
304            {
305                case 's':
306                    {
307                        OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
308                        if (value_sp)
309                            set_indexes.AppendValue (value_sp);
310                    }
311                    break;
312
313                case 'a':
314                    // When we don't use OptionValue::SetValueFromCString(const char *) to
315                    // set an option value, it won't be marked as being set in the options
316                    // so we make a call to let users know the value was set via option
317                    dump_all_sets.SetCurrentValue (true);
318                    dump_all_sets.SetOptionWasSet ();
319                    break;
320
321                case 'A':
322                    // When we don't use OptionValue::SetValueFromCString(const char *) to
323                    // set an option value, it won't be marked as being set in the options
324                    // so we make a call to let users know the value was set via option
325                    alternate_name.SetCurrentValue (true);
326                    dump_all_sets.SetOptionWasSet ();
327                    break;
328
329                default:
330                    error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
331                    break;
332            }
333            return error;
334        }
335
336        // Options table: Required for subclasses of Options.
337
338        static const OptionDefinition g_option_table[];
339
340        // Instance variables to hold the values for command options.
341        OptionValueArray set_indexes;
342        OptionValueBoolean dump_all_sets;
343        OptionValueBoolean alternate_name;
344    };
345
346    OptionGroupOptions m_option_group;
347    OptionGroupFormat m_format_options;
348    CommandOptions m_command_options;
349};
350
351const OptionDefinition
352CommandObjectRegisterRead::CommandOptions::g_option_table[] =
353{
354    { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
355    { LLDB_OPT_SET_1  , false, "set"      , 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
356    { LLDB_OPT_SET_2  , false, "all"      , 'a', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
357};
358
359uint32_t
360CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
361{
362    return sizeof(g_option_table)/sizeof(OptionDefinition);
363}
364
365
366//----------------------------------------------------------------------
367// "register write"
368//----------------------------------------------------------------------
369class CommandObjectRegisterWrite : public CommandObjectParsed
370{
371public:
372    CommandObjectRegisterWrite (CommandInterpreter &interpreter) :
373        CommandObjectParsed (interpreter,
374                             "register write",
375                             "Modify a single register value.",
376                             NULL,
377                             eFlagRequiresFrame         |
378                             eFlagRequiresRegContext    |
379                             eFlagProcessMustBeLaunched |
380                             eFlagProcessMustBePaused)
381    {
382        CommandArgumentEntry arg1;
383        CommandArgumentEntry arg2;
384        CommandArgumentData register_arg;
385        CommandArgumentData value_arg;
386
387        // Define the first (and only) variant of this arg.
388        register_arg.arg_type = eArgTypeRegisterName;
389        register_arg.arg_repetition = eArgRepeatPlain;
390
391        // There is only one variant this argument could be; put it into the argument entry.
392        arg1.push_back (register_arg);
393
394        // Define the first (and only) variant of this arg.
395        value_arg.arg_type = eArgTypeValue;
396        value_arg.arg_repetition = eArgRepeatPlain;
397
398        // There is only one variant this argument could be; put it into the argument entry.
399        arg2.push_back (value_arg);
400
401        // Push the data for the first argument into the m_arguments vector.
402        m_arguments.push_back (arg1);
403        m_arguments.push_back (arg2);
404    }
405
406    virtual
407    ~CommandObjectRegisterWrite ()
408    {
409    }
410
411protected:
412    virtual bool
413    DoExecute(Args& command, CommandReturnObject &result)
414    {
415        DataExtractor reg_data;
416        RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
417
418        if (command.GetArgumentCount() != 2)
419        {
420            result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
421            result.SetStatus (eReturnStatusFailed);
422        }
423        else
424        {
425            const char *reg_name = command.GetArgumentAtIndex(0);
426            const char *value_str = command.GetArgumentAtIndex(1);
427
428
429            // in most LLDB commands we accept $rbx as the name for register RBX - and here we would
430            // reject it and non-existant. we should be more consistent towards the user and allow them
431            // to say reg write $rbx - internally, however, we should be strict and not allow ourselves
432            // to call our registers $rbx in our own API
433            if (reg_name && *reg_name == '$')
434                reg_name = reg_name+1;
435
436            const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
437
438            if (reg_info)
439            {
440                RegisterValue reg_value;
441
442                Error error (reg_value.SetValueFromCString (reg_info, value_str));
443                if (error.Success())
444                {
445                    if (reg_ctx->WriteRegister (reg_info, reg_value))
446                    {
447                        // Toss all frames and anything else in the thread
448                        // after a register has been written.
449                        m_exe_ctx.GetThreadRef().Flush();
450                        result.SetStatus (eReturnStatusSuccessFinishNoResult);
451                        return true;
452                    }
453                }
454                if (error.AsCString())
455                {
456                    result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
457                                                 reg_name,
458                                                 value_str,
459                                                 error.AsCString());
460                }
461                else
462                {
463                    result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
464                                                 reg_name,
465                                                 value_str);
466                }
467                result.SetStatus (eReturnStatusFailed);
468            }
469            else
470            {
471                result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
472                result.SetStatus (eReturnStatusFailed);
473            }
474        }
475        return result.Succeeded();
476    }
477};
478
479
480//----------------------------------------------------------------------
481// CommandObjectRegister constructor
482//----------------------------------------------------------------------
483CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) :
484    CommandObjectMultiword (interpreter,
485                            "register",
486                            "A set of commands to access thread registers.",
487                            "register [read|write] ...")
488{
489    LoadSubCommand ("read",  CommandObjectSP (new CommandObjectRegisterRead (interpreter)));
490    LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter)));
491}
492
493
494//----------------------------------------------------------------------
495// Destructor
496//----------------------------------------------------------------------
497CommandObjectRegister::~CommandObjectRegister()
498{
499}
500