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