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/Scalar.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Interpreter/Args.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 #include "lldb/Interpreter/NamedOptionValue.h" 23 #include "lldb/Interpreter/Options.h" 24 #include "lldb/Target/ExecutionContext.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/RegisterContext.h" 27 #include "lldb/Target/Thread.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 //---------------------------------------------------------------------- 33 // "register read" 34 //---------------------------------------------------------------------- 35 class CommandObjectRegisterRead : public CommandObject 36 { 37 public: 38 CommandObjectRegisterRead (CommandInterpreter &interpreter) : 39 CommandObject (interpreter, 40 "register read", 41 "Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.", 42 //"register read [<reg-name1> [<reg-name2> [...]]]", 43 NULL, 44 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 45 m_options (interpreter) 46 { 47 CommandArgumentEntry arg; 48 CommandArgumentData register_arg; 49 50 // Define the first (and only) variant of this arg. 51 register_arg.arg_type = eArgTypeRegisterName; 52 register_arg.arg_repetition = eArgRepeatStar; 53 54 // There is only one variant this argument could be; put it into the argument entry. 55 arg.push_back (register_arg); 56 57 // Push the data for the first argument into the m_arguments vector. 58 m_arguments.push_back (arg); 59 } 60 61 virtual 62 ~CommandObjectRegisterRead () 63 { 64 } 65 66 Options * 67 GetOptions () 68 { 69 return &m_options; 70 } 71 72 bool 73 DumpRegister (const ExecutionContext &exe_ctx, 74 Stream &strm, 75 RegisterContext *reg_ctx, 76 const RegisterInfo *reg_info) 77 { 78 if (reg_info) 79 { 80 uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; 81 82 DataExtractor reg_data; 83 84 if (reg_ctx->ReadRegisterBytes(reg, reg_data)) 85 { 86 strm.Indent (); 87 strm.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>"); 88 Format format; 89 if (m_options.format == eFormatDefault) 90 format = reg_info->format; 91 else 92 format = m_options.format; 93 94 reg_data.Dump(&strm, 0, format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); 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_ctx->ReadRegisterAsUnsigned (reg, 0); 99 if (reg_addr) 100 { 101 Address so_reg_addr; 102 if (exe_ctx.target->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 { 251 OptionParsingStarting(); 252 } 253 254 virtual 255 ~CommandOptions () 256 { 257 } 258 259 virtual Error 260 SetOptionValue (uint32_t option_idx, const char *option_arg) 261 { 262 Error error; 263 char short_option = (char) m_getopt_table[option_idx].val; 264 switch (short_option) 265 { 266 case 'f': 267 error = Args::StringToFormat (option_arg, format, NULL); 268 break; 269 270 case 's': 271 { 272 OptionValueSP value_sp (OptionValueUInt64::Create (option_arg, error)); 273 if (value_sp) 274 set_indexes.AppendValue (value_sp); 275 } 276 break; 277 278 case 'a': 279 dump_all_sets.SetCurrentValue(true); 280 break; 281 282 default: 283 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option); 284 break; 285 } 286 return error; 287 } 288 289 void 290 OptionParsingStarting () 291 { 292 format = eFormatDefault; 293 set_indexes.Clear(); 294 dump_all_sets.Clear(); 295 } 296 297 const OptionDefinition* 298 GetDefinitions () 299 { 300 return g_option_table; 301 } 302 303 // Options table: Required for subclasses of Options. 304 305 static OptionDefinition g_option_table[]; 306 307 // Instance variables to hold the values for command options. 308 lldb::Format format; 309 OptionValueArray set_indexes; 310 OptionValueBoolean dump_all_sets; 311 }; 312 313 CommandOptions m_options; 314 }; 315 316 OptionDefinition 317 CommandObjectRegisterRead::CommandOptions::g_option_table[] = 318 { 319 { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format to use when dumping register values."}, 320 { LLDB_OPT_SET_1 , false, "set" , 's', required_argument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."}, 321 { LLDB_OPT_SET_2 , false, "all" , 'a', no_argument , NULL, 0, eArgTypeNone , "Show all register sets."}, 322 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL } 323 }; 324 325 326 327 //---------------------------------------------------------------------- 328 // "register write" 329 //---------------------------------------------------------------------- 330 class CommandObjectRegisterWrite : public CommandObject 331 { 332 public: 333 CommandObjectRegisterWrite (CommandInterpreter &interpreter) : 334 CommandObject (interpreter, 335 "register write", 336 "Modify a single register value.", 337 //"register write <reg-name> <value>", 338 NULL, 339 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 340 { 341 CommandArgumentEntry arg1; 342 CommandArgumentEntry arg2; 343 CommandArgumentData register_arg; 344 CommandArgumentData value_arg; 345 346 // Define the first (and only) variant of this arg. 347 register_arg.arg_type = eArgTypeRegisterName; 348 register_arg.arg_repetition = eArgRepeatPlain; 349 350 // There is only one variant this argument could be; put it into the argument entry. 351 arg1.push_back (register_arg); 352 353 // Define the first (and only) variant of this arg. 354 value_arg.arg_type = eArgTypeValue; 355 value_arg.arg_repetition = eArgRepeatPlain; 356 357 // There is only one variant this argument could be; put it into the argument entry. 358 arg2.push_back (value_arg); 359 360 // Push the data for the first argument into the m_arguments vector. 361 m_arguments.push_back (arg1); 362 m_arguments.push_back (arg2); 363 } 364 365 virtual 366 ~CommandObjectRegisterWrite () 367 { 368 } 369 370 virtual bool 371 Execute 372 ( 373 Args& command, 374 CommandReturnObject &result 375 ) 376 { 377 DataExtractor reg_data; 378 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 379 RegisterContext *reg_ctx = exe_ctx.GetRegisterContext (); 380 381 if (reg_ctx) 382 { 383 if (command.GetArgumentCount() != 2) 384 { 385 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); 386 result.SetStatus (eReturnStatusFailed); 387 } 388 else 389 { 390 const char *reg_name = command.GetArgumentAtIndex(0); 391 const char *value_str = command.GetArgumentAtIndex(1); 392 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 393 394 if (reg_info) 395 { 396 Scalar scalar; 397 Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size)); 398 if (error.Success()) 399 { 400 if (reg_ctx->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar)) 401 { 402 result.SetStatus (eReturnStatusSuccessFinishNoResult); 403 return true; 404 } 405 } 406 else 407 { 408 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", 409 reg_name, 410 value_str, 411 error.AsCString()); 412 result.SetStatus (eReturnStatusFailed); 413 } 414 } 415 else 416 { 417 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); 418 result.SetStatus (eReturnStatusFailed); 419 } 420 } 421 } 422 else 423 { 424 result.AppendError ("no current frame"); 425 result.SetStatus (eReturnStatusFailed); 426 } 427 return result.Succeeded(); 428 } 429 }; 430 431 432 //---------------------------------------------------------------------- 433 // CommandObjectRegister constructor 434 //---------------------------------------------------------------------- 435 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : 436 CommandObjectMultiword (interpreter, 437 "register", 438 "A set of commands to access thread registers.", 439 "register [read|write] ...") 440 { 441 LoadSubCommand ("read", CommandObjectSP (new CommandObjectRegisterRead (interpreter))); 442 LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter))); 443 } 444 445 446 //---------------------------------------------------------------------- 447 // Destructor 448 //---------------------------------------------------------------------- 449 CommandObjectRegister::~CommandObjectRegister() 450 { 451 } 452