1 //===-- CommandObjectRegister.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectRegister.h" 10 #include "lldb/Core/Debugger.h" 11 #include "lldb/Core/DumpRegisterInfo.h" 12 #include "lldb/Core/DumpRegisterValue.h" 13 #include "lldb/Host/OptionParser.h" 14 #include "lldb/Interpreter/CommandInterpreter.h" 15 #include "lldb/Interpreter/CommandOptionArgumentTable.h" 16 #include "lldb/Interpreter/CommandReturnObject.h" 17 #include "lldb/Interpreter/OptionGroupFormat.h" 18 #include "lldb/Interpreter/OptionValueArray.h" 19 #include "lldb/Interpreter/OptionValueBoolean.h" 20 #include "lldb/Interpreter/OptionValueUInt64.h" 21 #include "lldb/Interpreter/Options.h" 22 #include "lldb/Target/ExecutionContext.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/RegisterContext.h" 25 #include "lldb/Target/SectionLoadList.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Utility/Args.h" 28 #include "lldb/Utility/DataExtractor.h" 29 #include "lldb/Utility/RegisterValue.h" 30 #include "llvm/Support/Errno.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 // "register read" 36 #define LLDB_OPTIONS_register_read 37 #include "CommandOptions.inc" 38 39 class CommandObjectRegisterRead : public CommandObjectParsed { 40 public: 41 CommandObjectRegisterRead(CommandInterpreter &interpreter) 42 : CommandObjectParsed( 43 interpreter, "register read", 44 "Dump the contents of one or more register values from the current " 45 "frame. If no register is specified, dumps them all.", 46 nullptr, 47 eCommandRequiresFrame | eCommandRequiresRegContext | 48 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 49 m_format_options(eFormatDefault, UINT64_MAX, UINT64_MAX, 50 {{CommandArgumentType::eArgTypeFormat, 51 "Specify a format to be used for display. If this " 52 "is set, register fields will not be displayed."}}) { 53 AddSimpleArgumentList(eArgTypeRegisterName, eArgRepeatStar); 54 55 // Add the "--format" 56 m_option_group.Append(&m_format_options, 57 OptionGroupFormat::OPTION_GROUP_FORMAT | 58 OptionGroupFormat::OPTION_GROUP_GDB_FMT, 59 LLDB_OPT_SET_ALL); 60 m_option_group.Append(&m_command_options); 61 m_option_group.Finalize(); 62 } 63 64 ~CommandObjectRegisterRead() override = default; 65 66 void 67 HandleArgumentCompletion(CompletionRequest &request, 68 OptionElementVector &opt_element_vector) override { 69 if (!m_exe_ctx.HasProcessScope()) 70 return; 71 CommandObject::HandleArgumentCompletion(request, opt_element_vector); 72 } 73 74 Options *GetOptions() override { return &m_option_group; } 75 76 bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, 77 RegisterContext ®_ctx, const RegisterInfo ®_info, 78 bool print_flags) { 79 RegisterValue reg_value; 80 if (!reg_ctx.ReadRegister(®_info, reg_value)) 81 return false; 82 83 strm.Indent(); 84 85 bool prefix_with_altname = (bool)m_command_options.alternate_name; 86 bool prefix_with_name = !prefix_with_altname; 87 DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name, 88 prefix_with_altname, m_format_options.GetFormat(), 8, 89 exe_ctx.GetBestExecutionContextScope(), print_flags, 90 exe_ctx.GetTargetSP()); 91 if ((reg_info.encoding == eEncodingUint) || 92 (reg_info.encoding == eEncodingSint)) { 93 Process *process = exe_ctx.GetProcessPtr(); 94 if (process && reg_info.byte_size == process->GetAddressByteSize()) { 95 addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); 96 if (reg_addr != LLDB_INVALID_ADDRESS) { 97 Address so_reg_addr; 98 if (exe_ctx.GetTargetRef().ResolveLoadAddress(reg_addr, 99 so_reg_addr)) { 100 strm.PutCString(" "); 101 so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), 102 Address::DumpStyleResolvedDescription); 103 } 104 } 105 } 106 } 107 strm.EOL(); 108 return true; 109 } 110 111 bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm, 112 RegisterContext *reg_ctx, size_t set_idx, 113 bool primitive_only = false) { 114 uint32_t unavailable_count = 0; 115 uint32_t available_count = 0; 116 117 if (!reg_ctx) 118 return false; // thread has no registers (i.e. core files are corrupt, 119 // incomplete crash logs...) 120 121 const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx); 122 if (reg_set) { 123 strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown")); 124 strm.IndentMore(); 125 const size_t num_registers = reg_set->num_registers; 126 for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) { 127 const uint32_t reg = reg_set->registers[reg_idx]; 128 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg); 129 // Skip the dumping of derived register if primitive_only is true. 130 if (primitive_only && reg_info && reg_info->value_regs) 131 continue; 132 133 if (reg_info && DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info, 134 /*print_flags=*/false)) 135 ++available_count; 136 else 137 ++unavailable_count; 138 } 139 strm.IndentLess(); 140 if (unavailable_count) { 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 protected: 150 void DoExecute(Args &command, CommandReturnObject &result) override { 151 Stream &strm = result.GetOutputStream(); 152 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 153 154 if (command.GetArgumentCount() == 0) { 155 size_t set_idx; 156 157 size_t num_register_sets = 1; 158 const size_t set_array_size = m_command_options.set_indexes.GetSize(); 159 if (set_array_size > 0) { 160 for (size_t i = 0; i < set_array_size; ++i) { 161 set_idx = 162 m_command_options.set_indexes[i]->GetValueAs<uint64_t>().value_or( 163 UINT32_MAX); 164 if (set_idx < reg_ctx->GetRegisterSetCount()) { 165 if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) { 166 if (errno) 167 result.AppendErrorWithFormatv("register read failed: {0}\n", 168 llvm::sys::StrError()); 169 else 170 result.AppendError("unknown error while reading registers.\n"); 171 break; 172 } 173 } else { 174 result.AppendErrorWithFormat( 175 "invalid register set index: %" PRIu64 "\n", (uint64_t)set_idx); 176 break; 177 } 178 } 179 } else { 180 if (m_command_options.dump_all_sets) 181 num_register_sets = reg_ctx->GetRegisterSetCount(); 182 183 for (set_idx = 0; set_idx < num_register_sets; ++set_idx) { 184 // When dump_all_sets option is set, dump primitive as well as 185 // derived registers. 186 DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx, 187 !m_command_options.dump_all_sets.GetCurrentValue()); 188 } 189 } 190 } else { 191 if (m_command_options.dump_all_sets) { 192 result.AppendError("the --all option can't be used when registers " 193 "names are supplied as arguments\n"); 194 } else if (m_command_options.set_indexes.GetSize() > 0) { 195 result.AppendError("the --set <set> option can't be used when " 196 "registers names are supplied as arguments\n"); 197 } else { 198 for (auto &entry : command) { 199 // in most LLDB commands we accept $rbx as the name for register RBX 200 // - and here we would reject it and non-existant. we should be more 201 // consistent towards the user and allow them to say reg read $rbx - 202 // internally, however, we should be strict and not allow ourselves 203 // to call our registers $rbx in our own API 204 auto arg_str = entry.ref(); 205 arg_str.consume_front("$"); 206 207 if (const RegisterInfo *reg_info = 208 reg_ctx->GetRegisterInfoByName(arg_str)) { 209 // If they have asked for a specific format don't obscure that by 210 // printing flags afterwards. 211 bool print_flags = 212 !m_format_options.GetFormatValue().OptionWasSet(); 213 if (!DumpRegister(m_exe_ctx, strm, *reg_ctx, *reg_info, 214 print_flags)) 215 strm.Printf("%-12s = error: unavailable\n", reg_info->name); 216 } else { 217 result.AppendErrorWithFormat("Invalid register name '%s'.\n", 218 arg_str.str().c_str()); 219 } 220 } 221 } 222 } 223 } 224 225 class CommandOptions : public OptionGroup { 226 public: 227 CommandOptions() 228 : set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)), 229 dump_all_sets(false, false), // Initial and default values are false 230 alternate_name(false, false) {} 231 232 ~CommandOptions() override = default; 233 234 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 235 return llvm::ArrayRef(g_register_read_options); 236 } 237 238 void OptionParsingStarting(ExecutionContext *execution_context) override { 239 set_indexes.Clear(); 240 dump_all_sets.Clear(); 241 alternate_name.Clear(); 242 } 243 244 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 245 ExecutionContext *execution_context) override { 246 Status error; 247 const int short_option = GetDefinitions()[option_idx].short_option; 248 switch (short_option) { 249 case 's': { 250 OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error)); 251 if (value_sp) 252 set_indexes.AppendValue(value_sp); 253 } break; 254 255 case 'a': 256 // When we don't use OptionValue::SetValueFromCString(const char *) to 257 // set an option value, it won't be marked as being set in the options 258 // so we make a call to let users know the value was set via option 259 dump_all_sets.SetCurrentValue(true); 260 dump_all_sets.SetOptionWasSet(); 261 break; 262 263 case 'A': 264 // When we don't use OptionValue::SetValueFromCString(const char *) to 265 // set an option value, it won't be marked as being set in the options 266 // so we make a call to let users know the value was set via option 267 alternate_name.SetCurrentValue(true); 268 dump_all_sets.SetOptionWasSet(); 269 break; 270 271 default: 272 llvm_unreachable("Unimplemented option"); 273 } 274 return error; 275 } 276 277 // Instance variables to hold the values for command options. 278 OptionValueArray set_indexes; 279 OptionValueBoolean dump_all_sets; 280 OptionValueBoolean alternate_name; 281 }; 282 283 OptionGroupOptions m_option_group; 284 OptionGroupFormat m_format_options; 285 CommandOptions m_command_options; 286 }; 287 288 // "register write" 289 class CommandObjectRegisterWrite : public CommandObjectParsed { 290 public: 291 CommandObjectRegisterWrite(CommandInterpreter &interpreter) 292 : CommandObjectParsed(interpreter, "register write", 293 "Modify a single register value.", nullptr, 294 eCommandRequiresFrame | eCommandRequiresRegContext | 295 eCommandProcessMustBeLaunched | 296 eCommandProcessMustBePaused) { 297 CommandArgumentEntry arg1; 298 CommandArgumentEntry arg2; 299 CommandArgumentData register_arg; 300 CommandArgumentData value_arg; 301 302 // Define the first (and only) variant of this arg. 303 register_arg.arg_type = eArgTypeRegisterName; 304 register_arg.arg_repetition = eArgRepeatPlain; 305 306 // There is only one variant this argument could be; put it into the 307 // argument entry. 308 arg1.push_back(register_arg); 309 310 // Define the first (and only) variant of this arg. 311 value_arg.arg_type = eArgTypeValue; 312 value_arg.arg_repetition = eArgRepeatPlain; 313 314 // There is only one variant this argument could be; put it into the 315 // argument entry. 316 arg2.push_back(value_arg); 317 318 // Push the data for the first argument into the m_arguments vector. 319 m_arguments.push_back(arg1); 320 m_arguments.push_back(arg2); 321 } 322 323 ~CommandObjectRegisterWrite() override = default; 324 325 void 326 HandleArgumentCompletion(CompletionRequest &request, 327 OptionElementVector &opt_element_vector) override { 328 if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 329 return; 330 331 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 332 GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr); 333 } 334 335 protected: 336 void DoExecute(Args &command, CommandReturnObject &result) override { 337 DataExtractor reg_data; 338 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 339 340 if (command.GetArgumentCount() != 2) { 341 result.AppendError( 342 "register write takes exactly 2 arguments: <reg-name> <value>"); 343 } else { 344 auto reg_name = command[0].ref(); 345 auto value_str = command[1].ref(); 346 347 // in most LLDB commands we accept $rbx as the name for register RBX - 348 // and here we would reject it and non-existant. we should be more 349 // consistent towards the user and allow them to say reg write $rbx - 350 // internally, however, we should be strict and not allow ourselves to 351 // call our registers $rbx in our own API 352 reg_name.consume_front("$"); 353 354 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 355 356 if (reg_info) { 357 RegisterValue reg_value; 358 359 Status error(reg_value.SetValueFromString(reg_info, value_str)); 360 if (error.Success()) { 361 if (reg_ctx->WriteRegister(reg_info, reg_value)) { 362 // Toss all frames and anything else in the thread after a register 363 // has been written. 364 m_exe_ctx.GetThreadRef().Flush(); 365 result.SetStatus(eReturnStatusSuccessFinishNoResult); 366 return; 367 } 368 } 369 if (error.AsCString()) { 370 result.AppendErrorWithFormat( 371 "Failed to write register '%s' with value '%s': %s\n", 372 reg_name.str().c_str(), value_str.str().c_str(), 373 error.AsCString()); 374 } else { 375 result.AppendErrorWithFormat( 376 "Failed to write register '%s' with value '%s'", 377 reg_name.str().c_str(), value_str.str().c_str()); 378 } 379 } else { 380 result.AppendErrorWithFormat("Register not found for '%s'.\n", 381 reg_name.str().c_str()); 382 } 383 } 384 } 385 }; 386 387 // "register info" 388 class CommandObjectRegisterInfo : public CommandObjectParsed { 389 public: 390 CommandObjectRegisterInfo(CommandInterpreter &interpreter) 391 : CommandObjectParsed(interpreter, "register info", 392 "View information about a register.", nullptr, 393 eCommandRequiresFrame | eCommandRequiresRegContext | 394 eCommandProcessMustBeLaunched | 395 eCommandProcessMustBePaused) { 396 SetHelpLong(R"( 397 Name The name lldb uses for the register, optionally with an alias. 398 Size The size of the register in bytes and again in bits. 399 Invalidates (*) The registers that would be changed if you wrote this 400 register. For example, writing to a narrower alias of a wider 401 register would change the value of the wider register. 402 Read from (*) The registers that the value of this register is constructed 403 from. For example, a narrower alias of a wider register will be 404 read from the wider register. 405 In sets (*) The register sets that contain this register. For example the 406 PC will be in the "General Purpose Register" set. 407 Fields (*) A table of the names and bit positions of the values contained 408 in this register. 409 410 Fields marked with (*) may not always be present. Some information may be 411 different for the same register when connected to different debug servers.)"); 412 413 AddSimpleArgumentList(eArgTypeRegisterName); 414 } 415 416 ~CommandObjectRegisterInfo() override = default; 417 418 void 419 HandleArgumentCompletion(CompletionRequest &request, 420 OptionElementVector &opt_element_vector) override { 421 if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 422 return; 423 CommandObject::HandleArgumentCompletion(request, opt_element_vector); 424 } 425 426 protected: 427 void DoExecute(Args &command, CommandReturnObject &result) override { 428 if (command.GetArgumentCount() != 1) { 429 result.AppendError("register info takes exactly 1 argument: <reg-name>"); 430 return; 431 } 432 433 llvm::StringRef reg_name = command[0].ref(); 434 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 435 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 436 if (reg_info) { 437 DumpRegisterInfo( 438 result.GetOutputStream(), *reg_ctx, *reg_info, 439 GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 440 result.SetStatus(eReturnStatusSuccessFinishResult); 441 } else 442 result.AppendErrorWithFormat("No register found with name '%s'.\n", 443 reg_name.str().c_str()); 444 } 445 }; 446 447 // CommandObjectRegister constructor 448 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) 449 : CommandObjectMultiword(interpreter, "register", 450 "Commands to access registers for the current " 451 "thread and stack frame.", 452 "register [read|write|info] ...") { 453 LoadSubCommand("read", 454 CommandObjectSP(new CommandObjectRegisterRead(interpreter))); 455 LoadSubCommand("write", 456 CommandObjectSP(new CommandObjectRegisterWrite(interpreter))); 457 LoadSubCommand("info", 458 CommandObjectSP(new CommandObjectRegisterInfo(interpreter))); 459 } 460 461 CommandObjectRegister::~CommandObjectRegister() = default; 462