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