1//===-- CommandObjectArgs.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 "lldb/lldb-python.h" 11 12#include "CommandObjectArgs.h" 13 14// C Includes 15// C++ Includes 16// Other libraries and framework includes 17// Project includes 18#include "lldb/Interpreter/Args.h" 19#include "lldb/Core/Debugger.h" 20#include "lldb/Core/Module.h" 21#include "lldb/Core/Value.h" 22#include "lldb/Expression/ClangExpression.h" 23#include "lldb/Expression/ClangExpressionVariable.h" 24#include "lldb/Expression/ClangFunction.h" 25#include "lldb/Host/Host.h" 26#include "lldb/Interpreter/CommandInterpreter.h" 27#include "lldb/Interpreter/CommandReturnObject.h" 28#include "lldb/Symbol/ObjectFile.h" 29#include "lldb/Symbol/Variable.h" 30#include "lldb/Target/Process.h" 31#include "lldb/Target/Target.h" 32#include "lldb/Target/Thread.h" 33#include "lldb/Target/StackFrame.h" 34 35using namespace lldb; 36using namespace lldb_private; 37 38// This command is a toy. I'm just using it to have a way to construct the arguments to 39// calling functions. 40// 41 42CommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : 43 Options(interpreter) 44{ 45 // Keep only one place to reset the values to their defaults 46 OptionParsingStarting(); 47} 48 49 50CommandObjectArgs::CommandOptions::~CommandOptions () 51{ 52} 53 54Error 55CommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 56{ 57 Error error; 58 59 const int short_option = m_getopt_table[option_idx].val; 60 61 switch (short_option) 62 { 63 default: 64 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 65 break; 66 } 67 68 return error; 69} 70 71void 72CommandObjectArgs::CommandOptions::OptionParsingStarting () 73{ 74} 75 76const OptionDefinition* 77CommandObjectArgs::CommandOptions::GetDefinitions () 78{ 79 return g_option_table; 80} 81 82CommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) : 83 CommandObjectParsed (interpreter, 84 "args", 85 "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*", 86 "args"), 87 m_options (interpreter) 88{ 89} 90 91CommandObjectArgs::~CommandObjectArgs () 92{ 93} 94 95Options * 96CommandObjectArgs::GetOptions () 97{ 98 return &m_options; 99} 100 101bool 102CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) 103{ 104 ConstString target_triple; 105 106 107 Process *process = m_exe_ctx.GetProcessPtr(); 108 if (!process) 109 { 110 result.AppendError ("Args found no process."); 111 result.SetStatus (eReturnStatusFailed); 112 return false; 113 } 114 115 const ABI *abi = process->GetABI().get(); 116 if (!abi) 117 { 118 result.AppendError ("The current process has no ABI."); 119 result.SetStatus (eReturnStatusFailed); 120 return false; 121 } 122 123 const size_t num_args = args.GetArgumentCount (); 124 size_t arg_index; 125 126 if (!num_args) 127 { 128 result.AppendError ("args requires at least one argument"); 129 result.SetStatus (eReturnStatusFailed); 130 return false; 131 } 132 133 Thread *thread = m_exe_ctx.GetThreadPtr(); 134 135 if (!thread) 136 { 137 result.AppendError ("args found no thread."); 138 result.SetStatus (eReturnStatusFailed); 139 return false; 140 } 141 142 lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame (); 143 if (!thread_cur_frame) 144 { 145 result.AppendError ("The current thread has no current frame."); 146 result.SetStatus (eReturnStatusFailed); 147 return false; 148 } 149 150 ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule()); 151 if (!thread_module_sp) 152 { 153 result.AppendError ("The PC has no associated module."); 154 result.SetStatus (eReturnStatusFailed); 155 return false; 156 } 157 158 ClangASTContext &ast_context = thread_module_sp->GetClangASTContext(); 159 160 ValueList value_list; 161 162 for (arg_index = 0; arg_index < num_args; ++arg_index) 163 { 164 const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); 165 Value value; 166 value.SetValueType(Value::eValueTypeScalar); 167 ClangASTType clang_type; 168 169 char *int_pos; 170 if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int"))) 171 { 172 Encoding encoding = eEncodingSint; 173 174 int width = 0; 175 176 if (int_pos > arg_type_cstr + 1) 177 { 178 result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); 179 result.SetStatus (eReturnStatusFailed); 180 return false; 181 } 182 if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u') 183 { 184 result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); 185 result.SetStatus (eReturnStatusFailed); 186 return false; 187 } 188 if (arg_type_cstr[0] == 'u') 189 { 190 encoding = eEncodingUint; 191 } 192 193 char *width_pos = int_pos + 3; 194 195 if (!strcmp (width_pos, "8_t")) 196 width = 8; 197 else if (!strcmp (width_pos, "16_t")) 198 width = 16; 199 else if (!strcmp (width_pos, "32_t")) 200 width = 32; 201 else if (!strcmp (width_pos, "64_t")) 202 width = 64; 203 else 204 { 205 result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); 206 result.SetStatus (eReturnStatusFailed); 207 return false; 208 } 209 210 clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width); 211 212 if (!clang_type.IsValid()) 213 { 214 result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n", 215 arg_type_cstr, 216 (encoding == eEncodingSint ? "signed" : "unsigned"), 217 width); 218 219 result.SetStatus (eReturnStatusFailed); 220 return false; 221 } 222 } 223 else if (strchr (arg_type_cstr, '*')) 224 { 225 if (!strcmp (arg_type_cstr, "void*")) 226 clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType(); 227 else if (!strcmp (arg_type_cstr, "char*")) 228 clang_type = ast_context.GetCStringType (false); 229 else 230 { 231 result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); 232 result.SetStatus (eReturnStatusFailed); 233 return false; 234 } 235 } 236 else 237 { 238 result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); 239 result.SetStatus (eReturnStatusFailed); 240 return false; 241 } 242 243 value.SetClangType (clang_type); 244 value_list.PushValue(value); 245 } 246 247 if (!abi->GetArgumentValues (*thread, value_list)) 248 { 249 result.AppendError ("Couldn't get argument values"); 250 result.SetStatus (eReturnStatusFailed); 251 return false; 252 } 253 254 result.GetOutputStream ().Printf("Arguments : \n"); 255 256 for (arg_index = 0; arg_index < num_args; ++arg_index) 257 { 258 result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index)); 259 value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ()); 260 result.GetOutputStream ().Printf("\n"); 261 } 262 263 return result.Succeeded(); 264} 265 266OptionDefinition 267CommandObjectArgs::CommandOptions::g_option_table[] = 268{ 269 { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, 270 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 271}; 272 273