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