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