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 #include "CommandObjectRegister.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/DataExtractor.h" 17 #include "lldb/Core/Scalar.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Interpreter/Args.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 #include "lldb/Target/ExecutionContext.h" 23 #include "lldb/Target/RegisterContext.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 //---------------------------------------------------------------------- 29 // "register read" 30 //---------------------------------------------------------------------- 31 class CommandObjectRegisterRead : public CommandObject 32 { 33 public: 34 CommandObjectRegisterRead (CommandInterpreter &interpreter) : 35 CommandObject (interpreter, 36 "register read", 37 "Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.", 38 //"register read [<reg-name1> [<reg-name2> [...]]]", 39 NULL, 40 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 41 { 42 CommandArgumentEntry arg; 43 CommandArgumentData register_arg; 44 45 // Define the first (and only) variant of this arg. 46 register_arg.arg_type = eArgTypeRegisterName; 47 register_arg.arg_repetition = eArgRepeatStar; 48 49 // There is only one variant this argument could be; put it into the argument entry. 50 arg.push_back (register_arg); 51 52 // Push the data for the first argument into the m_arguments vector. 53 m_arguments.push_back (arg); 54 } 55 56 virtual 57 ~CommandObjectRegisterRead () 58 { 59 } 60 61 virtual bool 62 Execute 63 ( 64 Args& command, 65 CommandReturnObject &result 66 ) 67 { 68 StreamString &output_stream = result.GetOutputStream(); 69 DataExtractor reg_data; 70 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 71 RegisterContext *reg_context = exe_ctx.GetRegisterContext (); 72 73 if (reg_context) 74 { 75 const RegisterInfo *reg_info = NULL; 76 if (command.GetArgumentCount() == 0) 77 { 78 uint32_t set_idx; 79 const uint32_t num_register_sets = reg_context->GetRegisterSetCount(); 80 for (set_idx = 0; set_idx < num_register_sets; ++set_idx) 81 { 82 uint32_t unavailable_count = 0; 83 const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx); 84 output_stream.Printf ("%s:\n", reg_set->name); 85 output_stream.IndentMore (); 86 const uint32_t num_registers = reg_set->num_registers; 87 for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) 88 { 89 uint32_t reg = reg_set->registers[reg_idx]; 90 reg_info = reg_context->GetRegisterInfoAtIndex(reg); 91 if (reg_context->ReadRegisterBytes(reg, reg_data)) 92 { 93 output_stream.Indent (); 94 output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>"); 95 reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); 96 output_stream.EOL(); 97 } 98 else 99 { 100 ++unavailable_count; 101 } 102 } 103 if (unavailable_count) 104 { 105 output_stream.Indent (); 106 output_stream.Printf("%u registers were unavailable.\n", unavailable_count); 107 } 108 output_stream.IndentLess (); 109 output_stream.EOL(); 110 } 111 } 112 else 113 { 114 const char *arg_cstr; 115 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 116 { 117 reg_info = reg_context->GetRegisterInfoByName(arg_cstr); 118 119 if (reg_info) 120 { 121 output_stream.Printf("%-12s = ", reg_info->name); 122 if (reg_context->ReadRegisterBytes(reg_info->kinds[eRegisterKindLLDB], reg_data)) 123 { 124 reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); 125 } 126 else 127 { 128 output_stream.PutCString ("error: unavailable"); 129 } 130 output_stream.EOL(); 131 } 132 else 133 { 134 result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr); 135 } 136 } 137 } 138 } 139 else 140 { 141 result.AppendError ("no current frame"); 142 result.SetStatus (eReturnStatusFailed); 143 } 144 return result.Succeeded(); 145 } 146 }; 147 148 149 //---------------------------------------------------------------------- 150 // "register write" 151 //---------------------------------------------------------------------- 152 class CommandObjectRegisterWrite : public CommandObject 153 { 154 public: 155 CommandObjectRegisterWrite (CommandInterpreter &interpreter) : 156 CommandObject (interpreter, 157 "register write", 158 "Modify a single register value.", 159 //"register write <reg-name> <value>", 160 NULL, 161 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 162 { 163 CommandArgumentEntry arg1; 164 CommandArgumentEntry arg2; 165 CommandArgumentData register_arg; 166 CommandArgumentData value_arg; 167 168 // Define the first (and only) variant of this arg. 169 register_arg.arg_type = eArgTypeRegisterName; 170 register_arg.arg_repetition = eArgRepeatPlain; 171 172 // There is only one variant this argument could be; put it into the argument entry. 173 arg1.push_back (register_arg); 174 175 // Define the first (and only) variant of this arg. 176 value_arg.arg_type = eArgTypeValue; 177 value_arg.arg_repetition = eArgRepeatPlain; 178 179 // There is only one variant this argument could be; put it into the argument entry. 180 arg2.push_back (value_arg); 181 182 // Push the data for the first argument into the m_arguments vector. 183 m_arguments.push_back (arg1); 184 m_arguments.push_back (arg2); 185 } 186 187 virtual 188 ~CommandObjectRegisterWrite () 189 { 190 } 191 192 virtual bool 193 Execute 194 ( 195 Args& command, 196 CommandReturnObject &result 197 ) 198 { 199 DataExtractor reg_data; 200 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 201 RegisterContext *reg_context = exe_ctx.GetRegisterContext (); 202 203 if (reg_context) 204 { 205 if (command.GetArgumentCount() != 2) 206 { 207 result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); 208 result.SetStatus (eReturnStatusFailed); 209 } 210 else 211 { 212 const char *reg_name = command.GetArgumentAtIndex(0); 213 const char *value_str = command.GetArgumentAtIndex(1); 214 const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name); 215 216 if (reg_info) 217 { 218 Scalar scalar; 219 Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size)); 220 if (error.Success()) 221 { 222 if (reg_context->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar)) 223 { 224 result.SetStatus (eReturnStatusSuccessFinishNoResult); 225 return true; 226 } 227 } 228 else 229 { 230 result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", 231 reg_name, 232 value_str, 233 error.AsCString()); 234 result.SetStatus (eReturnStatusFailed); 235 } 236 } 237 else 238 { 239 result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); 240 result.SetStatus (eReturnStatusFailed); 241 } 242 } 243 } 244 else 245 { 246 result.AppendError ("no current frame"); 247 result.SetStatus (eReturnStatusFailed); 248 } 249 return result.Succeeded(); 250 } 251 }; 252 253 254 //---------------------------------------------------------------------- 255 // CommandObjectRegister constructor 256 //---------------------------------------------------------------------- 257 CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : 258 CommandObjectMultiword (interpreter, 259 "register", 260 "A set of commands to access thread registers.", 261 "register [read|write] ...") 262 { 263 LoadSubCommand ("read", CommandObjectSP (new CommandObjectRegisterRead (interpreter))); 264 LoadSubCommand ("write", CommandObjectSP (new CommandObjectRegisterWrite (interpreter))); 265 } 266 267 268 //---------------------------------------------------------------------- 269 // Destructor 270 //---------------------------------------------------------------------- 271 CommandObjectRegister::~CommandObjectRegister() 272 { 273 } 274