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