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/Debugger.h" 18 #include "lldb/Core/RegisterValue.h" 19 #include "lldb/Core/Scalar.h" 20 #include "lldb/Interpreter/Args.h" 21 #include "lldb/Interpreter/CommandInterpreter.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/OptionGroupFormat.h" 24 #include "lldb/Interpreter/OptionValueArray.h" 25 #include "lldb/Interpreter/OptionValueBoolean.h" 26 #include "lldb/Interpreter/OptionValueUInt64.h" 27 #include "lldb/Interpreter/Options.h" 28 #include "lldb/Target/ExecutionContext.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/RegisterContext.h" 31 #include "lldb/Target/SectionLoadList.h" 32 #include "lldb/Target/Thread.h" 33 #include "lldb/Utility/DataExtractor.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 for (auto &entry : command) { 216 // in most LLDB commands we accept $rbx as the name for register RBX - 217 // and here we would reject it and non-existant. we should be more 218 // consistent towards the user and allow them to say reg read $rbx - 219 // internally, however, we should be strict and not allow ourselves 220 // to call our registers $rbx in our own API 221 auto arg_str = entry.ref; 222 arg_str.consume_front("$"); 223 224 reg_info = reg_ctx->GetRegisterInfoByName(arg_str); 225 226 if (reg_info) { 227 if (!DumpRegister(m_exe_ctx, strm, reg_ctx, reg_info)) 228 strm.Printf("%-12s = error: unavailable\n", reg_info->name); 229 } else { 230 result.AppendErrorWithFormat("Invalid register name '%s'.\n", 231 arg_str.str().c_str()); 232 } 233 } 234 } 235 } 236 return result.Succeeded(); 237 } 238 239 class CommandOptions : public OptionGroup { 240 public: 241 CommandOptions() 242 : OptionGroup(), 243 set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)), 244 dump_all_sets(false, false), // Initial and default values are false 245 alternate_name(false, false) {} 246 247 ~CommandOptions() override = default; 248 249 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 250 return llvm::makeArrayRef(g_register_read_options); 251 } 252 253 void OptionParsingStarting(ExecutionContext *execution_context) override { 254 set_indexes.Clear(); 255 dump_all_sets.Clear(); 256 alternate_name.Clear(); 257 } 258 259 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 260 ExecutionContext *execution_context) override { 261 Error error; 262 const int short_option = GetDefinitions()[option_idx].short_option; 263 switch (short_option) { 264 case 's': { 265 OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error)); 266 if (value_sp) 267 set_indexes.AppendValue(value_sp); 268 } break; 269 270 case 'a': 271 // When we don't use OptionValue::SetValueFromCString(const char *) to 272 // set an option value, it won't be marked as being set in the options 273 // so we make a call to let users know the value was set via option 274 dump_all_sets.SetCurrentValue(true); 275 dump_all_sets.SetOptionWasSet(); 276 break; 277 278 case 'A': 279 // When we don't use OptionValue::SetValueFromCString(const char *) to 280 // set an option value, it won't be marked as being set in the options 281 // so we make a call to let users know the value was set via option 282 alternate_name.SetCurrentValue(true); 283 dump_all_sets.SetOptionWasSet(); 284 break; 285 286 default: 287 error.SetErrorStringWithFormat("unrecognized short option '%c'", 288 short_option); 289 break; 290 } 291 return error; 292 } 293 294 // Instance variables to hold the values for command options. 295 OptionValueArray set_indexes; 296 OptionValueBoolean dump_all_sets; 297 OptionValueBoolean alternate_name; 298 }; 299 300 OptionGroupOptions m_option_group; 301 OptionGroupFormat m_format_options; 302 CommandOptions m_command_options; 303 }; 304 305 //---------------------------------------------------------------------- 306 // "register write" 307 //---------------------------------------------------------------------- 308 class CommandObjectRegisterWrite : public CommandObjectParsed { 309 public: 310 CommandObjectRegisterWrite(CommandInterpreter &interpreter) 311 : CommandObjectParsed(interpreter, "register write", 312 "Modify a single register value.", nullptr, 313 eCommandRequiresFrame | eCommandRequiresRegContext | 314 eCommandProcessMustBeLaunched | 315 eCommandProcessMustBePaused) { 316 CommandArgumentEntry arg1; 317 CommandArgumentEntry arg2; 318 CommandArgumentData register_arg; 319 CommandArgumentData value_arg; 320 321 // Define the first (and only) variant of this arg. 322 register_arg.arg_type = eArgTypeRegisterName; 323 register_arg.arg_repetition = eArgRepeatPlain; 324 325 // There is only one variant this argument could be; put it into the 326 // argument entry. 327 arg1.push_back(register_arg); 328 329 // Define the first (and only) variant of this arg. 330 value_arg.arg_type = eArgTypeValue; 331 value_arg.arg_repetition = eArgRepeatPlain; 332 333 // There is only one variant this argument could be; put it into the 334 // argument entry. 335 arg2.push_back(value_arg); 336 337 // Push the data for the first argument into the m_arguments vector. 338 m_arguments.push_back(arg1); 339 m_arguments.push_back(arg2); 340 } 341 342 ~CommandObjectRegisterWrite() override = default; 343 344 protected: 345 bool DoExecute(Args &command, CommandReturnObject &result) override { 346 DataExtractor reg_data; 347 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 348 349 if (command.GetArgumentCount() != 2) { 350 result.AppendError( 351 "register write takes exactly 2 arguments: <reg-name> <value>"); 352 result.SetStatus(eReturnStatusFailed); 353 } else { 354 auto reg_name = command[0].ref; 355 auto value_str = command[1].ref; 356 357 // in most LLDB commands we accept $rbx as the name for register RBX - and 358 // here we would reject it and non-existant. we should be more consistent 359 // towards the user and allow them to say reg write $rbx - internally, 360 // however, we should be strict and not allow ourselves to call our 361 // registers $rbx in our own API 362 reg_name.consume_front("$"); 363 364 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 365 366 if (reg_info) { 367 RegisterValue reg_value; 368 369 Error error(reg_value.SetValueFromString(reg_info, value_str)); 370 if (error.Success()) { 371 if (reg_ctx->WriteRegister(reg_info, reg_value)) { 372 // Toss all frames and anything else in the thread 373 // after a register has been written. 374 m_exe_ctx.GetThreadRef().Flush(); 375 result.SetStatus(eReturnStatusSuccessFinishNoResult); 376 return true; 377 } 378 } 379 if (error.AsCString()) { 380 result.AppendErrorWithFormat( 381 "Failed to write register '%s' with value '%s': %s\n", 382 reg_name.str().c_str(), value_str.str().c_str(), 383 error.AsCString()); 384 } else { 385 result.AppendErrorWithFormat( 386 "Failed to write register '%s' with value '%s'", 387 reg_name.str().c_str(), value_str.str().c_str()); 388 } 389 result.SetStatus(eReturnStatusFailed); 390 } else { 391 result.AppendErrorWithFormat("Register not found for '%s'.\n", 392 reg_name.str().c_str()); 393 result.SetStatus(eReturnStatusFailed); 394 } 395 } 396 return result.Succeeded(); 397 } 398 }; 399 400 //---------------------------------------------------------------------- 401 // CommandObjectRegister constructor 402 //---------------------------------------------------------------------- 403 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) 404 : CommandObjectMultiword(interpreter, "register", 405 "Commands to access registers for the current " 406 "thread and stack frame.", 407 "register [read|write] ...") { 408 LoadSubCommand("read", 409 CommandObjectSP(new CommandObjectRegisterRead(interpreter))); 410 LoadSubCommand("write", 411 CommandObjectSP(new CommandObjectRegisterWrite(interpreter))); 412 } 413 414 CommandObjectRegister::~CommandObjectRegister() = default; 415