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 const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx); 138 if (reg_set) 139 { 140 strm.Printf ("%s:\n", reg_set->name); 141 strm.IndentMore (); 142 const size_t num_registers = reg_set->num_registers; 143 for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) 144 { 145 const uint32_t reg = reg_set->registers[reg_idx]; 146 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg); 147 // Skip the dumping of derived register if primitive_only is true. 148 if (primitive_only && reg_info && reg_info->value_regs) 149 continue; 150 if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info)) 151 ++available_count; 152 else 153 ++unavailable_count; 154 } 155 strm.IndentLess (); 156 if (unavailable_count) 157 { 158 strm.Indent (); 159 strm.Printf("%u registers were unavailable.\n", unavailable_count); 160 } 161 strm.EOL(); 162 } 163 return available_count > 0; 164 } 165 166 protected: 167 virtual bool 168 DoExecute (Args& command, CommandReturnObject &result) 169 { 170 Stream &strm = result.GetOutputStream(); 171 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); 172 173 const RegisterInfo *reg_info = NULL; 174 if (command.GetArgumentCount() == 0) 175 { 176 size_t set_idx; 177 178 size_t num_register_sets = 1; 179 const size_t set_array_size = m_command_options.set_indexes.GetSize(); 180 if (set_array_size > 0) 181 { 182 for (size_t i=0; i<set_array_size; ++i) 183 { 184 set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL); 185 if (set_idx != UINT32_MAX) 186 { 187 if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx)) 188 { 189 result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx); 190 result.SetStatus (eReturnStatusFailed); 191 break; 192 } 193 } 194 else 195 { 196 result.AppendError ("invalid register set index\n"); 197 result.SetStatus (eReturnStatusFailed); 198 break; 199 } 200 } 201 } 202 else 203 { 204 if (m_command_options.dump_all_sets) 205 num_register_sets = reg_ctx->GetRegisterSetCount(); 206 207 for (set_idx = 0; set_idx < num_register_sets; ++set_idx) 208 { 209 // When dump_all_sets option is set, dump primitive as well as derived registers. 210 DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue()); 211 } 212 } 213 } 214 else 215 { 216 if (m_command_options.dump_all_sets) 217 { 218 result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n"); 219 result.SetStatus (eReturnStatusFailed); 220 } 221 else if (m_command_options.set_indexes.GetSize() > 0) 222 { 223 result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n"); 224 result.SetStatus (eReturnStatusFailed); 225 } 226 else 227 { 228 const char *arg_cstr; 229 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 230 { 231 // in most LLDB commands we accept $rbx as the name for register RBX - and here we would 232 // reject it and non-existant. we should be more consistent towards the user and allow them 233 // to say reg read $rbx - internally, however, we should be strict and not allow ourselves 234 // to call our registers $rbx in our own API 235 if (*arg_cstr == '$') 236 arg_cstr = arg_cstr+1; 237 reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr); 238 239 if (reg_info) 240 { 241 if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info)) 242 strm.Printf("%-12s = error: unavailable\n", reg_info->name); 243 } 244 else 245 { 246 result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr); 247 } 248 } 249 } 250 } 251 return result.Succeeded(); 252 } 253 254 class CommandOptions : public OptionGroup 255 { 256 public: 257 CommandOptions () : 258 OptionGroup(), 259 set_indexes (OptionValue::ConvertTypeToMask (OptionValue::eTypeUInt64)), 260 dump_all_sets (false, false), // Initial and default values are false 261 alternate_name (false, false) 262 { 263 } 264 265 virtual 266 ~CommandOptions () 267 { 268 } 269 270 271 virtual uint32_t 272 GetNumDefinitions (); 273 274 virtual const OptionDefinition* 275 GetDefinitions () 276 { 277 return g_option_table; 278 } 279 280 virtual void 281 OptionParsingStarting (CommandInterpreter &interpreter) 282 { 283 set_indexes.Clear(); 284 dump_all_sets.Clear(); 285 alternate_name.Clear(); 286 } 287 288 virtual Error 289 SetOptionValue (CommandInterpreter &interpreter, 290 uint32_t option_idx, 291 const char *option_value) 292 { 293 Error error; 294 const int short_option = g_option_table[option_idx].short_option; 295 switch (short_option) 296 { 297 case 's': 298 { 299 OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error)); 300 if (value_sp) 301 set_indexes.AppendValue (value_sp); 302 } 303 break; 304 305 case 'a': 306 // When we don't use OptionValue::SetValueFromCString(const char *) to 307 // set an option value, it won't be marked as being set in the options 308 // so we make a call to let users know the value was set via option 309 dump_all_sets.SetCurrentValue (true); 310 dump_all_sets.SetOptionWasSet (); 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 alternate_name.SetCurrentValue (true); 318 dump_all_sets.SetOptionWasSet (); 319 break; 320 321 default: 322 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 323 break; 324 } 325 return error; 326 } 327 328 // Options table: Required for subclasses of Options. 329 330 static const OptionDefinition g_option_table[]; 331 332 // Instance variables to hold the values for command options. 333 OptionValueArray set_indexes; 334 OptionValueBoolean dump_all_sets; 335 OptionValueBoolean alternate_name; 336 }; 337 338 OptionGroupOptions m_option_group; 339 OptionGroupFormat m_format_options; 340 CommandOptions m_command_options; 341 }; 342 343 const OptionDefinition 344 CommandObjectRegisterRead::CommandOptions::g_option_table[] = 345 { 346 { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument , NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."}, 347 { LLDB_OPT_SET_1 , false, "set" , 's', required_argument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."}, 348 { LLDB_OPT_SET_2 , false, "all" , 'a', no_argument , NULL, 0, eArgTypeNone , "Show all register sets."}, 349 }; 350 351 uint32_t 352 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions () 353 { 354 return sizeof(g_option_table)/sizeof(OptionDefinition); 355 } 356 357 358 //---------------------------------------------------------------------- 359 // "register write" 360 //---------------------------------------------------------------------- 361 class CommandObjectRegisterWrite : public CommandObjectParsed 362 { 363 public: 364 CommandObjectRegisterWrite (CommandInterpreter &interpreter) : 365 CommandObjectParsed (interpreter, 366 "register write", 367 "Modify a single register value.", 368 NULL, 369 eFlagRequiresFrame | 370 eFlagRequiresRegContext | 371 eFlagProcessMustBeLaunched | 372 eFlagProcessMustBePaused) 373 { 374 CommandArgumentEntry arg1; 375 CommandArgumentEntry arg2; 376 CommandArgumentData register_arg; 377 CommandArgumentData value_arg; 378 379 // Define the first (and only) variant of this arg. 380 register_arg.arg_type = eArgTypeRegisterName; 381 register_arg.arg_repetition = eArgRepeatPlain; 382 383 // There is only one variant this argument could be; put it into the argument entry. 384 arg1.push_back (register_arg); 385 386 // Define the first (and only) variant of this arg. 387 value_arg.arg_type = eArgTypeValue; 388 value_arg.arg_repetition = eArgRepeatPlain; 389 390 // There is only one variant this argument could be; put it into the argument entry. 391 arg2.push_back (value_arg); 392 393 // Push the data for the first argument into the m_arguments vector. 394 m_arguments.push_back (arg1); 395 m_arguments.push_back (arg2); 396 } 397 398 virtual 399 ~CommandObjectRegisterWrite () 400 { 401 } 402 403 protected: 404 virtual bool 405 DoExecute(Args& command, CommandReturnObject &result) 406 { 407 DataExtractor reg_data; 408 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); 409 410 if (command.GetArgumentCount() != 2) 411 { 412 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); 413 result.SetStatus (eReturnStatusFailed); 414 } 415 else 416 { 417 const char *reg_name = command.GetArgumentAtIndex(0); 418 const char *value_str = command.GetArgumentAtIndex(1); 419 420 421 // in most LLDB commands we accept $rbx as the name for register RBX - and here we would 422 // reject it and non-existant. we should be more consistent towards the user and allow them 423 // to say reg write $rbx - internally, however, we should be strict and not allow ourselves 424 // to call our registers $rbx in our own API 425 if (reg_name && *reg_name == '$') 426 reg_name = reg_name+1; 427 428 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 429 430 if (reg_info) 431 { 432 RegisterValue reg_value; 433 434 Error error (reg_value.SetValueFromCString (reg_info, value_str)); 435 if (error.Success()) 436 { 437 if (reg_ctx->WriteRegister (reg_info, reg_value)) 438 { 439 // Toss all frames and anything else in the thread 440 // after a register has been written. 441 m_exe_ctx.GetThreadRef().Flush(); 442 result.SetStatus (eReturnStatusSuccessFinishNoResult); 443 return true; 444 } 445 } 446 if (error.AsCString()) 447 { 448 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", 449 reg_name, 450 value_str, 451 error.AsCString()); 452 } 453 else 454 { 455 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'", 456 reg_name, 457 value_str); 458 } 459 result.SetStatus (eReturnStatusFailed); 460 } 461 else 462 { 463 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); 464 result.SetStatus (eReturnStatusFailed); 465 } 466 } 467 return result.Succeeded(); 468 } 469 }; 470 471 472 //---------------------------------------------------------------------- 473 // CommandObjectRegister constructor 474 //---------------------------------------------------------------------- 475 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : 476 CommandObjectMultiword (interpreter, 477 "register", 478 "A set of commands to access thread registers.", 479 "register [read|write] ...") 480 { 481 LoadSubCommand ("read", CommandObjectSP (new CommandObjectRegisterRead (interpreter))); 482 LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter))); 483 } 484 485 486 //---------------------------------------------------------------------- 487 // Destructor 488 //---------------------------------------------------------------------- 489 CommandObjectRegister::~CommandObjectRegister() 490 { 491 } 492