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