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