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