Home | History | Annotate | Download | only in Commands
      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 
     34 using namespace lldb;
     35 using namespace lldb_private;
     36 
     37 //----------------------------------------------------------------------
     38 // "register read"
     39 //----------------------------------------------------------------------
     40 class CommandObjectRegisterRead : public CommandObjectParsed
     41 {
     42 public:
     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 = 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 
    171 protected:
    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 with errno: %d\n", 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 
    351 const OptionDefinition
    352 CommandObjectRegisterRead::CommandOptions::g_option_table[] =
    353 {
    354     { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument      , NULL, 0, eArgTypeNone      , "Display register names using the alternate register name if there is one."},
    355     { LLDB_OPT_SET_1  , false, "set"      , 's', required_argument, NULL, 0, eArgTypeIndex     , "Specify which register sets to dump by index."},
    356     { LLDB_OPT_SET_2  , false, "all"      , 'a', no_argument      , NULL, 0, eArgTypeNone      , "Show all register sets."},
    357 };
    358 
    359 uint32_t
    360 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions ()
    361 {
    362     return sizeof(g_option_table)/sizeof(OptionDefinition);
    363 }
    364 
    365 
    366 //----------------------------------------------------------------------
    367 // "register write"
    368 //----------------------------------------------------------------------
    369 class CommandObjectRegisterWrite : public CommandObjectParsed
    370 {
    371 public:
    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 
    411 protected:
    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 //----------------------------------------------------------------------
    483 CommandObjectRegister::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 //----------------------------------------------------------------------
    497 CommandObjectRegister::~CommandObjectRegister()
    498 {
    499 }
    500