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 "CommandObjectRegister.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/DataExtractor.h" 17 #include "lldb/Core/RegisterValue.h" 18 #include "lldb/Core/Scalar.h" 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Interpreter/Args.h" 21 #include "lldb/Interpreter/CommandInterpreter.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/Options.h" 24 #include "lldb/Interpreter/OptionGroupFormat.h" 25 #include "lldb/Interpreter/OptionValueArray.h" 26 #include "lldb/Interpreter/OptionValueBoolean.h" 27 #include "lldb/Interpreter/OptionValueUInt64.h" 28 #include "lldb/Target/ExecutionContext.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/RegisterContext.h" 31 #include "lldb/Target/SectionLoadList.h" 32 #include "lldb/Target/Thread.h" 33 #include "llvm/ADT/STLExtras.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 eCommandRequiresFrame | 50 eCommandRequiresRegContext | 51 eCommandProcessMustBeLaunched | 52 eCommandProcessMustBePaused ), 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 ~CommandObjectRegisterRead () override 78 { 79 } 80 81 Options * 82 GetOptions () override 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 = (bool)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 ? reg_set->name : "unknown") ); 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 bool 173 DoExecute (Args& command, CommandReturnObject &result) override 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: %s\n", strerror(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: %" PRIu64 "\n", (uint64_t)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 ~CommandOptions () override 274 { 275 } 276 277 278 uint32_t 279 GetNumDefinitions () override; 280 281 const OptionDefinition* 282 GetDefinitions () override 283 { 284 return g_option_table; 285 } 286 287 void 288 OptionParsingStarting (CommandInterpreter &interpreter) override 289 { 290 set_indexes.Clear(); 291 dump_all_sets.Clear(); 292 alternate_name.Clear(); 293 } 294 295 Error 296 SetOptionValue (CommandInterpreter &interpreter, 297 uint32_t option_idx, 298 const char *option_value) override 299 { 300 Error error; 301 const int short_option = g_option_table[option_idx].short_option; 302 switch (short_option) 303 { 304 case 's': 305 { 306 OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error)); 307 if (value_sp) 308 set_indexes.AppendValue (value_sp); 309 } 310 break; 311 312 case 'a': 313 // When we don't use OptionValue::SetValueFromCString(const char *) to 314 // set an option value, it won't be marked as being set in the options 315 // so we make a call to let users know the value was set via option 316 dump_all_sets.SetCurrentValue (true); 317 dump_all_sets.SetOptionWasSet (); 318 break; 319 320 case 'A': 321 // When we don't use OptionValue::SetValueFromCString(const char *) to 322 // set an option value, it won't be marked as being set in the options 323 // so we make a call to let users know the value was set via option 324 alternate_name.SetCurrentValue (true); 325 dump_all_sets.SetOptionWasSet (); 326 break; 327 328 default: 329 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 330 break; 331 } 332 return error; 333 } 334 335 // Options table: Required for subclasses of Options. 336 337 static const OptionDefinition g_option_table[]; 338 339 // Instance variables to hold the values for command options. 340 OptionValueArray set_indexes; 341 OptionValueBoolean dump_all_sets; 342 OptionValueBoolean alternate_name; 343 }; 344 345 OptionGroupOptions m_option_group; 346 OptionGroupFormat m_format_options; 347 CommandOptions m_command_options; 348 }; 349 350 const OptionDefinition 351 CommandObjectRegisterRead::CommandOptions::g_option_table[] = 352 { 353 { 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."}, 354 { LLDB_OPT_SET_1 , false, "set" , 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."}, 355 { LLDB_OPT_SET_2 , false, "all" , 'a', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Show all register sets."}, 356 }; 357 358 uint32_t 359 CommandObjectRegisterRead::CommandOptions::GetNumDefinitions () 360 { 361 return llvm::array_lengthof(g_option_table); 362 } 363 364 365 //---------------------------------------------------------------------- 366 // "register write" 367 //---------------------------------------------------------------------- 368 class CommandObjectRegisterWrite : public CommandObjectParsed 369 { 370 public: 371 CommandObjectRegisterWrite (CommandInterpreter &interpreter) : 372 CommandObjectParsed (interpreter, 373 "register write", 374 "Modify a single register value.", 375 NULL, 376 eCommandRequiresFrame | 377 eCommandRequiresRegContext | 378 eCommandProcessMustBeLaunched | 379 eCommandProcessMustBePaused) 380 { 381 CommandArgumentEntry arg1; 382 CommandArgumentEntry arg2; 383 CommandArgumentData register_arg; 384 CommandArgumentData value_arg; 385 386 // Define the first (and only) variant of this arg. 387 register_arg.arg_type = eArgTypeRegisterName; 388 register_arg.arg_repetition = eArgRepeatPlain; 389 390 // There is only one variant this argument could be; put it into the argument entry. 391 arg1.push_back (register_arg); 392 393 // Define the first (and only) variant of this arg. 394 value_arg.arg_type = eArgTypeValue; 395 value_arg.arg_repetition = eArgRepeatPlain; 396 397 // There is only one variant this argument could be; put it into the argument entry. 398 arg2.push_back (value_arg); 399 400 // Push the data for the first argument into the m_arguments vector. 401 m_arguments.push_back (arg1); 402 m_arguments.push_back (arg2); 403 } 404 405 ~CommandObjectRegisterWrite () override 406 { 407 } 408 409 protected: 410 bool 411 DoExecute(Args& command, CommandReturnObject &result) override 412 { 413 DataExtractor reg_data; 414 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); 415 416 if (command.GetArgumentCount() != 2) 417 { 418 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); 419 result.SetStatus (eReturnStatusFailed); 420 } 421 else 422 { 423 const char *reg_name = command.GetArgumentAtIndex(0); 424 const char *value_str = command.GetArgumentAtIndex(1); 425 426 427 // in most LLDB commands we accept $rbx as the name for register RBX - and here we would 428 // reject it and non-existant. we should be more consistent towards the user and allow them 429 // to say reg write $rbx - internally, however, we should be strict and not allow ourselves 430 // to call our registers $rbx in our own API 431 if (reg_name && *reg_name == '$') 432 reg_name = reg_name+1; 433 434 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 435 436 if (reg_info) 437 { 438 RegisterValue reg_value; 439 440 Error error (reg_value.SetValueFromCString (reg_info, value_str)); 441 if (error.Success()) 442 { 443 if (reg_ctx->WriteRegister (reg_info, reg_value)) 444 { 445 // Toss all frames and anything else in the thread 446 // after a register has been written. 447 m_exe_ctx.GetThreadRef().Flush(); 448 result.SetStatus (eReturnStatusSuccessFinishNoResult); 449 return true; 450 } 451 } 452 if (error.AsCString()) 453 { 454 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", 455 reg_name, 456 value_str, 457 error.AsCString()); 458 } 459 else 460 { 461 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'", 462 reg_name, 463 value_str); 464 } 465 result.SetStatus (eReturnStatusFailed); 466 } 467 else 468 { 469 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); 470 result.SetStatus (eReturnStatusFailed); 471 } 472 } 473 return result.Succeeded(); 474 } 475 }; 476 477 478 //---------------------------------------------------------------------- 479 // CommandObjectRegister constructor 480 //---------------------------------------------------------------------- 481 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : 482 CommandObjectMultiword (interpreter, 483 "register", 484 "A set of commands to access thread registers.", 485 "register [read|write] ...") 486 { 487 LoadSubCommand ("read", CommandObjectSP (new CommandObjectRegisterRead (interpreter))); 488 LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter))); 489 } 490 491 492 //---------------------------------------------------------------------- 493 // Destructor 494 //---------------------------------------------------------------------- 495 CommandObjectRegister::~CommandObjectRegister() 496 { 497 } 498