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