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
35 using namespace lldb;
36 using 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
CommandOptions(CommandInterpreter & interpreter)42 CommandObjectArgs::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
~CommandOptions()50 CommandObjectArgs::CommandOptions::~CommandOptions ()
51 {
52 }
53
54 Error
SetOptionValue(uint32_t option_idx,const char * option_arg)55 CommandObjectArgs::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
71 void
OptionParsingStarting()72 CommandObjectArgs::CommandOptions::OptionParsingStarting ()
73 {
74 }
75
76 const OptionDefinition*
GetDefinitions()77 CommandObjectArgs::CommandOptions::GetDefinitions ()
78 {
79 return g_option_table;
80 }
81
CommandObjectArgs(CommandInterpreter & interpreter)82 CommandObjectArgs::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
~CommandObjectArgs()91 CommandObjectArgs::~CommandObjectArgs ()
92 {
93 }
94
95 Options *
GetOptions()96 CommandObjectArgs::GetOptions ()
97 {
98 return &m_options;
99 }
100
101 bool
DoExecute(Args & args,CommandReturnObject & result)102 CommandObjectArgs::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
266 OptionDefinition
267 CommandObjectArgs::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