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