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